guides
Intended Documentation
Physical Authority API Reference
Every endpoint, every claim, every error code for /v1/physical/* — ground truth for direct HTTP integration.
Authority API Reference (DOC-P7)#
Audience: anyone integrating directly against the cloud HTTP API (typically because there's no SDK for your language yet).
Versioning: all endpoints under
/v1/physical/are stable. Breaking changes ship as/v2/physical/; we keep/v1/running for ≥12 months after/v2/GA.
Base URL#
Sandbox (issuance returns clearly tagged sandbox tokens, rejected by production verifiers):
Authentication#
All endpoints require an Authorization: Bearer <api_key> header. API keys are tenant-scoped and are issued from the Intended console.
API keys are NOT credentials for token-bound robots. The actorIdentity on the request body is what binds an issued token to a specific robot. TOK-P5 (IEEE 802.1AR DevID binding) hardens this further once shipped.
Common error envelope#
All non-2xx responses use this shape:
Error codes:
| HTTP | code | meaning |
|---|---|---|
| 400 | validation_error | request body failed schema validation; details.issues lists offending fields |
| 401 | unauthenticated | missing or invalid API key |
| 403 | forbidden | API key lacks permission for this tenant or resource |
| 404 | not_found | resource (token, snapshot, ticket) does not exist |
| 409 | conflict | duplicate requestId with different body (idempotency violation) |
| 422 | policy_denied | request was syntactically valid but the policy denies; details.safeDefault carries the fallback action |
| 423 | audit_gap_exceeded | edge audit chain has been disconnected longer than time_bounded_audit_gap_policy.max_gap_ms |
| 429 | rate_limited | per-tenant or per-actor rate limit exceeded; Retry-After header set |
| 500 | internal_error | server-side bug; safe to retry idempotent requests |
| 503 | unavailable | classifier or signer is temporarily unhealthy; safe to retry |
Endpoints#
POST /v1/physical/classify
Classifies a structured goal into an OIL v2 category. Does NOT issue a token — use /authority-tokens for that. Useful when your policy evaluation pipeline wants to inspect the classification before deciding whether to request a token.
Request:
Response (200):
failClosed: true indicates the classifier could not produce a confident result. Callers MUST treat this as a denial and transition to their declared safe-default.
POST /v1/physical/authority-tokens
Issues a short-lived Authority Token for a physical action.
Request:
Response (200, ALLOW):
Response (422, DENY):
Response (200, ESCALATE):
The caller polls /approvals/{ticketId} until approval, then re-calls /authority-tokens with operatorTicketId set to the approved ticket.
GET /v1/physical/approvals/{ticketId}
Polls the status of an escalated approval ticket.
Response (200):
When status == "approved", the caller may re-issue against /authority-tokens with operatorTicketId.
POST /v1/physical/snapshots
Records a PhysicalStateProvider snapshot in the audit chain without issuing a token. Useful for forensic checkpoints or for pre-staging state ahead of a sequence of related issuances.
Request:
Response (200):
GET /v1/physical/audit/{tokenJti}
Returns the audit-chain entry for a previously-issued token. Used by forensic replay tooling and by the SDK's debug helpers.
Response (200):
verifications[] is appended to as edge verifiers report their checks (when TOK-P1 ships).
GET /.well-known/jwks.json
Public JWKS for the cloud token signer. Verifiers cache this. Rotation is signaled by adding new kid values; old kids remain valid until their last token expires (~1 hour after rotation).
Idempotency#
POST /v1/physical/authority-tokens accepts an Idempotency-Key header. If the same key is submitted with the same body within 24 hours, the original token is returned. With a different body, the endpoint returns 409 conflict.
Recommended use: set the key to the DAG node ID + monotonic counter so retries on transient errors don't double-issue.
Rate limits#
Default per-tenant limits:
/classify: 100 req/sec sustained, 500 burst/authority-tokens: 50 req/sec sustained, 200 burst- Per
actorIdentity: 10 req/sec sustained, 30 burst
Higher limits available on enterprise plans. Limits are enforced per-region; the global limit is the sum.
Wire format details#
PhysicalStateValue discriminated union#
The unavailable variant has no attestation; it represents a predicate the customer's provider could not resolve in time.
safeDefault enum#
ignore exists for non-safety-critical actions (e.g. a logging-only agent) and SHOULD NOT appear in any policy clause that touches OIL-2900 (Embodied AI Safety).
realTimeTier enum#
rt-hard is reserved for nodes whose deadline miss is a safety event. Use it sparingly; the policy evaluator may apply stricter latency budgets.
See also#
packages/contracts/src/physical-ai.ts— TypeScript schemas (Zod)packages/intended-python/intended/physical.py— Python dataclasses- DOC-P4 Rust safety-critical firmware — the verifier side of the contract