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

1

Get your API key

Create an account and copy your API key from Settings → API Keys.
2

Issue a wallet

bash
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"
  }'
Response
json
{
  "wallet_id": "wlt_01J8X3A1B2C4D5E6F",
  "token": "ap_live_4f9a...c3d2",
  "balance": 10.00,
  "expires_at": "2026-06-10T14:00:00Z"
}
Store this token securely. It is shown once and cannot be retrieved.
3

Charge the wallet (from your agent)

bash
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"
  }'
Response
json
{
  "status": "approved",
  "transaction_id": "txn_01J8X4K2M9N3P5Q7R",
  "amount": 0.003,
  "remaining_balance": 9.997
}
4

Monitor in the dashboard

Every charge appears instantly in your AgentPay dashboard. Set up email or webhook alerts in Settings → Notifications.

Authentication

AgentPay uses two distinct bearer token types.

Token typePrefixUsed for
API keyap_live_ / ap_test_Issuing wallets, dashboard API
Wallet tokenap_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

POST /api/public/v1/charge

Headers:

  • Authorization: Bearer <wallet_token>
  • Idempotency-Key: <uuid> (recommended)
FieldTypeRequiredDescription
vendorstringYesVendor identifier, e.g. "openai"
amountnumberYesUSD amount, up to 6 decimal places
currencystringYes"USD" only in V1
descriptionstringYesHuman-readable. Shown in audit log.
categorystringYesllm_api, search, data, storage, external_api
metadataobjectNoStored for audit. Not evaluated.

Response codes

HTTPstatusMeaning
200approvedCharge processed, balance debited
202escalatedExceeds threshold, pending principal approval
400errorInvalid request (missing fields, bad amount)
401errorToken invalid, expired, or revoked
402blockedPolicy violation (over limit, wrong category)
429errorRate limit exceeded
500errorInternal error — retry with backoff

For 402 blocked responses, the body includes a reason code:

EXCEEDS_MAX_PER_TXINSUFFICIENT_BALANCEINVALID_CATEGORYVENDOR_BLOCKEDHARD_CAP_EXCEEDED

Idempotency

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.

Without an idempotency key, a network timeout followed by a retry may result in two charges for the same operation.

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

FieldTypeDefaultDescription
max_per_txnumberrequiredHard ceiling per transaction in USD
allowed_categoriesarrayrequiredCategories the agent may charge
escalate_if_single_tx_exceedsnumbernullNotify principal if single tx > this
escalate_if_cumulative_exceedsnumbernullNotify principal if total spend > this
hard_capnumbernullHard stop — blocks all charges beyond this
blocked_vendorsarray[]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.

bash
# 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

1

Agent sends a charge that exceeds a policy threshold

 
2

AgentPay returns 202 with an escalation_id and poll_url

 
3

Principal receives an email and approves or denies in the dashboard

 
4

Agent polls GET /api/public/v1/escalations/:id and receives approved or denied

 
202 response
json
{
  "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
}
Polling response when approved
json
{
  "status": "approved",
  "transaction_id": "txn_01J8X4K2M9N3P5Q7R",
  "remaining_balance": 9.15
}
Poll every 5–10 seconds. Escalations expire after 24 hours if not resolved — the charge is then automatically denied.

Polling for resolution

GET /api/public/v1/escalations/:id with the wallet token. Returns the same shape as the original charge once resolved.

bash
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

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

javascript
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

python
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.