Skip to content

Endpoint Groups

List endpoint groups

View source specification ↗
GET /endpoint-groups

Lists 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:read

Query parameters

enablementstring

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: ENABLED

Allowed values

  • ENABLED
  • DISABLED
  • *
ownerstring

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.

idstring

Exact group ID; overrides `owner` and `enablement`.

nextTokenstring

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.

maxResultsinteger

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

expandarray<string>

Expansion tokens that request related or computed fields for each result. Use `interfaces.attributes` to populate each group's `attributes` array with the stored values of its group routes. Use `groupRoutes` to include native routes and stored Port OS membership intent.

forceDeviceAttributeQueryboolean

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.

Returns

200

Endpoint groups retrieved successfully

Fields
resultsarray<EndpointGroup>Required

A logical grouping of endpoints that share common interfaces and ownership.

idstringRequired

The unique identifier for the endpoint group

pattern: "^port1/[^/]+/[^/]+/endpoint-groups/[^/]+$"

nameTypeValueRequired

The name of the endpoint group

ownerIdstringRequired

The ID of the owner of the endpoint group

enablementstringRequired

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: ENABLED

Allowed values

  • ENABLED
  • DISABLED
memberEndpointIdsarray<string>

List of member endpoint IDs of the endpoint group

interfacesarray<ApplicationInterface>Required

List of interfaces supported by the endpoint group

namestringRequired

The name of the interface

versionstring

The version of the interface

messagesarray<ApplicationInterfaceMessage>

Supported message subset. An omitted or empty list declares no supported messages.

namestringRequired

The name of the command

attributesarray<ApplicationInterfaceAttribute>

Supported attribute subset. An omitted or empty list declares no supported attributes.

namestringRequired

The name of the attribute

valueobject

the value of the attribute, this is an opaque resource object, so it can be any type of struct.

configurationobject

Interface-specific configuration published for discovery and enumeration.

etagstringRequired

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.

redirectedFromstring

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`.

parentGroupIdstring

The canonical parent group derived from `IS_PART_OF` relationships, when the group has one.

childGroupIdsarray<string>

Canonical child groups derived from `IS_PART_OF` relationships.

controllersarray<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.

endpointIdstringRequired

The controlling endpoint.

interfacesarray<RelationshipInterface>Required

Interfaces and messages the endpoint supports on the group.

Capability-interface applicability of a relationship, for example the robotic-vacuum-cleaner messages a `CAN_CONTROL` edge supports on a room.

namestringRequired

The capability interface namespace.

minLength: 1

versionstringRequired

The capability interface version.

minLength: 1

messagesarray<string>

Message names of the interface the relationship applies to. An explicit empty array applies to no messages. Omission retains every message supported by the source interface.

uniqueItems: true

Itemstring

minLength: 1

attributesarray<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.

groupRouteIdstringRequired

The typed ID of the group route the value was reported for.

pluginIdstringRequired

The plugin that owns the group route and reported the value.

providerstringRequired

The display name of that plugin.

namespacestringRequired

The capability interface namespace for this attribute

namestringRequired

The name of the attribute within the namespace

versionstringRequired

The capability interface version the value conforms to.

valueobject

The attribute value payload, structure depends on the attribute schema. Omitted when `error` is present.

errorError

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.

sampledAtstring

When the provider observed the value. Omitted when the provider did not say.

format: "date-time"

groupRoutesarray<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.

etagstringRequired

Opaque strong version of the stored native route. Send as If-Match when deleting.

pluginProfileIdstring

Stable profile ID from the registered plugin declaration.

minLength: 1

ontologicalTypesarray<string>

Actual native group route classifications.

idstringRequired

Unique group route ID.

pattern: "^port1/[^/]+/[^/]+/endpoint-group-routes/[^/]+$"

associatedGroupIdstring

The associated endpoint group ID; omitted for an orphaned route.

pattern: "^port1/[^/]+/[^/]+/endpoint-groups/[^/]+$"

associatedPluginIdstringRequired

Associated plugin ID.

associatedPluginRouteIdstringRequired

Stable plugin-owned route ID. Match synchronized plugin or fixture membership with this value, not the Port OS group route `id`.

associatedAuthLinkIdstringRequired

Associated auth link ID.

ownerIdstringRequired

Group route owner's ID.

memberPluginRouteIdsarray<string>

Member plugin route IDs.

interfacesarray<RouteInterface>Required

Supported interfaces.

namestringRequired

The name of the interface

versionstring

the version of the interface

messagesarray<ApplicationInterfaceMessage>

Supported inbound message subset for the declared interface version. An omitted or empty list declares no supported messages; null also declares none. A supplied array contains distinct canonical names for implemented messages.

nullable: true

namestringRequired

The name of the command

attributesarray<ApplicationInterfaceAttribute>

Supported attribute subset. An omitted or empty list declares no supported attributes.

namestringRequired

The name of the attribute

valueobject

the value of the attribute, this is an opaque resource object, so it can be any type of struct.

configurationobject

The configuration of the interface

pluginCustomMetadataobject

Provider-defined route metadata for plugin use.

namestring

The provider-native group name, which can differ from the customer aggregate name.

enablementstringRequired

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: ENABLED

Allowed values

  • ENABLED
  • DISABLED
memberEndpointIdsarray<string>

Resolved Port OS endpoint IDs in this native route.

uniqueItems: true

portosRouteEndpointGroupPortosRoute

Stored customer membership intent, populated only under expand=groupRoutes.

paginationContextPaginationContext
errorsarray<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.

familystringRequired

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.

codestringRequired

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.

messagestringRequired

Plain-language description of the failure and the suggested next action.

detailsErrorDetails

Optional typed context for an error. Fields are additive and only populated when the error can safely expose that context to API clients.

errorsarray<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.

pluginRouteIdstring

Plugin-owned identifier of the rejected route or group route. Set unless the item is a relationship.

relationshipExternalIdstring

Plugin-owned `externalId` of the rejected relationship. Set only for relationship items.

interfacestring

Canonical capability interface name the failure applies to, when the failure is interface-specific.

versionstring

Declared capability interface version the failure applies to, when the failure is interface-specific.

codestringRequired

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.

familystringRequired

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.

statusintegerRequired

HTTP-equivalent status code of the item failure.

minimum: 400

maximum: 599

messagestringRequired

Plain-language description of the failure and the suggested fix.

Errors

400 BAD_REQUEST

Bad request - missing required parameters

Check the request fields and any validation details, then correct the payload.

401 UNAUTHORIZED

Unauthorized - invalid or missing authentication token

Obtain a valid access token, then retry.

403 FORBIDDEN

Forbidden - insufficient permissions

Check the linked account and its permissions for the device or resource.

500 INTERNAL

Internal server error

Retry with backoff only when the operation is safe to repeat. Include the error code when reporting persistent failures.

Upsert Endpoint Group

View source specification ↗
POST /endpoint-groups

Updates or creates an endpoint group.

For example:

  1. Update the name of a group.
  2. Change the members of a group.
  3. 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:manage

Header parameters

Idempotency-KeystringRequired

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-Matchstring

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

Required

Fields

itemUpsertEndpointGroupItemRequired

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.

providerSyncstring

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_EFFORT

Allowed values

  • PORTOS_ONLY
  • BEST_EFFORT
  • FAIL_ON_PROVIDER_ERROR

Returns

200

Endpoint group created successfully

Fields
itemEndpointGroup

A logical grouping of endpoints that share common interfaces and ownership.

statusstringRequired

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

  • APPLIED
  • PARTIALLY_APPLIED
  • NOT_APPLIED
providerDispatchesarray<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.

pluginIdstring

The admitted provider plugin ID, omitted when provider metadata is not readable.

authLinkIdstring

The provider account authorization link ID; omitted without metadata read visibility, empty for a readable account without a link.

groupRouteIdstring

The provider-native group route ID within this plugin and account, omitted without native-route read visibility.

namespacestringRequired

The message capability namespace.

namestringRequired

The canonical message name.

statusstringRequired

A planned, verified, failed or undeclared provider dispatch; a timeout is FAILED.

Allowed values

  • PLANNED
  • SUCCEEDED
  • FAILED
  • NOT_SUPPORTED
reasonstring

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_DECLARED
  • OUTSIDE_PRINCIPAL
errorError

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.

impliedRemovalsarray<EndpointGroupImpliedRemoval>

Authorized native memberships displaced by an explicit move.

In-scope membership removals implied by an exclusive provider move.

groupRouteIdstringRequired

The Port OS group route affected by the removal.

minLength: 1

memberEndpointIdsarray<string>Required

Endpoint members removed from this route.

uniqueItems: true

Itemstring

minLength: 1

errorsarray<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.

familystringRequired

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.

codestringRequired

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.

messagestringRequired

Plain-language description of the failure and the suggested next action.

detailsErrorDetails

Optional typed context for an error. Fields are additive and only populated when the error can safely expose that context to API clients.

errorsarray<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.

pluginRouteIdstring

Plugin-owned identifier of the rejected route or group route. Set unless the item is a relationship.

relationshipExternalIdstring

Plugin-owned `externalId` of the rejected relationship. Set only for relationship items.

interfacestring

Canonical capability interface name the failure applies to, when the failure is interface-specific.

versionstring

Declared capability interface version the failure applies to, when the failure is interface-specific.

codestringRequired

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.

familystringRequired

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.

statusintegerRequired

HTTP-equivalent status code of the item failure.

minimum: 400

maximum: 599

messagestringRequired

Plain-language description of the failure and the suggested fix.

Response headers
ETagstring

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_REQUEST

Bad request - invalid request payload

Check the request fields and any validation details, then correct the payload.

401 UNAUTHORIZED

Unauthorized - invalid or missing authentication token

Obtain a valid access token, then retry.

403 FORBIDDEN

Forbidden - insufficient permissions

Check the linked account and its permissions for the device or resource.

404 NOT_FOUND

Named group does not exist

Verify the target identifier and that its endpoint or plugin route still exists.

409 IDEMPOTENCY_KEY_IN_FLIGHT

The same idempotency key is in flight

Check the device’s current mode or state. Retry only after the conflict is resolved.

412 PRECONDITION_FAILED

The group version does not match If-Match

Inspect the returned code and family and follow the error handling guide.

422 IDEMPOTENCY_KEY_REUSED

The same idempotency key was used with another payload

Correct the rejected value using the constraints in the error details or request schema.

428 PRECONDITION_REQUIRED

If-Match is required for replacement

Inspect the returned code and family and follow the error handling guide.

500 INTERNAL

Internal server error

Retry with backoff only when the operation is safe to repeat. Include the error code when reporting persistent failures.

Manage Endpoint Groups

View source specification ↗
POST /endpoint-groups-manage

Evaluates 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:manage

Header parameters

Idempotency-Keystring

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

Required

Fields

validateOnlyboolean

When true, runs authorization and validation and returns what would happen, writing nothing and sending no provider messages. Dispatches are PLANNED or NOT_SUPPORTED. A validate-only request neither requires nor consumes an `Idempotency-Key`.

Default: false

operationsarray<EndpointGroupsManageOperation>Required
Item9 variants

One endpoint group management operation, discriminated by `operation`. Unknown operations are rejected with 400.

discriminator: operation

requestIdstringRequired

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

operationstringRequired

Operation discriminator.

Allowed values

  • CREATE_GROUP
nameTypeValueRequired
memberEndpointIdsarray<string>

Endpoint IDs.

uniqueItems: true

Itemstring

minLength: 1

providerSyncstring

Provider synchronization policy; defaults to BEST_EFFORT.

Default: BEST_EFFORT

Allowed values

  • PORTOS_ONLY
  • BEST_EFFORT
  • FAIL_ON_PROVIDER_ERROR

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
statusstringRequired

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

  • COMMITTED
  • FAILED
  • PARTIALLY_SUCCEEDED
resultsarray<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.

requestIdstringRequired

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

operationstringRequired

Discriminator of an endpoint group management operation.

groupEndpointGroupEtagReference

A group addressed together with the etag the client last read, validated inside the management transaction.

deletedGroupIdstring

The deleted group ID (`DELETE_GROUP`).

targetEndpointGroupEtagReference

A group addressed together with the etag the client last read, validated inside the management transaction.

redirectsarray<EndpointGroupRedirect>

Redirects written by `MERGE_INTO`.

A merged-away group ID and the group it now redirects to. Reads and control follow redirects; mutations fail with GROUP_MERGED.

fromstringRequired

The merged-away group ID.

tostringRequired

The group it redirects to.

statusstringRequired

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

  • APPLIED
  • PARTIALLY_APPLIED
  • NOT_APPLIED
providerDispatchesarray<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.

pluginIdstring

The admitted provider plugin ID, omitted when provider metadata is not readable.

authLinkIdstring

The provider account authorization link ID; omitted without metadata read visibility, empty for a readable account without a link.

groupRouteIdstring

The provider-native group route ID within this plugin and account, omitted without native-route read visibility.

namespacestringRequired

The message capability namespace.

namestringRequired

The canonical message name.

statusstringRequired

A planned, verified, failed or undeclared provider dispatch; a timeout is FAILED.

Allowed values

  • PLANNED
  • SUCCEEDED
  • FAILED
  • NOT_SUPPORTED
reasonstring

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_DECLARED
  • OUTSIDE_PRINCIPAL
errorError

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.

impliedRemovalsarray<EndpointGroupImpliedRemoval>

Authorized native memberships displaced by an explicit move.

In-scope membership removals implied by an exclusive provider move.

groupRouteIdstringRequired

The Port OS group route affected by the removal.

minLength: 1

memberEndpointIdsarray<string>Required

Endpoint members removed from this route.

uniqueItems: true

Itemstring

minLength: 1

sourceEndpointGroupEtagReference

A group addressed together with the etag the client last read, validated inside the management transaction.

errorsarray<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.

requestIdstringRequired

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

codestringRequired

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.

familystringRequired

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.

statusintegerRequired

HTTP-equivalent status code of the item failure.

minimum: 400

maximum: 599

messagestringRequired

Plain-language description of the failure and the suggested next action.

resourceIdstring

The resource the failure applies to, when it is not the operation's primary target.

errorsarray<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.

pluginRouteIdstring

Plugin-owned identifier of the rejected route or group route. Set unless the item is a relationship.

relationshipExternalIdstring

Plugin-owned `externalId` of the rejected relationship. Set only for relationship items.

interfacestring

Canonical capability interface name the failure applies to, when the failure is interface-specific.

versionstring

Declared capability interface version the failure applies to, when the failure is interface-specific.

codestringRequired

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.

familystringRequired

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.

statusintegerRequired

HTTP-equivalent status code of the item failure.

minimum: 400

maximum: 599

messagestringRequired

Plain-language description of the failure and the suggested fix.

Errors

400 IDEMPOTENCY_KEY_REQUIRED

Malformed 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 UNAUTHORIZED

Unauthorized - invalid or missing authentication token

Obtain a valid access token, then retry.

403 FORBIDDEN

Forbidden - token lacks the group:manage scope

Check the linked account and its permissions for the device or resource.

409 IDEMPOTENCY_KEY_IN_FLIGHT

A 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_REUSED

The `Idempotency-Key` was already used with a different payload

Correct the rejected value using the constraints in the error details or request schema.

500 INTERNAL

Internal server error

Retry with backoff only when the operation is safe to repeat. Include the error code when reporting persistent failures.

Get an endpoint group

View source specification ↗
GET /{namespace}/{principalType}/{principalId}/endpoint-groups/{groupId}

Get an endpoint group by ID.

Required scope

group:read

Path parameters

namespacestringRequired

The namespace of the principal

principalTypestringRequired

The type of principal

principalIdstringRequired

The ID of the principal

groupIdstringRequired

The ID of the endpoint group to retrieve

Query parameters

expandarray<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.

forceDeviceAttributeQueryboolean

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
idstringRequired

The unique identifier for the endpoint group

pattern: "^port1/[^/]+/[^/]+/endpoint-groups/[^/]+$"

nameTypeValueRequired

The name of the endpoint group

ownerIdstringRequired

The ID of the owner of the endpoint group

enablementstringRequired

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: ENABLED

Allowed values

  • ENABLED
  • DISABLED
memberEndpointIdsarray<string>

List of member endpoint IDs of the endpoint group

interfacesarray<ApplicationInterface>Required

List of interfaces supported by the endpoint group

namestringRequired

The name of the interface

versionstring

The version of the interface

messagesarray<ApplicationInterfaceMessage>

Supported message subset. An omitted or empty list declares no supported messages.

namestringRequired

The name of the command

attributesarray<ApplicationInterfaceAttribute>

Supported attribute subset. An omitted or empty list declares no supported attributes.

namestringRequired

The name of the attribute

valueobject

the value of the attribute, this is an opaque resource object, so it can be any type of struct.

configurationobject

Interface-specific configuration published for discovery and enumeration.

etagstringRequired

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.

redirectedFromstring

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`.

parentGroupIdstring

The canonical parent group derived from `IS_PART_OF` relationships, when the group has one.

childGroupIdsarray<string>

Canonical child groups derived from `IS_PART_OF` relationships.

controllersarray<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.

endpointIdstringRequired

The controlling endpoint.

interfacesarray<RelationshipInterface>Required

Interfaces and messages the endpoint supports on the group.

Capability-interface applicability of a relationship, for example the robotic-vacuum-cleaner messages a `CAN_CONTROL` edge supports on a room.

namestringRequired

The capability interface namespace.

minLength: 1

versionstringRequired

The capability interface version.

minLength: 1

messagesarray<string>

Message names of the interface the relationship applies to. An explicit empty array applies to no messages. Omission retains every message supported by the source interface.

uniqueItems: true

Itemstring

minLength: 1

attributesarray<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.

groupRouteIdstringRequired

The typed ID of the group route the value was reported for.

pluginIdstringRequired

The plugin that owns the group route and reported the value.

providerstringRequired

The display name of that plugin.

namespacestringRequired

The capability interface namespace for this attribute

namestringRequired

The name of the attribute within the namespace

versionstringRequired

The capability interface version the value conforms to.

valueobject

The attribute value payload, structure depends on the attribute schema. Omitted when `error` is present.

errorError

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.

sampledAtstring

When the provider observed the value. Omitted when the provider did not say.

format: "date-time"

groupRoutesarray<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.

etagstringRequired

Opaque strong version of the stored native route. Send as If-Match when deleting.

pluginProfileIdstring

Stable profile ID from the registered plugin declaration.

minLength: 1

ontologicalTypesarray<string>

Actual native group route classifications.

idstringRequired

Unique group route ID.

pattern: "^port1/[^/]+/[^/]+/endpoint-group-routes/[^/]+$"

associatedGroupIdstring

The associated endpoint group ID; omitted for an orphaned route.

pattern: "^port1/[^/]+/[^/]+/endpoint-groups/[^/]+$"

associatedPluginIdstringRequired

Associated plugin ID.

associatedPluginRouteIdstringRequired

Stable plugin-owned route ID. Match synchronized plugin or fixture membership with this value, not the Port OS group route `id`.

associatedAuthLinkIdstringRequired

Associated auth link ID.

ownerIdstringRequired

Group route owner's ID.

memberPluginRouteIdsarray<string>

Member plugin route IDs.

interfacesarray<RouteInterface>Required

Supported interfaces.

namestringRequired

The name of the interface

versionstring

the version of the interface

messagesarray<ApplicationInterfaceMessage>

Supported inbound message subset for the declared interface version. An omitted or empty list declares no supported messages; null also declares none. A supplied array contains distinct canonical names for implemented messages.

nullable: true

namestringRequired

The name of the command

attributesarray<ApplicationInterfaceAttribute>

Supported attribute subset. An omitted or empty list declares no supported attributes.

namestringRequired

The name of the attribute

valueobject

the value of the attribute, this is an opaque resource object, so it can be any type of struct.

configurationobject

The configuration of the interface

pluginCustomMetadataobject

Provider-defined route metadata for plugin use.

namestring

The provider-native group name, which can differ from the customer aggregate name.

enablementstringRequired

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: ENABLED

Allowed values

  • ENABLED
  • DISABLED
memberEndpointIdsarray<string>

Resolved Port OS endpoint IDs in this native route.

uniqueItems: true

portosRouteEndpointGroupPortosRoute

Stored customer membership intent, populated only under expand=groupRoutes.

Response headers
ETagstring

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_REQUEST

Invalid request payload

Check the request fields and any validation details, then correct the payload.

401 UNAUTHORIZED

Unauthorized - invalid or missing authentication token

Obtain a valid access token, then retry.

403 FORBIDDEN

Forbidden - insufficient permissions

Check the linked account and its permissions for the device or resource.

404 NOT_FOUND

Endpoint group not found

Verify the target identifier and that its endpoint or plugin route still exists.

500 INTERNAL

Internal server error

Retry with backoff only when the operation is safe to repeat. Include the error code when reporting persistent failures.

Delete an endpoint group

View source specification ↗
DELETE /{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:manage

Path parameters

namespacestringRequired

The namespace of the principal

principalTypestringRequired

The type of principal

principalIdstringRequired

The ID of the principal

groupIdstringRequired

The ID of the endpoint group to delete

Query parameters

providerSyncstring

Provider synchronization policy for group deletion; defaults to BEST_EFFORT.

Default: BEST_EFFORT

Allowed values

  • PORTOS_ONLY
  • BEST_EFFORT
  • FAIL_ON_PROVIDER_ERROR

Header parameters

If-MatchstringRequired

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-KeystringRequired

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
statusstringRequired

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

  • APPLIED
  • PARTIALLY_APPLIED
  • NOT_APPLIED
providerDispatchesarray<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.

pluginIdstring

The admitted provider plugin ID, omitted when provider metadata is not readable.

authLinkIdstring

The provider account authorization link ID; omitted without metadata read visibility, empty for a readable account without a link.

groupRouteIdstring

The provider-native group route ID within this plugin and account, omitted without native-route read visibility.

namespacestringRequired

The message capability namespace.

namestringRequired

The canonical message name.

statusstringRequired

A planned, verified, failed or undeclared provider dispatch; a timeout is FAILED.

Allowed values

  • PLANNED
  • SUCCEEDED
  • FAILED
  • NOT_SUPPORTED
reasonstring

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_DECLARED
  • OUTSIDE_PRINCIPAL
errorError

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.

impliedRemovalsarray<EndpointGroupImpliedRemoval>

Authorized native memberships displaced by an explicit move.

In-scope membership removals implied by an exclusive provider move.

groupRouteIdstringRequired

The Port OS group route affected by the removal.

minLength: 1

memberEndpointIdsarray<string>Required

Endpoint members removed from this route.

uniqueItems: true

Itemstring

minLength: 1

groupEndpointGroupEtagReference

A group addressed together with the etag the client last read, validated inside the management transaction.

deletedGroupIdstring

Deleted group ID on an applied delete.

errorsarray<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.

familystringRequired

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.

codestringRequired

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.

messagestringRequired

Plain-language description of the failure and the suggested next action.

detailsErrorDetails

Optional typed context for an error. Fields are additive and only populated when the error can safely expose that context to API clients.

errorsarray<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.

pluginRouteIdstring

Plugin-owned identifier of the rejected route or group route. Set unless the item is a relationship.

relationshipExternalIdstring

Plugin-owned `externalId` of the rejected relationship. Set only for relationship items.

interfacestring

Canonical capability interface name the failure applies to, when the failure is interface-specific.

versionstring

Declared capability interface version the failure applies to, when the failure is interface-specific.

codestringRequired

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.

familystringRequired

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.

statusintegerRequired

HTTP-equivalent status code of the item failure.

minimum: 400

maximum: 599

messagestringRequired

Plain-language description of the failure and the suggested fix.

Errors

400 BAD_REQUEST

Invalid request payload

Check the request fields and any validation details, then correct the payload.

401 UNAUTHORIZED

Unauthorized - invalid or missing authentication token

Obtain a valid access token, then retry.

403 FORBIDDEN

Forbidden - insufficient permissions

Check the linked account and its permissions for the device or resource.

404 NOT_FOUND

Endpoint group not found

Verify the target identifier and that its endpoint or plugin route still exists.

409 IDEMPOTENCY_KEY_IN_FLIGHT

A 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_FAILED

The 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_REUSED

The same Idempotency-Key was used with another payload

Correct the rejected value using the constraints in the error details or request schema.

428 PRECONDITION_REQUIRED

The If-Match header is missing

Inspect the returned code and family and follow the error handling guide.

500 INTERNAL

Internal server error

Retry with backoff only when the operation is safe to repeat. Include the error code when reporting persistent failures.