Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.usemandate.io/llms.txt

Use this file to discover all available pages before exploring further.

The policy engine is the enforcement core of Mandate. It runs a sequential series of checks — agent status, mandate validity, merchant allowlist, category allowlist, per-transaction limit, and total budget — and returns a machine-readable decision. Two endpoints expose the engine: POST /v1/policy/evaluate for full evaluation (which also creates a transaction record), and POST /v1/verify-agent for a read-only pre-flight check.

Policy checks

The engine runs these checks in order. The first failure terminates evaluation and returns the corresponding reason code.
#CheckFailure reason code
1Agent existsagent_revoked
2Agent status is "active"agent_revoked
3Mandate exists and belongs to the agentmandate_expired
4Mandate status is "active"mandate_expired
5Mandate expires_at is in the futuremandate_expired
6merchant_domain is in allowed_sellers, or allowlist contains "*"merchant_not_allowed
7category is in allowed_categories, or allowlist contains "*", or allowlist is emptymerchant_not_allowed
8amountmax_spend_per_transactionamount_exceeds_per_transaction_limit
9spent_total + amountmax_spend_totaltotal_budget_exceeded
An empty allowed_categories array ([]) means no category restriction — all categories are permitted. Pass ["*"] or an explicit list to enforce category-level control.

Evaluate policy


POST /v1/policy/evaluate
Runs all policy checks for a proposed payment and records the outcome. If approved, a pending transaction is created and transitions to approved. If denied, the transaction transitions to denied and the endpoint returns HTTP 402. The Mandate SDK calls this endpoint automatically as part of the fetchWithPayment() flow. You can also call it directly for custom payment orchestration or to pre-validate a request before generating a proof. Request body
agent_id
string
required
The agent attempting the payment.
mandate_id
string
required
The mandate authorizing this payment.
merchant_domain
string
required
The domain of the merchant being paid, e.g. "api.example.com". Checked against the mandate’s allowed_merchants list.
amount
string
required
The payment amount as a decimal string, e.g. "0.10". Checked against max_spend_per_transaction and the remaining budget.
currency
string
default:"USDC"
The currency for this payment. Currently "USDC" only.
resource_url
string
required
The full URL of the resource being purchased, e.g. "https://api.example.com/data/companies/AAPL". Stored on the resulting transaction record.
category
string
Optional resource category label, e.g. "data". Checked against the mandate’s allowed_categories list.
curl --request POST https://api.kya.dev/v1/policy/evaluate \
  --header "Authorization: Bearer ky_sand_••••••••••••••••" \
  --header "Content-Type: application/json" \
  --data '{
    "agent_id": "agent_abc123",
    "mandate_id": "mandate_xyz789",
    "merchant_domain": "api.example.com",
    "amount": "0.10",
    "currency": "USDC",
    "resource_url": "https://api.example.com/data/companies/AAPL",
    "category": "data"
  }'
Response 200 — approved
decision
string
required
"approved" when all policy checks pass.
reason_code
string
required
"within_policy" when approved.
reason_detail
string
Human-readable explanation. null when approved.
agent_id
string
required
The agent ID from the request.
mandate_id
string
required
The mandate ID from the request.
transaction_id
string
required
The ID of the transaction record created for this evaluation.
Example response — approved
{
  "decision": "approved",
  "reason_code": "within_policy",
  "reason_detail": null,
  "agent_id": "agent_abc123",
  "mandate_id": "mandate_xyz789",
  "transaction_id": "transaction_def456"
}
Response 402 — denied
Example response — denied
{
  "decision": "denied",
  "reason_code": "amount_exceeds_per_transaction_limit",
  "reason_detail": null,
  "agent_id": "agent_abc123",
  "mandate_id": "mandate_xyz789",
  "transaction_id": "transaction_def456"
}
Possible reason_code values on denial: agent_revoked, mandate_expired, merchant_not_allowed, amount_exceeds_per_transaction_limit, total_budget_exceeded.

Verify agent


POST /v1/verify-agent
Runs the same policy checks as POST /v1/policy/evaluate but does not create a transaction record or charge the mandate. Use this for pre-flight checks — for example, to validate that an agent’s mandate is still active and has sufficient budget before starting a multi-step workflow. Returns HTTP 200 when the agent is authorized and 403 when denied. Request body Same fields as POST /v1/policy/evaluate.
agent_id
string
required
The agent to verify.
mandate_id
string
required
The mandate to check authorization against.
merchant_domain
string
required
The merchant domain to validate against the allowlist.
amount
string
required
The intended payment amount as a decimal string.
currency
string
default:"USDC"
The currency for the intended payment.
resource_url
string
required
The URL of the resource the agent intends to access.
category
string
Optional resource category to check against the mandate’s category allowlist.
curl --request POST https://api.kya.dev/v1/verify-agent \
  --header "Authorization: Bearer ky_sand_••••••••••••••••" \
  --header "Content-Type: application/json" \
  --data '{
    "agent_id": "agent_abc123",
    "mandate_id": "mandate_xyz789",
    "merchant_domain": "api.example.com",
    "amount": "0.10",
    "currency": "USDC",
    "resource_url": "https://api.example.com/data/companies/AAPL",
    "category": "data"
  }'
Response 200 — authorized
verified
boolean
required
true when the agent exists and is active.
authorized
boolean
required
true when all policy checks pass.
payment_ready
boolean
required
true when the agent is ready to make a payment under this mandate.
agent
object
required
mandate
object
required
risk
object
required
recommendation
string
required
"accept" when authorized, "deny" when not.
reason_code
string
required
"within_policy" when authorized. One of agent_revoked, mandate_expired, merchant_not_allowed, amount_exceeds_per_transaction_limit, total_budget_exceeded when denied.
Example response — authorized
{
  "verified": true,
  "authorized": true,
  "payment_ready": true,
  "agent": {
    "id": "agent_abc123",
    "name": "Research Assistant",
    "capabilities": ["data-fetch", "financial-research"],
    "status": "active"
  },
  "mandate": {
    "id": "mandate_xyz789",
    "purpose": "Financial data research",
    "currency": "USDC",
    "remaining_budget": "9.50",
    "expires_at": "2024-12-31T23:59:59+00:00"
  },
  "risk": {
    "score": 0,
    "flags": []
  },
  "recommendation": "accept",
  "reason_code": "within_policy"
}
Response 403 — denied Same structure as the 200 response but with authorized: false, payment_ready: false, recommendation: "deny", and the appropriate reason_code.
Example response — denied
{
  "verified": false,
  "authorized": false,
  "payment_ready": false,
  "agent": {
    "id": "agent_abc123",
    "name": "unknown",
    "capabilities": [],
    "status": "unknown"
  },
  "mandate": {
    "id": "mandate_xyz789",
    "purpose": "",
    "currency": "USDC",
    "remaining_budget": "0",
    "expires_at": ""
  },
  "risk": { "score": 0, "flags": [] },
  "recommendation": "deny",
  "reason_code": "agent_revoked"
}