AgentPay API
Issue scoped wallets to autonomous agents. Charge from those wallets in real time, with hard policy guarantees and human-in-the-loop escalations.
Quick start
Get your API key
Issue a wallet
curl -X POST https://agentpay.dev/api/public/v1/wallets \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "agent_research_001",
"budget": { "amount": 10.00, "currency": "USD" },
"policy": {
"max_per_tx": 0.50,
"allowed_categories": ["llm_api", "search"],
"escalate_if_single_tx_exceeds": 1.00,
"escalate_if_cumulative_exceeds": 8.00
},
"expires_in": "24h"
}'{
"wallet_id": "wlt_01J8X3A1B2C4D5E6F",
"token": "ap_live_4f9a...c3d2",
"balance": 10.00,
"expires_at": "2026-06-10T14:00:00Z"
}Charge the wallet (from your agent)
curl -X POST https://agentpay.dev/api/public/v1/charge \
-H "Authorization: Bearer WALLET_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"vendor": "openai",
"amount": 0.003,
"currency": "USD",
"description": "GPT-4o completion — 1,847 tokens",
"category": "llm_api"
}'{
"status": "approved",
"transaction_id": "txn_01J8X4K2M9N3P5Q7R",
"amount": 0.003,
"remaining_balance": 9.997
}Monitor in the dashboard
Authentication
AgentPay uses two distinct bearer token types.
| Token type | Prefix | Used for |
|---|---|---|
| API key | ap_live_ / ap_test_ | Issuing wallets, dashboard API |
| Wallet token | ap_wallet_ | Charging from an agent |
API keys are created in Settings → API Keys. Wallet tokens are returned once at wallet creation. Both are bearer tokens passed in the Authorization header.
Test mode
Keys prefixed with ap_test_ operate against a sandbox ledger. No real funds are moved, escalations auto-approve after 30 seconds, and rate limits are relaxed. Use test mode in CI and during agent development.
Charge a wallet
Headers:
- Authorization: Bearer <wallet_token>
- Idempotency-Key: <uuid> (recommended)
| Field | Type | Required | Description |
|---|---|---|---|
| vendor | string | Yes | Vendor identifier, e.g. "openai" |
| amount | number | Yes | USD amount, up to 6 decimal places |
| currency | string | Yes | "USD" only in V1 |
| description | string | Yes | Human-readable. Shown in audit log. |
| category | string | Yes | llm_api, search, data, storage, external_api |
| metadata | object | No | Stored for audit. Not evaluated. |
Response codes
| HTTP | status | Meaning |
|---|---|---|
| 200 | approved | Charge processed, balance debited |
| 202 | escalated | Exceeds threshold, pending principal approval |
| 400 | error | Invalid request (missing fields, bad amount) |
| 401 | error | Token invalid, expired, or revoked |
| 402 | blocked | Policy violation (over limit, wrong category) |
| 429 | error | Rate limit exceeded |
| 500 | error | Internal error — retry with backoff |
For 402 blocked responses, the body includes a reason code:
EXCEEDS_MAX_PER_TXINSUFFICIENT_BALANCEINVALID_CATEGORYVENDOR_BLOCKEDHARD_CAP_EXCEEDEDIdempotency
Pass a unique Idempotency-Key header on every charge request. If your agent retries after a timeout, AgentPay returns the original response without double-charging.
Keys are UUIDs. Results are cached for 24 hours.
Rate limits
Two limits apply per request:
- Per wallet token: 60 requests / minute
- Per principal (aggregate): 500 requests / minute across all wallets
Exceeding either limit returns 429 with a Retry-After header.
Issue a wallet
POST /api/public/v1/wallets with an API key. Returns the wallet ID and a one-time wallet token. See the Quick start example above for the full request shape.
Wallet policy
| Field | Type | Default | Description |
|---|---|---|---|
| max_per_tx | number | required | Hard ceiling per transaction in USD |
| allowed_categories | array | required | Categories the agent may charge |
| escalate_if_single_tx_exceeds | number | null | Notify principal if single tx > this |
| escalate_if_cumulative_exceeds | number | null | Notify principal if total spend > this |
| hard_cap | number | null | Hard stop — blocks all charges beyond this |
| blocked_vendors | array | [] | Explicit vendor blocklist |
Pause & revoke
Pause a wallet to reject all new charges while preserving its balance and audit history. Revoke to permanently disable; remaining balance returns to the principal account.
# Pause
curl -X POST https://agentpay.dev/api/public/v1/wallets/wlt_.../pause \
-H "Authorization: Bearer YOUR_API_KEY"
# Revoke
curl -X POST https://agentpay.dev/api/public/v1/wallets/wlt_.../revoke \
-H "Authorization: Bearer YOUR_API_KEY"How escalations work
Agent sends a charge that exceeds a policy threshold
AgentPay returns 202 with an escalation_id and poll_url
Principal receives an email and approves or denies in the dashboard
Agent polls GET /api/public/v1/escalations/:id and receives approved or denied
{
"status": "escalated",
"escalation_id": "esc_01J8X4K2M9N3P5Q7U",
"reason": "SINGLE_TX_THRESHOLD_EXCEEDED",
"reason_detail": "Requested $0.85 exceeds threshold $0.50",
"poll_url": "/api/public/v1/escalations/esc_01J8X4...",
"amount": 0.85
}{
"status": "approved",
"transaction_id": "txn_01J8X4K2M9N3P5Q7R",
"remaining_balance": 9.15
}Polling for resolution
GET /api/public/v1/escalations/:id with the wallet token. Returns the same shape as the original charge once resolved.
curl https://agentpay.dev/api/public/v1/escalations/esc_01J8X4... \
-H "Authorization: Bearer WALLET_TOKEN"Possible status values: pending, approved, denied, expired.
cURL
See the Quick start for ready-to-run cURL examples covering wallet issuance and charging.
Python
import httpx
import uuid
WALLET_TOKEN = "ap_wallet_your_token_here"
response = httpx.post(
"https://agentpay.dev/api/public/v1/charge",
headers={
"Authorization": f"Bearer {WALLET_TOKEN}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"vendor": "openai",
"amount": 0.003,
"currency": "USD",
"description": "GPT-4o completion",
"category": "llm_api",
}
)
result = response.json()
if result["status"] == "approved":
print(f"Charged. Remaining: ${result['remaining_balance']}")
elif result["status"] == "escalated":
# Poll for resolution
poll_url = result["poll_url"]Node.js
const response = await fetch(
'https://agentpay.dev/api/public/v1/charge',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${walletToken}`,
'Idempotency-Key': crypto.randomUUID(),
'Content-Type': 'application/json',
},
body: JSON.stringify({
vendor: 'openai',
amount: 0.003,
currency: 'USD',
description: 'GPT-4o completion',
category: 'llm_api',
}),
}
);
const { status, remaining_balance } = await response.json();LangChain agent
from langchain.tools import tool
import httpx, uuid
@tool
def agent_pay(
vendor: str,
amount: float,
description: str,
category: str = "llm_api"
) -> dict:
"""Pay a vendor from the agent's wallet.
Use this before calling any paid external API."""
response = httpx.post(
"https://agentpay.dev/api/public/v1/charge",
headers={
"Authorization": f"Bearer {WALLET_TOKEN}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"vendor": vendor,
"amount": amount,
"currency": "USD",
"description": description,
"category": category,
}
)
return response.json()Add this tool to your LangChain agent's tool list. The agent will call agent_pay before any vendor API that incurs a cost.