Integration

API reference

Every endpoint. REST over HTTPS, JSON in and out. All POSTs accept an optional Idempotency-Key header. Base URL: https://agentpay-mvp.vercel.app/v1

POST/v1/cards

Create a virtual card

Resolves the effective policy (default + optional override). If approval_required is true, returns 202 PENDING_APPROVAL. Otherwise places an off-session auth-hold on the user's saved payment method and mints a Stripe Issuing virtual card.

Request body

{
  amount_cents: number      // required, 1..50000
  agent_id?: string         // optional identifier for your agent
  purpose?: string          // optional human description (<=500 chars)
  policy_override?: {
    approval_required?: boolean
    max_amount_cents?: number
  }
}

Example

curl -X POST https://agentpay-mvp.vercel.app/v1/cards \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount_cents": 2000,
    "agent_id": "claude-desktop",
    "purpose": "Cloudflare domain"
  }'

Responses

201Auto-approved, card minted
{
  "id": "card_01HX...",
  "status": "OPEN",
  "last_four": "4242",
  "expiration": "12/29",
  "spending_limit_cents": 2000,
  "remaining_cents": 2000,
  "agent_id": "claude-desktop",
  "created_at": "2026-04-22T15:32:11Z"
}
202Policy requires approval
{
  "status": "PENDING_APPROVAL",
  "approval_id": "appr_01HX...",
  "expires_at": "2026-04-22T16:32:11Z"
}
403Setup required (KYB / PM missing)
{
  "error": {
    "code": "setup_required",
    "message": "AgentPay setup must be completed before cards can be issued. Open: <setup_url>",
    "details": {
      "missing": ["kyb", "payment_method"],
      "setup_url": "https://app.agentpay.dev/setup?return=mcp"
    },
    "request_id": "req_..."
  }
}
403Policy violation
{
  "error": {
    "code": "policy_violation",
    "message": "Amount 60000 exceeds policy max_amount_cents 50000",
    "details": { "max_amount_cents": 50000, "requested": 60000 },
    "request_id": "req_..."
  }
}
GET/v1/cards

List cards

Returns the user's cards in reverse-chronological order.

Query

?status=OPEN|USED|CLOSED|PENDING_APPROVAL   # optional filter
?agent_id=claude-desktop                      # optional filter
?limit=50                                     # max 100

Example

curl "https://agentpay-mvp.vercel.app/v1/cards?status=OPEN&limit=20" \
  -H "Authorization: Bearer sk_test_..."

Responses

200
{
  "data": [
    {
      "id": "card_01HX...",
      "status": "OPEN",
      "last_four": "4242",
      "expiration": "12/29",
      "amount_cents": 2000,
      "agent_id": "claude-desktop",
      "purpose": "Cloudflare domain",
      "created_at": "2026-04-22T15:32:11Z"
    }
  ]
}
GET/v1/cards/:id

Get a card (with PAN/CVV reveal)

Returns the card plus a Stripe ephemeral_key_secret you can use client-side with Stripe.js to reveal the PAN and CVV securely. We never return raw PAN or CVV ourselves.

Example

curl "https://agentpay-mvp.vercel.app/v1/cards/card_01HX..." \
  -H "Authorization: Bearer sk_test_..."

Responses

200
{
  "id": "card_01HX...",
  "status": "OPEN",
  "last_four": "4242",
  "expiration": "12/29",
  "amount_cents": 2000,
  "agent_id": "claude-desktop",
  "purpose": "Cloudflare domain",
  "created_at": "2026-04-22T15:32:11Z",
  "closed_at": null,
  "stripe_card_id": "ic_1...",
  "ephemeral_key_secret": "ek_test_..."  // use with Stripe.js to reveal PAN/CVV
}
POST/v1/cards/:id/close

Close a card

Revokes the card in Stripe and cancels the auth-hold on your PM (if still open). Idempotent — closing a closed card returns OK.

Example

curl -X POST "https://agentpay-mvp.vercel.app/v1/cards/card_01HX.../close" \
  -H "Authorization: Bearer sk_test_..."

Responses

200
{ "ok": true, "status": "CLOSED" }
GET/v1/balance

Get spend summary

Aggregate of your active holds and open cards. Useful for a status tool or CLI dashboard.

Example

curl "https://agentpay-mvp.vercel.app/v1/balance" -H "Authorization: Bearer sk_test_..."

Responses

200
{
  "held_cents": 1500,
  "open_cards": 2,
  "pending_approvals": 0,
  "max_per_card_cents": 50000,
  "approval_required": false,
  "setup_complete": true
}
GET/v1/policies/default

Get default policy

Example

curl "https://agentpay-mvp.vercel.app/v1/policies/default" -H "Authorization: Bearer sk_test_..."

Responses

200
{ "approval_required": false, "max_amount_cents": 50000 }
PUT/v1/policies/default

Update default policy

Request body

{
  approval_required?: boolean
  max_amount_cents?: number   // 1..50000
}

Example

curl -X PUT "https://agentpay-mvp.vercel.app/v1/policies/default" \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{"approval_required": true}'

Responses

200
{ "approval_required": true, "max_amount_cents": 10000 }
GET/v1/approvals

List pending approvals

Query

?status=PENDING|APPROVED|REJECTED|EXPIRED   # default PENDING

Example

curl "https://agentpay-mvp.vercel.app/v1/approvals" -H "Authorization: Bearer sk_test_..."

Responses

200
{
  "data": [
    {
      "id": "appr_01HX...",
      "amount_cents": 1000,
      "agent_id": "claude-desktop",
      "purpose": "API credits",
      "status": "PENDING",
      "expires_at": "2026-04-22T16:32:11Z",
      "created_at": "2026-04-22T15:32:11Z"
    }
  ]
}
POST/v1/approvals/:id/approve

Approve a pending request

Runs the auth-hold + mint flow synchronously. Returns the newly-issued card.

Example

curl -X POST "https://agentpay-mvp.vercel.app/v1/approvals/appr_01HX.../approve" \
  -H "Authorization: Bearer sk_test_..."

Responses

201
{
  "id": "card_01HX...",
  "status": "OPEN",
  "last_four": "4242",
  ...
}
POST/v1/approvals/:id/reject

Reject a pending request

Request body

{ reason?: string }

Example

curl -X POST "https://agentpay-mvp.vercel.app/v1/approvals/appr_01HX.../reject" \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{"reason":"out of budget"}'

Responses

200
{ "ok": true, "status": "REJECTED" }