Skip to navigation

Decide a write

API key required. This is the core of Writ — call it before the agent performs any consequential write. The check matches the request against the tenant’s verb policy and any live grants on five fields: sponsor, agent, verb, target, purpose. All five must match a grant for it to apply.

Decision flow, in order:

  1. The request names an environment outside dev, staging, prod → DENY, fail closed. The request is never silently evaluated against a different scope; the denial is receipted with no policy attribution.
  2. The principal (sponsorId + agentId) was revoked → DENY (“principal revoked by sponsor”), even under an allow policy.
  3. The verb’s effective policy mode is allow → ALLOW.
  4. The verb’s effective policy mode is deny → DENY.
  5. A live, unspent grant matches all five fields → ALLOW and the grant is spent (single-use).
  6. The mode is step_up with no live grant → STEP_UP: a human sponsor approves via POST /v1/grants, then the agent re-checks.
  7. Otherwise (require_grant with no live grant) → DENY.

The effective policy resolves per-verb by precedence: the calling API key’s per-principal override first, then the named environment’s per-environment override (when environment is given and known), then the tenant default. Overrides are sparse — a verb an override doesn’t name inherits downward. Every receipt records the policyId and policyVersion of the policy that supplied the verb’s mode.

Custom-verb aliases resolve before policy lookup: if the verb names a deprecated custom verb (a rename alias) or differs only in case from the registry, the check runs against the resolved verb and the receipt carries resolvedVerb — the verb the policy was actually evaluated for. verb always echoes exactly what the caller sent.

Every check writes a receipt — including DENYs. The refusal itself is auditable. Decisions are returned as HTTP 200 even when the decision is DENY or STEP_UP; only auth, quota, and malformed requests change the status code.

On ALLOW, the response is the receipt plus authToken: a 90-second HMAC-signed token (writ_at_...) bound to this exact sponsor/agent/verb/target/purpose, and tokenExpiresIn. The action adapter enforces the token at the point of action; verify it against what the agent actually did with POST /v1/tokens/verify to catch purpose drift. The token is returned to the caller only — it is never stored in the receipt.

The free tier is 10,000 receipts per tenant per calendar month. Past that, checks return 402 until the quota resets or a payment method is added.

Authentication

AuthorizationBearer

Bearer authentication of the form Bearer <token>, where token is your auth token.

Request

This endpoint expects any.

Response

ALLOW, DENY, or STEP_UP, plus a receipt. On ALLOW the response also carries authToken, a 90-second HMAC-signed token bound to this exact sponsor/agent/verb/target/purpose, and tokenExpiresIn. STEP_UP means the tenant policy requires a human sponsor to approve; the sponsor mints a grant via POST /v1/grants and the agent re-checks.

Errors

400
Bad Request Error
401
Unauthorized Error
402
Payment Required Error