Skip to content

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.

OAuth2 Token Endpoint

View source specification ↗
POST /auth/token

This API is used to generate OAuth2 tokens.

The current OAuth token endpoint supports:

  1. Refresh token grants.
  2. 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

Required

Fields

grant_typestringRequired

The OAuth grant type. Use authorization_code for code exchange, or refresh_token to exchange a refresh token for an access token.

client_idstringRequired

The client ID.

client_secretstring

Required for confidential clients. Public DCR/CIMD clients omit this field and use PKCE.

subject_tokenstring

Identity token to exchange; required for urn:ietf:params:oauth:grant-type:token-exchange.

subject_token_typestring

Subject token type; use urn:ietf:params:oauth:token-type:id_token for identity token exchange.

requested_token_typestring

Requested token type for identity token exchange.

audiencestring

Target audience for identity token exchange.

device_codestring

Device code; required for urn:ietf:params:oauth:grant-type:device_code.

codestring

Authorization code; required when grant_type is authorization_code.

refresh_tokenstring

The refresh token; required when grant_type is refresh_token.

redirect_uristring

Redirect URI; required when grant_type is authorization_code.

code_verifierstring

Original PKCE verifier; required for public-client code exchange.

resourcestring

Exact resource from authorization; canonical issuer for REST or issuer/mcp for MCP. Required for DCR and CIMD.

format: "uri"

scopestring

Optional narrower subset during refresh; cannot add scopes.

client_assertionstring

Signed JWT proving client identity (RFC 7523); required with client_assertion_type for private_key_jwt clients using the client_credentials grant.

maxLength: 8192

client_assertion_typestring

Must be urn:ietf:params:oauth:client-assertion-type:jwt-bearer when client_assertion is set.

Allowed values

  • urn:ietf:params:oauth:client-assertion-type:jwt-bearer

Returns

200

Token generated successfully

Fields
access_tokenstringRequired

The access token

token_typestringRequired

The token type

expires_inintegerRequired

The token expiration time in seconds

refresh_tokenstring

Rotating refresh credential for resource-bound grants; store privately.

scopestring

Granted space-separated scopes.

Errors

400

Invalid request payload

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

500

Internal server error

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

Revoke a delegated REST or MCP grant

View source specification ↗
POST /auth/revoke

Possession 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

Request body

Required

Fields

tokenstringRequired
client_idstringRequired

Returns

200

Grant revoked or token was already invalid.

No response body.

Errors

400

Invalid request or client mismatch.

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

503

Revocation storage unavailable; do not claim success.

Wait for the provider or bridge to recover, then retry safely with backoff.

Enumerate Tokens

View source specification ↗
GET /tokens

Lists 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

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

minimum: 1

maximum: 100

expandarray<string>

Expansion tokens that request related or computed fields for each result. When omitted, the response contains only the default, shallower set of fields for each result.

Returns

200

Tokens retrieved successfully

Fields
resultsarray<TokenListItem>Required

A token in a list response (no raw JWT).

purposestring

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

Allowed values

  • API
  • WEBSITE_LOGIN
idstring

Token identifier (same as JWT jti).

subjectstring

Principal path that is the subject of the token.

created_atstring

When the token was created (ISO 8601).

format: "date-time"

expires_atstring

When the token expires (ISO 8601).

format: "date-time"

client_idstring

OAuth client ID for the token (e.g. custom-access-token client).

scopestring

Space-separated scopes, if any.

labelstring

Human-readable label, if set.

etagstringRequired

Opaque strong resource version.

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

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

401 UNAUTHORIZED

Unauthorized

Obtain a valid access token, then retry.

403 INSUFFICIENT_PERMISSIONS

Forbidden - not allowed to list tokens

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 Token

View source specification ↗
POST /tokens

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

purposestring

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

Allowed values

  • API
  • WEBSITE_LOGIN
subjectstring

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_ininteger

Lifetime in seconds, default 3600. Website sign-in keys allow 1 to 2073600 seconds (24 days).

scopestring

Space-separated scopes. Optional; default no scopes. See scopes documentation for allowed values and semantics.

labelstring

Optional human-readable label for the token (e.g. "CLI token").

idstring

Existing server-assigned token identifier for a label-only full replacement. On replacement only id and label may be supplied.

Returns

200

Stored resource returned; authorized retries replay the same committed response for 24 hours.

Fields
idstringRequired

Token identifier (same as JWT jti). Use for list/delete and in the DELETE URL.

tokenstring

Raw bearer returned on create and its authorized idempotent replay only. Never returned by reads or replacements.

expires_atstringRequired

When the token expires (ISO 8601).

format: "date-time"

etagstringRequired

Opaque strong resource version.

subjectstring

Principal path that is the subject of the token.

created_atstring

When the token was created (ISO 8601).

format: "date-time"

client_idstring

OAuth client ID for the token (e.g. custom-access-token client).

scopestring

Space-separated scopes, if any.

labelstring

Human-readable label, if set.

purposestring

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

Allowed values

  • API
  • WEBSITE_LOGIN
Response headers
ETagstring

Strong entity tag matching the response body.

Errors

400 IDEMPOTENCY_KEY_REQUIRED

Invalid request or missing Idempotency-Key.

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

401 UNAUTHORIZED

Authentication required.

Obtain a valid access token, then retry.

403 FORBIDDEN

Caller lacks resource permission.

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

404 NOT_FOUND

The addressed resource does not exist.

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

409 IDEMPOTENCY_KEY_IN_FLIGHT

The idempotency request is in flight.

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

412 PRECONDITION_FAILED

The resource version changed.

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

422 IDEMPOTENCY_KEY_REUSED

The same key was used for a different request.

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

428 PRECONDITION_REQUIRED

If-Match is required for replacement or delete.

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

500 INTERNAL

The operation could not be committed.

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

Invalidate Token

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

Path parameters

tokenIdstringRequired

The token identifier (partial ID)

namespacestringRequired

The namespace of the principal

principalTypestringRequired

The type of principal

principalIdstringRequired

The ID of the principal

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

Returns

200

Stored resource returned; authorized retries replay the same committed response for 24 hours.

No response body.

Errors

400 IDEMPOTENCY_KEY_REQUIRED

Invalid request or missing Idempotency-Key.

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

401 UNAUTHORIZED

Authentication required.

Obtain a valid access token, then retry.

403 FORBIDDEN

Caller lacks resource permission.

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

404 NOT_FOUND

The addressed resource does not exist.

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

409 IDEMPOTENCY_KEY_IN_FLIGHT

The idempotency request is in flight.

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

412 PRECONDITION_FAILED

The resource version changed.

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

422 IDEMPOTENCY_KEY_REUSED

The same key was used for a different request.

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

428 PRECONDITION_REQUIRED

If-Match is required for replacement or delete.

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

500 INTERNAL

The operation could not be committed.

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

Get Token

View source specification ↗
GET /{namespace}/{principalType}/{principalId}/tokens/{tokenId}

Returns token metadata and its strong version, without the bearer credential.

Required scope

Any authenticated access token

Path parameters

tokenIdstringRequired

The token identifier (partial ID)

namespacestringRequired

The namespace of the principal

principalTypestringRequired

The type of principal

principalIdstringRequired

The ID of the principal

Returns

200

Stored resource returned; authorized retries replay the same committed response for 24 hours.

Fields
purposestring

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

Allowed values

  • API
  • WEBSITE_LOGIN
idstring

Token identifier (same as JWT jti).

subjectstring

Principal path that is the subject of the token.

created_atstring

When the token was created (ISO 8601).

format: "date-time"

expires_atstring

When the token expires (ISO 8601).

format: "date-time"

client_idstring

OAuth client ID for the token (e.g. custom-access-token client).

scopestring

Space-separated scopes, if any.

labelstring

Human-readable label, if set.

etagstringRequired

Opaque strong resource version.

Response headers
ETagstring

Strong entity tag matching the response body.

Errors

401 UNAUTHORIZED

Authentication required.

Obtain a valid access token, then retry.

403 FORBIDDEN

Permission denied.

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

404 NOT_FOUND

Token not found.

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