Convert user intent into signed mandates and verify consequential agent actions against mandate, policy and approvals.
Production API: https://agentmandate-api.com
Get a free API key · Documentation · Pricing · Status
Free tier: 500 verified actions/month. No card required. Paid plans from $299/month.
Request a key. The token arrives by email; exchange it for the key, which is shown once.
curl -X POST https://agentmandate-api.com/v1/keys \
-H 'content-type: application/json' \
-d '{"email": "you@example.com"}'Then call the API:
curl -X POST https://agentmandate-api.com/v1/mandates \
-H "Authorization: Bearer $KEY" \
-H 'content-type: application/json' \
-d '{"principal":"user_8814","agent":"agent_procurement_v3",
"expiresAt":"2026-12-31T23:59:59Z","currency":"USD",
"totalSpendCapMinor":500000,
"grants":[{"action":"payments.transfer","resources":["vendor.acme"],
"maxAmountMinor":100000,"approvalRequiredAboveMinor":25000}]}'Every endpoint below has a runnable playground on the documentation page.
| Endpoint | Auth | Description |
|---|---|---|
GET /health |
public | Liveness and deployed version |
GET / |
public | Service index — endpoints, auth and error format |
POST /v1/mandates |
API key | Issue a signed mandate |
POST /v1/verify |
API key | Verify proposed actions against a mandate |
POST /v1/mandates/{id}/revoke |
API key | Revoke a mandate |
GET /v1/revocations |
API key | List the mandates you have revoked |
POST /v1/demo/verify |
public | Public demo — issue and verify in one call, without a key |
GET /v1/violations |
public | Every violation code the engine can return |
POST /v1/checkout |
public | Start a hosted Square checkout for a paid tier |
POST /v1/keys |
public | Request a free sandbox API key (sends a verification email) |
GET /v1/keys |
API key | List your API keys for this API |
POST /v1/keys/claim |
public | Exchange an emailed claim token for the API key |
POST /v1/keys/{id}/revoke |
API key | Revoke one of your API keys |
POST /v1/keys/{id}/rotate |
API key | Replace one of your API keys with a new secret |
GET /v1/usage |
API key | Your consumption and remaining allowance for this period |
GET /v1/subscription |
API key | Your current plan, billing window and available changes (dashboard session required) |
POST /v1/subscription/plan |
API key | Upgrade or downgrade to another plan (dashboard session required) |
POST /v1/subscription/cancel |
API key | Cancel this plan and end metered access (dashboard session required) |
GET /v1/invoices |
API key | Every invoice issued against this account, newest first (dashboard session required) |
GET /v1/payments |
API key | Every payment attempted against this account and how it went (dashboard session required) |
The full machine-readable contract is openapi.json, generated
from the deployed route table rather than maintained by hand. A
Postman collection is included.
Python — sdk/python
from agent_mandate import AgentMandate
client = AgentMandate() # reads AGENT_MANDATE_API_KEY
signed = client.issue_mandate(
principal="user_8814",
agent="agent_procurement_v3",
expires_at="2026-12-31T23:59:59Z",
currency="USD",
total_spend_cap_minor=500_000,
grants=[{
"action": "payments.transfer",
"resources": ["vendor.acme"],
"maxAmountMinor": 100_000,
"approvalRequiredAboveMinor": 25_000,
}],
)
res = client.verify(signed, {
"agent": "agent_procurement_v3",
"action": "payments.transfer",
"resource": "vendor.acme",
"amountMinor": 30_000,
"currency": "USD",
})
receipt = res["receipts"][0]
if receipt["decision"] == "allow":
do_transfer()
elif receipt["decision"] == "requires_approval":
queue_for_human(receipt)
else:
log_denied(receipt["violations"])TypeScript — sdk/typescript
import { AgentMandate } from './agent-mandate.js'
const client = new AgentMandate() // reads AGENT_MANDATE_API_KEY
const signed = await client.issueMandate({
principal: 'user_8814',
agent: 'agent_procurement_v3',
expiresAt: '2026-12-31T23:59:59Z',
currency: 'USD',
totalSpendCapMinor: 500_000,
grants: [{
action: 'payments.transfer',
resources: ['vendor.acme'],
maxAmountMinor: 100_000,
approvalRequiredAboveMinor: 25_000,
}],
})
const { receipts } = await client.verify(signed, {
agent: 'agent_procurement_v3',
action: 'payments.transfer',
resource: 'vendor.acme',
amountMinor: 30_000,
currency: 'USD',
})
switch (receipts[0].decision) {
case 'allow': return doTransfer()
case 'requires_approval': return queueForHuman(receipts[0])
case 'deny': return logDenied(receipts[0].violations)
}Every failure returns the same shape. Branch on code, which is a stable enum;
message is for humans and may change.
{"error": {"code": "invalid_api_key", "message": "...", "requestId": "0f3c8b12-…"}}requestId appears on every response and in the x-request-id header. Quote it
in any support request.
Open an issue in this repository, or see the contact route at https://agentmandate-api.com/docs.

