Access control
Use access control to decide who can do what with a resource.
Rules grant or deny permissions on a resource to principals. You can also evaluate a rule to check what a principal is allowed to do.
/access-control-rulesUpsert Access Control Rule
Requires a signed user/session or the existing authenticated client flow. The anonymous DCR delegated device profile cannot invoke this operation.
Required scope
Any authenticated access token
Header 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
- operation
stringRequired The operation to grant access to. This could be a read, write, delete, etc. Please see the access controls list specification for all operations and their descriptions.
- resource
stringRequired The resource to grant access to. This could be an endpoint, a flow, a secret, etc. You can define this as either a class of resources, or a specific resource. Examples: - port1/principals/alice/endpoints/thermostat-zero grants access to that thermostat - port1/principals/alice/flows/* grants access to all flows owned by alice
- identity
stringRequired The identity to grant access to. This could be a user, a role, a group, etc. You can define this as either a class of identities, or a specific identity. Examples: - port1/principals/bob grants access to bob - * just grants access to all identities
Returns
200
Access control rule upserted successfully
Fields
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
400Invalid request payload
Check the request fields and any validation details, then correct the payload.
401 UNAUTHORIZEDAuthentication is required
Obtain a valid access token, then retry.
403 FORBIDDENThe caller may not perform this action
Check the linked account and its permissions for the device or resource.
404 NOT_FOUNDThe named resource does not exist
Verify the target identifier and that its endpoint or plugin route still exists.
409 IDEMPOTENCY_KEY_IN_FLIGHTA request with this 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 access control rule; re-read the rule and retry
Inspect the returned code and family and follow the error handling guide.
422 IDEMPOTENCY_KEY_REUSEDThe idempotency key was already 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 a replacement or deletion
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.
/access-control-rulesGet access-control rules owned by the authenticated caller by default. Supplying an owner selects that owner's rules, and an ID selects one rule; results remain subject to the caller's access-control-rule-read permissions. The default page size is 10 and the maximum page size is 100.
Requires a signed user/session or the existing authenticated client flow. The anonymous DCR delegated device profile cannot invoke this operation.
Required scope
Any authenticated access token
Query parameters
- owner
string Owner whose access-control rules to get. Defaults to the authenticated caller unless an ID is supplied. A different owner requires read permission for each returned rule.
- id
string Exact access-control rule identifier to retrieve. The result is included only when the caller has read permission.
- 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.
Returns
200
Access control rules retrieved successfully
Fields
- results
array<AccessControlRule>Required - 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
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 owner, ID, page size, or pagination token
Check the request fields and any validation details, then correct the payload.
401 UNAUTHORIZEDAuthentication is required
Obtain a valid access token, then retry.
500 INTERNALInternal server error
Retry with backoff only when the operation is safe to repeat. Include the error code when reporting persistent failures.
/access-control-rule-audit-entriesRead the audit of access-control rule changes, newest first. Every rule upsert and delete records who made it, through which client, why, and under which request, plus the rule as it was written. Entries hold identifiers and the rule's shape only, never token text. Entries older than the configured retention (auth.audit.retentionDays, default 365) are pruned at server start.
Only operator callers (operational tokens) and system zero may read the audit; any other caller receives 403. The default page size is 50 and the maximum is 200.
Required scope
Any authenticated access token
Query parameters
Returns
200
Audit entries retrieved successfully
Fields
- results
array<AccessControlRuleAuditEntry>Required Audit entries, newest first.
One recorded access-control rule change. Holds identifiers and the rule's shape only, never token text.
Errors
400 BAD_REQUESTInvalid filter, page size, time or pagination token
Check the request fields and any validation details, then correct the payload.
401 UNAUTHORIZEDAuthentication is required
Obtain a valid access token, then retry.
403 FORBIDDENThe caller is not an operator
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.
/access-control-rules/evaluateEvaluate an access control rule.
Requires a signed user/session or the existing authenticated client flow. The anonymous DCR delegated device profile cannot invoke this operation.
Required scope
Any authenticated access token
Request body
Fields
- entities
array<AccessControlEntity>Required - type
stringRequired The type of the entity
Allowed values
flowsflownodesflowportsflowlinksflow-runsprincipalssystemsaccountsaccess-control-rulestokenssecretsauth-linksoauth-clientspluginsendpointsendpoint-simulatorsendpoint-groupsvirtual-endpoint-groupsendpoint-group-routesroutesdevice-interfacesapplication-interfacesmessagessubscriptionsplugin-subscriptionviews
- type
Returns
200
Access control rule evaluated successfully
Fields
Errors
400Invalid request payload
Check the request fields and any validation details, then correct the payload.
500Internal server error
Retry with backoff only when the operation is safe to repeat. Include the error code when reporting persistent failures.
/{namespace}/{principalType}/{principalId}/access-control-rules/{ruleId}Delete an access control rule.
Requires a signed user/session or the existing authenticated client flow. The anonymous DCR delegated device profile cannot invoke this operation.
Required scope
Any authenticated access token
Header 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
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
Returns
200
Access control rule deleted successfully
No response body.
Errors
400Invalid request payload
Check the request fields and any validation details, then correct the payload.
401 UNAUTHORIZEDAuthentication is required
Obtain a valid access token, then retry.
403 FORBIDDENThe caller may not perform this action
Check the linked account and its permissions for the device or resource.
404 NOT_FOUNDThe named resource does not exist
Verify the target identifier and that its endpoint or plugin route still exists.
409 IDEMPOTENCY_KEY_IN_FLIGHTA request with this 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 access control rule; re-read the rule and retry
Inspect the returned code and family and follow the error handling guide.
422 IDEMPOTENCY_KEY_REUSEDThe idempotency key was already 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 a replacement or deletion
Inspect the returned code and family and follow the error handling guide.
500Internal server error
Retry with backoff only when the operation is safe to repeat. Include the error code when reporting persistent failures.