Give agents a budget, not your card.
A mandate is a scope your customer approves once: how much per purchase, how much per day, which merchants and categories, and until when. AgentPay checks every agent payment against it before money moves.
- per_txn_max
- daily_max
- merchants · categories
- expires · revoke
- agent
- Travel Assistant · agent_9Xk2f1
- per_txn_max
- ₹15,000
- daily_max
- ₹40,000
- merchants
- allowlist · example
- expires
- 24h · auto-expires
categories
- travel
- food
- subscriptions
- electronics
- gambling
revoke DELETE /v1/mandates/mnd_a21f
Agents can decide. The permission model hasn’t caught up.
A saved card has no spending rules
A card on file can’t tell a ₹500 lunch order from a ₹50,000 laptop. Whatever the agent decides to buy, the card pays for.
Approving every payment defeats the agent
If each purchase waits for the customer to come back and confirm, the agent is just a slower checkout.
Disputes stall on a missing approval
Support can see the charge but not what the customer agreed to, so refunds and chargebacks turn into guesswork.
Approve once. Checked every time.
The customer sets the boundary. AgentPay holds the agent to it on every payment, and you can withdraw it with one call.
Limits set once
Your app proposes them; the customer approves
Agent shops
Picks the fare, the order or the renewal
Each payment checked
Before any money moves
- Allowed merchant
- Under the cap
- Mandate still live
- Risk score clears
Rail settles
UPI, card, wallet or netbanking
Off in one call
Any later payment is declined
Patterns teams build first.
Trip-budget booking
An agent books a fare inside a per-trip cap, travel category only.
- per_txn_max₹15,000
- categoriestravel
- expires72h
Node
Weekly grocery reorder
A repeat order to one merchant under a daily ceiling.
- merchantsexample
- daily_max₹3,000
- expires30d
Python
Voice bill pay
The caller confirms by voice; the agent pays inside their mandate.
- per_txn_max₹5,000
- step-upVoice ID
- railUPI
Node
Checkout inside a chat
An assistant pays from the conversation through AgentPay's MCP server.
- per_txn_max₹2,000
- merchantsexample
- expires1h
MCP
Hotel hold, final bill
Hold a ceiling at check-in, capture the real amount at checkout.
- per_txn_max₹20,000
- holdat check-in
- captureat checkout
cURL
Team licence renewals
Renew seats on a card; revoke the mandate when the owner leaves.
- categoriessoftware
- railcards
- revokeon offboarding
REST
Create, pay, revoke.
One scenario in four languages: a travel mandate capped per purchase and per day, a payment against it, then withdrawal.
- Create the mandate and send the customer to approve it
- Pay against it from the agent
- Revoke it when the job is done
// Illustrative — the mandate API shape may change before launch.
const mandate = await agentpay.mandates.create({
per_txn_max: 15000,
daily_max: 40000,
currency: "INR",
merchants: ["example"],
categories: ["travel"],
expires: "24h",
});
console.log(mandate.approval_url); // send to the customer; they approve once
const payment = await agentpay.pay({
amount: 12840, currency: "INR", merchant: "example", mandate: mandate.id,
});
console.log(payment.status); // "captured"
await agentpay.mandates.revoke(mandate.id); // DELETE /v1/mandates/{id}# Illustrative — the mandate API shape may change before launch.
mandate = agentpay.mandates.create(
per_txn_max=15000,
daily_max=40000,
currency="INR",
merchants=["example"],
categories=["travel"],
expires="24h",
)
print(mandate.approval_url) # send to the customer; they approve once
payment = agentpay.pay(
amount=12840, currency="INR", merchant="example", mandate=mandate.id,
)
print(payment.status) # "captured"
agentpay.mandates.revoke(mandate.id) # DELETE /v1/mandates/{id}// Illustrative — the mandate API shape may change before launch.
m, err := client.Mandates.Create(ctx, &agentpay.MandateParams{
PerTxnMax: 15000, DailyMax: 40000, Currency: "INR",
Merchants: []string{"example"},
Categories: []string{"travel"},
Expires: "24h",
})
if err != nil {
return err
}
notifyCustomer(m.ApprovalURL) // they approve once
p, err := client.Pay(ctx, &agentpay.PaymentParams{
Amount: 12840, Currency: "INR", Merchant: "example", Mandate: m.ID,
})
if err != nil {
return err
}
if p.Status != "captured" {
return fmt.Errorf("payment %s", p.Status)
}
return client.Mandates.Revoke(ctx, m.ID) // DELETE /v1/mandates/{id}# Illustrative — the mandate API shape may change before launch.
curl https://api.agentpay.dev/v1/mandates \
-H "Authorization: Bearer sk_test_…" \
-d per_txn_max=15000 -d daily_max=40000 -d currency=INR \
-d "merchants[]=example" -d "categories[]=travel" \
-d expires=24h
# → { "id": "mnd_a21f", "approval_url": "…" }
curl https://api.agentpay.dev/v1/payments \
-H "Authorization: Bearer sk_test_…" \
-H "Idempotency-Key: 6f1c-a21f" \
-d amount=12840 -d currency=INR -d merchant=example -d mandate=mnd_a21f
# → { "id": "pay_9Xk2f1c4", "status": "captured", "mandate": "mnd_a21f" }
curl -X DELETE https://api.agentpay.dev/v1/mandates/mnd_a21f \
-H "Authorization: Bearer sk_test_…"Wherever your agent already runs.
Mandates are available wherever an agent can make a call: over MCP, over REST, or from a typed SDK.
MCP server
REST API
Webhooks
Node.js
Python
Voice SDK
UPI
Cards
Wallets
Netbanking
NPCI
UPI and retail payments network
Yes Bank
Banking and settlement
Juspay
Payments orchestration
Any agent that can reach an MCP server or make an HTTP request can hold a mandate.
Card data stays off your servers
The agent holds a mandate ID; card data stays off your servers.
Every decision comes back with the payment
Each response carries the policy result, the risk score and the mandate it ran under.
Safe to retry
Idempotency keys make retries harmless, and webhooks are retried until you acknowledge them.
Test before money moves
Sandbox keys run the full mandate flow without touching a real account.
Questions teams ask first.
What is a mandate?
A set of spending limits your customer signs off on for one agent: the most it can pay at once, the most per day, where it can pay, and when the permission ends. The agent holds a mandate ID (mnd_…), never card details.
Who approves it, and how often?
Your customer, once, through the approval link returned when the mandate is created. After that the agent pays without asking again, as long as each payment fits.
What if a payment falls outside the scope?
It is declined, and the decline comes back in the payment response, so the agent can tell the customer instead of retrying.
How do I revoke one?
DELETE /v1/mandates/{id}. Any payment the agent attempts afterwards is declined at authorization.
Does the check add a round trip?
No. Policy, risk and mandate checks run inside the payment call, and the response reports latency_ms.
Which payment methods can a mandate cover?
The mandate governs the agent, not the instrument; the rail is chosen per payment across UPI, cards, wallets and netbanking.
Can I test without moving money?
Yes. Sandbox keys (sk_test_…) run the whole flow: create, approve, pay, decline and revoke.
Does it work with my agent framework?
If your agent can reach an MCP server or make an HTTP request, yes. Payments are available over MCP and REST, with typed SDKs for Node and Python.
Rolling mandates out across a fleet of agents?
Tell us what your agents buy. We’ll help you set the limits and get you sandbox keys.
- Per-agent per-payment and daily caps
- Merchant allowlists and category controls
- Mandates that end on a date you set
- One-call revocation
- Policy and risk decision returned on every payment
- Idempotent endpoints
- Webhooks retried until acknowledged
- No card data on your servers
- Voice step-up with Voice ID