---
title: "Evaluate one exact agent action and bind it to a single-use execution grant"
method: POST
path: "/v1/authority/grants"
---

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

`POST /v1/authority/grants`

## Request

- Base URL: `https://api.decionis.com`
- URL: `https://api.decionis.com/v1/authority/grants`
- Auth: HTTP bearer

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`, and the
`decision:shadow` confinement) 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.

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

## Headers

- `Idempotency-Key` string

## Request body

- ExecutionAuthorityRequest
  - `protocol_version` 'agent-safe.intent/1', required
  - `tenant_id` string, uuid, required
  - `intent_id` string, uuid, required
  - `captured_at` string, date-time, required
  - `expires_at` string, date-time, required: Must be later than captured_at and no more than five minutes after it.
  - `actor` ExecutionIntentActor, required
    - `id` string, required
    - `type` string, required
    - `runtime` string
    - `trust_level` string
  - `action` ExecutionIntentAction, required
    - `type` string, required
    - `resource` string, required
    - `parameters` object, required
  - `context` object, required: The trusted runtime's context, entirely inside the canonical intent hash. Open by design, with three reserved keys. `idempotency_key` is required and carries the retry identity. `enforcement_boundary` and `workload` are what an enforcement boundary reports about itself and about the software that proposed the action; each is validated against its schema when present, and an absent signal is an answer rather than a placeholder, so a policy that requires provenance refuses on its absence. `runtime_attribution` is reserved for Decionis, which computes it from those reports, and a request that supplies it is refused.
    - `enforcement_boundary` EnforcementBoundarySignal: Which enforcement boundary admitted the intent. The identity is of the configured logical boundary, not of the process running it: a restart, a rescheduling or a scale-out leaves it unchanged, and the container, pod and node are deliberately absent, so an effect's evidence names the door rather than whichever instance was alive at the time.
      - `boundary_id` string, required: What the operator calls this boundary, or a stable id derived from its configuration.
      - `agentsafe_version` string, required
      - `protocol_version` 'agent-safe.intent/1', required
      - `deployment_type` string, required: What the boundary was installed as, for example docker, kubernetes or linux.
      - `environment` string
      - `conformance_version` string
      - `placement` object: Stable placement only. It survives a restart and is what a policy means by an environment and a region.
        - `cluster_id` string
        - `namespace` string
        - `region` string
        - `workload_id` string
    - `workload` WorkloadSignal: What software proposed the action, as a runtime reported it. Decionis records the report and does not establish it: image digests, provenance attestations and publisher verification belong to the container and OCI tooling that produced them. Every field is optional but `provenance`, because a workload cannot be expressed without saying who reported it and how far that report goes.
      - `runtime` string
      - `artifact_type` string
      - `image` string
      - `digest` string
      - `publisher` string
      - `provenance` object, required
        - `source` string, required: Who reported it, for example docker, kubernetes or operator.
        - `trust_level` 'unverified' | 'supplied' | 'observed' | 'verified', required: How far the producer said its report goes. It is the producer's claim, recorded as such: Decionis neither raises nor lowers it. A policy that means the platform checked something matches on the decision's `runtime_attribution.platform_verified` instead, which Decionis computes and a caller cannot assert.
  - `downstream_target` ExecutionDownstreamTarget, required
    - `system` string, required
    - `operation` string, required
    - `environment` string
    - `endpoint` string
  - `policy_projection` ExecutionPolicyProjection: Exact policy-routing vocabulary committed into the intent. Protocol adapters use it when their evaluated decision type differs from the executable action type; legacy generic callers may omit it.
    - `decision_type` string, required
    - `transaction_type` string, nullable, required
    - `workflow_key` string, nullable, required
    - `channel` string, nullable, required
  - `expected_effect_digest` string: Digest-only commitment to the expected downstream state.
  - `intent_hash` string, required: SHA-256 of the UTF-8 canonical JSON ExecutionIntentBinding. Objects are recursively key-sorted using ECMAScript's default UTF-16 code-unit ordering and serialized with JSON.stringify semantics.
  - `mode` 'SHADOW' | 'PARALLEL' | 'ENFORCEMENT', required
  - `escalation` ManagedEscalationRequest: Requests Decionis-owned Presence orchestration. This object is outside the canonical ExecutionIntentBinding hash and is included in request replay validation. It is valid only in ENFORCEMENT mode.
    - `mode` 'MANAGED', required
    - `approver` union: Optional narrowing constraints. These values do not assign a role; effective identity and role are resolved from trusted tenant identity configuration and verified Presence evidence.
      - object
        - `principal_id` string, required
        - `role_id` string
      - object
        - `principal_id` string
        - `role_id` string, required
    - `verification_requirements` ManagedEscalationVerificationRequirements: Optional equal-or-stronger constraints applied to the policy-issued AuthorityRequirement. They can never downgrade policy requirements.
      - `methods` string[], required
      - `level` 'STANDARD' | 'HIGH_CONFIDENCE'
  - `executor` AuthorityExecutor: Who will carry out a granted action, and how it takes authority: a `dispatch` executor presents the execution token at the claim; a `permit` executor runs inside a platform that holds a single-use permit and reports its own native receipt. Delivery information only: never part of the canonical intent, its hash, or the grant's binding, and it changes nothing about the decision.
    - `platform` string, required
    - `style` 'dispatch' | 'permit', required
    - `version` string, required
  - `evidence` object
    - `humanApproval` union: A Presence receipt (bank-designated roles, verified with Presence) or a presence provider's attestation (verified against the key the organisation registered for it). Either is evidence for a fresh policy evaluation, never authority by itself.
      - PresenceHumanApprovalEvidence
        - `provider` 'presence', required
        - `requestId` string, required
        - `receiptDossierId` string, required
      - AttestedHumanApprovalEvidence: A presence provider's signed attestation that a person was present for this exact intent (for example, the cardholder tapping their own card), as a compact JWS whose payload is PresenceAttestationClaims.
        - `provider` 'attestation', required
        - `attestation` string, required
    - `signals` SignedSignalEvidence[]: Producers' signed standing signals about the subject, each verified against the producer's registered key (purpose `signed_signal`) or an admitted presence provider's JWKS, and written as facts under `agent_safe.signed_signals`. Bound to no intent; presented with or without a human approval, in any mode. Two under one `signal.name` are refused.
      - `token` string, required

## Response `200`

Bound policy decision; only ALLOW carries an execution token

- ExecutionAuthorityDecision
  - `decision_id` string, required
  - `chain_id` string, nullable, required
  - `status` 'ALLOW' | 'BLOCK' | 'ESCALATE' | 'REVIEW_REQUIRED' | 'ERROR', required
  - `should_execute` boolean, required
  - `authority_classification` 'AUTHORITATIVE' | 'OBSERVATIONAL', required: Authority possessed by an artifact, independent of its verdict. Only AUTHORITATIVE artifacts may become execution-eligible.
  - `execution_eligible` boolean, required: True only for an AUTHORITATIVE ALLOW carrying an exact-action ExecutionBinding and executable grant.
  - `execution_binding_digest` string, nullable, required
  - `reason_codes` string[], required
  - `action_hash` string, required
  - `policy_version` string, nullable, required
  - `mode` 'SHADOW' | 'PARALLEL' | 'ENFORCEMENT' | 'null', nullable, required
  - `execution_token` string, nullable, required: Present only when status is ALLOW and should_execute is true.
  - `execution_token_jti` string, nullable, required: Single-use identifier of the issued execution token.
  - `execution_token_key_id` string, nullable, required: Identifier of the key that signed the issued execution token.
  - `execution_token_expires_at` string, date-time, nullable, required
  - `dossier_id` string, nullable, required
  - `dossier_sha256` string, nullable, required
  - `dossier_url` string, nullable, required
  - `approval_request_id` string, nullable, required
  - `ledger_entry_id` string, nullable, required
  - `managed_escalation` ManagedEscalationReference: Non-authorizing status locator. It is not an ExecutionBinding, claim token, invitation, or executable capability.
    - `outcome` 'ESCALATE_PENDING' | 'ALLOW' | 'BLOCK' | 'ERROR', required
    - `escalation_id` string, required
    - `intent_id` string, uuid, required
    - `status` 'PENDING_PRESENCE' | 'PRESENCE_REQUESTED' | 'AWAITING_APPROVER' | 'PRESENCE_VERIFIED' | 'REAUTHORIZING' | 'GRANT_READY' | 'EXPIRED' | 'REJECTED' | 'BLOCKED' | 'CANCELLED' | 'FAILED', required
    - `expires_at` string, date-time, required
    - `reason_codes` string[], required
  - `verification` DecisionDossierVerificationEnvelope: The share-safe way to verify a Decision Dossier without an account: a page and an API URL carrying an expiring share-link capability (`?sig=`, `&exp=`) that gates access, and the pointers to the Ed25519 proof that establishes authenticity. The capability is an access gate, never proof; the signatures in the proof bundle are the proof.
    - `verification_page_url` string, uri, required: The public page that runs the verification for anyone who opens it.
    - `verification_url` string, uri, required: The public verify route, `/v1/public/decision-dossiers/{dossier_id}/verify`, with its capability.
    - `verification_api_path` string
    - `signature` string, required
    - `signature_algorithm` string
    - `signature_scheme` 'hmac-v1' | 'hmac-v2-org-scoped'
    - `link_expires_at` string, date-time, nullable
    - `link_exp` string, nullable: The expiry in epoch seconds, as it appears in the link.
    - `asymmetric_proof` object, nullable
    - `asymmetric_proof_bundle` object, nullable
  - `escalation_requirement` EscalationRequirement: Where an ESCALATE goes: which authority the policy requires (its kind and role, never a person) and who proves that person, by which method. The runtime holding the intent hands the cardholder's tap to the provider named here and resumes with the attestation; a bank role goes to Decionis Presence. Only a fresh evaluation with the proof as evidence can turn the hold into a grant.
    - `requirement_id` string, nullable, required: The issued Presence requirement's id when one was issued (a managed escalation); null for a direct one.
    - `expires_at` string, date-time, required
    - `selector` object, nullable, required
      - `kind` 'ROLE' | 'PRINCIPAL', required
      - `role_id` string
    - `verification` object, nullable, required
      - `provider` string, required: `decionis` for Decionis Presence; otherwise the admitted presence provider's id.
      - `methods` string[], required
      - `level` 'STANDARD' | 'HIGH_CONFIDENCE', required
  - `permit_id` string, uuid: Present only when the request named a `permit` executor and a grant was issued: the grant's jti (`execution_token_jti`), the `{grantId}` of `/v1/authority/grants/{grantId}`.
  - `intent_sha256` string: Present with `permit_id`: the intent hash (`action_hash`) as bare lowercase hex, written as `dossier_sha256` is.
  - `expires_at` string, date-time: Present with `permit_id`: when the grant stops being claimable (`execution_token_expires_at`).

## Other responses

- `400`: Structured API error
- `401`: Structured API error
- `403`: Structured API error
- `409`: Presence evidence, a presence attestation or a signed signal failed verification, MANAGED escalation was combined with human-approval evidence, or the idempotency key is already bound
- `429`: Structured API error
- `503`: Authority or grant store unavailable; no execution is authorized

---

[API](https://skmtc.dev/decionis/apis/decionis-policy-evaluation-api.md) · [All operations](https://skmtc.dev/decionis/apis/decionis-policy-evaluation-api/llms.txt) · [OpenAPI document](https://skmtc.dev/decionis/apis/decionis-policy-evaluation-api/revisions/357f5e459d0c?raw)
