POST /v1/check
The core endpoint. Call this before your agent touches user data. A check accepts one or more scopes and returns one decision plus one receipt envelope per scope.
See Decisions and Attributes for the full list of supported verbs, reason codes, request attributes, and scope constraints.
Request
POST /v1/check
Authorization: Bearer allowly_l1_s001_...
Content-Type: application/json
{
"authorization_id": "auth_01HXZ2A0K1L2M3N4P5Q6R7S8T9",
"scopes": ["contact.enrich", "outreach.send"],
"resource": "edge:emp_8821:conn_9f2a",
"session_id": "sess_7f2",
"context": {
"initiated_by": "user",
"origin": "chat"
}
}
| Field | Required | Description |
|---|---|---|
authorization_id | yes | The authorization authorizing this scope. Returned when you created the authorization via POST /v1/authorizations. |
scopes | yes | Array of permission names being checked (e.g. email.send, contact.enrich). Each must match a scope on the authorization. Empty arrays and duplicate scopes are rejected. |
resource | no | Identifier of the action target. Omit or use null if the action has no specific resource. |
session_id | no | Customer-assigned session label, recorded in the receipt for later querying. |
estimated_cost_micros | required for budgeted authorizations | Estimated action cost in micro-USD. Budgeted checks currently support exactly one scope. See Budget Gate. |
context | no | Opaque object of additional facts, recorded in the receipt. |
user_id and agent_id are not in the request — they are looked up from the authorization. This prevents spoofing.
Response — allow
{
"authorization_id": "auth_01HXZ2A0K1L2M3N4P5Q6R7S8T9",
"user_id": "emp_8821",
"agent_id": "referral_outreach",
"authorization_expires_at": "2026-12-31T00:00:00Z",
"policy_version": "2026-04-17.1",
"results": {
"outreach.send": {
"decision": "allow",
"reason": "authorization_granted_scope_active",
"receipt": {
"status": "pending",
"receipt_id": "rcp_01HXZ2B...",
"ready_at_estimate": "2026-04-21T14:32:18.482Z",
"url": "https://api.allowly.ai/v1/receipts/rcp_01HXZ2B..."
}
}
}
}
Response — deny
{
"authorization_id": "auth_01HXZ2A...",
"user_id": "emp_8821",
"agent_id": "referral_outreach",
"authorization_expires_at": "2026-12-31T00:00:00Z",
"policy_version": "2026-04-17.1",
"results": {
"outreach.send": {
"decision": "deny",
"reason": "authorization_revoked",
"receipt": {
"status": "pending",
"receipt_id": "rcp_01HXZ2C...",
"ready_at_estimate": "2026-04-21T14:32:18.482Z",
"url": "https://api.allowly.ai/v1/receipts/rcp_01HXZ2C..."
}
}
}
}
Every denial is also receipted — the signed record of what was blocked is audit evidence too.
Response — budget evaluated
If the authorization has a budget, each evaluated result includes a budget block. An over-budget action returns deny with reason: "budget_exceeded".
{
"authorization_id": "auth_01HXZ2A...",
"user_id": "emp_8821",
"agent_id": "referral_outreach",
"authorization_expires_at": "2026-12-31T00:00:00Z",
"policy_version": "2026-04-17.1",
"results": {
"llm.enrich": {
"decision": "allow",
"reason": "authorization_granted_scope_active",
"budget": {
"limit_micros": 50000000,
"spent_micros": 120000,
"estimated_cost_micros": 24000,
"spent_after_micros": 144000
},
"receipt": {
"status": "pending",
"receipt_id": "rcp_01HXZ2C...",
"ready_at_estimate": "2026-04-21T14:32:18.482Z",
"url": "https://api.allowly.ai/v1/receipts/rcp_01HXZ2C..."
}
}
}
}
Response — confirm
{
"authorization_id": "auth_01HXZ2A...",
"user_id": "emp_8821",
"agent_id": "referral_outreach",
"authorization_expires_at": "2026-12-31T00:00:00Z",
"policy_version": "2026-04-17.1",
"results": {
"outreach.send": {
"decision": "confirm",
"reason": "scope_requires_user_confirmation",
"confirm_nonce": "cnf_01HXZ...",
"confirm_expires_at": "2026-04-21T14:47:17.482Z",
"confirm_prompt_hint": "outreach.send",
"receipt": {
"status": "pending",
"receipt_id": "rcp_01HXZ2D...",
"ready_at_estimate": "2026-04-21T14:32:18.482Z",
"url": "https://api.allowly.ai/v1/receipts/rcp_01HXZ2D..."
}
}
}
}
Show the user a prompt using confirm_prompt_hint, then call POST /v1/confirmations/{nonce} with their response.
Response — escalate
{
"authorization_id": "auth_01HXZ2A...",
"user_id": "emp_8821",
"agent_id": "referral_outreach",
"authorization_expires_at": "2026-12-31T00:00:00Z",
"policy_version": "2026-04-17.1",
"results": {
"candidate.delete": {
"decision": "escalate",
"reason": "escalation_required",
"escalation": {
"escalation_id": "esc_01HXZ...",
"status": "pending",
"escalation_to": "compliance",
"expires_at": "2026-04-22T14:32:17.482Z"
},
"escalation_id": "esc_01HXZ...",
"escalation_to": "compliance",
"escalation_expires_at": "2026-04-22T14:32:17.482Z",
"receipt": {
"status": "pending",
"receipt_id": "rcp_01HXZ2E...",
"ready_at_estimate": "2026-04-21T14:32:18.482Z",
"url": "https://api.allowly.ai/v1/receipts/rcp_01HXZ2E..."
}
}
}
}
Route the request to the configured approver, then call POST /v1/escalations/{escalation_id}/resolve. If approved, re-call /check with the same authorization, scope, and resource — the next result returns allow once.
Decision values
For the complete reason-code table, see Decisions and Attributes.
| Decision | Reason codes |
|---|---|
allow | authorization_granted_scope_active |
deny | authorization_not_found, authorization_revoked, authorization_expired, scope_not_authorized, rate_limit_exceeded, resource_tombstoned, budget_exceeded, escalation_rejected |
confirm | scope_requires_user_confirmation |
escalate | escalation_required |
The receipt envelope
Each item in results has a receipt field. The default response is a pending envelope:
{
"status": "pending",
"receipt_id": "rcp_01HXZ2B...",
"ready_at_estimate": "2026-04-21T14:32:18.482Z",
"url": "https://api.allowly.ai/v1/receipts/rcp_01HXZ2B..."
}
The signed receipt is produced asynchronously. Fetch it at url when you need the audit artifact. See Receipts.
Inline signing (?wait=true)
Add ?wait=true to block up to 5 seconds for signing to complete. Returns the signed shape if it finishes in time, otherwise falls back to pending. Use this only when you need synchronous audit evidence.
POST /v1/check?wait=true
Latency
The decision is immediately usable. Receipt signing happens off the critical path.