Tokens
Use tokens when you already have credentials and need an access token, or when you want to manage the long-lived tokens you hand to a CLI, device automation or agent.
Tokens are JWTs vended by principals for token exchange. A principal may create tokens, and list and delete the tokens it owns. The raw JWT is returned only once at creation. Exchange it at the OAuth token endpoint for an access token, then refresh or revoke the grant there.
/auth/tokenThis API is used to generate OAuth2 tokens.
The current OAuth token endpoint supports:
- Refresh token grants.
- Authorization code token grants.
Public DCR/CIMD clients exchange authorization_code with client_id, redirect_uri, code_verifier and the same resource as the consent request. No client_secret is issued. Refresh these grants with grant_type refresh_token, client_id, rotating refresh_token and the original resource. Store the replacement securely.
Required scope
Not required
Request body
Fields
- grant_type
stringRequired The OAuth grant type. Use authorization_code for code exchange, or refresh_token to exchange a refresh token for an access token.
- client_secret
string Required for confidential clients. Public DCR/CIMD clients omit this field and use PKCE.
- subject_token
string Identity token to exchange; required for urn:ietf:params:oauth:grant-type:token-exchange.
- subject_token_type
string Subject token type; use urn:ietf:params:oauth:token-type:id_token for identity token exchange.
- resource
string Exact resource from authorization; canonical issuer for REST or issuer/mcp for MCP. Required for DCR and CIMD.
format: "uri"
Returns
200
Token generated successfully
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.
/auth/revokePossession of the matching refresh token proves revocation authority. The endpoint invalidates the grant family; it does not delete the client or other users' grants.
Required scope
Not required
Returns
200
Grant revoked or token was already invalid.
No response body.
Errors
400Invalid request or client mismatch.
Check the request fields and any validation details, then correct the payload.
503Revocation storage unavailable; do not claim success.
Wait for the provider or bridge to recover, then retry safely with backoff.
/tokensLists tokens owned by the authenticated principal. A principal may only list tokens they own.
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
Returns
200
Tokens retrieved successfully
Fields
- results
array<TokenListItem>Required A token in a list response (no raw JWT).
- purpose
string API keys authenticate automation. WEBSITE_LOGIN keys grant full account website sign-in and explicit OAuth consent, cannot have restricted scopes, and must be created through an existing account sign-in. Keys expire and can be revoked; OAuth connections approved with a website key are revoked separately.
Default:
APIAllowed values
APIWEBSITE_LOGIN
- purpose
- 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
Check the request fields and any validation details, then correct the payload.
401 UNAUTHORIZEDUnauthorized
Obtain a valid access token, then retry.
403 INSUFFICIENT_PERMISSIONSForbidden - not allowed to list tokens
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.
/tokensCreates a revocable credential, or replaces the complete writable label of an existing token. Replacement accepts only id and label; credential identity, purpose, scope and expiry are immutable. Raw tokens appear only in create and its authorized replay. Responses are retained privately for 24 hours.
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
- purpose
string API keys authenticate automation. WEBSITE_LOGIN keys grant full account website sign-in and explicit OAuth consent, cannot have restricted scopes, and must be created through an existing account sign-in. Keys expire and can be revoked; OAuth connections approved with a website key are revoked separately.
Default:
APIAllowed values
APIWEBSITE_LOGIN
- subject
string Identity for the token. Use ~self for the current user (resolved to the authenticated principal at create time), or that same principal's full path. Other principals are rejected.
- expires_in
integer Lifetime in seconds, default 3600. Website sign-in keys allow 1 to 2073600 seconds (24 days).
Returns
200
Stored resource returned; authorized retries replay the same committed response for 24 hours.
Fields
- token
string Raw bearer returned on create and its authorized idempotent replay only. Never returned by reads or replacements.
- purpose
string API keys authenticate automation. WEBSITE_LOGIN keys grant full account website sign-in and explicit OAuth consent, cannot have restricted scopes, and must be created through an existing account sign-in. Keys expire and can be revoked; OAuth connections approved with a website key are revoked separately.
Default:
APIAllowed values
APIWEBSITE_LOGIN
Response headers
- ETag
string Strong entity tag matching the response body.
Errors
400 IDEMPOTENCY_KEY_REQUIREDInvalid request or missing Idempotency-Key.
Check the request fields and any validation details, then correct the payload.
401 UNAUTHORIZEDAuthentication required.
Obtain a valid access token, then retry.
403 FORBIDDENCaller lacks resource permission.
Check the linked account and its permissions for the device or resource.
404 NOT_FOUNDThe addressed resource does not exist.
Verify the target identifier and that its endpoint or plugin route still exists.
409 IDEMPOTENCY_KEY_IN_FLIGHTThe idempotency request is in flight.
Check the device’s current mode or state. Retry only after the conflict is resolved.
412 PRECONDITION_FAILEDThe resource version changed.
Inspect the returned code and family and follow the error handling guide.
422 IDEMPOTENCY_KEY_REUSEDThe same key was used for a different request.
Correct the rejected value using the constraints in the error details or request schema.
428 PRECONDITION_REQUIREDIf-Match is required for replacement or delete.
Inspect the returned code and family and follow the error handling guide.
500 INTERNALThe operation could not be committed.
Retry with backoff only when the operation is safe to repeat. Include the error code when reporting persistent failures.
/{namespace}/{principalType}/{principalId}/tokens/{tokenId}Revokes the access key's active record so subsequent website and API requests using that bearer are rejected. The token ID is the ID returned by create/list and carried in its JWT jti claim. Only the owner may revoke it. OAuth connections explicitly approved with a website key are independent grants and must be revoked separately.
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
Stored resource returned; authorized retries replay the same committed response for 24 hours.
No response body.
Errors
400 IDEMPOTENCY_KEY_REQUIREDInvalid request or missing Idempotency-Key.
Check the request fields and any validation details, then correct the payload.
401 UNAUTHORIZEDAuthentication required.
Obtain a valid access token, then retry.
403 FORBIDDENCaller lacks resource permission.
Check the linked account and its permissions for the device or resource.
404 NOT_FOUNDThe addressed resource does not exist.
Verify the target identifier and that its endpoint or plugin route still exists.
409 IDEMPOTENCY_KEY_IN_FLIGHTThe idempotency request is in flight.
Check the device’s current mode or state. Retry only after the conflict is resolved.
412 PRECONDITION_FAILEDThe resource version changed.
Inspect the returned code and family and follow the error handling guide.
422 IDEMPOTENCY_KEY_REUSEDThe same key was used for a different request.
Correct the rejected value using the constraints in the error details or request schema.
428 PRECONDITION_REQUIREDIf-Match is required for replacement or delete.
Inspect the returned code and family and follow the error handling guide.
500 INTERNALThe operation could not be committed.
Retry with backoff only when the operation is safe to repeat. Include the error code when reporting persistent failures.
/{namespace}/{principalType}/{principalId}/tokens/{tokenId}Returns token metadata and its strong version, without the bearer credential.
Required scope
Any authenticated access token
Returns
200
Stored resource returned; authorized retries replay the same committed response for 24 hours.
Fields
- purpose
string API keys authenticate automation. WEBSITE_LOGIN keys grant full account website sign-in and explicit OAuth consent, cannot have restricted scopes, and must be created through an existing account sign-in. Keys expire and can be revoked; OAuth connections approved with a website key are revoked separately.
Default:
APIAllowed values
APIWEBSITE_LOGIN
Response headers
- ETag
string Strong entity tag matching the response body.
Errors
401 UNAUTHORIZEDAuthentication required.
Obtain a valid access token, then retry.
403 FORBIDDENPermission denied.
Check the linked account and its permissions for the device or resource.
404 NOT_FOUNDToken not found.
Verify the target identifier and that its endpoint or plugin route still exists.