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 principal (sponsorId + agentId) was revoked → **DENY** ("principal revoked by sponsor"), even under an allow policy. 2. The verb's policy mode is `allow` → **ALLOW**. 3. The verb's policy mode is `deny` → **DENY**. 4. A live, unspent grant matches all five fields → **ALLOW** and the grant is spent (single-use). 5. The mode is `step_up` with no live grant → **STEP_UP**: a human sponsor must approve via `POST /v1/grants`, then the agent re-checks. 6. Otherwise (`require_grant` with no live grant) → **DENY**. **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 commit time; 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 1,000 receipts per tenant per calendar month. Past that, checks return **402** until the quota resets or a payment method is added.

Authentication

AuthorizationBearer
Your Writ API key (writ_...) as an Authorization Bearer header. The sponsor token (writ_sp_...) is a separate credential used only for grants, revokes, and reinstate — it goes in the same Authorization header on those endpoints. In the Fern docs playground, paste the key here; it is stored in this browser only.

Request

This endpoint expects an object.
sponsorIdstringRequired

The human sponsor on whose behalf the agent acts (e.g. s_42).

agentIdstringRequired

The agent performing the write (e.g. support-agent-07).

verbstringRequired

The consequential action (e.g. refund, provision, admit).

targetstringRequired

What the action applies to (e.g. order #88412).

purposestringRequired

Why — the stated intent, bound into the auth token (e.g. Refund order #88412, close ticket #2210).

ttlSecondsintegerOptional

Grants only: how long the grant lives. Default 90, min 1, max 3600.

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