guides
Intended Documentation
API Quickstart
Obtain an intended_live_ API key, submit your first intent to POST /intent, and handle the APPROVED (200), ESCALATED (202), and DENIED (403) outcomes.
API Quickstart#
This quickstart submits an action to the canonical runtime route, POST /intent, and walks through the three decision outcomes. The submitted action is an IntentRequest — not an action/resource/subject triple — and the route returns the legacy decision vocabulary APPROVED / ESCALATED / DENIED mapped to HTTP 200 / 202 / 403.
Note
POST /intent returns APPROVED / ESCALATED / DENIED. The modern POST /authority/evaluate route returns a different vocabulary (ALLOW / DENY / REQUIRE_APPROVAL / ESCALATE). They are distinct — don't mix them.
Step 1 — Get an API key#
Mint a tenant API key from the console. Customer keys are prefixed intended_live_…. There is no separate sandbox or test key — one kind of key covers every use, and the environment label you can attach to a key is cosmetic (it does not gate authorization, billing, or data isolation). A legacy mrt_… prefix is still accepted for older staff keys.
Store the key and your tenant id as shell variables. Keep the key server-side; it is stored only as a SHA-256 hash and can never be recovered from Intended.
Step 2 — Submit an intent#
The request body is an IntentRequest: who wants to do what, to which system, with what risk. Intended returns a decision and, on approval, a signed token. Your agent runs the action itself — Intended decides and proves; your agent acts.
For agent actions, POST /v1/agent-intent takes a flatter body.
Request fields#
| Field | Type | Required | Notes |
|---|---|---|---|
tenantId | string | yes | Must match the tenant your credential resolves to. |
actor.id | string | yes | The acting identity. |
actor.type | "user" | "service" | yes | |
targetSystem | string | yes | The system the action targets, for example acme/platform-api. |
proposedAction | string | yes | Human-readable description of the action. |
riskContext.baseRiskScore | integer 0–100 | yes | Starting risk before modifiers. |
riskContext.policyCompliant | boolean | yes | |
riskContext.requiresPrivilegedAccess | boolean | no (default false) | Adds +20 to risk when true. |
riskContext.touchesProduction | boolean | no (default false) | Adds +20 to risk when true. |
riskContext.containsSensitiveData | boolean | no (default false) | Adds +15 to risk when true. |
The effective risk score is baseRiskScore + (privileged ? 20 : 0) + (production ? 20 : 0) + (sensitive ? 15 : 0), capped at 100.
Step 3 — Handle the outcome#
The response body carries authorityDecision, and on approval, the signed token:
| Outcome | HTTP | What you get | What to do |
|---|---|---|---|
| APPROVED | 200 | authorityDecisionToken present. | Act, and have the receiving service verify the token first (see below). |
| ESCALATED | 202 | escalationId returned; no token issued. | Route to your approval queue; resubmit or resume after a human approves. |
| DENIED | 403 | No token (fail-closed). | Surface the rationale; the action is not authorized. |
A validation failure returns 400 VALIDATION_ERROR. Any internal failure during evaluation returns 500 AUTHORITY_LOOP_FAILED — the runtime fails closed rather than letting an action through on error.
Step 4 — Verify the token before you execute#
The authorityDecisionToken is an Ed25519 JWT bound to this one intent. The system that performs the action must verify it locally before acting — cloud approval alone is not sufficient.
sdk.verifyAuthorityToken(...) delegates to @intended/verify's verifyToken. See Verify Decision Tokens for the full flow, including consuming the single-use nonce in your service.
Next steps#
- Verify Decision Tokens — local Ed25519 verification.
- Enforcement SDK — the full
@intended-inc/sdkmethod reference. - Error Patterns — every status and error code.
- API Authentication — credentials, scopes, rate limits. </content>