Skip to content

Principals

Use principals when you manage who can act in Port OS.

Principals are people, endpoints, or organizations. They can perform actions on resources, and can be granted permissions to access resources.

Enumerate Principals

View source specification ↗
GET /principals

Lists principals owned by the authenticated caller by default. Supplying an owner selects that owner's principals, subject to the caller's principal-read permissions. Supplying an ID selects a single principal, subject to the same permission check. 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

ownerstring

Owner whose principals to list. Defaults to the authenticated caller when ID is not supplied. A different owner requires principal-read permission for each returned principal.

idstring

Exact principal identifier to retrieve. The result is included only when the caller has principal-read permission.

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.

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

Returns

200

Principals retrieved successfully

Fields
resultsarray<Principal>Required
idstringRequired

The unique identifier for the principal

pattern: "^port1/[^/]+/[^/]+$"

ownerIdstring

The owner ID of the principal

namestring

The name of the principal

googleEmailstring

The Google email associated with the principal

googleIdentitystring

The Google identity associated with the principal

appleEmailstring

The Apple email associated with the principal

etagstringRequired

Opaque strong version of the principal resource.

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

Invalid owner, ID, page size, or pagination token

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

401 UNAUTHORIZED

Authentication is required

Obtain a valid access token, then retry.

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 Principal

View source specification ↗
POST /principals

Creates a server-assigned principal or fully replaces the writable name of an existing principal. Omitted name clears it. Owner and identity-provider fields are server-owned.

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

itemPrincipalInputRequired

Complete writable principal document. Omit id to create; send an existing id with If-Match to replace. An omitted name becomes empty.

Returns

200

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

Fields
resultPrincipalRequired
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.

Get Principal

View source specification ↗
GET /principals/{principalId}

Returns one authorized principal and its strong version.

Required scope

Any authenticated access token

Path parameters

principalIdstringRequired

Server-assigned principal identifier or its final ID segment.

Returns

200

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

Fields
idstringRequired

The unique identifier for the principal

pattern: "^port1/[^/]+/[^/]+$"

ownerIdstring

The owner ID of the principal

namestring

The name of the principal

googleEmailstring

The Google email associated with the principal

googleIdentitystring

The Google identity associated with the principal

appleEmailstring

The Apple email associated with the principal

etagstringRequired

Opaque strong version of the principal resource.

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

Principal not found.

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

Delete Principal

View source specification ↗
DELETE /principals/{principalId}

Deletes the observed principal version. First deletion of an unknown ID returns 404; an authorized retry replays its stored successful response.

Required scope

Any authenticated access token

Path parameters

principalIdstringRequired

Server-assigned principal identifier or its final ID segment.

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.