Execution grants

Read and verify an execution grant without consuming it

GET
/v1/authority/grants/{grantId}

The handler of the deprecated alias POST /v1/execution/verify-token. A GET carries no body, so the execution token is presented in the x-decionis-execution-token header (required; never logged) and the intent hash, optionally, as the intent_hash query parameter.

Verifies the token's Ed25519 signature, issuer and lifetime; that the caller is authorised for the organisation the grant names (the caller's own organisation for an organisation API key); that the token's jti is {grantId} (otherwise 409 GRANT_ID_MISMATCH); and, when intent_hash is supplied, that the grant is bound to it (otherwise 409 GRANT_BINDING_MISMATCH). The intent hash commits to the tenant, actor, action and downstream target the alias checks field by field. Reading a grant never authorizes execution: only a claim does.

Authorization

ApiKeyAuth
AuthorizationBearer <token>

An organization API key. Its scopes decide what it may call; decision:shadow is the narrowest: SHADOW evaluations through POST /v1/authority/grants or its alias POST /v1/authority/enforce-and-bind only (DECISION_SHADOW_MODE_DENIED in any other mode; DECISION_SHADOW_FIELD_DENIED for a body carrying context.decionis_policy, evidence or escalation), with no integration dispatch. A key whose only scope is decision:shadow (an AgentSafe hosted gateway's) reaches exactly those two, POST /v1/auth/credential-context, POST /v1/hosted-gateway/keys/confirm and POST /v1/hosted-gateway/keys/revoke-self; every other route answers 403 HOSTED_GATEWAY_KEY_PATH_DENIED. decision:enforce is an enforced hosted gateway's key: evaluations in SHADOW or ENFORCEMENT through POST /v1/authority/grants or its alias (400 DECISION_ENFORCE_FIELD_DENIED for a body carrying context.decionis_policy; it never holds policy:write), and the grants and managed escalations they bind. A key whose scopes are decision:enforce (with or without decision:shadow) reaches exactly POST /v1/authority/enforce-and-bind, POST /v1/authority/grants, GET /v1/authority/grants/{grant_id}, POST /v1/authority/grants/{grant_id}/claims, POST /v1/authority/grants/{grant_id}/receipts, POST /v1/authority/grants/{grant_id}/reconciliations, POST /v1/execution/verify-token, POST /v1/execution/claim-token, POST /v1/execution/consume-token, POST /v1/execution/finalize-token, GET /v1/authority/escalations/{escalation_id}, DELETE /v1/authority/escalations/{escalation_id}, POST /v1/auth/credential-context, POST /v1/hosted-gateway/keys/confirm and POST /v1/hosted-gateway/keys/revoke-self, each id a UUID; every other route answers 403 HOSTED_GATEWAY_KEY_PATH_DENIED.

In: header

Path Parameters

grantId*string

The execution grant's jti: the execution_token_jti returned when the grant was issued, the jti recorded for the grant, and the jti claim of the signed execution token. The token remains the bearer proof; a token whose jti is not this id is refused with GRANT_ID_MISMATCH.

Formatuuid

Query Parameters

intent_hash?string
Match^sha256:[0-9a-f]{64}$

Header Parameters

x-decionis-execution-token*string

The execution token, as issued. Redacted from request logs.

Length1 <= length <= 20000

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/v1/authority/grants/497f6eca-6276-4993-bfeb-53cbbbba6f08" \  -H "x-decionis-execution-token: string"
{  "valid": true,  "should_execute": true,  "would_block": true,  "verdict": "APPROVE",  "reason_codes": [    "string"  ],  "claims": {    "iss": "string",    "sub": "string",    "aud": "string",    "org_id": "a40f5d1f-d889-42e9-94ea-b9b33585fc6b",    "dossier_id": "string",    "decision_id": "string",    "chain_id": "string",    "action": "string",    "decision": "allow",    "scope": "execute",    "binding": {      "intent_hash": "string",      "execution_binding_digest": "string",      "execution_payload_digest": "string",      "execution_payload_canonicalization_profile": "string",      "execution_nonce": "string",      "execution_correlation_id": "string",      "expected_effect_digest": "string",      "expected_state_version": "string",      "authority_protocol_version": "1.0"    },    "jti": "string",    "iat": 0,    "nbf": 0,    "exp": 0  },  "claim_token": "string",  "claim_validated_at": "2019-08-24T14:15:22Z",  "claim_lease_expires_at": "2019-08-24T14:15:22Z",  "claim_attestation": "string",  "evidence": {},  "evidence_durably_queued": true,  "decision_chain_evidence_recorded": true}

Evaluate one exact agent action and bind it to a single-use execution grant POST

The grant resource. Decionis recomputes the SHA-256 hash of the canonical execution intent, evaluates policy, and issues a short-lived Ed25519 execution grant only for an ALLOW evaluated in ENFORCEMENT mode. This is the handler of the deprecated alias `POST /v1/authority/enforce-and-bind`, registered twice: every rule documented there (Idempotency-Key binding, Presence and attestation evidence, signed signals, MANAGED escalation, the verification envelope by client version, `context.decionis_policy`, the `decision:shadow` confinement, the scopes each mode needs and the workspace-owner rule, the EXPECTED_EFFECT_DIGEST_MISSING warning, and the BLOCK when a held allowance cannot be reserved) applies here unchanged. The issued grant is addressed afterwards as `/v1/authority/grants/{grantId}`, where `grantId` is the grant's `jti`: the `execution_token_jti` of this response, the `jti` recorded for the grant, and the `jti` claim of the signed execution token. `POST /v1/authority/evaluate` and `POST /v1/authority/enforce`, which the legacy `@decionis/sdk-node` 0.1.0 calls and this API never served, answer 410 `LEGACY_AUTHORITY_ROUTE_RETIRED` naming this route and `@decionis/sdk`, which replaces that package. `executor` (optional) says who will carry the grant out. It is never part of the canonical intent, its hash, or the grant's binding. When `executor.style` is `permit` and a grant was issued, the decision also carries `permit_id` (the grant's jti), `intent_sha256` (the intent hash as bare hex, written as `dossier_sha256` is) and `expires_at` (`execution_token_expires_at`). Without `executor`, or with `dispatch`, the response is exactly the enforce-and-bind response. A MANAGED escalation's locator-only summary carries no grant, so it never carries permit fields.

Revalidate and atomically claim a grant once, immediately before commit POST

The handler of the deprecated aliases `POST /v1/execution/claim-token` and `POST /v1/execution/consume-token`, with the same body and the same responses: execution is authorized only when `should_execute` is `true`, `claim_token` is non-null and `claim_lease_expires_at` is still live at the downstream boundary, and a live claim returns `claim_attestation`. The verified token's `jti` must be `{grantId}`; otherwise the answer is 409 `GRANT_ID_MISMATCH` and nothing is claimed. When the grant's binding draws on a held allowance (`allowance_draws`), the claim converts the grant's reservation in the same transaction that consumes the grant and inserts its concurrency scopes. A grant whose reservation is not live cannot be claimed: the answer is 409 `NONCE_REPLAY_DETECTED`, as for any grant that can no longer be consumed, and nothing is claimed. A live claim must be finalized at `/receipts` (alias `/v1/execution/finalize-token`) before `claim_lease_expires_at`, with COMMITTED, FAILED or INDETERMINATE; the 200 says so in `x-decionis-action-required: FINALIZE_BEFORE_LEASE_EXPIRY`. A claim left unfinalized past its lease is recorded INDETERMINATE and keeps its concurrency scopes (its execution target and bound material signals): every later claim on any of them answers 409 REVIEW `CURRENT_STATE_UNRESOLVED` with `evidence.nonce_claim_state` INDETERMINATE, and `x-decionis-blocking-grant` names the grant whose claim holds the scope, until that attempt is reconciled at `/v1/authority/grants/{grantId}/reconciliations`.