Product
One call from the agent.
An agent asks to pay. Enruta checks the policy your controller signed, issues a signed mandate or routes the request to a named person, executes on your own rail, and seals one record of every payment.
How it works
Five steps, one payment. Click through, or use the arrow keys.
> request_payment
agent=agt_procurement_02 payee=store.enruta.ai (verified)
amount=168.40 USD purpose="20 reams A4 paper, 1 stapler"
checkout=ucp:chk_8f3… evidence=[quote sha256:…] idempotency=a3c9…
Six moments
What must be true at each step, and what Enruta holds.
1
Consent
A bounded authority is delegated to a named agent.
holds: policy · mandate
2
Identity
The agent shows who it is and whose authority it carries.
holds: attestation
3
Decision
The request is checked against the policy, inside the budget.
holds: decision · inputs
4
Execution
The mandate becomes a control and a licensed rail moves the money.
holds: instruction · receipt
5
Post-purchase
Declines, refunds and disputes are handled with the mandate as evidence.
holds: dispute file
6
Reconciliation
Settlement is matched and the record is sealed for the audit window.
holds: sealed record
Decide
A policy your controller signed, evaluated in order, reserved atomically.
Try the sample policy. Change the payee, the amount or the category and watch the decision, the reasons and what would be compiled onto the card.
decision
step_up
approval_requiredabove $150: a named person must sign
approval: {
required_from: "usr_controller", method: "passkey",
binds: "sha256:<request hash>", expires_in: "15m"
}
mandate: null // issued after the signatureExecute
The mandate becomes the control your rail already understands.
Enruta decides first, then compiles the decision into the rail’s own control. The rail moves the money on your account. Enruta never does.
The mandate becomes
A single-use virtual card on your own Stripe account: amount equal to the mandate, the payee as the allowed merchant, expiry equal to the mandate’s. The real-time authorization request is answered against the mandate inside the two-second window.
The card token reaches the payee. The card number never reaches the agent and is never stored by Enruta.
// on allow — on the customer's Stripe account, with a key the administrator scoped
issuing.cards.create({
cardholder: "ich_agent_procurement_02",
type: "virtual",
spending_controls: {
spending_limits: [{ amount: 16840, interval: "per_authorization" }],
allowed_merchant_countries: ["US"],
},
metadata: { mandate: "mnd_7c2a…d1f0", agent: "agt_procurement_02" },
})
// issuing_authorization.request → answered in 41 ms
{ "approved": true, "metadata": { "mandate": "mnd_7c2a…d1f0" } }The mandate becomes
A spend limit for the mandate’s amount and purpose, with the merchant and category restrictions the policy allows; the virtual card is issued against it.
Enruta matches the posted transaction back to the mandate after it lands.
POST /developer/v1/funds
{
"display_name": "mnd_7c2a…d1f0 · office supplies",
"spending_restrictions": {
"limit": { "amount": 16840, "currency_code": "USD" },
"transaction_amount_limit": { "amount": 16840, "currency_code": "USD" },
"allowed_vendors": ["vendor_store_enruta"],
"lock_date": "2026-11-30T18:18:10Z"
}
}The mandate becomes
A virtual card with a spend limit equal to the mandate, on a cardholder your administrator created in Mercury.
Transactions are read back to fill the record’s outcome.
POST /api/v1/cards
{
"userId": "usr_agent_procurement_02",
"type": "virtual",
"kind": "debit",
"spendLimit": { "amountCents": 16840, "interval": "total" },
"nickname": "mnd_7c2a…d1f0"
}The mandate becomes
For invoices, an approval scoped to one bill from an approver identity your administrator assigned to Enruta. Enruta reads with an auditor-role user and writes only the approval.
The approval, the approver and the mandate land in the record; the ACH or check runs on Bill.com as before.
approve(bill = "INV-4471", approver = "enruta-approver",
mandate = "mnd_…", amount = 13200.00)
// everything outside the mandated batch stays human-releasedThe mandate becomes
For merchants on the Universal Commerce Protocol, the mandate is the `ap2.checkout_mandate` proof the merchant requires before it completes the checkout. The merchant's consent object is kept in the record by digest.
The same record fields fill from a UCP checkout as from a card authorization.
complete_checkout({
id: "chk_8f3…",
meta: { "idempotency-key": "a3c9…" },
payment: {
ap2: { checkout_mandate: "<signed mandate bound to chk_8f3… at 168.40 USD>" },
handler_id: "com.google.pay" // or dev.shopify.card — never a raw PAN
}
})Prove
One file per payment. Verifiable in 2033 without us.
Sixteen core fields that AP2 mandates, ACP allowances, UCP consent objects, x402 and MPP receipts, card-issuer authorizations and finance-system exports all map into, plus six addendum fields for the rails procurement pays on.
Canonicalized, hashed, chained per customer, rolled into a daily root, time-stamped by public authorities. Everything that changes after sealing lives in a companion bundle, so a record can be renewed for seven years without being touched.
$ npx enruta-verify rec_01J9Q2W6G5X8ZK3R7T1V9M4N2B.json
enruta-verify 0.1.0
canonical form ok
seal ok sha256:b0d4…71c9
chain ok prev rec_01J9Q2VZ…
timestamps ok 4 of 4 proofs valid
keys ok snapshot 2026-09
PASSReconcile
Joined per payment, exceptions surfaced weekly.
- credential→
- authorization→
- posted transaction→
- receipt→
- ledger
The weekly report has fixed fields: payment, bill or purchase order, vendor, amount, rail, agent task, policy version, decision, exception code, approval and release events with their actors, release method, agreement with the human outcome, record hash and verifier status. Your controller signs it; your auditor can re-run it.
Where it runs
The same five tools in every host.
The plugin bundles the MCP server, the enruta-pay skill and a hook that blocks checkout calls without a mandate.
/plugin marketplace add enruta-ai/claude-plugin
/plugin install enruta@enrutaSettings → Connectors → Add custom connector, then sign in with your Enruta account.
https://mcp.enruta.ai/mcpDeveloper mode under Settings → Security and login, then add a plugin pointing at the MCP server. Plus, Pro, Business or Enterprise.
https://mcp.enruta.ai/mcpOne command. The agent key comes from an environment variable, never from the config file.
codex mcp add enruta --url https://mcp.enruta.ai/mcp --bearer-token-env-var ENRUTA_AGENT_KEYStreamable HTTP with a bearer header.
{
"mcpServers": {
"enruta": {
"url": "https://mcp.enruta.ai/mcp",
"headers": { "Authorization": "Bearer ${ENRUTA_AGENT_KEY}" }
}
}
}What Enruta is not
- Not a processor. Money moves on the rail you already have.
- Not a wallet. Enruta holds no balances and no card numbers.
- Not a percentage. Priced per sealed record, never in basis points of your flow.
Working with the first design partners.
A small number of finance teams and agent vendors are shaping the first records with us. If your agents already pay, or are about to, write to us.
hello@enruta.ai