AgentCard API

Direct REST reference for AgentCard user accounts — everything the agentcard CLI does, callable from your own code. If you're a platform issuing cards on behalf of your customers with an ak_live_ API key, use the Partner API instead.

Base URL:  https://agentcard.ai

The model

Request a card credential for a purchase, choosing the payment source:

The two sources have separate account-level spend limits, plus a shared hard daily ceiling ($200/day for normal direct accounts, UTC).

Authentication

All endpoints take a session token as a bearer header:

Authorization: Bearer <session-token>

Get a token by logging in with the CLI (npx agentcard signup --email you@example.com); it's stored at ~/.agentcard/config.json as token. Sessions expire — re-run signup to refresh. Requests from locked accounts return 401.

Conventions

Common error codes on spend attempts (both sources unless noted):

HTTPcodeMeaning
400amount_over_maxOver the per-card cap ($150 during beta)
400no_payment_methodNo saved funding card (issued source only) — run agentcard setup
400over_spend_limitAccount budget exceeded; payload has spendLimitCents/spentCents/remainingCents, plus limitSource: "connected" for connected purchases
403account_blockedAccount blocked by fraud controls
403account_lockedAccount locked — contact support
403identity_verification_requiredComplete KYC first (see Identity below)
403daily_spend_limit_exceededShared daily ceiling reached; resets at UTC midnight
402hold_failedYour bank declined the hold (issued source only)
500issue_failedHold succeeded but minting failed; the hold is released automatically
503platform_unavailableIssuance temporarily paused

Account

GET /api/me

Profile and setup state: email, paymentMethod ({id, last4, brand, expMonth, expYear} or null), spendLimitCents, agentEmail, walletAddress, locked/lockedReason, and identity fields.

GET /api/limits

Both spend budgets:

{
  "spendLimitCents": 10000,
  "spendLimitPeriod": "all_time",
  "spentCents": 3300,
  "remainingCents": 6700,
  "connected": {
    "spendLimitCents": 10000,
    "spentCents": 900,
    "remainingCents": 9100
  }
}

Top-level fields are the issued cards + wallet budget; connected is the connected-card budget. Issued usage counts captured spend plus live unexpired card exposure; connected usage counts retrieved one-time credentials plus live unexpired approvals.

POST /api/limits

{ "amountCents": 20000, "source": "issued" }

source is "issued" (default) or "connected". Lowering a limit applies immediately (as long as it isn't below current spend). Raising it emails the account owner an approval link (expires in 24h; a newer request for the same bucket supersedes older links). Response status is "updated", "unchanged", or "pending" and always carries limitSource.

Identity (KYC)

New or non-exempt accounts must verify identity before spending. POST /api/identity/verification-session returns a hosted verification url to hand to the user; spend endpoints return identity_verification_required until it's done.


Purchases (unified, read-only)

One read model across both purchase kinds. Writes stay on the kind-specific endpoints below.

GET /api/purchases

Query params: limit (1–100, default 50), before (ISO date cursor), kind (issued_card | connected).

{
  "purchases": [
    {
      "id": "cmc...",
      "kind": "issued_card",
      "providerId": null,
      "status": "ready",
      "sourceStatus": "issued",
      "amountCents": 2500,
      "currency": "USD",
      "merchant": null,
      "item": null,
      "last4": "4242",
      "network": "visa",
      "capturedAmountCents": null,
      "createdAt": "...",
      "expiresAt": "...",
      "completedAt": null,
      "links": {}
    }
  ]
}

Connected purchases additionally carry merchant ({name, url}), item, providerId (the provider instruction id), and links.approval / links.credentials.

Unified status vocabulary (raw kind-specific status is always in sourceStatus):

StatusMeaning
pendingBeing set up (hold placed / card minting)
awaiting_approvalConnected: waiting for the browser passkey approval
readyUsable now — live issued card, or approved unclaimed connected purchase
completedMoney moved or the one-time credential was released
expiredPassed expiresAt unused
canceledClosed before use
declinedPre-authorization rejection; no money moved
failedPost-authorization failure

GET /api/purchases/:id

Single purchase in the same shape. :id can be an issued-card request id, a connected purchase id, or the provider instruction id. Card credentials are never served here — use the kind-specific endpoints below.


Issued cards (default source)

POST /api/spend-requests

{ "amountCents": 2500 }

Runs the spend gate (KYC, budgets, daily ceiling), places a hold on your saved payment method, mints the card, and returns it in full — the only time issued-card details are generated:

{
  "id": "cmc...",
  "amountCents": 2500,
  "expiresAt": "...",
  "pan": "4242424242424242",
  "cvv": "123",
  "last4": "4242",
  "expiryMonth": 6,
  "expiryYear": 2029,
  "zip": "94108",
  "cardholderName": "Alchemy Agentcard",
  "billingAddress": { "line1": "77 Geary St", "city": "San Francisco", "state": "CA", "postalCode": "94108", "country": "US" }
}

Use the cardholder name and billing address exactly as returned — mismatches cause declines. One approved authorization up to amountCents, then the card locks.

GET /api/spend-requests · GET /api/spend-requests/:id

List your issued-card requests / fetch one. While a card is live (status: "issued", unexpired), the detail endpoint re-fetches and includes pan/cvv/expiry/billing.

POST /api/spend-requests/:id/cancel

Cancel an unused issued card: closes the card and releases the hold immediately. Idempotent once canceled; used/expired cards return 409 with code: "not_cancelable" and the current status; a 502 cancel_failed means the card is already unusable but the hold release needs a retry of the same call.

GET /api/3ds-codes

{ "codes": [{ "code": "123456" }] } — verification codes received in the last 5 minutes, newest first. Call only after a merchant checkout asks for a 3DS code; match by charge amount.


Connected cards (experimental source)

Requires the connected-card program flag; endpoints return 404 when disabled.

Enrollment

POST /api/agentic/instructions — create a purchase

{
  "paymentMethodId": "cm...",            // optional; default card used otherwise
  "network": "auto",                     // auto | visa | mastercard
  "merchant": { "name": "Asha Tea House", "url": "https://order.example.com" },
  "item": "Jasmine tea tin",
  "amount": { "value": "24.50", "currency": "USD" },
  "expiresInMinutes": 15,                // 1–1440, default 15
  "idempotencyKey": "order-8861"         // optional; also accepted as Idempotency-Key header
}

Response includes the instruction (with provider instructionId), the selected paymentMethod, and approvalUrl / statusUrl / credentialsUrl. Replaying the same idempotencyKey with the same body returns the original instruction (idempotentReplay: true); a different body returns 409.

Approval

POST /api/agentic/browser-token with { "purpose": "instruction-approval", "instructionId": "<providerId>" }, then open <approvalUrl>#agentic_token=<token> for the user — they approve with a passkey. Poll GET /api/agentic/instructions/:instructionId until status is approved (terminal failures: declined, failed, expired, cancelled).

POST /api/agentic/instructions/:instructionId/credentials

One-time credential retrieval for an approved, unexpired instruction — returned exactly once:

{
  "ok": true,
  "credentials": {
    "card": { "number": "...", "expiration_month": "...", "expiration_year": "...", "cvc": "..." },
    "expires_at": "..."
  }
}

Browser action tokens cannot call this endpoint; it requires the session token.

GET /api/agentic/instructions

List recent purchase instructions (most recent 100).


Funding payment method

Spend controls, in one place

ControlScopeDefault
Per-card capEach issued card / connected purchase$150
Issued account budgetIssued cards + wallet spend$100, raiseable
Connected account budgetConnected-card purchases$100, raiseable
Daily ceilingEverything, per UTC day$200 (hard)
KYCAll spend for new/non-exempt accountsRequired

Budget raises are approved by the account owner over email (POST /api/limits). The daily ceiling cannot be raised through the API.