Endpoint Groups
An endpoint group is a way to group a set of endpoints.
/endpoint-groupsLists the caller's enabled endpoint groups; id reads one. Unknown parameters get a 400. The MCP group_query tool reads through this.
Required scope
group:readQuery parameters
- enablement
string Filter the results by enablement. Enablement is a customer setting that stops Port OS from using a resource without deleting it. Port OS uses it in place of deletion because it cannot delete a device on the provider's side. Defaults to ENABLED. Use DISABLED to list only disabled resources, or '*' to include both enabled and disabled resources. Looking up a resource by its exact id ignores this filter.
Default:
ENABLEDAllowed values
ENABLEDDISABLED*
- owner
string Filter the results by the owner of the resource. Defaults to the authenticated caller's resources when omitted. Use '~caller' to make that scope explicit. Another owner can be selected only for resources the caller can read.
- nextToken
string Opaque token for the next page of results. Pass the continuation token returned by the previous response, unchanged. Omit it to start from the first page.
- maxResults
integer Maximum number of results to return in one page. Defaults to 100. Values from 1 through 100 are accepted.
minimum: 1
maximum: 100
Default:
100
Returns
200
Endpoint groups retrieved successfully
Fields
- results
array<EndpointGroup>Required A logical grouping of endpoints that share common interfaces and ownership.
- id
stringRequired The unique identifier for the endpoint group
pattern: "^port1/[^/]+/[^/]+/endpoint-groups/[^/]+$"
- enablement
stringRequired Whether Port OS uses an endpoint or group. A disabled one is hidden from collections by default and cannot be sent device messages or targeted by them; exact authorized reads still return it. Rediscovery never changes it, so disabling is how a user hides a discovered device or room for good.
Default:
ENABLEDAllowed values
ENABLEDDISABLED
- etag
stringRequired Opaque strong entity tag of this group version, for example `"12"`. It changes once per transaction when meaningful customer intent, provider contributions, membership, interfaces, names, association or enablement changes. Identical rediscovery leaves it unchanged. Send it as `If-Match` (or as the operation `etag` in `/endpoint-groups-manage`) when mutating the group.
- redirectedFrom
string Set when the group was read through a merged-away ID: the ID that was requested, which now redirects to this group. Mutations must use this group's `id`.
- parentGroupId
string The canonical parent group derived from `IS_PART_OF` relationships, when the group has one.
- controllers
array<EndpointGroupController> Endpoints that declare `CAN_CONTROL` on one of this group's group routes, with the messages they support on it.
An endpoint able to act on a group through a `CAN_CONTROL` relationship, with the interface messages it supports there. Being a controller does not grant authorization.
- attributes
array<GroupRouteAttributeState> The group's state: every attribute value stored for its group routes, one entry per group route and attribute, tagged with the group route and provider. Populated only when the read is called with `expand=interfaces.attributes`.
One attribute value reported for one group route of an endpoint group. A group's state is the set of its group routes' values; values from different providers are never aggregated, so each entry names the group route and the provider that reported it. When a forced read reaches the provider and the provider answers without a value for a declared attribute, the entry carries no `value` and an `error` with code `PROVIDER_NO_STATE` instead of being omitted.
- groupRoutes
array<EndpointGroupRoute> Native provider contributions, populated only under expand=groupRoutes.
A route within an endpoint group linking a plugin route to a group with interface metadata.
- associatedGroupId
string The associated endpoint group ID; omitted for an orphaned route.
pattern: "^port1/[^/]+/[^/]+/endpoint-groups/[^/]+$"
- associatedPluginRouteId
stringRequired Stable plugin-owned route ID. Match synchronized plugin or fixture membership with this value, not the Port OS group route `id`.
- interfaces
array<RouteInterface>Required Supported interfaces.
- enablement
stringRequired Whether Port OS uses an endpoint or group. A disabled one is hidden from collections by default and cannot be sent device messages or targeted by them; exact authorized reads still return it. Rediscovery never changes it, so disabling is how a user hides a discovered device or room for good.
Default:
ENABLEDAllowed values
ENABLEDDISABLED
- associatedGroupId
- id
- errors
array<Error> Partial query errors collected while returning available results.
The one Port OS error shape, returned by every REST error response and every MCP tool error. `code` names the specific failure and `family` its broad class; both are closed enums, so clients branch on them and show `message`, which says what failed and what to do next.
- family
stringRequired The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.
Allowed values
NOT_FOUNDBAD_REQUESTUNAUTHORIZEDFORBIDDENCONFLICTGONEPRECONDITION_FAILEDPRECONDITION_REQUIREDPAYLOAD_TOO_LARGEUNSUPPORTED_MEDIA_TYPEUNPROCESSABLE_ENTITYLOCKEDTOO_MANY_REQUESTSBAD_GATEWAYSERVICE_UNAVAILABLEGATEWAY_TIMEOUTNOT_IMPLEMENTEDINTERNAL_SERVER_ERRORREQUEST_INVALIDAUTHENTICATIONPERMISSIONENDPOINT_NOT_FOUNDENDPOINT_STATE_CONFLICTENDPOINT_UNAVAILABLERATE_LIMITPROVIDER_BAD_RESPONSEPROVIDER_UNAVAILABLEPROVIDER_TIMEOUT
- code
stringRequired The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.
Allowed values
BAD_REQUESTUNAUTHORIZEDFORBIDDENINSUFFICIENT_SCOPENOT_FOUNDCONFLICTUNPROCESSABLE_ENTITYUNSUPPORTED_OPERATIONTOO_MANY_REQUESTSSERVICE_UNAVAILABLENOT_IMPLEMENTEDINTERNALCHECKSUM_MISMATCHFILE_TOO_LARGESTORAGE_UNAVAILABLEINSUFFICIENT_PERMISSIONSINVALID_FILE_TYPEQUOTA_EXCEEDEDCONCURRENT_MODIFICATIONENDPOINT_UNREACHABLEBRIDGE_UNREACHABLECLOUD_CONTROL_DISABLEDENDPOINT_BUSYENDPOINT_LOW_POWERAUTHORIZATION_CREDENTIAL_INVALIDAUTHORIZATION_CREDENTIAL_EXPIREDINVALID_DIRECTIVEINVALID_VALUEVALUE_OUT_OF_RANGENOT_SUPPORTED_IN_CURRENT_MODERATE_LIMIT_EXCEEDEDPROVIDER_SERVICE_UNAVAILABLEPROVIDER_TIMEOUTPROVIDER_INTERNAL_ERRORINVALID_PROVIDER_RESPONSEOUTCOME_UNKNOWNPRECONDITION_FAILEDAUTH_LINK_NOT_READYAUTH_LINK_NOT_DISCONNECTABLEPRECONDITION_REQUIREDIDEMPOTENCY_KEY_REQUIREDIDEMPOTENCY_KEY_REUSEDIDEMPOTENCY_KEY_IN_FLIGHTIDEMPOTENCY_KEY_INVALIDGROUP_MERGEDMULTI_ROOM_UNSUPPORTEDMAP_NOT_ACTIVETARGET_UNSUPPORTEDTARGET_AMBIGUOUSTARGET_GROUP_NOT_FOUNDTARGET_GROUP_DISABLEDDUPLICATE_TARGET_GROUPMESSAGE_UNSUPPORTEDMESSAGE_AMBIGUOUSENDPOINT_DISABLEDENDPOINT_ROUTE_CHANGEDENDPOINT_HAS_DEPENDENCIESENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVEENDPOINT_COMMITTED_CLEANUP_PENDINGDEEP_QUERY_FAILEDPROVIDER_NO_STATEEVENT_MANAGEMENT_DISABLEDSUBSCRIPTION_IDENTITY_IMMUTABLEUNSUPPORTED_MEDIA_TYPEEVENT_PAYLOAD_TOO_LARGEREQUEST_BODY_TOO_LARGEEVENT_IDENTITY_CONFLICTEVENT_INGRESS_QUOTA_EXCEEDEDEVENT_RECEIPT_EXPIREDEVENT_STORAGE_UNAVAILABLEEVENT_DEAD_LETTER_NOT_FOUNDEVENT_REDRIVE_CONFLICTEVENT_REDRIVE_EXPIREDRECEIPT_CONTEXT_EXPIREDEVENT_MAINTENANCE_INCOMPLETEUNKNOWN_INTERFACEINVALID_CONFIGURATIONINVALID_PLUGIN_MANIFESTINVALID_ATTRIBUTEINVALID_PROVIDER_MESSAGEUNDECLARED_CAPABILITYPLUGIN_ROUTE_ID_CONFLICTUNRESOLVED_REFERENCEINVALID_RELATIONSHIPRELATIONSHIP_CYCLEMULTIPLE_PARENTSFLOW_VALIDATION_FAILEDPROVIDER_SYNC_UNSUPPORTED
- details
ErrorDetails Optional typed context for an error. Fields are additive and only populated when the error can safely expose that context to API clients.
- errors
array<SynchronizationItemError> Every rejected item when a request that is validated item by item and applied atomically fails, such as a discovery `SynchronizationRequest` whose routes, group routes or relationships are rejected. Omitted for single-item failures.
One rejected discovery item of a `SynchronizationRequest`, keyed by the plugin-owned identity of the rejected item: `pluginRouteId` for a route or group route, or `relationshipExternalId` for a relationship. Exactly one of the two is set. It shares the `code`, `family`, `status` and `message` fields of `BatchItemError`; discovery items are keyed by plugin-owned identity because they carry no `requestId`. A request with any rejected item is rejected as a whole and lists every rejected item.
- pluginRouteId
string Plugin-owned identifier of the rejected route or group route. Set unless the item is a relationship.
- relationshipExternalId
string Plugin-owned `externalId` of the rejected relationship. Set only for relationship items.
- interface
string Canonical capability interface name the failure applies to, when the failure is interface-specific.
- version
string Declared capability interface version the failure applies to, when the failure is interface-specific.
- code
stringRequired The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.
Allowed values
BAD_REQUESTUNAUTHORIZEDFORBIDDENINSUFFICIENT_SCOPENOT_FOUNDCONFLICTUNPROCESSABLE_ENTITYUNSUPPORTED_OPERATIONTOO_MANY_REQUESTSSERVICE_UNAVAILABLENOT_IMPLEMENTEDINTERNALCHECKSUM_MISMATCHFILE_TOO_LARGESTORAGE_UNAVAILABLEINSUFFICIENT_PERMISSIONSINVALID_FILE_TYPEQUOTA_EXCEEDEDCONCURRENT_MODIFICATIONENDPOINT_UNREACHABLEBRIDGE_UNREACHABLECLOUD_CONTROL_DISABLEDENDPOINT_BUSYENDPOINT_LOW_POWERAUTHORIZATION_CREDENTIAL_INVALIDAUTHORIZATION_CREDENTIAL_EXPIREDINVALID_DIRECTIVEINVALID_VALUEVALUE_OUT_OF_RANGENOT_SUPPORTED_IN_CURRENT_MODERATE_LIMIT_EXCEEDEDPROVIDER_SERVICE_UNAVAILABLEPROVIDER_TIMEOUTPROVIDER_INTERNAL_ERRORINVALID_PROVIDER_RESPONSEOUTCOME_UNKNOWNPRECONDITION_FAILEDAUTH_LINK_NOT_READYAUTH_LINK_NOT_DISCONNECTABLEPRECONDITION_REQUIREDIDEMPOTENCY_KEY_REQUIREDIDEMPOTENCY_KEY_REUSEDIDEMPOTENCY_KEY_IN_FLIGHTIDEMPOTENCY_KEY_INVALIDGROUP_MERGEDMULTI_ROOM_UNSUPPORTEDMAP_NOT_ACTIVETARGET_UNSUPPORTEDTARGET_AMBIGUOUSTARGET_GROUP_NOT_FOUNDTARGET_GROUP_DISABLEDDUPLICATE_TARGET_GROUPMESSAGE_UNSUPPORTEDMESSAGE_AMBIGUOUSENDPOINT_DISABLEDENDPOINT_ROUTE_CHANGEDENDPOINT_HAS_DEPENDENCIESENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVEENDPOINT_COMMITTED_CLEANUP_PENDINGDEEP_QUERY_FAILEDPROVIDER_NO_STATEEVENT_MANAGEMENT_DISABLEDSUBSCRIPTION_IDENTITY_IMMUTABLEUNSUPPORTED_MEDIA_TYPEEVENT_PAYLOAD_TOO_LARGEREQUEST_BODY_TOO_LARGEEVENT_IDENTITY_CONFLICTEVENT_INGRESS_QUOTA_EXCEEDEDEVENT_RECEIPT_EXPIREDEVENT_STORAGE_UNAVAILABLEEVENT_DEAD_LETTER_NOT_FOUNDEVENT_REDRIVE_CONFLICTEVENT_REDRIVE_EXPIREDRECEIPT_CONTEXT_EXPIREDEVENT_MAINTENANCE_INCOMPLETEUNKNOWN_INTERFACEINVALID_CONFIGURATIONINVALID_PLUGIN_MANIFESTINVALID_ATTRIBUTEINVALID_PROVIDER_MESSAGEUNDECLARED_CAPABILITYPLUGIN_ROUTE_ID_CONFLICTUNRESOLVED_REFERENCEINVALID_RELATIONSHIPRELATIONSHIP_CYCLEMULTIPLE_PARENTSFLOW_VALIDATION_FAILEDPROVIDER_SYNC_UNSUPPORTED
- family
stringRequired The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.
Allowed values
NOT_FOUNDBAD_REQUESTUNAUTHORIZEDFORBIDDENCONFLICTGONEPRECONDITION_FAILEDPRECONDITION_REQUIREDPAYLOAD_TOO_LARGEUNSUPPORTED_MEDIA_TYPEUNPROCESSABLE_ENTITYLOCKEDTOO_MANY_REQUESTSBAD_GATEWAYSERVICE_UNAVAILABLEGATEWAY_TIMEOUTNOT_IMPLEMENTEDINTERNAL_SERVER_ERRORREQUEST_INVALIDAUTHENTICATIONPERMISSIONENDPOINT_NOT_FOUNDENDPOINT_STATE_CONFLICTENDPOINT_UNAVAILABLERATE_LIMITPROVIDER_BAD_RESPONSEPROVIDER_UNAVAILABLEPROVIDER_TIMEOUT
- pluginRouteId
- family
Errors
400 BAD_REQUESTBad request - missing required parameters
Check the request fields and any validation details, then correct the payload.
401 UNAUTHORIZEDUnauthorized - invalid or missing authentication token
Obtain a valid access token, then retry.
403 FORBIDDENForbidden - insufficient permissions
Check the linked account and its permissions for the device or resource.
500 INTERNALInternal server error
Retry with backoff only when the operation is safe to repeat. Include the error code when reporting persistent failures.
/endpoint-groupsUpdates or creates an endpoint group.
For example:
- Update the name of a group.
- Change the members of a group.
- Split or merge multiple groups.
An operation that updates or creates an endpoint group also tries to update the underlying plugin's data, such as Philips Hue or Roborock groups. If you update the group on the Port OS side, Port OS tries its best to sync that data to Philips Hue or Roborock.
Required scope
group:manageHeader parameters
- Idempotency-Key
stringRequired Client-chosen key that makes a non-idempotent request retry-safe, following draft-ietf-httpapi-idempotency-key-header. A committed response is stored for 24 hours and replayed for the same principal, operation, key and payload. Missing key returns 400 IDEMPOTENCY_KEY_REQUIRED, a key longer than 255 characters returns 400 IDEMPOTENCY_KEY_INVALID, the same key with a different payload returns 422, and the same key while the first request is still in flight returns 409. Requests rolled back before external provider attempts do not consume the key. Group mutations retain terminal failed responses after provider attempts together with received provider truth; their operation contract defines these replayable outcomes.
minLength: 1
maxLength: 255
- If-Match
string Required for a full replacement when the request identifies an existing resource. Send that resource's quoted strong etag from its last GET. A missing condition on a replacement returns 428 PRECONDITION_REQUIRED; a stale condition returns 412 PRECONDITION_FAILED. Omit this header when creating a new resource without an id. Wildcards are accepted only where the operation explicitly permits them.
minLength: 1
Request body
Fields
- item
UpsertEndpointGroupItemRequired Full customer document. Omit id to create; an id replaces an existing group. Membership is the complete desired effective member set, reconciled against provider truth through the group management engine.
- providerSync
string Provider synchronization policy. BEST_EFFORT asks declared providers first and saves local fallback intent on failure. FAIL_ON_PROVIDER_ERROR fails the customer batch on a failed supported dispatch while retaining received provider truth. PORTOS_ONLY changes local intent. Undeclared messages are reported as NOT_SUPPORTED and do not prevent local changes.
Default:
BEST_EFFORTAllowed values
PORTOS_ONLYBEST_EFFORTFAIL_ON_PROVIDER_ERROR
Returns
200
Endpoint group created successfully
Fields
- status
stringRequired APPLIED commits without a failed-dispatch fallback; PARTIALLY_APPLIED commits with one. NOT_APPLIED reports provider attempts from a failed customer batch and carries no group etag.
Allowed values
APPLIEDPARTIALLY_APPLIEDNOT_APPLIED
- providerDispatches
array<EndpointGroupProviderDispatch>Required One provider message for this operation. SUCCEEDED requires a valid read-back reply establishing the requested condition. Provider identities are present only with the same native-route or account read visibility required by the public query projection. An authorized write can still return a redacted dispatch outcome; its namespace, name, status, reason and error code remain. Errors for hidden metadata use a generic message and omit details.
- authLinkId
string The provider account authorization link ID; omitted without metadata read visibility, empty for a readable account without a link.
- groupRouteId
string The provider-native group route ID within this plugin and account, omitted without native-route read visibility.
- status
stringRequired A planned, verified, failed or undeclared provider dispatch; a timeout is FAILED.
Allowed values
PLANNEDSUCCEEDEDFAILEDNOT_SUPPORTED
- reason
string Why no provider dispatch was sent. NOT_DECLARED means the provider does not declare the message. OUTSIDE_PRINCIPAL means native mutations are limited to accounts owned by the original caller; sharing a group or endpoint does not grant native account-management authority. Local intent can still apply without dispatching to the foreign account.
Allowed values
NOT_DECLAREDOUTSIDE_PRINCIPAL
- error
Error The one Port OS error shape, returned by every REST error response and every MCP tool error. `code` names the specific failure and `family` its broad class; both are closed enums, so clients branch on them and show `message`, which says what failed and what to do next.
- authLinkId
- errors
array<Error>Required The one Port OS error shape, returned by every REST error response and every MCP tool error. `code` names the specific failure and `family` its broad class; both are closed enums, so clients branch on them and show `message`, which says what failed and what to do next.
- family
stringRequired The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.
Allowed values
NOT_FOUNDBAD_REQUESTUNAUTHORIZEDFORBIDDENCONFLICTGONEPRECONDITION_FAILEDPRECONDITION_REQUIREDPAYLOAD_TOO_LARGEUNSUPPORTED_MEDIA_TYPEUNPROCESSABLE_ENTITYLOCKEDTOO_MANY_REQUESTSBAD_GATEWAYSERVICE_UNAVAILABLEGATEWAY_TIMEOUTNOT_IMPLEMENTEDINTERNAL_SERVER_ERRORREQUEST_INVALIDAUTHENTICATIONPERMISSIONENDPOINT_NOT_FOUNDENDPOINT_STATE_CONFLICTENDPOINT_UNAVAILABLERATE_LIMITPROVIDER_BAD_RESPONSEPROVIDER_UNAVAILABLEPROVIDER_TIMEOUT
- code
stringRequired The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.
Allowed values
BAD_REQUESTUNAUTHORIZEDFORBIDDENINSUFFICIENT_SCOPENOT_FOUNDCONFLICTUNPROCESSABLE_ENTITYUNSUPPORTED_OPERATIONTOO_MANY_REQUESTSSERVICE_UNAVAILABLENOT_IMPLEMENTEDINTERNALCHECKSUM_MISMATCHFILE_TOO_LARGESTORAGE_UNAVAILABLEINSUFFICIENT_PERMISSIONSINVALID_FILE_TYPEQUOTA_EXCEEDEDCONCURRENT_MODIFICATIONENDPOINT_UNREACHABLEBRIDGE_UNREACHABLECLOUD_CONTROL_DISABLEDENDPOINT_BUSYENDPOINT_LOW_POWERAUTHORIZATION_CREDENTIAL_INVALIDAUTHORIZATION_CREDENTIAL_EXPIREDINVALID_DIRECTIVEINVALID_VALUEVALUE_OUT_OF_RANGENOT_SUPPORTED_IN_CURRENT_MODERATE_LIMIT_EXCEEDEDPROVIDER_SERVICE_UNAVAILABLEPROVIDER_TIMEOUTPROVIDER_INTERNAL_ERRORINVALID_PROVIDER_RESPONSEOUTCOME_UNKNOWNPRECONDITION_FAILEDAUTH_LINK_NOT_READYAUTH_LINK_NOT_DISCONNECTABLEPRECONDITION_REQUIREDIDEMPOTENCY_KEY_REQUIREDIDEMPOTENCY_KEY_REUSEDIDEMPOTENCY_KEY_IN_FLIGHTIDEMPOTENCY_KEY_INVALIDGROUP_MERGEDMULTI_ROOM_UNSUPPORTEDMAP_NOT_ACTIVETARGET_UNSUPPORTEDTARGET_AMBIGUOUSTARGET_GROUP_NOT_FOUNDTARGET_GROUP_DISABLEDDUPLICATE_TARGET_GROUPMESSAGE_UNSUPPORTEDMESSAGE_AMBIGUOUSENDPOINT_DISABLEDENDPOINT_ROUTE_CHANGEDENDPOINT_HAS_DEPENDENCIESENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVEENDPOINT_COMMITTED_CLEANUP_PENDINGDEEP_QUERY_FAILEDPROVIDER_NO_STATEEVENT_MANAGEMENT_DISABLEDSUBSCRIPTION_IDENTITY_IMMUTABLEUNSUPPORTED_MEDIA_TYPEEVENT_PAYLOAD_TOO_LARGEREQUEST_BODY_TOO_LARGEEVENT_IDENTITY_CONFLICTEVENT_INGRESS_QUOTA_EXCEEDEDEVENT_RECEIPT_EXPIREDEVENT_STORAGE_UNAVAILABLEEVENT_DEAD_LETTER_NOT_FOUNDEVENT_REDRIVE_CONFLICTEVENT_REDRIVE_EXPIREDRECEIPT_CONTEXT_EXPIREDEVENT_MAINTENANCE_INCOMPLETEUNKNOWN_INTERFACEINVALID_CONFIGURATIONINVALID_PLUGIN_MANIFESTINVALID_ATTRIBUTEINVALID_PROVIDER_MESSAGEUNDECLARED_CAPABILITYPLUGIN_ROUTE_ID_CONFLICTUNRESOLVED_REFERENCEINVALID_RELATIONSHIPRELATIONSHIP_CYCLEMULTIPLE_PARENTSFLOW_VALIDATION_FAILEDPROVIDER_SYNC_UNSUPPORTED
- details
ErrorDetails Optional typed context for an error. Fields are additive and only populated when the error can safely expose that context to API clients.
- errors
array<SynchronizationItemError> Every rejected item when a request that is validated item by item and applied atomically fails, such as a discovery `SynchronizationRequest` whose routes, group routes or relationships are rejected. Omitted for single-item failures.
One rejected discovery item of a `SynchronizationRequest`, keyed by the plugin-owned identity of the rejected item: `pluginRouteId` for a route or group route, or `relationshipExternalId` for a relationship. Exactly one of the two is set. It shares the `code`, `family`, `status` and `message` fields of `BatchItemError`; discovery items are keyed by plugin-owned identity because they carry no `requestId`. A request with any rejected item is rejected as a whole and lists every rejected item.
- pluginRouteId
string Plugin-owned identifier of the rejected route or group route. Set unless the item is a relationship.
- relationshipExternalId
string Plugin-owned `externalId` of the rejected relationship. Set only for relationship items.
- interface
string Canonical capability interface name the failure applies to, when the failure is interface-specific.
- version
string Declared capability interface version the failure applies to, when the failure is interface-specific.
- code
stringRequired The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.
Allowed values
BAD_REQUESTUNAUTHORIZEDFORBIDDENINSUFFICIENT_SCOPENOT_FOUNDCONFLICTUNPROCESSABLE_ENTITYUNSUPPORTED_OPERATIONTOO_MANY_REQUESTSSERVICE_UNAVAILABLENOT_IMPLEMENTEDINTERNALCHECKSUM_MISMATCHFILE_TOO_LARGESTORAGE_UNAVAILABLEINSUFFICIENT_PERMISSIONSINVALID_FILE_TYPEQUOTA_EXCEEDEDCONCURRENT_MODIFICATIONENDPOINT_UNREACHABLEBRIDGE_UNREACHABLECLOUD_CONTROL_DISABLEDENDPOINT_BUSYENDPOINT_LOW_POWERAUTHORIZATION_CREDENTIAL_INVALIDAUTHORIZATION_CREDENTIAL_EXPIREDINVALID_DIRECTIVEINVALID_VALUEVALUE_OUT_OF_RANGENOT_SUPPORTED_IN_CURRENT_MODERATE_LIMIT_EXCEEDEDPROVIDER_SERVICE_UNAVAILABLEPROVIDER_TIMEOUTPROVIDER_INTERNAL_ERRORINVALID_PROVIDER_RESPONSEOUTCOME_UNKNOWNPRECONDITION_FAILEDAUTH_LINK_NOT_READYAUTH_LINK_NOT_DISCONNECTABLEPRECONDITION_REQUIREDIDEMPOTENCY_KEY_REQUIREDIDEMPOTENCY_KEY_REUSEDIDEMPOTENCY_KEY_IN_FLIGHTIDEMPOTENCY_KEY_INVALIDGROUP_MERGEDMULTI_ROOM_UNSUPPORTEDMAP_NOT_ACTIVETARGET_UNSUPPORTEDTARGET_AMBIGUOUSTARGET_GROUP_NOT_FOUNDTARGET_GROUP_DISABLEDDUPLICATE_TARGET_GROUPMESSAGE_UNSUPPORTEDMESSAGE_AMBIGUOUSENDPOINT_DISABLEDENDPOINT_ROUTE_CHANGEDENDPOINT_HAS_DEPENDENCIESENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVEENDPOINT_COMMITTED_CLEANUP_PENDINGDEEP_QUERY_FAILEDPROVIDER_NO_STATEEVENT_MANAGEMENT_DISABLEDSUBSCRIPTION_IDENTITY_IMMUTABLEUNSUPPORTED_MEDIA_TYPEEVENT_PAYLOAD_TOO_LARGEREQUEST_BODY_TOO_LARGEEVENT_IDENTITY_CONFLICTEVENT_INGRESS_QUOTA_EXCEEDEDEVENT_RECEIPT_EXPIREDEVENT_STORAGE_UNAVAILABLEEVENT_DEAD_LETTER_NOT_FOUNDEVENT_REDRIVE_CONFLICTEVENT_REDRIVE_EXPIREDRECEIPT_CONTEXT_EXPIREDEVENT_MAINTENANCE_INCOMPLETEUNKNOWN_INTERFACEINVALID_CONFIGURATIONINVALID_PLUGIN_MANIFESTINVALID_ATTRIBUTEINVALID_PROVIDER_MESSAGEUNDECLARED_CAPABILITYPLUGIN_ROUTE_ID_CONFLICTUNRESOLVED_REFERENCEINVALID_RELATIONSHIPRELATIONSHIP_CYCLEMULTIPLE_PARENTSFLOW_VALIDATION_FAILEDPROVIDER_SYNC_UNSUPPORTED
- family
stringRequired The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.
Allowed values
NOT_FOUNDBAD_REQUESTUNAUTHORIZEDFORBIDDENCONFLICTGONEPRECONDITION_FAILEDPRECONDITION_REQUIREDPAYLOAD_TOO_LARGEUNSUPPORTED_MEDIA_TYPEUNPROCESSABLE_ENTITYLOCKEDTOO_MANY_REQUESTSBAD_GATEWAYSERVICE_UNAVAILABLEGATEWAY_TIMEOUTNOT_IMPLEMENTEDINTERNAL_SERVER_ERRORREQUEST_INVALIDAUTHENTICATIONPERMISSIONENDPOINT_NOT_FOUNDENDPOINT_STATE_CONFLICTENDPOINT_UNAVAILABLERATE_LIMITPROVIDER_BAD_RESPONSEPROVIDER_UNAVAILABLEPROVIDER_TIMEOUT
- pluginRouteId
- family
Response headers
- ETag
string Opaque strong entity tag of the returned resource version. Send it back in `If-Match` on the next mutation of the same resource.
Errors
400 BAD_REQUESTBad request - invalid request payload
Check the request fields and any validation details, then correct the payload.
401 UNAUTHORIZEDUnauthorized - invalid or missing authentication token
Obtain a valid access token, then retry.
403 FORBIDDENForbidden - insufficient permissions
Check the linked account and its permissions for the device or resource.
404 NOT_FOUNDNamed group does not exist
Verify the target identifier and that its endpoint or plugin route still exists.
409 IDEMPOTENCY_KEY_IN_FLIGHTThe same idempotency key is in flight
Check the device’s current mode or state. Retry only after the conflict is resolved.
412 PRECONDITION_FAILEDThe group version does not match If-Match
Inspect the returned code and family and follow the error handling guide.
422 IDEMPOTENCY_KEY_REUSEDThe same idempotency key was used with another payload
Correct the rejected value using the constraints in the error details or request schema.
428 PRECONDITION_REQUIREDIf-Match is required for replacement
Inspect the returned code and family and follow the error handling guide.
500 INTERNALInternal server error
Retry with backoff only when the operation is safe to repeat. Include the error code when reporting persistent failures.
/endpoint-groups-manageEvaluates at most 20 group operations with shared starting etags. Contradictory batch intent returns 400 before provider dispatch; operation order does not make incompatible edits valid. BEST_EFFORT is the default for create, delete, add, remove, move and rename. Merge and both enablement operations accept only PORTOS_ONLY. Declared providers are called before one transaction reconciles replies and saves permitted customer intent with final group etags. Item outcomes use HTTP 200 and requestId correlation. PARTIALLY_SUCCEEDED is saved with local fallback; FAILED can retain received provider truth and attempted dispatch outcomes while rejecting customer intent. Idempotency-Key is required unless validateOnly is true, and terminal responses after provider attempts replay for 24 hours without resending messages.
Required scope
group:manageHeader parameters
- Idempotency-Key
string Required when this request changes state; omitting it returns 400 IDEMPOTENCY_KEY_REQUIRED. The operation documents its read-only modes, which neither require nor consume a key. Committed responses replay for 24 hours for the same principal, operation, key and payload. Reusing a key with a different payload returns 422; an in-flight request returns 409. The key must contain between 1 and 255 characters when provided for a mutation.
minLength: 1
maxLength: 255
Request body
Fields
Returns
200
Batch evaluated. COMMITTED and PARTIALLY_SUCCEEDED save customer changes; FAILED rejects customer intent but retains valid provider truth and the failed receipt after provider attempts. Inspect operation status and providerDispatches, including on HTTP 200.
Fields
- status
stringRequired COMMITTED means all customer operations applied. PARTIALLY_SUCCEEDED means they applied with a reported provider fallback. FAILED means customer intent did not commit; operation-specific contracts state whether already received provider observations are retained.
Allowed values
COMMITTEDFAILEDPARTIALLY_SUCCEEDED
- results
array<EndpointGroupsManageResult>Required One operation outcome correlated by requestId. Applied results use final committed group etags; MOVE_MEMBER returns source and target. NOT_APPLIED reports attempted provider dispatches from a failed customer batch without group, source or target etags. Dispatch errors remain attached to their entries. Operations that reached no provider are omitted from failed batch results.
- requestId
stringRequired Client-chosen identifier for one operation in a batch request. It must be unique within the request and is echoed in the matching result or error so items are correlated by ID, never by position.
minLength: 1
maxLength: 64
- operation
stringRequired Discriminator of an endpoint group management operation.
Allowed values
CREATE_GROUPDELETE_GROUPSET_NAMEADD_MEMBERSREMOVE_MEMBERSMERGE_INTOSET_ENABLEMENTMOVE_MEMBERSET_GROUP_ROUTE_ENABLEMENT
- group
EndpointGroupEtagReference A group addressed together with the etag the client last read, validated inside the management transaction.
- target
EndpointGroupEtagReference A group addressed together with the etag the client last read, validated inside the management transaction.
- status
stringRequired APPLIED commits without a failed-dispatch fallback; PARTIALLY_APPLIED commits with one. NOT_APPLIED reports provider attempts from a failed customer batch and carries no group etag.
Allowed values
APPLIEDPARTIALLY_APPLIEDNOT_APPLIED
- providerDispatches
array<EndpointGroupProviderDispatch>Required This operation's provider messages; an empty array is explicit.
One provider message for this operation. SUCCEEDED requires a valid read-back reply establishing the requested condition. Provider identities are present only with the same native-route or account read visibility required by the public query projection. An authorized write can still return a redacted dispatch outcome; its namespace, name, status, reason and error code remain. Errors for hidden metadata use a generic message and omit details.
- authLinkId
string The provider account authorization link ID; omitted without metadata read visibility, empty for a readable account without a link.
- groupRouteId
string The provider-native group route ID within this plugin and account, omitted without native-route read visibility.
- status
stringRequired A planned, verified, failed or undeclared provider dispatch; a timeout is FAILED.
Allowed values
PLANNEDSUCCEEDEDFAILEDNOT_SUPPORTED
- reason
string Why no provider dispatch was sent. NOT_DECLARED means the provider does not declare the message. OUTSIDE_PRINCIPAL means native mutations are limited to accounts owned by the original caller; sharing a group or endpoint does not grant native account-management authority. Local intent can still apply without dispatching to the foreign account.
Allowed values
NOT_DECLAREDOUTSIDE_PRINCIPAL
- error
Error The one Port OS error shape, returned by every REST error response and every MCP tool error. `code` names the specific failure and `family` its broad class; both are closed enums, so clients branch on them and show `message`, which says what failed and what to do next.
- authLinkId
- requestId
- errors
array<BatchItemError>Required Error for one operation of an atomic batch, correlated by the operation's `requestId`. `status` is the HTTP status the operation would have returned on its own.
- requestId
stringRequired Client-chosen identifier for one operation in a batch request. It must be unique within the request and is echoed in the matching result or error so items are correlated by ID, never by position.
minLength: 1
maxLength: 64
- code
stringRequired The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.
Allowed values
BAD_REQUESTUNAUTHORIZEDFORBIDDENINSUFFICIENT_SCOPENOT_FOUNDCONFLICTUNPROCESSABLE_ENTITYUNSUPPORTED_OPERATIONTOO_MANY_REQUESTSSERVICE_UNAVAILABLENOT_IMPLEMENTEDINTERNALCHECKSUM_MISMATCHFILE_TOO_LARGESTORAGE_UNAVAILABLEINSUFFICIENT_PERMISSIONSINVALID_FILE_TYPEQUOTA_EXCEEDEDCONCURRENT_MODIFICATIONENDPOINT_UNREACHABLEBRIDGE_UNREACHABLECLOUD_CONTROL_DISABLEDENDPOINT_BUSYENDPOINT_LOW_POWERAUTHORIZATION_CREDENTIAL_INVALIDAUTHORIZATION_CREDENTIAL_EXPIREDINVALID_DIRECTIVEINVALID_VALUEVALUE_OUT_OF_RANGENOT_SUPPORTED_IN_CURRENT_MODERATE_LIMIT_EXCEEDEDPROVIDER_SERVICE_UNAVAILABLEPROVIDER_TIMEOUTPROVIDER_INTERNAL_ERRORINVALID_PROVIDER_RESPONSEOUTCOME_UNKNOWNPRECONDITION_FAILEDAUTH_LINK_NOT_READYAUTH_LINK_NOT_DISCONNECTABLEPRECONDITION_REQUIREDIDEMPOTENCY_KEY_REQUIREDIDEMPOTENCY_KEY_REUSEDIDEMPOTENCY_KEY_IN_FLIGHTIDEMPOTENCY_KEY_INVALIDGROUP_MERGEDMULTI_ROOM_UNSUPPORTEDMAP_NOT_ACTIVETARGET_UNSUPPORTEDTARGET_AMBIGUOUSTARGET_GROUP_NOT_FOUNDTARGET_GROUP_DISABLEDDUPLICATE_TARGET_GROUPMESSAGE_UNSUPPORTEDMESSAGE_AMBIGUOUSENDPOINT_DISABLEDENDPOINT_ROUTE_CHANGEDENDPOINT_HAS_DEPENDENCIESENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVEENDPOINT_COMMITTED_CLEANUP_PENDINGDEEP_QUERY_FAILEDPROVIDER_NO_STATEEVENT_MANAGEMENT_DISABLEDSUBSCRIPTION_IDENTITY_IMMUTABLEUNSUPPORTED_MEDIA_TYPEEVENT_PAYLOAD_TOO_LARGEREQUEST_BODY_TOO_LARGEEVENT_IDENTITY_CONFLICTEVENT_INGRESS_QUOTA_EXCEEDEDEVENT_RECEIPT_EXPIREDEVENT_STORAGE_UNAVAILABLEEVENT_DEAD_LETTER_NOT_FOUNDEVENT_REDRIVE_CONFLICTEVENT_REDRIVE_EXPIREDRECEIPT_CONTEXT_EXPIREDEVENT_MAINTENANCE_INCOMPLETEUNKNOWN_INTERFACEINVALID_CONFIGURATIONINVALID_PLUGIN_MANIFESTINVALID_ATTRIBUTEINVALID_PROVIDER_MESSAGEUNDECLARED_CAPABILITYPLUGIN_ROUTE_ID_CONFLICTUNRESOLVED_REFERENCEINVALID_RELATIONSHIPRELATIONSHIP_CYCLEMULTIPLE_PARENTSFLOW_VALIDATION_FAILEDPROVIDER_SYNC_UNSUPPORTED
- family
stringRequired The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.
Allowed values
NOT_FOUNDBAD_REQUESTUNAUTHORIZEDFORBIDDENCONFLICTGONEPRECONDITION_FAILEDPRECONDITION_REQUIREDPAYLOAD_TOO_LARGEUNSUPPORTED_MEDIA_TYPEUNPROCESSABLE_ENTITYLOCKEDTOO_MANY_REQUESTSBAD_GATEWAYSERVICE_UNAVAILABLEGATEWAY_TIMEOUTNOT_IMPLEMENTEDINTERNAL_SERVER_ERRORREQUEST_INVALIDAUTHENTICATIONPERMISSIONENDPOINT_NOT_FOUNDENDPOINT_STATE_CONFLICTENDPOINT_UNAVAILABLERATE_LIMITPROVIDER_BAD_RESPONSEPROVIDER_UNAVAILABLEPROVIDER_TIMEOUT
- errors
array<SynchronizationItemError> Typed validation failures inside this operation when one report contains several rejected routes, interfaces or relationships.
One rejected discovery item of a `SynchronizationRequest`, keyed by the plugin-owned identity of the rejected item: `pluginRouteId` for a route or group route, or `relationshipExternalId` for a relationship. Exactly one of the two is set. It shares the `code`, `family`, `status` and `message` fields of `BatchItemError`; discovery items are keyed by plugin-owned identity because they carry no `requestId`. A request with any rejected item is rejected as a whole and lists every rejected item.
- pluginRouteId
string Plugin-owned identifier of the rejected route or group route. Set unless the item is a relationship.
- relationshipExternalId
string Plugin-owned `externalId` of the rejected relationship. Set only for relationship items.
- interface
string Canonical capability interface name the failure applies to, when the failure is interface-specific.
- version
string Declared capability interface version the failure applies to, when the failure is interface-specific.
- code
stringRequired The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.
Allowed values
BAD_REQUESTUNAUTHORIZEDFORBIDDENINSUFFICIENT_SCOPENOT_FOUNDCONFLICTUNPROCESSABLE_ENTITYUNSUPPORTED_OPERATIONTOO_MANY_REQUESTSSERVICE_UNAVAILABLENOT_IMPLEMENTEDINTERNALCHECKSUM_MISMATCHFILE_TOO_LARGESTORAGE_UNAVAILABLEINSUFFICIENT_PERMISSIONSINVALID_FILE_TYPEQUOTA_EXCEEDEDCONCURRENT_MODIFICATIONENDPOINT_UNREACHABLEBRIDGE_UNREACHABLECLOUD_CONTROL_DISABLEDENDPOINT_BUSYENDPOINT_LOW_POWERAUTHORIZATION_CREDENTIAL_INVALIDAUTHORIZATION_CREDENTIAL_EXPIREDINVALID_DIRECTIVEINVALID_VALUEVALUE_OUT_OF_RANGENOT_SUPPORTED_IN_CURRENT_MODERATE_LIMIT_EXCEEDEDPROVIDER_SERVICE_UNAVAILABLEPROVIDER_TIMEOUTPROVIDER_INTERNAL_ERRORINVALID_PROVIDER_RESPONSEOUTCOME_UNKNOWNPRECONDITION_FAILEDAUTH_LINK_NOT_READYAUTH_LINK_NOT_DISCONNECTABLEPRECONDITION_REQUIREDIDEMPOTENCY_KEY_REQUIREDIDEMPOTENCY_KEY_REUSEDIDEMPOTENCY_KEY_IN_FLIGHTIDEMPOTENCY_KEY_INVALIDGROUP_MERGEDMULTI_ROOM_UNSUPPORTEDMAP_NOT_ACTIVETARGET_UNSUPPORTEDTARGET_AMBIGUOUSTARGET_GROUP_NOT_FOUNDTARGET_GROUP_DISABLEDDUPLICATE_TARGET_GROUPMESSAGE_UNSUPPORTEDMESSAGE_AMBIGUOUSENDPOINT_DISABLEDENDPOINT_ROUTE_CHANGEDENDPOINT_HAS_DEPENDENCIESENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVEENDPOINT_COMMITTED_CLEANUP_PENDINGDEEP_QUERY_FAILEDPROVIDER_NO_STATEEVENT_MANAGEMENT_DISABLEDSUBSCRIPTION_IDENTITY_IMMUTABLEUNSUPPORTED_MEDIA_TYPEEVENT_PAYLOAD_TOO_LARGEREQUEST_BODY_TOO_LARGEEVENT_IDENTITY_CONFLICTEVENT_INGRESS_QUOTA_EXCEEDEDEVENT_RECEIPT_EXPIREDEVENT_STORAGE_UNAVAILABLEEVENT_DEAD_LETTER_NOT_FOUNDEVENT_REDRIVE_CONFLICTEVENT_REDRIVE_EXPIREDRECEIPT_CONTEXT_EXPIREDEVENT_MAINTENANCE_INCOMPLETEUNKNOWN_INTERFACEINVALID_CONFIGURATIONINVALID_PLUGIN_MANIFESTINVALID_ATTRIBUTEINVALID_PROVIDER_MESSAGEUNDECLARED_CAPABILITYPLUGIN_ROUTE_ID_CONFLICTUNRESOLVED_REFERENCEINVALID_RELATIONSHIPRELATIONSHIP_CYCLEMULTIPLE_PARENTSFLOW_VALIDATION_FAILEDPROVIDER_SYNC_UNSUPPORTED
- family
stringRequired The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.
Allowed values
NOT_FOUNDBAD_REQUESTUNAUTHORIZEDFORBIDDENCONFLICTGONEPRECONDITION_FAILEDPRECONDITION_REQUIREDPAYLOAD_TOO_LARGEUNSUPPORTED_MEDIA_TYPEUNPROCESSABLE_ENTITYLOCKEDTOO_MANY_REQUESTSBAD_GATEWAYSERVICE_UNAVAILABLEGATEWAY_TIMEOUTNOT_IMPLEMENTEDINTERNAL_SERVER_ERRORREQUEST_INVALIDAUTHENTICATIONPERMISSIONENDPOINT_NOT_FOUNDENDPOINT_STATE_CONFLICTENDPOINT_UNAVAILABLERATE_LIMITPROVIDER_BAD_RESPONSEPROVIDER_UNAVAILABLEPROVIDER_TIMEOUT
- pluginRouteId
- requestId
Errors
400 IDEMPOTENCY_KEY_REQUIREDMalformed request, unknown operation, duplicate `requestId`, or missing (`IDEMPOTENCY_KEY_REQUIRED`) or over-long (`IDEMPOTENCY_KEY_INVALID`) `Idempotency-Key` for a mutation. validateOnly requests neither require nor consume a key.
Check the request fields and any validation details, then correct the payload.
401 UNAUTHORIZEDUnauthorized - invalid or missing authentication token
Obtain a valid access token, then retry.
403 FORBIDDENForbidden - token lacks the group:manage scope
Check the linked account and its permissions for the device or resource.
409 IDEMPOTENCY_KEY_IN_FLIGHTA request with the same `Idempotency-Key` is still in flight
Check the device’s current mode or state. Retry only after the conflict is resolved.
422 IDEMPOTENCY_KEY_REUSEDThe `Idempotency-Key` was already used with a different payload
Correct the rejected value using the constraints in the error details or request schema.
500 INTERNALInternal server error
Retry with backoff only when the operation is safe to repeat. Include the error code when reporting persistent failures.
/{namespace}/{principalType}/{principalId}/endpoint-groups/{groupId}Get an endpoint group by ID.
Required scope
group:readQuery parameters
- expand
array<string> Expansion tokens that request related or computed fields for the returned resource. Use `interfaces.attributes` to populate the group's `attributes` array with the stored values of its group routes.
- forceDeviceAttributeQuery
boolean Asks each provider for fresh values of the group routes before the response is returned. Only applied when `expand` includes `interfaces.attributes`. Absent, invalid or `false` values return the stored values. A forced read includes only attributes refreshed by that request. If a provider cannot be reached or rejects the request, the request returns `500 DEEP_QUERY_FAILED` instead of presenting stored values as fresh. If a provider answers but gives no value for a declared attribute, that attribute is returned without a `value` and with an `error` whose code is `PROVIDER_NO_STATE`; the request still succeeds.
Returns
200
Endpoint group retrieved successfully
Fields
- id
stringRequired The unique identifier for the endpoint group
pattern: "^port1/[^/]+/[^/]+/endpoint-groups/[^/]+$"
- enablement
stringRequired Whether Port OS uses an endpoint or group. A disabled one is hidden from collections by default and cannot be sent device messages or targeted by them; exact authorized reads still return it. Rediscovery never changes it, so disabling is how a user hides a discovered device or room for good.
Default:
ENABLEDAllowed values
ENABLEDDISABLED
- etag
stringRequired Opaque strong entity tag of this group version, for example `"12"`. It changes once per transaction when meaningful customer intent, provider contributions, membership, interfaces, names, association or enablement changes. Identical rediscovery leaves it unchanged. Send it as `If-Match` (or as the operation `etag` in `/endpoint-groups-manage`) when mutating the group.
- redirectedFrom
string Set when the group was read through a merged-away ID: the ID that was requested, which now redirects to this group. Mutations must use this group's `id`.
- parentGroupId
string The canonical parent group derived from `IS_PART_OF` relationships, when the group has one.
- controllers
array<EndpointGroupController> Endpoints that declare `CAN_CONTROL` on one of this group's group routes, with the messages they support on it.
An endpoint able to act on a group through a `CAN_CONTROL` relationship, with the interface messages it supports there. Being a controller does not grant authorization.
- attributes
array<GroupRouteAttributeState> The group's state: every attribute value stored for its group routes, one entry per group route and attribute, tagged with the group route and provider. Populated only when the read is called with `expand=interfaces.attributes`.
One attribute value reported for one group route of an endpoint group. A group's state is the set of its group routes' values; values from different providers are never aggregated, so each entry names the group route and the provider that reported it. When a forced read reaches the provider and the provider answers without a value for a declared attribute, the entry carries no `value` and an `error` with code `PROVIDER_NO_STATE` instead of being omitted.
- groupRoutes
array<EndpointGroupRoute> Native provider contributions, populated only under expand=groupRoutes.
A route within an endpoint group linking a plugin route to a group with interface metadata.
- associatedGroupId
string The associated endpoint group ID; omitted for an orphaned route.
pattern: "^port1/[^/]+/[^/]+/endpoint-groups/[^/]+$"
- associatedPluginRouteId
stringRequired Stable plugin-owned route ID. Match synchronized plugin or fixture membership with this value, not the Port OS group route `id`.
- interfaces
array<RouteInterface>Required Supported interfaces.
- enablement
stringRequired Whether Port OS uses an endpoint or group. A disabled one is hidden from collections by default and cannot be sent device messages or targeted by them; exact authorized reads still return it. Rediscovery never changes it, so disabling is how a user hides a discovered device or room for good.
Default:
ENABLEDAllowed values
ENABLEDDISABLED
- associatedGroupId
Response headers
- ETag
string Opaque strong entity tag of the returned resource version. Send it back in `If-Match` on the next mutation of the same resource.
Errors
400 BAD_REQUESTInvalid request payload
Check the request fields and any validation details, then correct the payload.
401 UNAUTHORIZEDUnauthorized - invalid or missing authentication token
Obtain a valid access token, then retry.
403 FORBIDDENForbidden - insufficient permissions
Check the linked account and its permissions for the device or resource.
404 NOT_FOUNDEndpoint group not found
Verify the target identifier and that its endpoint or plugin route still exists.
500 INTERNALInternal server error
Retry with backoff only when the operation is safe to repeat. Include the error code when reporting persistent failures.
/{namespace}/{principalType}/{principalId}/endpoint-groups/{groupId}Delete a group with BEST_EFFORT provider synchronization by default. HTTP 200 is an evaluated outcome; inspect status and errors. Failed provider attempts can return NOT_APPLIED while retaining received provider truth. DELETE accepts no request body. A first delete of an unknown id returns 404; retries of an accepted delete replay the saved response for 24 hours.
Required scope
group:manageHeader parameters
- If-Match
stringRequired The quoted strong entity tag of the resource the client last read (its `etag` field or `ETag` response header). The mutation is applied only when it still matches: a stale value returns 412 PRECONDITION_FAILED and a missing header returns 428 PRECONDITION_REQUIRED. Wildcards are accepted only where the operation explicitly permits them.
minLength: 1
- Idempotency-Key
stringRequired Client-chosen key that makes a non-idempotent request retry-safe, following draft-ietf-httpapi-idempotency-key-header. A committed response is stored for 24 hours and replayed for the same principal, operation, key and payload. Missing key returns 400 IDEMPOTENCY_KEY_REQUIRED, a key longer than 255 characters returns 400 IDEMPOTENCY_KEY_INVALID, the same key with a different payload returns 422, and the same key while the first request is still in flight returns 409. Requests rolled back before external provider attempts do not consume the key. Group mutations retain terminal failed responses after provider attempts together with received provider truth; their operation contract defines these replayable outcomes.
minLength: 1
maxLength: 255
Returns
200
Evaluated delete outcome; inspect status and errors even on HTTP 200.
Fields
- status
stringRequired APPLIED commits without a failed-dispatch fallback; PARTIALLY_APPLIED commits with one. NOT_APPLIED reports provider attempts from a failed customer batch and carries no group etag.
Allowed values
APPLIEDPARTIALLY_APPLIEDNOT_APPLIED
- providerDispatches
array<EndpointGroupProviderDispatch>Required One provider message for this operation. SUCCEEDED requires a valid read-back reply establishing the requested condition. Provider identities are present only with the same native-route or account read visibility required by the public query projection. An authorized write can still return a redacted dispatch outcome; its namespace, name, status, reason and error code remain. Errors for hidden metadata use a generic message and omit details.
- authLinkId
string The provider account authorization link ID; omitted without metadata read visibility, empty for a readable account without a link.
- groupRouteId
string The provider-native group route ID within this plugin and account, omitted without native-route read visibility.
- status
stringRequired A planned, verified, failed or undeclared provider dispatch; a timeout is FAILED.
Allowed values
PLANNEDSUCCEEDEDFAILEDNOT_SUPPORTED
- reason
string Why no provider dispatch was sent. NOT_DECLARED means the provider does not declare the message. OUTSIDE_PRINCIPAL means native mutations are limited to accounts owned by the original caller; sharing a group or endpoint does not grant native account-management authority. Local intent can still apply without dispatching to the foreign account.
Allowed values
NOT_DECLAREDOUTSIDE_PRINCIPAL
- error
Error The one Port OS error shape, returned by every REST error response and every MCP tool error. `code` names the specific failure and `family` its broad class; both are closed enums, so clients branch on them and show `message`, which says what failed and what to do next.
- authLinkId
- group
EndpointGroupEtagReference A group addressed together with the etag the client last read, validated inside the management transaction.
- errors
array<Error>Required The one Port OS error shape, returned by every REST error response and every MCP tool error. `code` names the specific failure and `family` its broad class; both are closed enums, so clients branch on them and show `message`, which says what failed and what to do next.
- family
stringRequired The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.
Allowed values
NOT_FOUNDBAD_REQUESTUNAUTHORIZEDFORBIDDENCONFLICTGONEPRECONDITION_FAILEDPRECONDITION_REQUIREDPAYLOAD_TOO_LARGEUNSUPPORTED_MEDIA_TYPEUNPROCESSABLE_ENTITYLOCKEDTOO_MANY_REQUESTSBAD_GATEWAYSERVICE_UNAVAILABLEGATEWAY_TIMEOUTNOT_IMPLEMENTEDINTERNAL_SERVER_ERRORREQUEST_INVALIDAUTHENTICATIONPERMISSIONENDPOINT_NOT_FOUNDENDPOINT_STATE_CONFLICTENDPOINT_UNAVAILABLERATE_LIMITPROVIDER_BAD_RESPONSEPROVIDER_UNAVAILABLEPROVIDER_TIMEOUT
- code
stringRequired The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.
Allowed values
BAD_REQUESTUNAUTHORIZEDFORBIDDENINSUFFICIENT_SCOPENOT_FOUNDCONFLICTUNPROCESSABLE_ENTITYUNSUPPORTED_OPERATIONTOO_MANY_REQUESTSSERVICE_UNAVAILABLENOT_IMPLEMENTEDINTERNALCHECKSUM_MISMATCHFILE_TOO_LARGESTORAGE_UNAVAILABLEINSUFFICIENT_PERMISSIONSINVALID_FILE_TYPEQUOTA_EXCEEDEDCONCURRENT_MODIFICATIONENDPOINT_UNREACHABLEBRIDGE_UNREACHABLECLOUD_CONTROL_DISABLEDENDPOINT_BUSYENDPOINT_LOW_POWERAUTHORIZATION_CREDENTIAL_INVALIDAUTHORIZATION_CREDENTIAL_EXPIREDINVALID_DIRECTIVEINVALID_VALUEVALUE_OUT_OF_RANGENOT_SUPPORTED_IN_CURRENT_MODERATE_LIMIT_EXCEEDEDPROVIDER_SERVICE_UNAVAILABLEPROVIDER_TIMEOUTPROVIDER_INTERNAL_ERRORINVALID_PROVIDER_RESPONSEOUTCOME_UNKNOWNPRECONDITION_FAILEDAUTH_LINK_NOT_READYAUTH_LINK_NOT_DISCONNECTABLEPRECONDITION_REQUIREDIDEMPOTENCY_KEY_REQUIREDIDEMPOTENCY_KEY_REUSEDIDEMPOTENCY_KEY_IN_FLIGHTIDEMPOTENCY_KEY_INVALIDGROUP_MERGEDMULTI_ROOM_UNSUPPORTEDMAP_NOT_ACTIVETARGET_UNSUPPORTEDTARGET_AMBIGUOUSTARGET_GROUP_NOT_FOUNDTARGET_GROUP_DISABLEDDUPLICATE_TARGET_GROUPMESSAGE_UNSUPPORTEDMESSAGE_AMBIGUOUSENDPOINT_DISABLEDENDPOINT_ROUTE_CHANGEDENDPOINT_HAS_DEPENDENCIESENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVEENDPOINT_COMMITTED_CLEANUP_PENDINGDEEP_QUERY_FAILEDPROVIDER_NO_STATEEVENT_MANAGEMENT_DISABLEDSUBSCRIPTION_IDENTITY_IMMUTABLEUNSUPPORTED_MEDIA_TYPEEVENT_PAYLOAD_TOO_LARGEREQUEST_BODY_TOO_LARGEEVENT_IDENTITY_CONFLICTEVENT_INGRESS_QUOTA_EXCEEDEDEVENT_RECEIPT_EXPIREDEVENT_STORAGE_UNAVAILABLEEVENT_DEAD_LETTER_NOT_FOUNDEVENT_REDRIVE_CONFLICTEVENT_REDRIVE_EXPIREDRECEIPT_CONTEXT_EXPIREDEVENT_MAINTENANCE_INCOMPLETEUNKNOWN_INTERFACEINVALID_CONFIGURATIONINVALID_PLUGIN_MANIFESTINVALID_ATTRIBUTEINVALID_PROVIDER_MESSAGEUNDECLARED_CAPABILITYPLUGIN_ROUTE_ID_CONFLICTUNRESOLVED_REFERENCEINVALID_RELATIONSHIPRELATIONSHIP_CYCLEMULTIPLE_PARENTSFLOW_VALIDATION_FAILEDPROVIDER_SYNC_UNSUPPORTED
- details
ErrorDetails Optional typed context for an error. Fields are additive and only populated when the error can safely expose that context to API clients.
- errors
array<SynchronizationItemError> Every rejected item when a request that is validated item by item and applied atomically fails, such as a discovery `SynchronizationRequest` whose routes, group routes or relationships are rejected. Omitted for single-item failures.
One rejected discovery item of a `SynchronizationRequest`, keyed by the plugin-owned identity of the rejected item: `pluginRouteId` for a route or group route, or `relationshipExternalId` for a relationship. Exactly one of the two is set. It shares the `code`, `family`, `status` and `message` fields of `BatchItemError`; discovery items are keyed by plugin-owned identity because they carry no `requestId`. A request with any rejected item is rejected as a whole and lists every rejected item.
- pluginRouteId
string Plugin-owned identifier of the rejected route or group route. Set unless the item is a relationship.
- relationshipExternalId
string Plugin-owned `externalId` of the rejected relationship. Set only for relationship items.
- interface
string Canonical capability interface name the failure applies to, when the failure is interface-specific.
- version
string Declared capability interface version the failure applies to, when the failure is interface-specific.
- code
stringRequired The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.
Allowed values
BAD_REQUESTUNAUTHORIZEDFORBIDDENINSUFFICIENT_SCOPENOT_FOUNDCONFLICTUNPROCESSABLE_ENTITYUNSUPPORTED_OPERATIONTOO_MANY_REQUESTSSERVICE_UNAVAILABLENOT_IMPLEMENTEDINTERNALCHECKSUM_MISMATCHFILE_TOO_LARGESTORAGE_UNAVAILABLEINSUFFICIENT_PERMISSIONSINVALID_FILE_TYPEQUOTA_EXCEEDEDCONCURRENT_MODIFICATIONENDPOINT_UNREACHABLEBRIDGE_UNREACHABLECLOUD_CONTROL_DISABLEDENDPOINT_BUSYENDPOINT_LOW_POWERAUTHORIZATION_CREDENTIAL_INVALIDAUTHORIZATION_CREDENTIAL_EXPIREDINVALID_DIRECTIVEINVALID_VALUEVALUE_OUT_OF_RANGENOT_SUPPORTED_IN_CURRENT_MODERATE_LIMIT_EXCEEDEDPROVIDER_SERVICE_UNAVAILABLEPROVIDER_TIMEOUTPROVIDER_INTERNAL_ERRORINVALID_PROVIDER_RESPONSEOUTCOME_UNKNOWNPRECONDITION_FAILEDAUTH_LINK_NOT_READYAUTH_LINK_NOT_DISCONNECTABLEPRECONDITION_REQUIREDIDEMPOTENCY_KEY_REQUIREDIDEMPOTENCY_KEY_REUSEDIDEMPOTENCY_KEY_IN_FLIGHTIDEMPOTENCY_KEY_INVALIDGROUP_MERGEDMULTI_ROOM_UNSUPPORTEDMAP_NOT_ACTIVETARGET_UNSUPPORTEDTARGET_AMBIGUOUSTARGET_GROUP_NOT_FOUNDTARGET_GROUP_DISABLEDDUPLICATE_TARGET_GROUPMESSAGE_UNSUPPORTEDMESSAGE_AMBIGUOUSENDPOINT_DISABLEDENDPOINT_ROUTE_CHANGEDENDPOINT_HAS_DEPENDENCIESENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVEENDPOINT_COMMITTED_CLEANUP_PENDINGDEEP_QUERY_FAILEDPROVIDER_NO_STATEEVENT_MANAGEMENT_DISABLEDSUBSCRIPTION_IDENTITY_IMMUTABLEUNSUPPORTED_MEDIA_TYPEEVENT_PAYLOAD_TOO_LARGEREQUEST_BODY_TOO_LARGEEVENT_IDENTITY_CONFLICTEVENT_INGRESS_QUOTA_EXCEEDEDEVENT_RECEIPT_EXPIREDEVENT_STORAGE_UNAVAILABLEEVENT_DEAD_LETTER_NOT_FOUNDEVENT_REDRIVE_CONFLICTEVENT_REDRIVE_EXPIREDRECEIPT_CONTEXT_EXPIREDEVENT_MAINTENANCE_INCOMPLETEUNKNOWN_INTERFACEINVALID_CONFIGURATIONINVALID_PLUGIN_MANIFESTINVALID_ATTRIBUTEINVALID_PROVIDER_MESSAGEUNDECLARED_CAPABILITYPLUGIN_ROUTE_ID_CONFLICTUNRESOLVED_REFERENCEINVALID_RELATIONSHIPRELATIONSHIP_CYCLEMULTIPLE_PARENTSFLOW_VALIDATION_FAILEDPROVIDER_SYNC_UNSUPPORTED
- family
stringRequired The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.
Allowed values
NOT_FOUNDBAD_REQUESTUNAUTHORIZEDFORBIDDENCONFLICTGONEPRECONDITION_FAILEDPRECONDITION_REQUIREDPAYLOAD_TOO_LARGEUNSUPPORTED_MEDIA_TYPEUNPROCESSABLE_ENTITYLOCKEDTOO_MANY_REQUESTSBAD_GATEWAYSERVICE_UNAVAILABLEGATEWAY_TIMEOUTNOT_IMPLEMENTEDINTERNAL_SERVER_ERRORREQUEST_INVALIDAUTHENTICATIONPERMISSIONENDPOINT_NOT_FOUNDENDPOINT_STATE_CONFLICTENDPOINT_UNAVAILABLERATE_LIMITPROVIDER_BAD_RESPONSEPROVIDER_UNAVAILABLEPROVIDER_TIMEOUT
- pluginRouteId
- family
Errors
400 BAD_REQUESTInvalid request payload
Check the request fields and any validation details, then correct the payload.
401 UNAUTHORIZEDUnauthorized - invalid or missing authentication token
Obtain a valid access token, then retry.
403 FORBIDDENForbidden - insufficient permissions
Check the linked account and its permissions for the device or resource.
404 NOT_FOUNDEndpoint group not found
Verify the target identifier and that its endpoint or plugin route still exists.
409 IDEMPOTENCY_KEY_IN_FLIGHTA request with the same Idempotency-Key is in flight
Check the device’s current mode or state. Retry only after the conflict is resolved.
412 PRECONDITION_FAILEDThe If-Match etag does not match the current group version; re-read the group and retry
Inspect the returned code and family and follow the error handling guide.
422 IDEMPOTENCY_KEY_REUSEDThe same Idempotency-Key was used with another payload
Correct the rejected value using the constraints in the error details or request schema.
428 PRECONDITION_REQUIREDThe If-Match header is missing
Inspect the returned code and family and follow the error handling guide.
500 INTERNALInternal server error
Retry with backoff only when the operation is safe to repeat. Include the error code when reporting persistent failures.