# Create an access token Source: https://docs.agentcard.sh/api-reference/access-tokens/create openapi.json POST /api/v2/oauth/token Exchanges your `client_id` + `client_secret` for a platform access token (OAuth2 client credentials, RFC 6749 §4.4). The token lives one hour — when it expires, exchange again; there are no refresh tokens on this grant. Get your credentials in the Agentcard dashboard under **Organization → Developer → Credentials**. A sandbox client mints tokens that act in sandbox; a production client acts in production. You can also send the credentials as HTTP Basic (`Authorization: Basic base64(client_id:client_secret)`) instead of in the form body. This endpoint is rate limited to 30 requests per 5 minutes per IP — cache the token and reuse it until it expires. The exchange is also available at its original path, `POST /api/v1/oauth/token` — both addresses serve the same endpoint, and existing integrations do not need to change. New integrations should use `/api/v2/oauth/token`. **Test it right here** — paste your `client_id` and `client_secret` into the playground on the right and hit **Send**. Copy the `access_token` from the response into the **Authorization** field of any other endpoint page to call it live. A sandbox client runs everything in sandbox. # Introspect credential Source: https://docs.agentcard.sh/api-reference/access-tokens/introspect openapi.json GET /api/v2 Returns the organization and mode your token acts as. Useful as a health check and to confirm you're pointed at the right credential. # Access tokens Source: https://docs.agentcard.sh/api-reference/access-tokens/overview Exchange your client credentials for the platform token every other call needs. An **access token** authenticates your platform. You mint it by exchanging your organization's `client_id` and `client_secret` with the OAuth2 client-credentials grant, and you send it as the bearer on every platform endpoint. * Tokens live **one hour**. There are no refresh tokens on this grant. When one expires, exchange again. * A **sandbox** client mints sandbox tokens; a **production** client mints production tokens. The host is the same. * Get credentials in the dashboard under **Organization → Developer → Credentials**. ## The access token object | Field | Type | Description | | -------------- | ------- | --------------------------------------- | | `access_token` | string | The bearer for every platform endpoint. | | `token_type` | string | Always `Bearer`. | | `expires_in` | integer | Seconds until expiry. Always 3600. | | `scope` | string | Always `api`. | ```json theme={null} { "access_token": "eyJhbGciOiJIUzI1NiIs…", "token_type": "Bearer", "expires_in": 3600, "scope": "api" } ``` Introspecting a token returns an `api_v2` object: `organization_id` and `test_mode` (true for a sandbox client). ## Endpoints | Endpoint | | | -------------------------- | ------------------------------------------------------------------------------------------------------------- | | `POST /api/v2/oauth/token` | [Create an access token](/api-reference/access-tokens/create) | | `GET /api/v2` | [Introspect credential](/api-reference/access-tokens/introspect): which organization and mode a token acts as | # Get the Blooio connection Source: https://docs.agentcard.sh/api-reference/blooio/connection GET https://api.agentcard.sh/api/v2/blooio/connection Whether your organization has connected Blooio, and with which scopes. ```bash cURL theme={null} curl https://api.agentcard.sh/api/v2/blooio/connection \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json 200 theme={null} { "object": "blooio_connection", "connected": true, "blooio_organization_ids": ["borg_…"], "scopes": ["messages:send", "numbers:read"], "token_expires_at": "2026-10-07T17:00:00Z", "created_at": "2026-09-07T17:00:00Z", "updated_at": "2026-09-07T17:00:00Z" } ``` **Errors.** `404 not_found` when no Blooio connection exists for the organization. Start one with [Start the Blooio connection](/api-reference/blooio/oauth-start). # Start the Blooio connection Source: https://docs.agentcard.sh/api-reference/blooio/oauth-start POST https://api.agentcard.sh/api/v2/blooio/oauth/start Mint the Blooio consent URL to send your operator to. The URL carries a signed state bound to your organization. Open it in a browser as the Blooio account owner and approve. Blooio redirects to Agentcard, which completes the exchange and shows a "Blooio connected" page. ```bash cURL theme={null} curl -X POST https://api.agentcard.sh/api/v2/blooio/oauth/start \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json 200 theme={null} { "object": "blooio_oauth_start", "authorize_url": "https://app.blooio.com/oauth/authorize?client_id=bloapp_…&redirect_uri=…&response_type=code&state=…" } ``` **Errors.** `503 blooio_not_configured` when the integration is unavailable. # Blooio connection Source: https://docs.agentcard.sh/api-reference/blooio/overview Connect your organization's Blooio account so Agentcard can send wallet links from your own Blooio numbers. If your iMessage agent runs on [Blooio](https://blooio.com), you can connect your Blooio account to Agentcard once. After that, Agentcard sends wallet and approval links from your Blooio numbers, within the scopes you granted, so the user sees them in the same thread as your agent. The flow is OAuth: you request a consent URL, send your operator to it, they approve in Blooio, and Blooio redirects back to Agentcard. Agentcard stores the tokens encrypted and reports the connection here. ## The Blooio connection object | Field | Type | Description | | -------------------------- | -------------- | -------------------------------------------------------------------- | | `object` | string | `blooio_connection` | | `connected` | boolean | Always true when the object exists. A missing connection is a `404`. | | `blooio_organization_ids` | string\[] | The Blooio organizations the install covers. | | `scopes` | string\[] | What Blooio granted (for example `messages:send`). | | `token_expires_at` | string or null | When Blooio's token expires. Agentcard refreshes it. | | `created_at`, `updated_at` | string | | ```json theme={null} { "object": "blooio_connection", "connected": true, "blooio_organization_ids": ["borg_…"], "scopes": ["messages:send", "numbers:read"], "token_expires_at": "2026-10-07T17:00:00Z", "created_at": "2026-09-07T17:00:00Z", "updated_at": "2026-09-07T17:00:00Z" } ``` ## Endpoints | Endpoint | | | --------------------------------- | ----------------------------------------------------------------------------------------- | | `POST /api/v2/blooio/oauth/start` | [Start the Blooio connection](/api-reference/blooio/oauth-start): returns the consent URL | | `GET /api/v2/blooio/connection` | [Get the Blooio connection](/api-reference/blooio/connection) | # Close a card Source: https://docs.agentcard.sh/api-reference/cards/close openapi.json POST /api/v2/cards/{card_id}/close Close a card after checkout. Idempotent: closing a closed card answers `200`. One-time cards also close themselves after their first approved charge. Close the card when checkout is done. Idempotent, so closing twice is safe. One-time cards also close themselves after the first approved charge; closing explicitly just ends the credential's life sooner. # Create a card Source: https://docs.agentcard.sh/api-reference/cards/create openapi.json POST /api/v2/cards Create a one-time virtual card against the member's added card, then key its credentials into your checkout and [close it](/companies/api/reference/member-card-close) when you're done. Sandbox answers `201` with an open test card. Production answers `202 approval_pending` with an `approval_url` the member confirms with a passkey; retry with the SAME `Idempotency-Key` (or watch [flow status](/companies/api/reference/member-flow-status)) until the card is `open`, then read it once on [Get a card](/companies/api/reference/member-card-get). Credentials stay valid for about an hour, so create the card right before checkout. Create a one-time virtual card against the member's added card. This is the bring-your-own-checkout flow: create the card, key its `credentials` into the merchant's payment form yourself, then [close it](/api-reference/cards/close). **Sandbox** answers `201` with an open test card, credentials included. **Production** answers `202 approval_pending` with an `approval_url` the member confirms with a passkey; retry with the **same** `Idempotency-Key` until the card is `open`. Credentials stay valid for about an hour, so create the card right before checkout, not ahead of time. # Get the member flow status Source: https://docs.agentcard.sh/api-reference/cards/flow-status openapi.json GET /api/v2/flow_status One read that answers "what should happen next for this member": add a card, create a card, share an approval link, or fetch the open card. Authenticated with the member's connection token from [Verify the code](/companies/api/reference/connect-verify). One read that answers "what happens next for this member", with the single `next_action` to take: hand them an add-a-card link, create a card, share an approval link, or fetch the open card. Poll this between steps instead of polling [Get a card](/api-reference/cards/get), which notifies the member on every credential read. All member endpoints authenticate with the member's connection token from [Verify the code](/api-reference/connections/verify), kept fresh with [Refresh the connection](/api-reference/connections/refresh). # Get a card Source: https://docs.agentcard.sh/api-reference/cards/get openapi.json GET /api/v2/cards/{card_id} Authoritative card state. While the card is `open` it carries `credentials` (number, expiry, CVC) to key into the checkout. Each read of an open card notifies the member that the credentials were accessed, so fetch once when you are ready to pay rather than polling; poll [flow status](/companies/api/reference/member-flow-status) instead. Authoritative card state. An `open` card carries `credentials` (number, expiry, CVC) to key into the checkout. Every read of an open card notifies the member that its credentials were accessed. Fetch once when you are ready to pay; for progress, poll [flow status](/api-reference/cards/flow-status) instead. Never persist the credentials. # List the member's cards Source: https://docs.agentcard.sh/api-reference/cards/list openapi.json GET /api/v2/cards The member's wallet as this connection sees it: added cards (attachments, pending included) and the cards created against them. The member's wallet as this connection sees it: their added cards (attachments, pending ones included, so you can watch an add finish) and the one-time cards created against them. # Cards Source: https://docs.agentcard.sh/api-reference/cards/overview One-time virtual cards created against a member's added card, authenticated as the member. A **card** here is a one-time virtual card Agentcard creates against a card the member has added. Your agent keys its credentials into a checkout, and the card closes itself after its first approved charge (or when you close it). Every endpoint in this resource is authenticated with the **member's connection token** from [Verify the code](/api-reference/connections/verify), not your platform token. Start with **flow status**: one read that says what should happen next for this member (add a card, create a card, share an approval link, or fetch the open card). ## The card object | Field | Type | Description | | ------------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `object` | string | `card` | | `id` | string | | | `status` | string | `approval_pending` (production, until the member approves), `open` (carries credentials), `in_use`, `pausing` (a charge paused the card; the card network has not confirmed yet), `paused`, `closing` (a charge spent the card; the network has not confirmed yet), `closed`. `pausing` and `closing` finish on their own. | | `spend_limit_cents`, `balance_cents` | integer | | | `connected_card_id` | string | The attachment this card draws on. | | `last4`, `expiry` | string | | | `approval_url`, `expires_at` | string | Only while `approval_pending`. | | `credentials` | object | Only on an `open` card: number, expiry, CVC to key into a checkout. Never persist it. Each read notifies the member. | | `credentials_status` | string | `protected` when the member requires an approval per reveal; `retry` when the read should be retried. | | `closed_reason` | string | Only when `closed`: `used`, `canceled`, `expired`, `declined`. | ## The flow status object One read that says what to do next for a member. | Field | Type | Description | | ---------------- | ------ | ------------------------------------------------------------------------------------------------- | | `status` | string | `no_card_attached`, `attach_pending`, `attach_failed`, `ready`, `approval_pending`, `card_ready`. | | `next_action` | object | `{ type, id, url, expires_at }`. `url` is the page to hand the member. | | `attached_cards` | array | The member's added cards: `id`, `status`, `network`, `brand`, `last4`, `art_url`. | | `card` | object | The open or pending card, when there is one. | ```json theme={null} { "object": "flow_status", "status": "ready", "next_action": { "type": "create_card" }, "attached_cards": [{ "id": "ca_123", "status": "active", "network": "visa", "brand": "Visa", "last4": "7318", "art_url": null }] } ``` ## Endpoints | Endpoint | | | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | | `GET /api/v2/flow_status` | [Get the member flow status](/api-reference/cards/flow-status) | | `GET /api/v2/cards` | [List the member's cards](/api-reference/cards/list) | | `POST /api/v2/cards` | [Create a card](/api-reference/cards/create): sandbox returns an open card, production returns `approval_pending` with an `approval_url` | | `GET /api/v2/cards/{card_id}` | [Get a card](/api-reference/cards/get): carries credentials while `open`; each read notifies the member | | `POST /api/v2/cards/{card_id}/close` | [Close a card](/api-reference/cards/close) | # Record consent Source: https://docs.agentcard.sh/api-reference/connections/consent openapi.json POST /api/v2/connect/consent Records that the user authorized your platform to act on their behalf. Safe to retry — it's idempotent per user, so a repeat call updates the same record instead of creating a duplicate. ## What your terms must disclose Recording consent attests that your connect UI showed the user your terms for the Agentcard connection, and those terms must include this line (or equivalent): > By connecting, you also agree to [Crossmint's Privacy Policy](https://www.crossmint.com/legal/privacy-policy) — Crossmint may process payments when you add funds. Consents recorded through this endpoint enable Apple Pay, Google Pay, and card funding on embedded links. Connections without a recorded consent keep the default funding options. # Start attested onboarding Source: https://docs.agentcard.sh/api-reference/connections/onboarding-attempt-create openapi.json POST /api/v2/onboarding_attempts Create an onboarding attempt for a phone number you already hold and text the returned `wallet_url` to the user. No Agentcard account exists yet: the user sees the wallet instantly, and our one-time code fires exactly once, inside our page, at their first money action. You never see or relay the code. Requires the attested-onboarding capability on your organization (ask us to enable it). The response is identical whether or not the phone already belongs to an Agentcard account. ## How it works You already know your user's phone number, so assert it: create an attempt and text the returned `wallet_url` into your thread. The user opens it and sees their Agentcard wallet immediately. No account exists yet, nothing was created beyond the attempt, and no code has been sent. The one-time code fires exactly once, inside our page, at the user's first money action (adding their card, or their first purchase confirmation). Passing it creates the account, or binds the phone's existing Agentcard account, and records the connection for your client. You never see or relay the code; that is the anti-phishing property of the whole flow. Then: 1. Listen for the `connection.created` webhook. It carries `user_id`, your `external_user_id`, and `onboarding_attempt_id`. 2. Call [the exchange](/api-reference/connections/onboarding-attempt-exchange) once to collect the connection token pair, and keep it alive with [`POST /api/v2/connect/refresh`](/api-reference/connections/refresh). Attempts expire after 48 hours. Daily quotas apply per organization and per phone number. The capability is enabled per organization; ask us to turn it on. # Exchange the attempt Source: https://docs.agentcard.sh/api-reference/connections/onboarding-attempt-exchange openapi.json POST /api/v2/onboarding_attempts/{id}/exchange One-time collection of the user's connection after they verified (you'll know from the `connection.created` webhook, which carries `onboarding_attempt_id`). Returns the same token pair `connect/verify` would have: store `access_token`, `refresh_token`, and `user.id`, and keep the session alive with `POST /api/v2/connect/refresh`. Only the client that created the attempt can exchange it, and only once. ## How it works After the user verifies (the `connection.created` webhook tells you), exchange the attempt once for the connection: the same `access_token`, `refresh_token`, and `user.id` that `connect/verify` returns. Store all three and refresh with [`POST /api/v2/connect/refresh`](/api-reference/connections/refresh); the user never sees a code again. Only the client that created the attempt can exchange it, and only once. A `409 not_converted` means the user hasn't verified yet; a `410 already_exchanged` means you already collected the pair, so use the tokens you stored. # Get an onboarding attempt Source: https://docs.agentcard.sh/api-reference/connections/onboarding-attempt-get openapi.json GET /api/v2/onboarding_attempts/{id} Inspect an attempt's state while you wait for `connection.created`: whether the person has verified, whether the grant was already exchanged, and when the attempt expires. Only the client that created the attempt can read it. ## How it works Read an attempt's state while you wait for the `connection.created` webhook: `pending` means the person hasn't verified yet, `converted` means they have (and `user_id` is present), `expired` means the link died unused, and `exchanged` tells you whether the grant was already collected. Only the client that created the attempt can read it; anything else answers the same `404` as an unknown id. # Connections Source: https://docs.agentcard.sh/api-reference/connections/overview Connect a user to your platform: send a code, verify it, and get a token that acts as them. A **connection** links one of your users to your platform. You send a one-time code to their email or phone, they read it back, and you receive a token pair: the `access_token` acts **as that user** (it is the bearer on `/buy` and the member-token card endpoints) and the `refresh_token` keeps it alive. Completing the code is the authorization. There is no separate approval screen. Connection access tokens expire after one hour. Each refresh returns a new refresh token and invalidates the old one. **Attested onboarding** is the variant for users you already know by phone number: you create an onboarding attempt, text the returned wallet link, and the code fires once inside our page at their first money action. You collect the connection afterwards. ## The connection object Returned by [Verify the code](/api-reference/connections/verify), [Refresh the connection](/api-reference/connections/refresh), and the onboarding-attempt exchange. | Field | Type | Description | | --------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `object` | string | `connection` | | `access_token` | string | The user's connection token. Acts as this user. Bearer on `/buy` and the member-token card endpoints. Never the `Authorization` header of a platform endpoint. | | `refresh_token` | string | Exchange it on `/connect/refresh` before `access_token` expires. Each refresh returns a new one and invalidates the old. | | `token_type` | string | `Bearer` | | `expires_in` | integer | Seconds until `access_token` expires (3600). | | `user.id` | string | Store it. Every platform endpoint names the user by this id. | | `user.email` | string or null | Set when the user connected by email. | | `user.phone` | string or null | Set when the user connected by phone. | ```json theme={null} { "object": "connection", "access_token": "act_1a2b3c…", "refresh_token": "rct_4d5e6f…", "token_type": "Bearer", "expires_in": 3600, "user": { "id": "user_7g8h9i", "email": "user@example.com", "phone": null } } ``` ## The onboarding attempt object | Field | Type | Description | | ------------ | ------- | ----------------------------------------------------------------------- | | `id` | string | `oa_…` | | `wallet_url` | string | The link to text the user. Returned on create. | | `verified` | boolean | Whether the person has completed the one-time code inside our page. | | `exchanged` | boolean | Whether the connection was already collected. The exchange is one-time. | | `expires_at` | string | When the attempt stops being exchangeable. | ## Endpoints | Endpoint | | | ------------------------------------------------ | ------------------------------------------------------------------------------------- | | `POST /api/v2/connect/start` | [Send a code](/api-reference/connections/start) | | `POST /api/v2/connect/verify` | [Verify the code](/api-reference/connections/verify): returns the token pair | | `POST /api/v2/connect/consent` | [Record consent](/api-reference/connections/consent) | | `POST /api/v2/connect/refresh` | [Refresh the connection](/api-reference/connections/refresh) | | `POST /api/v2/onboarding_attempts` | [Start attested onboarding](/api-reference/connections/onboarding-attempt-create) | | `GET /api/v2/onboarding_attempts/{id}` | [Get an onboarding attempt](/api-reference/connections/onboarding-attempt-get) | | `POST /api/v2/onboarding_attempts/{id}/exchange` | [Exchange for the connection](/api-reference/connections/onboarding-attempt-exchange) | Webhook: `connection.created`. # Refresh the connection Source: https://docs.agentcard.sh/api-reference/connections/refresh openapi.json POST /api/v2/connect/refresh Connection access tokens expire after one hour. Exchange the refresh token for a new pair before then. Each refresh returns a **new** refresh token and invalidates the old one — replace the stored token every time. Reusing a refresh token that was already exchanged (beyond the short retry window) is treated as a sign the token leaked: every session of that user's connection with your client is revoked, and none of its tokens can be refreshed again. Reconnect the user with [Start a connection](/api-reference/connections/start). # Send a code Source: https://docs.agentcard.sh/api-reference/connections/start openapi.json POST /api/v2/connect/start Sends a one-time code to the user by email or phone. Provide **exactly one** of `email` or `phone`. Codes are valid for 10 minutes. If you've designed a connect email in your dashboard, we send that branded email; otherwise we send a default one. # Verify the code Source: https://docs.agentcard.sh/api-reference/connections/verify openapi.json POST /api/v2/connect/verify Checks the code the user entered and, on success, connects the user and returns the token pair to store. Completing the code **is** the authorization — there is no separate approval screen. The returned `access_token` is the **user's connection token**: it acts on behalf of this user (send it as the bearer token to the MCP server to create cards, check balances, and shop as them). It is not the platform token — the endpoints in this reference keep using your platform access token and name the user with `user_id`. A code can be verified once: a second verify of the same attempt returns `invalid_connect_attempt`. In **sandbox** the code is always `111111`. The `access_token` returned here is the **user's connection token** — it acts on behalf of this user. Send it as the bearer token to the [MCP server](/vault/integrations/ecommerce-apis/purchase-api#over-mcp) to create cards, check balances, and shop as them. It is **not** the platform token you send to the endpoints in this reference — those keep using your [platform access token](/api-reference/access-tokens/create) and name the user with `user_id`. # Get embed origins Source: https://docs.agentcard.sh/api-reference/embed-origins/get GET https://api.agentcard.sh/api/v2/embed_origins The origins currently allowed to frame the wallet embed. ```bash cURL theme={null} curl https://api.agentcard.sh/api/v2/embed_origins \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json 200 theme={null} { "object": "embed_origins", "origins": ["https://app.example.com", "http://localhost:3000"] } ``` # Embed origins Source: https://docs.agentcard.sh/api-reference/embed-origins/overview The web origins allowed to iframe the wallet embed. **Embed origins** are the sites permitted to frame the Agentcard wallet embed (the Wallet SDK's `frame-ancestors`). The list is configuration, not a credential: origins end up verbatim in a public CSP header. It is empty by default, in which case the embed only renders inside Agentcard's own surfaces. Origins must be HTTPS. `http://localhost` and other loopback hosts are allowed for local development. Anything with a path or query is reduced to its origin. ## The embed origins object | Field | Type | Description | | --------- | --------- | --------------------------------------------------------------------------------------------------------------- | | `object` | string | `embed_origins` | | `origins` | string\[] | The full allowlist, normalized to bare origins. Empty means the embed renders only on Agentcard's own surfaces. | ```json theme={null} { "object": "embed_origins", "origins": ["https://app.example.com", "http://localhost:3000"] } ``` ## Endpoints | Endpoint | | | --------------------------- | --------------------------------------------------------- | | `GET /api/v2/embed_origins` | [Get embed origins](/api-reference/embed-origins/get) | | `PUT /api/v2/embed_origins` | [Replace embed origins](/api-reference/embed-origins/put) | # Replace embed origins Source: https://docs.agentcard.sh/api-reference/embed-origins/put PUT https://api.agentcard.sh/api/v2/embed_origins Set the full list of origins allowed to frame the wallet embed. The list is replaced, not merged. Send every origin you want allowed. Web origins. HTTPS only, except loopback hosts for local development. Duplicates are dropped. ```bash cURL theme={null} curl -X PUT https://api.agentcard.sh/api/v2/embed_origins \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"origins": ["https://app.example.com", "http://localhost:3000"]}' ``` ```json 200 theme={null} { "object": "embed_origins", "origins": ["https://app.example.com", "http://localhost:3000"] } ``` **Errors.** `400 invalid_origin` names the value that was refused. `400 invalid_request` when the array exceeds the maximum length. # Import a verification Source: https://docs.agentcard.sh/api-reference/identity-verification/import openapi.json POST /api/v2/kyc/import Import a verification you already ran on your **own Sumsub account** (Reusable KYC). Generate a single-use share token for the Agentcard client id, send it here, and the user skips document capture and the face scan. A successful import drops into the exact same status contract as a fresh verification: poll `GET /api/v2/kyc` or listen for `identity.verification.updated`. Requires one-time partner pairing between your Sumsub account and Agentcard's (per environment) — ask your Agentcard contact to enable it. Share tokens are single-use with a short TTL, so generate one fresh per import attempt. ## Where the token comes from The `share_token` is a Sumsub artifact you mint on your own account, so this endpoint only applies if you run KYC on Sumsub yourself. Generate it with Sumsub's `POST /resources/accessTokens/shareToken`, with `forClientId` set to the Agentcard client id from your pairing setup. Tokens are single-use and expire after their `ttlInSecs`: generate one right before each import call, never from storage. ## After the import The import creates the verification on Agentcard's side, and from that moment nothing distinguishes it from one your user ran here. Poll [GET /api/v2/kyc](/api-reference/identity-verification/status) or consume the `identity.verification.updated` webhook; a `needs_information` status carries the exact `required_fields` to submit via [POST /api/v2/kyc/information](/api-reference/identity-verification/submit-information). If the shared verification did not carry a residential address, the import returns `needs_information` right away: submit the address (and any other listed field) as soon as the import call returns, in that order. Submitting information before the import would start a separate verification on Agentcard's side, and the import then returns `409 verification_in_progress`. That information call returns `pending`, and the card issuer application is filed right after it, so the verification moves to review without waiting for a scheduled retry. If the issuer cannot take the application at that moment, the user's timeline in your Agentcard dashboard records the failure and the retry runs automatically. # Identity verification Source: https://docs.agentcard.sh/api-reference/identity-verification/overview Verify a connected user's identity: upload their ID, submit extra fields, then a short face scan. **Identity verification** (KYC) is required before a user can hold a balance or be issued a card. The flow runs in your own UI: upload the front and back of the user's ID, send any `required_fields` the back-of-ID response asks for, then show the `iframe_url` for the face scan. Track the result by polling status or listening for `identity.verification.updated`. Already verified the user on your own Sumsub account? **Import** the verification with a share token and the user skips document capture and the face scan. ## The verification object | Field | Type | Description | | ----------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------- | | `object` | string | `kyc` | | `status` | string | `awaiting_documents`, `needs_information`, `requires_verification`, `pending`, `approved`, `rejected`. | | `required_fields` | array | Only on `needs_information`: exactly the fields to collect and post to `/kyc/information`. | | `iframe_url` | string | On every actionable status: the hosted page that collects what the verification still needs (documents, fields, or the face scan). | | `warnings` | array | On document uploads: actionable feedback safe to show the user. | | `extracted` | object | On document uploads: what the document reader pulled off the image, to prefill your form. | | `reason` | string | On `needs_information`, `awaiting_documents`, `requires_verification`, `rejected`: an end-user-safe explanation. | ```json theme={null} { "object": "kyc", "status": "needs_information", "required_fields": ["address_line1", "postal_code"], "iframe_url": "https://in.sumsub.com/websdk/p/…" } ``` ## Endpoints | Endpoint | | | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | | `POST /api/v2/kyc/documents/front` | [Upload the front of the ID](/api-reference/identity-verification/upload-front) | | `POST /api/v2/kyc/documents/back` | [Upload the back of the ID](/api-reference/identity-verification/upload-back): the branch point (`needs_information`, `requires_verification`, `rejected`) | | `POST /api/v2/kyc/information` | [Submit information](/api-reference/identity-verification/submit-information) | | `GET /api/v2/kyc` | [Get verification status](/api-reference/identity-verification/status) | | `POST /api/v2/kyc/simulate` | [Simulate an outcome](/api-reference/identity-verification/simulate) (test mode only) | | `POST /api/v2/kyc/import` | [Import a verification](/api-reference/identity-verification/import) (Sumsub share token) | Webhook: `identity.verification.updated`. # Simulate an outcome (test mode) Source: https://docs.agentcard.sh/api-reference/identity-verification/simulate openapi.json POST /api/v2/kyc/simulate **Test mode only.** Drives a test-mode verification to a chosen terminal outcome instantly — test verifications never complete on their own. The simulated verdict flows through the same status contract and fires the same `identity.verification.updated` webhook a real review produces, so your status handling and webhook consumer are exercised end to end. Requires a test-mode client credential; live tokens get `403 sandbox_only`. ## Why this exists Test-mode verifications never complete on their own — there is no reviewer behind them. This endpoint is the missing verdict: pick an outcome and the verification reaches it instantly, through the same status contract and the same `identity.verification.updated` webhook a real review produces. | Outcome | What your integration sees | | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `approved` | Status flips to `approved` — the happy path. | | `rejected` | Terminal `rejected` with a `reason` — the failure state to surface to the user. | | `requires_input` | A retryable bounce: `requires_verification` with a `reason`, pointing back at the `iframe_url` (the test-mode chooser). Test mode never asks for documents or typed details, so this is the retry state your UI must handle. | Pass a custom `reason` to see exactly how your UI renders a specific review message. Re-simulating overwrites the previous outcome, so a single test user can walk approved → rejected → approved without reconnecting. Live tokens are refused with `403 sandbox_only`: live verifications are decided by the identity provider. # Get verification status Source: https://docs.agentcard.sh/api-reference/identity-verification/status openapi.json GET /api/v2/kyc Polls the current verification status — the alternative to the `identity.verification.updated` webhook. ## Status values Every KYC response carries exactly one status. | Status | Meaning | What to do | | ----------------------- | ----------------------------------- | -------------------------------------------------------------------------------------- | | `awaiting_documents` | Waiting for the ID images. | Upload the front and back — or hand the user the `iframe_url`. | | `needs_information` | The review asked for typed details. | Submit the `required_fields` — or hand the user the `iframe_url`, which collects them. | | `requires_verification` | Ready for the face scan. | Show the user the `iframe_url`. | | `pending` | Under review. | Wait — no action needed. | | `approved` | Verified. | Done. | | `rejected` | Not verified. | The user did not pass. | ## Fully hosted, or fully custom Every **actionable** status (`awaiting_documents`, `needs_information`, `requires_verification`) carries an `iframe_url` — a hosted page that walks the user through whatever the verification still needs: document capture, any typed details the review asks for, and the face scan. That gives you two integration styles with the same API: * **Fully hosted**: ignore the upload and submit endpoints entirely. Whenever the status is actionable, hand the user the `iframe_url` (new tab or embedded) — the flow completes end to end on the hosted page, and no identity documents or personal details ever pass through your servers. * **Fully custom**: drive the [document upload](/api-reference/identity-verification/upload-front) and [information submit](/api-reference/identity-verification/submit-information) endpoints from your own UI, and use the `iframe_url` only at `requires_verification` for the scan. The link is short-lived: always surface the one from your freshest status read or `identity.verification.updated` event rather than storing it. **Test mode reports a smaller status set.** A sandbox verification never asks for identity: it reports only `requires_verification` (the `iframe_url` is the test-mode chooser), `pending`, `approved`, or `rejected`, so `awaiting_documents` and `needs_information` never appear. Complete it with [simulate](/api-reference/identity-verification/simulate) or the chooser; rehearse the full collection state machine against live with a real document. # Submit information Source: https://docs.agentcard.sh/api-reference/identity-verification/submit-information openapi.json POST /api/v2/kyc/information Submits the extra fields requested by a `needs_information` response. Send only the fields listed in `required_fields`; values are trimmed, and a blank value counts as not provided. For a fresh verification, the response returns the `iframe_url` for the face scan. For an imported verification (Reusable KYC), the submit that completes the residential address returns `pending` and files the card issuer application right after it, in the background, so the response never waits on the issuer; the verification then moves to `approved` or `rejected` through the status poll or the `identity.verification.updated` webhook. Repeating the request is safe: it returns the current status. # Upload the back of the ID Source: https://docs.agentcard.sh/api-reference/identity-verification/upload-back openapi.json POST /api/v2/kyc/documents/back Uploads the back of the document. The response tells you what to do next — this is the branch point of the flow: - `needs_information` → collect exactly the `required_fields` and post them to `/kyc/information`. - `requires_verification` → show the user the `iframe_url` for the face scan. - `rejected` → the document couldn't be verified. # Upload the front of the ID Source: https://docs.agentcard.sh/api-reference/identity-verification/upload-front openapi.json POST /api/v2/kyc/documents/front Uploads the front of the user's identity document as a base64-encoded image. This step acknowledges receipt; the next step (`back`) tells you what comes next. Any upload response may include a `warnings` array with actionable feedback (for example, that the other side of the document is still needed). The response's `extracted` object carries what the document reader pulled off the image — use it to prefill your details form so the user confirms instead of typing. # API reference Source: https://docs.agentcard.sh/api-reference/overview Every v2 endpoint, grouped by the resource it acts on. Each page has parameters, responses, and a live playground. Base URL: `https://api.agentcard.sh` There is no separate sandbox host. Whether a call runs in **sandbox** or **production** is decided by the credential you use, never by the URL. ## Resources Exchange client credentials for the platform token every call needs. Connect a user to your platform and get a token that acts as them. Store a user's own card and authorize checkouts with it. One conversational endpoint that places real orders. One-time virtual cards created against a member's added card. KYC: documents, extra fields, face scan, status. A connected user's balance and how to fund it. One texted link that opens the user's wallet: in the thread on iPhone, in the browser everywhere else. Register where events are delivered and rotate signing secrets. Web origins allowed to iframe the wallet embed. Let Agentcard send wallet links from your Blooio numbers. ## Authentication Every endpoint is called from your backend with a **platform access token**: ``` Authorization: Bearer ``` Mint it on [Create an access token](/api-reference/access-tokens/create) from your `client_id` and `client_secret` (dashboard → Organization → Developer → Credentials). A sandbox client mints sandbox tokens, a production client mints production tokens. Tokens live one hour. ## Two tokens, two jobs | Token | Where you get it | What it does | | ------------------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------------------- | | **Platform access token** | [Create an access token](/api-reference/access-tokens/create) | Authenticates **your platform**. The bearer on almost every endpoint here. | | **Connection token** | [Verify the code](/api-reference/connections/verify) | Acts **as one user**. The bearer on `/buy` and on the member-token card endpoints. | The connection token belongs to the user. Platform endpoints name the user with `user_id` instead of taking their token. Keep it fresh with [Refresh the connection](/api-reference/connections/refresh). ## Test from this reference 1. Open [Create an access token](/api-reference/access-tokens/create), paste a sandbox `client_id` and `client_secret`, hit **Send**. 2. Paste the `access_token` into the **Authorization** field on any endpoint page. It is remembered as you move between pages. 3. Fill the parameters and hit **Send**. You are hitting the live API. In sandbox the connect code is always `111111`. ## Errors Every error uses the same envelope: ```json theme={null} { "error": { "code": "invalid_code", "message": "That code is invalid or expired.", "docs": "https://docs.agentcard.sh/api-reference/overview" } } ``` `code` is stable and machine-readable. Branch on it. `message` is safe to log. Each endpoint page lists the codes it can return. ## Webhooks Events are signed and delivered to the endpoints you register under [Webhook endpoints](/api-reference/webhook-endpoints/overview). Every event and its payload is documented in the [Webhooks](/webhooks/overview) tab. # Buy Source: https://docs.agentcard.sh/api-reference/purchases/buy openapi.json POST /buy One conversational endpoint that places real orders. Send the user's request as plain text in `ask`; thread follow-ups with `conversation_id`; place a shown cart by echoing its `hash` in `confirm` (or an array of hashes for several carts). Money only moves on a confirm, and only for exactly the cart the hash describes. # Conversation status Source: https://docs.agentcard.sh/api-reference/purchases/conversation openapi.json GET /buy/conversations/{id} The server's view of a /buy conversation, for a confirm whose response never arrived: whether a turn is still running, the last checkout attempt (any outcome, with its code and approval link), and every order the conversation placed, read from the ledger. Same bearer scoping as POST /buy. # Merchant catalogue Source: https://docs.agentcard.sh/api-reference/purchases/merchants openapi.json GET /buy/merchants The live catalogue for rail selection: every merchant id /buy accepts, its display name, and whether this user still needs to link an account there. Same bearer scoping as POST /buy. Merchant ids are the public ids /buy uses in `placements[].merchant` and `unmatched[].merchant` (`retail` covers Amazon, Walmart, Target, Best Buy, Home Depot, Lowe's, Macy's, Wayfair, Staples, Kohl's and B&H Photo). # Purchases Source: https://docs.agentcard.sh/api-reference/purchases/overview One conversational endpoint that builds a cart at a real merchant and places the order once you confirm. The **Purchase API** is a turn-based loop on one endpoint. You send what the user wants as plain text in `ask`, follow up with the same `conversation_id`, and place a shown cart by echoing its `hash` in `confirm`. Money moves only on a confirm, and only for exactly the cart the hash describes. The bearer is a **user** token: the connection `access_token` or a cardholder `buy_token`. A platform token is rejected, because a purchase always runs as one user. Use a client timeout of at least 120 seconds. ## The purchase response object Every `200` from `POST /buy` carries the same envelope. Each field is always present and `null` when empty. | Field | Type | Description | | ----------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------ | | `conversation_id` | string | The thread. Send it back on every follow-up. | | `status` | string | `needs_input`, `order_placed`, `partially_placed`, `declined`. The only field you branch on. | | `reply` | string | The assistant's turn as prose. `messages` carries it split into chat bubbles. | | `cart` | object or null | The most recently shown cart. See below. | | `carts` | array | Every open cart in the conversation, each with its own `hash`. | | `catalog` | object or null | The last product search as data, with an `as_of` stamp. | | `unmatched` | array | Asks that did not make it into a cart: `{ merchant, requested, reason, detail, at }`. | | `order_id` | string or null | Set when this call placed an order. Reconcile on it. | | `payment_source` | object or null | `{ source, brand, last4 }`. `source` is `balance`, `added_card`, `vault`, `company_balance`, or `stored_payment_method`. | | `decline_code` | string or null | `vault_approval_required`, `byoc_approval_required`, `sandbox_mode`, `items_unavailable`, … | | `approval_url` | string or null | Send to the user when the confirm paused. | | `charge_status` | string or null | `none`, `confirming`, `settled`, `unknown`. | | `placements` | array or null | Per-cart outcomes of a multi-cart confirm. | | `error_code` | string or null | Machine-readable loop failure. | ## The cart object | Field | Type | Description | | -------------------------------------------- | --------------- | ---------------------------------------------------------------------------------------------------- | | `merchant`, `merchant_name` | string | Rail id (`retail`, `doordash`, …) and display name. | | `items[]` | array | `{ name, qty, priceCents, product_id }`. | | `serviceFeesCents`, `tipCents`, `totalCents` | integer | The all-in total the user approves. | | `approvedCeilingCents` | integer or null | The most a confirm can authorize when tax and shipping finalize later. Null when equal to the total. | | `hash` | string | Identifies exactly this cart at this price. Echo it in `confirm`. | ```json theme={null} { "merchant": "retail", "merchant_name": "Amazon", "items": [{ "name": "Cafe Mesa de los Santos Colombian Ground Coffee, 16 oz", "qty": 1, "priceCents": 2250, "product_id": "https://www.amazon.com/dp/B07ZQ5C4RB" }], "serviceFeesCents": 56, "tipCents": 0, "totalCents": 2306, "approvedCeilingCents": 3444, "hash": "9f2c4a1b8e3d5f07" } ``` ## Endpoints | Endpoint | | | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------- | | `POST /buy` | [Buy](/api-reference/purchases/buy): ask, follow up, confirm | | `GET /buy/merchants` | [List the merchants](/api-reference/purchases/merchants) `/buy` can place at | | `GET /buy/conversations/{id}` | [Read a purchase conversation](/api-reference/purchases/conversation): reconcile a confirm whose response never arrived | Webhooks: `order.placed`, `order.failed`, `order.confirmed`. The guide is [Agentcard's Purchase API](/vault/integrations/ecommerce-apis/purchase-api). # Cancel a checkout authorization Source: https://docs.agentcard.sh/api-reference/vault/authorizations-cancel POST https://api.agentcard.sh/api/v2/checkout/authorizations/{id}/cancel Abandon a paused merchant request before the user's device has started sending the card. Call it when your agent gives up on a checkout while the authorization is still `awaiting_approval`. The authorization becomes `declined` with reason `merchant_request_aborted` and the user's approval link stops working. Idempotent: cancelling a cancelled authorization answers `200`. The authorization id. ```bash cURL theme={null} curl -X POST https://api.agentcard.sh/api/v2/checkout/authorizations/cauth_2q9d1x8f3k2m4t7w/cancel \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{}' ``` ```json 200 theme={null} { "id": "cauth_2q9d1x8f3k2m4t7w", "status": "declined", "reason": "merchant_request_aborted", "cancelled": true, "processor_request_started": false } ``` **Errors.** `409 outcome_unknown`: the user's device already started sending the card, so the authorization can no longer be cancelled. Resolve its existing outcome (read it, confirm with the merchant) before another attempt. `404 not_found`: unknown id, or an authorization created by another client. # Create a checkout authorization Source: https://docs.agentcard.sh/api-reference/vault/authorizations-create POST https://api.agentcard.sh/api/v2/checkout/authorizations Pause a captured processor request until the user approves it with their passkey. Post the request your browser captured when the agent submitted a placeholder card to a recognized payment processor. Agentcard returns an `approvalUrl` for the user. When they approve, their device sends the real card to the processor and the authorization carries the processor `response` you replay into the paused request. The SDK makes this call for you. Call it directly only if you run your own interception. The connected user whose vaulted card pays. Shown to the user on the approval screen. Up to 120 printable characters. Judged by nothing: your presets judge the merchant Agentcard names from `checkout_origin` and the payment request. The origin of the checkout page the payment form was on, such as `https://shop.example.com`. The SDK sends it. With the merchant identity inside `request`, this names the merchant your presets judge; without it, a merchant, category, or place rule refuses the purchase as unknown. Your hint at the amount: an integer in the currency's smallest unit (2306 for \$23.06), or a decimal string in normal units (`"23.06"`). Caps use the amount the processor charges. Send `amount` to have a purchase judged the moment your agent opens it. A hint more than one smallest unit away from the processor's amount is refused with `amount_mismatch` and nothing is charged. ISO 4217 code for `amount`. Both together or neither. Older checkout SDKs (0.5.0 and 0.6.0) send the integer as `amount_cents`; it is still accepted and means the same as an integer `amount`. The total your browser read off the checkout page, in the smallest unit, with `page_currency`. The SDK sends it when you give it a reader. Used only when neither the processor's request nor `amount` names an amount. The payment processor: `stripe`, `shopify`, `square`, `recurly`, `razorpay`, `adyen`, `tranzila`. `token` (default), `cse` (Adyen), or `hosted_form` (Tranzila). Required for `cse` and `hosted_form`. Which of the user's vaulted cards should pay. Defaults to the most recently added. The user can still pick another. The captured processor request: `url`, `method`, `headers`, `body`. ```bash cURL theme={null} curl -X POST https://api.agentcard.sh/api/v2/checkout/authorizations \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "user": "usr_8f3k2m", "merchant": "Example Shop", "checkout_origin": "https://shop.example.com", "amount": 2306, "currency": "usd", "psp": "stripe", "request": { "url": "https://api.stripe.com/v1/tokens", "method": "POST", "headers": { "content-type": "application/x-www-form-urlencoded" }, "body": "card[number]=&..." } }' ``` ```json 201 theme={null} { "id": "cauth_2q9d1x8f3k2m4t7w", "object": "checkout_authorization", "status": "awaiting_approval", "mode": "token", "amount": 2306, "currency": "usd", "amount_display": "$23.06", "amount_authority": "agent", "amount_verified": null, "charged_amount": null, "charged_currency": null, "replay_attempted": false, "approvalUrl": "https://vault.agentcard.sh/authorize?id=cauth_2q9d1x8f3k2m4t7w", "expiresAt": "2026-08-27T21:15:00Z" } ``` **Errors.** `400 mode_required`, `400 mode_mismatch`, `400 currency_required` / `amount_required` (half a pair), `400 amount_invalid` (a non-integer number, or more decimals than the currency has), `400 amount_ambiguous` (a string without a decimal point), `404 card_not_found`, `409 amount_mismatch` (the processor's amount disagrees with `amount`; carries `expected_cents` and `actual_cents`), `409 intent_not_confirmable`, `502 amount_unverifiable`. `403` with a rule's code (`merchant_denied`, `category_unknown`, `geo_unknown`, `currency_denied`, `spend_rate_exceeded`, and the others) when one of your [attached presets](/vault/set-rules-on-a-card) refuses the purchase; the body carries `preset`, `attachment`, `rule`, `message`, `stage: "create"`, and `refusals`, every preset that refused with its `preset`, `attachment`, and `rule` (the fields before it are the first entry), and no authorization is created. Authorizations expire after 15 minutes without approval. When you fulfill the paused browser request with the approved `response`, add `access-control-allow-origin` echoing the request's `Origin` and `access-control-allow-credentials: true`, or the page rejects it. # Get a checkout authorization Source: https://docs.agentcard.sh/api-reference/vault/authorizations-get GET https://api.agentcard.sh/api/v2/checkout/authorizations/{id} The authoritative state of one authorization, including the processor response once approved. The authorization id. ```bash cURL theme={null} curl https://api.agentcard.sh/api/v2/checkout/authorizations/cauth_2q9d1x8f3k2m4t7w \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json 200 theme={null} { "id": "cauth_2q9d1x8f3k2m4t7w", "object": "checkout_authorization", "status": "approved", "mode": "token", "psp": "stripe", "merchant": "shop.example.com", "amount": 2306, "currency": "usd", "amount_display": "$23.06", "amount_authority": "processor", "amount_verified": true, "charged_amount": 2306, "charged_currency": "usd", "charged_kind": "captured", "replay_attempted": true, "response": { "status": 200, "headers": { "content-type": "application/json" }, "body": "{\"id\":\"tok_…\"}" } } ``` `awaiting_approval`, `approved`, `submitted_on_device` (hosted-form processors only; no processor evidence exists), `declined`, or `expired`. On `approved` in `token` mode: the processor's response to replay into the paused request. On `approved` in `cse` mode: the encrypted card fields to write into the paused body, plus `remove` for sibling keys to drop. The amount, in the currency's smallest unit, with `currency` and `amount_display` (the human form, `$23.06`). Null until an authority names one. Who named the amount: `processor` (the payment request, or the Stripe intent read back), `agent` (the `amount` your agent sent), `page` (the total read off the checkout page), or `none`. The highest known wins, and the processor's is read right before the card is sent. Whether what the processor charged matches the approved amount. Null when there was nothing to compare. `captured`, `authorized`, `none`, or null. On `declined`: `user_declined`, `amount_mismatch`, `intent_not_confirmable`, or `processor_refused` (with `psp_error_code`). Optional on a Razorpay `processor_refused` result: bounded `reason`, `source`, `step`, `payment_id`, and `order_id` identifiers reported by the processor. Raw response bodies and descriptions are excluded. Older records may not contain these details. True when a device may already have sent the card. On `expired`, treat the outcome as unknown and check the processor. An approval is not an order. Confirm the order with the merchant before acting on it. `processor_refused` means the device reported a rejected processor request. A generic code such as Razorpay's `BAD_REQUEST_ERROR` does not establish an issuer decline or prove that nothing was charged. Check the merchant payment status before starting another attempt. # List a user's vaulted cards Source: https://docs.agentcard.sh/api-reference/vault/cards-list GET https://api.agentcard.sh/api/v2/vault_cards Display fields for the cards a user has stored. Never card data. Use it to skip enrollment for a returning user, and to pick the `id` to pass as `card_id` on a checkout authorization. The user whose cards to list. ```bash cURL theme={null} curl "https://api.agentcard.sh/api/v2/vault_cards?user_id=usr_8f3k2m" \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json 200 theme={null} { "object": "list", "data": [ { "id": "vc_9m4t2p", "brand": "visa", "last4": "4832", "exp_month": 12, "exp_year": 2029, "created_at": "2026-09-02T18:41:07Z" } ] } ``` The response never includes a card number or anything that could decrypt one. # Assess checkout cases Source: https://docs.agentcard.sh/api-reference/vault/coverage-assess POST https://api.agentcard.sh/api/v2/checkout/coverage/assess Label up to 1,000 observed processor requests as recognized, unsupported, or unverified before you build. Send the processor endpoints your automation observed at your target merchants, without card data or request bodies. Each case comes back labelled, with a weighted share of your traffic the Vault recognizes. 1 to 1,000 cases with unique `id`s. Your label for the case. The processor URL the checkout page called. Default `POST`. `one_time` (default), `save_card`, `subscription_initial`, `subscription_renewal`. Relative checkout traffic. Default 1. Default false. ```bash cURL theme={null} curl -X POST https://api.agentcard.sh/api/v2/checkout/coverage/assess \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "cases": [ { "id": "merchant-a-one-time", "request_url": "https://api.stripe.com/v1/payment_methods", "method": "POST", "scenario": "one_time", "weight": 40, "requires_3ds": true } ] }' ``` ```json 200 theme={null} { "object": "checkout_coverage_assessment", "recognized_traffic_share": 1, "purchase_success_rate": null, "counts": { "recognized": 1, "unsupported": 0, "unverified": 0 }, "results": [ { "id": "merchant-a-one-time", "status": "recognized", "reason": "request_format_recognized_not_purchase_verified", "psp": "stripe", "mode": "token", "next_action": "validate_checkout" } ] } ``` `recognized` (a known processor request format), `unsupported` (for example an iframe-bound VGS tokenization or a non-POST), or `unverified` (a renewal the merchant bills itself, or a format the registry does not know). Always null. Endpoint recognition is not a purchase test. # Get checkout coverage Source: https://docs.agentcard.sh/api-reference/vault/coverage-get GET https://api.agentcard.sh/api/v2/checkout/coverage What the direct SDK can pause and complete, processor by processor, with its modes and limitations. A richer view than [recognizers](/api-reference/vault/recognizers): for each processor it says how the card reaches it, where a bank challenge surfaces, and what the Vault does not cover (subscription renewals, unbound Stripe tokens). It describes the direct SDK only. KERNEL's native integration has its own coverage. ```bash cURL theme={null} curl https://api.agentcard.sh/api/v2/checkout/coverage \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json 200 theme={null} { "object": "checkout_coverage", "integration": "direct_sdk", "merchant_confirmation_required": true, "validation": "merchant_and_browser_test_required", "processors": [ { "psp": "stripe", "mode": "token", "methods": ["POST"], "hosts": ["api.stripe.com"], "client_side_encryption": "not_supported", "challenge_surface": "merchant_browser", "outcome": "merchant_confirmation_required", "request_flows": [ { "flow": "tokenization", "coverage": "tokenization_response_only", "amount_authority": "agent" }, { "flow": "direct_payment_intent_confirm", "coverage": "card_bearing_template_required", "amount_authority": "requires_amount_and_currency_verification" }, { "flow": "token_to_payment_intent_confirm", "coverage": "unsupported_unbound_intent" } ], "limitations": [] } ] } ``` Recognition is not a purchase test. Validate each merchant and browser combination end to end before marking it covered. # Vault Source: https://docs.agentcard.sh/api-reference/vault/overview Store a user's own card once, then authorize checkouts that pay with it. The **Vault** holds a user's own cards, encrypted on their device with a passkey. Three resources make it up: * A **vault session** is a single-use link you send the user. They open it, type their card, and save it with a passkey and a master password. When it links you get their `user_id`. * A **checkout authorization** is a paused payment. Your browser (or the SDK) captured the request the merchant's page sent to its payment processor with a placeholder card; you post it here, the user approves on their own device, and that device pays with the real card. * A checkout preparation lets the user approve before your browser starts a short-lived card request. The SDK applies that approval to one fresh request on Square, Braintree, Worldpay, Bambora or Mercado Pago. Every call takes a platform access token. An API key is refused with `400 client_credentials_required`. ## The vault session object | Field | Type | Description | | ------------------------------- | --------------- | ------------------------------------------------------------------------ | | `object` | string | `vault_session` | | `id` | string | `vs_…`. Read the session by this id, never by the token inside `url`. | | `status` | string | `pending`, `linked`, or `expired`. | | `url` | string | The single-use link to send the user. | | `user_id` | string or null | The user the session belongs to. Null on an open session until it links. | | `linked_at` | string or null | When the session linked. | | `poll_interval` | integer | Seconds to wait between reads. | | `code_sends`, `verify_attempts` | integer or null | Connected sessions only: how many times the code was sent and tried. | | `expires_at` | string | Lifetime end. Default 24 hours after creation. | | `test_mode` | boolean | Whether a sandbox credential created it. | ```json theme={null} { "object": "vault_session", "id": "vs_2q9d1x8f3k2m4t7w", "status": "linked", "url": "https://vault.agentcard.sh/v?vs=vs_2q9d1x8f3k2m4t7w.3k1v…", "user_id": "usr_8f3k2m", "linked_at": "2026-09-02T18:41:07Z", "poll_interval": 3, "expires_at": "2026-09-03T18:00:00Z", "test_mode": false } ``` ## The vault card object Display fields only. Never a card number or anything that could decrypt one. | Field | Type | Description | | ----------------------- | ------- | --------------------------------------------------------- | | `id` | string | `vc_…`. Pass it as `card_id` to pay with a specific card. | | `brand` | string | `visa`, `mastercard`, `amex`, `discover`, … | | `last4` | string | | | `exp_month`, `exp_year` | integer | | | `created_at` | string | | ## The checkout authorization object | Field | Type | Description | | ---------------------------------------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `object` | string | `checkout_authorization` | | `id` | string | `cauth_…` | | `status` | string | `awaiting_approval`, `approved`, `submitted_on_device` (hosted-form processors), `declined`, `expired`. | | `mode` | string | `token`, `cse` (Adyen), or `hosted_form` (Tranzila). How the card reaches the processor. | | `psp` | string | The processor: `stripe`, `shopify`, `square`, `recurly`, `razorpay`, `adyen`, `tranzila`. | | `merchant` | string | What the user saw on the approval screen. | | `amount`, `currency`, `amount_display` | integer, string, string | The amount in the currency's smallest unit (2306 for \$23.06), its ISO code, and the human form (`$23.06`). Null until an authority names one. | | `amount_authority` | string | Who named the amount: `processor` (the payment request, or the Stripe intent read back), `agent` (your `amount`), `page` (the checkout page's total), or `none`. | | `amount_verified` | boolean or null | After the charge: whether the processor charged the approved amount. Null when there was nothing to compare. | | `charged_amount`, `charged_currency`, `charged_kind` | | What was collected. `charged_kind` is `captured`, `authorized`, `none`, or null. | | `approvalUrl` | string | The link to send the user while `awaiting_approval`. | | `response` | object | On `approved` in `token` mode: the processor's response to replay into the paused request. | | `substitutions` | object | On `approved` in `cse` mode: encrypted fields to write into the paused body, plus `remove`. | | `reason` | string | On `declined`: `user_declined`, `amount_mismatch`, `intent_not_confirmable`, `processor_refused`, `merchant_request_aborted`. | | `psp_error_code` | string or null | The processor's refusal code when `reason` is `processor_refused`. | | `processor_error` | object | Optional bounded Razorpay `reason`, `source`, `step`, `payment_id`, and `order_id` identifiers on `processor_refused`. No raw processor body or description. A generic request error does not prove issuer decline or no charge; reconcile before retrying. | | `replay_attempted` | boolean | True when a device may already have sent the card. | | `expiresAt` | string | 15 minutes after creation. | ```json theme={null} { "id": "cauth_2q9d1x8f3k2m4t7w", "object": "checkout_authorization", "status": "approved", "mode": "token", "psp": "stripe", "merchant": "shop.example.com", "amount": 2306, "currency": "usd", "amount_display": "$23.06", "amount_authority": "processor", "amount_verified": true, "charged_amount": 2306, "charged_currency": "usd", "charged_kind": "captured", "replay_attempted": true } ``` ## Approve before Pay Ask for approval before starting the merchant’s card request. A preparation carries the same displayed amount and merchant fields as an authorization, plus: | Field | Type | Description | | ------------------ | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | | `object` | string | `checkout_preparation` | | `id` | string | `cprep_…` | | `status` | string | `awaiting_approval` → `ready` → `bound`, or `cancelled` / `expired`. | | `checkout_key` | string | Your key for repeating the create request without creating another preparation. | | `merchant_origin` | string | The exact origin of the merchant page. | | `psp` | string | `square`, `braintree`, `worldpay`, `bambora` or `mercado_pago`. | | `environment` | string | `production` or `sandbox` for Square, Braintree and Worldpay; `shared` for Bambora and Mercado Pago. Shared endpoints do not establish processor test mode. | | `card_id` | string or null | The card the user selected (or you preselected). | | `approvalUrl` | string | Present while `awaiting_approval` or `ready`. | | `ready_expires_at` | string or null | How long a `ready` approval can still be bound. | | `authorization_id` | string or null | Set once `bound`. The authorization then speaks for the payment. | | `payment_status` | string | `not_started`, or `authorization_pending` once bound. | ## Endpoints | Endpoint | | | -------------------------------------------------- | ---------------------------------------------------------------------------------------------- | | `POST /api/v2/vault_sessions` | [Create a vault session](/api-reference/vault/sessions-create) | | `GET /api/v2/vault_sessions/{id}` | [Get a vault session](/api-reference/vault/sessions-get) | | `GET /api/v2/vault_cards` | [List a user's vaulted cards](/api-reference/vault/cards-list) | | `POST /api/v2/checkout/vault_link` | [Send a user their vault link](/api-reference/vault/vault-link): Agentcard delivers it for you | | `POST /api/v2/checkout/authorizations` | [Create a checkout authorization](/api-reference/vault/authorizations-create) | | `GET /api/v2/checkout/authorizations/{id}` | [Get a checkout authorization](/api-reference/vault/authorizations-get) | | `POST /api/v2/checkout/authorizations/{id}/cancel` | [Cancel a checkout authorization](/api-reference/vault/authorizations-cancel) | | `GET /api/v2/checkout/recognizers` | [List recognized processors](/api-reference/vault/recognizers) | | `GET /api/v2/checkout/coverage` | [Get checkout coverage](/api-reference/vault/coverage-get) | | `POST /api/v2/checkout/coverage/assess` | [Assess checkout cases](/api-reference/vault/coverage-assess) | | `POST /api/v2/checkout/preparations` | [Create a checkout preparation](/api-reference/vault/preparations-create) | | `GET /api/v2/checkout/preparations/{id}` | [Get a checkout preparation](/api-reference/vault/preparations-get) | | `POST /api/v2/checkout/preparations/{id}/cancel` | [Cancel a checkout preparation](/api-reference/vault/preparations-cancel) | Webhooks: `vault.session_linked`, `vault.card_stored`, `checkout_authorization.approved`, `checkout_authorization.submitted`, `checkout_authorization.declined`, `checkout_authorization.expired`, `checkout_authorization.amount_mismatch`. The `@agent-cards/checkout` SDK wraps the authorization and preparation calls for Playwright and CDP browsers. See [Creating a cart](/vault/creating-a-cart). # Cancel a checkout preparation Source: https://docs.agentcard.sh/api-reference/vault/preparations-cancel POST https://api.agentcard.sh/api/v2/checkout/preparations/{id}/cancel Abandon a Square preparation that has not been bound to a merchant request. The preparation id. ```bash cURL theme={null} curl -X POST https://api.agentcard.sh/api/v2/checkout/preparations/cprep_66d0a1f2b3c4d5e6f7a8b9c0/cancel \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{}' ``` ```json 200 theme={null} { "id": "cprep_66d0a1f2b3c4d5e6f7a8b9c0", "object": "checkout_preparation", "status": "cancelled" } ``` **Errors.** `409 preparation_bound`: the preparation already belongs to a merchant request. The error carries `authorization_id`; cancel that authorization instead, if it has not started replaying. The body must be an empty object. # Approve before checkout Source: https://docs.agentcard.sh/api-reference/vault/preparations-create POST https://api.agentcard.sh/api/v2/checkout/preparations Ask the user to approve before a short-lived card tokenization request starts. Ask the user to approve the merchant and amount before your browser clicks Pay. The user picks a card and keeps the approval page open. Your browser then starts one fresh card request while the approval is ready. Approval does not mean the merchant received payment. Use `controller.prepare()` with the checkout SDK on Playwright or CDP. Call this API directly only when your integration handles request interception. Create the preparation before the first card request; a preparation cannot resume an earlier request that timed out. The connected user whose added card pays. The merchant name shown to the user. Up to 120 printable characters. The amount the user approves: an integer in the currency's smallest unit (`100` with `usd` displays `$1.00`), or a decimal string in normal units (`"1.00"`). A card token does not enforce the merchant's eventual charge. The ISO 4217 currency code, such as `usd`. `square`, `braintree`, `worldpay`, `bambora` or `mercado_pago`. Use `token`. A stable key for this checkout attempt, from 16 to 128 characters. An identical request returns the existing preparation; a changed merchant, amount, card or other approved value is refused. The exact HTTPS merchant origin, such as `https://merchant.example`. Use `http://localhost` only for local checkout. Use the processor's environment from the table below. Preselect one of the user's added cards. | Processor | `environment` | Request that can use the approval | | ------------ | ------------------------- | ---------------------------------------------------------------------------------------------------------- | | Square | `production` or `sandbox` | Card tokenization on the matching Square host. | | Braintree | `production` or `sandbox` | A single guest `TokenizeCreditCard` mutation with explicit `options.validate: false`. | | Worldpay | `production` or `sandbox` | A fresh card request to `/sessions/card` on the matching Access Worldpay host. | | Bambora | `shared` | A fresh card request to `/scripts/tokenization/tokens` on `api.bam.shift4api.net` or `api.na.bambora.com`. | | Mercado Pago | `shared` | A fresh card request to `api.mercadopago.com/v1/card_tokens`. | Bambora and Mercado Pago use the same endpoint for test and live requests. `shared` does not select test mode. Configure the merchant's processor account for testing; Agentcard cannot determine that account's mode from the request URL or a key prefix. The response's `sandbox` field describes the connected app's Agentcard mode separately. Braintree configuration queries do not consume an approval. Braintree saved-card operations, compound mutations and its REST fallback cannot use a preparation. Worldpay, Bambora and Mercado Pago preparations require fresh card details; saved-card and recurring requests cannot use the approval. The request and responses below come from a local API test with sample user and card records. The test made no processor request. Replace the user and card identifiers with your connected user's values. ## Send the request ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v2/checkout/preparations \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "user": "cmturxope0000cbpss123jxee", "merchant": "Merchant example", "amount": 100, "currency": "usd", "card_id": "cmturxopj0004cbpswhqdeyju", "psp": "worldpay", "mode": "token", "checkout_key": "ed8f8370-2e7a-4255-b1eb-116f1220d687", "merchant_origin": "https://merchant.example", "environment": "sandbox" }' ``` ```json theme={null} { "id": "cprep_2e357e4b01c88063fd805764", "object": "checkout_preparation", "status": "awaiting_approval", "user": "cmturxope0000cbpss123jxee", "merchant": "Merchant example", "merchant_origin": "https://merchant.example", "amount": 100, "currency": "usd", "amount_display": "$1.00", "amount_authority": "agent", "psp": "worldpay", "mode": "token", "environment": "sandbox", "sandbox": true, "testMode": true, "vaultOrigin": "https://vault.agentcard.sh", "url": "https://try.access.worldpay.com/sessions/card", "card_id": "cmturxopj0004cbpswhqdeyju", "cardId": "cmturxopj0004cbpswhqdeyju", "checkout_key": "ed8f8370-2e7a-4255-b1eb-116f1220d687", "binding_hash": null, "expiresAt": "2026-09-10T00:28:24.470Z", "ready_expires_at": null, "createdAt": "2026-09-10T00:13:24.471Z", "authorization_id": null, "payment_status": "not_started", "approvalUrl": "https://vault.agentcard.sh/authorize?id=cprep_2e357e4b01c88063fd805764" } ``` `awaiting_approval` waits for the user. `ready` allows one fresh request until `ready_expires_at`. `bound` links to `authorization_id`; `cancelled` and `expired` cannot be used. Deliver the link when the preparation is created. The user must keep the same page open after approving. Start Pay immediately after the preparation becomes `ready`. Readiness lasts at most 30 seconds. A changed checkout, navigation, cancellation or early request prevents the SDK from using the approval. Check the merchant's outcome before creating a new checkout attachment; the SDK never retries the payment automatically. ## Correct the environment An unsupported processor and environment combination returns HTTP `400`. For example, Worldpay with `environment: "shared"` returned this response from the local API test: ```json theme={null} { "error": { "code": "invalid_request", "message": "Choose an environment supported by this processor.", "docs": "https://docs.agentcard.sh" } } ``` Retry with `environment: "sandbox"` for the Worldpay sandbox: ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v2/checkout/preparations \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "user": "cmturxope0000cbpss123jxee", "merchant": "Merchant example", "amount": 100, "currency": "usd", "card_id": "cmturxopj0004cbpswhqdeyju", "psp": "worldpay", "mode": "token", "checkout_key": "ed8f8370-2e7a-4255-b1eb-116f1220d687", "merchant_origin": "https://merchant.example", "environment": "sandbox" }' ``` | Code | Meaning | What to do | | ----------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------ | | `invalid_request` | A required value is missing or invalid, including an unsupported environment. | Correct the named value and resend the create request. | | `not_found` | The user is not connected to your app. | Connect the user before creating a preparation. | | `card_not_found` | The requested card is unavailable to that user. | Choose a card from the user's added cards. | # Wait for checkout approval Source: https://docs.agentcard.sh/api-reference/vault/preparations-get GET https://api.agentcard.sh/api/v2/checkout/preparations/{id} Read a preparation until the user is ready for a fresh card request. Poll the preparation after delivering its approval link. Start the merchant's Pay action only after `status` becomes `ready` and before `ready_expires_at`. The user must keep the approval page open. The preparation identifier returned by the create request. ```bash theme={null} curl https://api.agentcard.sh/api/v2/checkout/preparations/cprep_2e357e4b01c88063fd805764 \ -H "Authorization: Bearer $ORG_TOKEN" ``` The response below comes from the same local API test as [Create a checkout preparation](/api-reference/vault/preparations-create). The sample approval has not sent a processor request. ```json theme={null} { "id": "cprep_2e357e4b01c88063fd805764", "object": "checkout_preparation", "status": "ready", "user": "cmturxope0000cbpss123jxee", "merchant": "Merchant example", "merchant_origin": "https://merchant.example", "amount": 100, "currency": "usd", "amount_display": "$1.00", "amount_authority": "agent", "psp": "worldpay", "mode": "token", "environment": "sandbox", "sandbox": true, "testMode": true, "vaultOrigin": "https://vault.agentcard.sh", "url": "https://try.access.worldpay.com/sessions/card", "card_id": "cmturxopj0004cbpswhqdeyju", "cardId": "cmturxopj0004cbpswhqdeyju", "checkout_key": "ed8f8370-2e7a-4255-b1eb-116f1220d687", "binding_hash": "239d8ce07b3c4a23a60f9bffe718aea63a3940dd62f2454041440d35401ce3e2", "expiresAt": "2026-09-10T00:28:24.470Z", "ready_expires_at": "2026-09-10T00:13:54.494Z", "createdAt": "2026-09-10T00:13:24.471Z", "authorization_id": null, "payment_status": "not_started", "approvalUrl": "https://vault.agentcard.sh/authorize?id=cprep_2e357e4b01c88063fd805764" } ``` After `status` becomes `bound`, read the linked authorization with [Get a checkout authorization](/api-reference/vault/authorizations-get). The preparation then reports `payment_status: "authorization_pending"`; the merchant's receipt or payment record determines whether the purchase completed. # Attach a preset Source: https://docs.agentcard.sh/api-reference/vault/presets-attach PUT https://api.agentcard.sh/api/v2/vault/presets/{name}/attachments Attach a saved preset to one of a user's stored cards. Only the purchases paid with that card are judged. A preset applies only where it is attached. Attach it to a stored card and every purchase paid with that card is judged. A cap counts the purchases paid with that card. Attaching twice is one attachment. Takes a platform access token or an API key. See [Set rules on a card](/vault/set-rules-on-a-card). A preset attached to a card is judged when your agent opens the purchase if the card is already known, because the agent pinned it with `card_id` or the user has exactly one stored card; otherwise it is judged right before the card is sent, once the user has unlocked it. The preset's name. `card`. A stored card id from [List a user's vaulted cards](/api-reference/vault/cards-list) or the `vault.card_stored` event. ```bash cURL theme={null} curl -X PUT https://api.agentcard.sh/api/v2/vault/presets/office-supplies/attachments \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"kind": "card", "target_id": "CARD_ID"}' ``` ```json 200 theme={null} { "object": "vault_preset", "name": "office-supplies", "id": "cmtvwbc0g000bjpcc88yiyx8z", "version": 1, "summary": "Up to $50.00 per day. Merchants: EXAMPLE SHOP, ACME. Currency: USD.", "attachments": [ { "kind": "card", "target_id": "CARD_ID", "last4": "7318" } ] } ``` **Errors.** `404 preset_not_found` when no preset of that name is saved. `404 card_not_found` when the card id is not a card stored by one of your users. `400 invalid_request` for a `kind` other than `card`, or a missing `target_id`. # Delete a preset Source: https://docs.agentcard.sh/api-reference/vault/presets-delete DELETE https://api.agentcard.sh/api/v2/vault/presets/{name} Delete a preset and every attachment it had. Its rules stop applying everywhere at once. Save the name again later and its caps count from nothing. Takes a platform access token or an API key. See [Set rules on a card](/vault/set-rules-on-a-card). The preset's name. ```bash cURL theme={null} curl -X DELETE https://api.agentcard.sh/api/v2/vault/presets/office-supplies \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json 200 theme={null} { "object": "vault_preset", "name": "office-supplies", "deleted": true } ``` **Errors.** `404 preset_not_found` when no preset of that name is saved. # Detach a preset Source: https://docs.agentcard.sh/api-reference/vault/presets-detach DELETE https://api.agentcard.sh/api/v2/vault/presets/{name}/attachments Detach a preset from a stored card, one API client, or the company. The purchases it covered there stop being judged by it. Send the same `kind` and `target_id` you attached with, in the body or as query parameters. The preset stays in your library, attached wherever else you put it. Takes a platform access token or an API key. See [Set rules on a card](/vault/set-rules-on-a-card). The preset's name. `card`. The stored card id the preset was attached to. ```bash cURL theme={null} curl -X DELETE https://api.agentcard.sh/api/v2/vault/presets/office-supplies/attachments \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"kind": "card", "target_id": "CARD_ID"}' ``` ```json 200 theme={null} { "object": "vault_preset", "name": "office-supplies", "id": "cmtvwbc0g000bjpcc88yiyx8z", "version": 1, "summary": "Up to $50.00 per day. Merchants: EXAMPLE SHOP, ACME. Currency: USD.", "attachments": [] } ``` **Errors.** `404 preset_not_found` when no preset of that name is saved. `400 invalid_request` for a missing `target_id`, or for a `kind` other than `card`, the only kind; any other value is refused as unknown. # Get a preset Source: https://docs.agentcard.sh/api-reference/vault/presets-get GET https://api.agentcard.sh/api/v2/vault/presets/{name} One saved preset, its rules in plain words, and where it is attached. Takes a platform access token or an API key. See [Set rules on a card](/vault/set-rules-on-a-card). The preset's name. ```bash cURL theme={null} curl https://api.agentcard.sh/api/v2/vault/presets/office-supplies \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json 200 theme={null} { "object": "vault_preset", "name": "office-supplies", "id": "cmtvwbc0g000bjpcc88yiyx8z", "version": 1, "summary": "Up to $50.00 per day. Merchants: EXAMPLE SHOP, ACME. Currency: USD.", "attachments": [ { "kind": "card", "target_id": "cmtvwbbzj0006jpccycjrkqy4", "last4": "7318" } ] } ``` **Errors.** `404 preset_not_found` when no preset of that name is saved. # List presets Source: https://docs.agentcard.sh/api-reference/vault/presets-list GET https://api.agentcard.sh/api/v2/vault/presets Every preset your company has saved, each with where it is attached. Presets are optional: a company that has saved none gets an empty list, and nothing is filtered until a preset is attached. Takes a platform access token or an API key. See [Set rules on a card](/vault/set-rules-on-a-card). ```bash cURL theme={null} curl https://api.agentcard.sh/api/v2/vault/presets \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json 200 theme={null} { "object": "list", "data": [ { "object": "vault_preset", "name": "office-supplies", "id": "cmtvwbc0g000bjpcc88yiyx8z", "version": 1, "summary": "Up to $50.00 per day. Merchants: EXAMPLE SHOP, ACME. Currency: USD.", "attachments": [ { "kind": "card", "target_id": "cmtvwbbzj0006jpccycjrkqy4", "last4": "7318" } ] } ] } ``` One entry per preset: `name`, the `id` and `version` of the rules in force, `summary` in plain words, and `attachments`, each with `kind` (`card`), `target_id` (the stored card id), and the card's `last4`. # Save a preset Source: https://docs.agentcard.sh/api-reference/vault/presets-put PUT https://api.agentcard.sh/api/v2/vault/presets/{name} Save a named preset, or replace its rules. Saving filters nothing until the preset is attached. The rules are replaced, not merged: send every rule the preset should hold. A replacement keeps every attachment, and purchases already counted toward a cap stay counted, so replacing the rules never resets a rolling window. Saving a preset attaches it to nothing; attach it to a stored card. Takes a platform access token or an API key. See [Set rules on a card](/vault/set-rules-on-a-card). Write the rules one of three ways: as the fields below, as `preset` with a built-in name (`daily`, `cli_only`, `weekday_meals`, or `ai_labs`), or as `privileges`, an array of rules in the same shape a card preset takes. 1 to 64 letters, digits, hyphens or underscores, starting with a letter or digit. Cap on the purchases under each attachment, over all time, in US dollars. Rolling 24-hour cap, in US dollars, for the purchases under each attachment. Rolling 7-day cap, in US dollars. Rolling 30-day cap, in US dollars. Categories the merchant must be in, comma-separated: `meals`, `groceries`, `travel`, `software`, `ai`, `wellness`, `retail`. Judged on the merchant Agentcard names from `checkout_origin` and the payment request, never on the `merchant` text. Comma-separated patterns the merchant's name or checkout host must match, such as `EXAMPLE SHOP,shop.example.com`. The `merchant` text your agent sends is not matched. Places the merchant must be in, comma-separated: a country (`US`, `Canada`), a US state (`California`, `US-CA`), or a region (`europe`, `north-america`, `apac`). The currencies a purchase may be in, comma-separated, by code or common name: `usd,eur` or `dollars,euros`. `mon,tue`, or `weekdays` / `weekends`. For example `9-17`, 24-hour clock, in `timezone`. IANA zone for `only_days` and `only_hours`. Default `UTC`. Where purchases may come from. Vault purchases come from your agent and count as `api`. What the preset does when a purchase breaks any of its rules: `strict` refuses it (the default), `watch` lets it through and tells you. A built-in name instead of the fields above. The rules as an array, for a rule the fields do not cover, such as `{"kind": "merchant_allow", "patterns": ["BRAXTER'S DELI"]}`. ```bash cURL theme={null} curl -X PUT https://api.agentcard.sh/api/v2/vault/presets/office-supplies \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"per_day": 50, "only_merchants": "EXAMPLE SHOP,ACME", "currencies": "usd"}' ``` ```json 200 theme={null} { "object": "vault_preset", "name": "office-supplies", "id": "cmtvwbc0g000bjpcc88yiyx8z", "version": 1, "summary": "Up to $50.00 per day. Merchants: EXAMPLE SHOP, ACME. Currency: USD.", "attachments": [] } ``` A merchant Agentcard does not know has no category and no country, so a category or place rule on a `strict` preset refuses a purchase there with `category_unknown` or `geo_unknown`; see [Where the merchant comes from](/vault/set-rules-on-a-card#where-the-merchant-comes-from). **Errors.** `400 policy_invalid` when the name or the rules cannot be read; the message names the field or the rule. `502 policy_update_failed` when the rules could not be saved; nothing changed. # List recognized processors Source: https://docs.agentcard.sh/api-reference/vault/recognizers GET https://api.agentcard.sh/api/v2/checkout/recognizers The processor request formats Agentcard can pause and complete. The SDK reads this on every `syncRegistry()`, so new processors reach your agents without an SDK release. Call it yourself if you run your own interception: pause requests that match an entry and leave everything else untouched. Comma-separated modes to include: `token`, `cse`, `hosted_form`. Default `token,cse`. Ask for `hosted_form` only if your runtime can finish a hosted-form submission. ```bash cURL theme={null} curl "https://api.agentcard.sh/api/v2/checkout/recognizers?modes=token,cse" \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json 200 theme={null} { "object": "list", "data": [ { "psp": "stripe", "mode": "token", "url": "https://api.stripe.com/v1/tokens", "methods": ["POST"] }, { "psp": "stripe", "mode": "token", "url": "https://api.stripe.com/v1/payment_methods", "methods": ["POST"] }, { "psp": "shopify", "mode": "token", "url": "https://deposit.us.shopifycs.com/sessions", "methods": ["POST"] }, { "psp": "adyen", "mode": "cse", "url": "https://checkoutshopper-live.adyen.com/checkoutshopper/v1/sessions/*/payments", "methods": ["POST"], "encrypted_fields": ["encryptedCardNumber", "encryptedExpiryMonth", "encryptedExpiryYear", "encryptedSecurityCode"] } ] } ``` Supported today: Stripe, Shopify, Square, Recurly, Razorpay (`token`), Adyen (`cse`), Tranzila (`hosted_form`). `/v2/checkout/*` and `/api/v2/checkout/*` are the same routes. # Create a vault session Source: https://docs.agentcard.sh/api-reference/vault/sessions-create POST https://api.agentcard.sh/api/v2/vault_sessions Create a single-use link the user opens to store a card behind their passkey. Create the session, then deliver `url` to the user in the thread or app you already share with them. One link is one enrollment: send it to one person and bind the `user_id` you receive to them. Omit for a new user: the session is **open**, the user is created at enrollment, and their id arrives in `vault.session_linked` (or on the session read). Pass an id you already hold and the session is **connected**: opening the link sends a one-time code to the contact on that account and verifying it signs the user in. Connected sessions only, E.164. Used only when the account has no contact on file at all. Refused on open sessions. Lifetime in seconds, 60 to 172800. Default 24 hours. Sessions are single use. ```bash cURL theme={null} curl -X POST https://api.agentcard.sh/api/v2/vault_sessions \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{}' ``` ```json 201 theme={null} { "object": "vault_session", "id": "vs_2q9d1x8f3k2m4t7w", "user_id": null, "url": "https://vault.agentcard.sh/v?vs=vs_2q9d1x8f3k2m4t7w.3k1v…", "channel": null, "destination": null, "expires_at": "2026-08-28T21:00:00Z", "poll_interval": 3, "test_mode": false } ``` Read the session by this id, never by the token inside `url`. The link to send the user. Null on an open session until it links. Seconds to wait between reads if you poll. **Errors.** `400 client_credentials_required` (API key used), `400 contact_missing` (connected session, nothing to send a code to), `429 rate_limited` (open sessions are budgeted at 200 per organization per rolling 24 hours). # Get a vault session Source: https://docs.agentcard.sh/api-reference/vault/sessions-get GET https://api.agentcard.sh/api/v2/vault_sessions/{id} Read a session until the user finishes. The poll alternative to the vault.session_linked webhook. The `id` from the create response. Not the `vs=` token inside `url`. ```bash cURL theme={null} curl https://api.agentcard.sh/api/v2/vault_sessions/vs_2q9d1x8f3k2m4t7w \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json 200 theme={null} { "object": "vault_session", "id": "vs_2q9d1x8f3k2m4t7w", "status": "linked", "user_id": "usr_8f3k2m", "linked_at": "2026-09-02T18:41:07Z", "poll_interval": 3, "code_sends": null, "verify_attempts": null, "channel": null, "expires_at": "2026-09-03T18:00:00Z", "created_at": "2026-09-02T18:00:00Z", "test_mode": false } ``` `pending` (wait `poll_interval` seconds and read again), `linked` (store `user_id`, stop), or `expired` (create a new session). The id to store once `linked`. A connected session carries it from the start. How many times a connected user asked for their code. Null on open sessions. How many codes a connected user tried. Null on open sessions. **Budget.** 40 reads a minute per session, 600 a minute across your account. Honor `poll_interval` and you never see a `429`. Only the client that created the session can read it; anything else is a `404`. # Send a user their vault link Source: https://docs.agentcard.sh/api-reference/vault/vault-link POST https://api.agentcard.sh/api/v2/checkout/vault_link Have Agentcard text or email a connected user the link that adds a card to their vault. The delivered version of [Create a vault session](/api-reference/vault/sessions-create). Agentcard creates a connected session for the user and sends the link to the phone or email on their account. Use it when you don't run your own messaging channel. If you do, create the session yourself and send its `url`. The connected user to send the link to. ```bash cURL theme={null} curl -X POST https://api.agentcard.sh/api/v2/checkout/vault_link \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"user": "usr_8f3k2m"}' ``` ```json 202 theme={null} { "object": "vault_link", "sent": true, "user": "usr_8f3k2m" } ``` True when Agentcard delivered the link. On a dedicated branded Vault, automatic delivery is off: `sent` is false and the response carries `url` for you to deliver. **Errors.** `404 not_found` (user not connected to your platform), `422 contact_missing` (no phone or email on file to receive the code). # Create a wallet link Source: https://docs.agentcard.sh/api-reference/wallet-links/create POST https://api.agentcard.sh/api/v2/wallet_links Mint a short-lived link that opens the user's wallet. Text the URL as is. The connected user. Recorded consent is required first (`POST /api/v2/connect/consent`). Lifetime in seconds, 60 to 86400. Default 15 minutes. ```bash cURL theme={null} curl -X POST https://api.agentcard.sh/api/v2/wallet_links \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"user_id": "usr_8f3k2m"}' ``` ```json 201 theme={null} { "object": "wallet_link", "id": "wl_3k1v9d2q", "user_id": "usr_8f3k2m", "status": "active", "url": "https://app.agentcard.sh/w/wl_3k1v9d2q.…", "expires_at": "2026-09-07T18:15:00Z", "test_mode": false } ``` Links are safe to text: preview fetches never consume them. For a payment approval, append `?merchant=Wandy%27s&amount=1275` to `url`. **Errors.** `404 not_found` (wallet links not enabled for your organization, or unknown user), `403 wallet_link_unavailable`, `402 subscription_required` (production only), `422 user_info_required` with `missing_fields: ["consent"]`. # Wallet links Source: https://docs.agentcard.sh/api-reference/wallet-links/overview One texted link that opens a connected user's wallet, as an iMessage App Clip on iOS and a hosted page everywhere else. A **wallet link** is the one-call integration for messaging agents. You mint a link for a connected user and text it. Opening it opens the Agentcard wallet, where the user adds a card or approves a payment, then returns to the thread. All wallet UI lives on Agentcard's surface; you implement connect, consent, and this call, and observe the rest over webhooks. A link allows up to 20 opens inside its lifetime (15 minutes by default). Create a fresh one at the moment it is needed rather than reusing old ones. Append `merchant` and `amount` (in cents) to the URL to open straight onto the approval sheet for a specific charge. Wallet links are enabled per organization. If the endpoint answers `404` for your organization, ask us to turn it on. ## The wallet link object | Field | Type | Description | | ------------ | ------- | ---------------------------------------------------------------------------- | | `object` | string | `wallet_link` | | `id` | string | `wl_…` | | `user_id` | string | The connected user. | | `status` | string | `active` | | `url` | string | The link to text. Opens the App Clip on iOS, the hosted `/w` page elsewhere. | | `expires_at` | string | Default 15 minutes after creation. | | `test_mode` | boolean | | ```json theme={null} { "object": "wallet_link", "id": "wl_3k1v9d2q", "user_id": "usr_8f3k2m", "status": "active", "url": "https://app.agentcard.sh/w/wl_3k1v9d2q.…", "expires_at": "2026-09-07T18:15:00Z", "test_mode": false } ``` ## Endpoints | Endpoint | | | --------------------------- | ---------------------------------------------------------- | | `POST /api/v2/wallet_links` | [Create a wallet link](/api-reference/wallet-links/create) | Webhooks: `wallet_link.opened`, `vault.card_stored`, `connected_card.updated`, `connection.created`. # Create a funding session Source: https://docs.agentcard.sh/api-reference/wallet/fund openapi.json POST /api/v2/wallet/fund Returns an Apple Pay / Google Pay payment link for the amount you specify. Show it in your UI; when the user completes the payment the funds land in their wallet. The link is single-use and expires after 30 minutes. Requires a phone verification fresh within 60 days — see `POST /api/v2/wallet/phone/start`. ## How it works Ask for a funding session for an amount; we return a `checkout_url`. There are two kinds, picked with `link_type`: * **`hosted`** (default): an Agentcard-hosted payment page. Render it anywhere — an "Add funds" button, a QR code, a chat message — and the user opens it and pays with Apple Pay, Google Pay, or card. Safe to relay: the underlying payment order is created only when the user opens the page. Creating a hosted session is free; an unopened link costs nothing. * **`embedded`**: an in-app payment link, minted immediately. Load `checkout_url` in a `WKWebView` (iOS) or Android WebView and the user pays without leaving your app. When the payment completes, the funds land in the user's wallet. Poll [`GET /api/v2/wallet/fund/{session_id}`](/api-reference/wallet/fund-status) to know when — that endpoint is the source of truth for money; treat any client-side signal as advisory. ## Fees: send the exact amount **Agentcard covers the payment provider's fee.** Send `amount_cents` for exactly what the user should receive — the wallet is credited the full amount. Do **not** gross up the charge to compensate for fees; that just over-charges your user. * `fee_cents` on the create and status responses is the provider's fee (which Agentcard absorbs) when known, or `null` while it isn't yet — `null` means "unknown", never "free". * `fees_covered` tells you whether the fee is on us: `true` (it is — the user receives the full `amount_cents`), `false` (an anomalous fee we won't absorb — the wallet receives the net amount), or `null` (fee not known yet). `false` is rare; treat it as net delivery rather than failing the flow. ## Requirements * **The user must be identity-verified.** Funding reuses the user's completed identity verification — there is no separate verification step inside checkout. If the user isn't verified, create-session returns `422 kyc_required`; run identity verification first, then retry. Other verification-related 422s: * `funding_profile_required` — a one-time funding profile is missing (collect it, then retry). * `kyc_transfer_required` — the user's existing verification needs a one-time carry-over before funding (a single extra step, no re-verification). * `unsupported` — the user's verification can't be used for funding. The body's `reason` names the wall. `restricted_country` (or a `*_region_unsupported` value) means the user's country of residence isn't served for funding: nothing about their verification is missing, so don't send them back through identity verification. `incomplete_address`, `no_identity_document`, `no_nationality`, `no_phone`, and `no_full_ssn` (US residents) clear once that detail is on the user's verification. * **Amount bounds come from the API.** If the amount is out of range you get `422 amount_out_of_range` with `min_amount_cents` and `max_amount_cents` in the response — read those rather than hardcoding limits. * **Link lifetime.** Every session has a 30-minute window (`expires_at`), but a link is consumed by use, not just by time. A `hosted` link is single-use: the moment the user opens the page and starts the payment sheet, that link is spent, even if they close it without paying. An `embedded` link must be rendered immediately (its underlying payment token lives about 5 minutes). * **Abandoned sessions need no cleanup.** There is no cancel endpoint because none is needed: an unpaid session never charges, holds no funds, and flips to `expired` on its own. To retry, create a new session at any time; sessions are independent of each other, and creating `hosted` sessions is free and not throttled. See [session status](/api-reference/wallet/fund-status) for the poll-side rule. ## Embedded: in-app checkout Create the session with `link_type: "embedded"`, hand `checkout_url` to your app, and load it in a WebView: ```swift theme={null} let webView = WKWebView(frame: .zero, configuration: WKWebViewConfiguration()) webView.load(URLRequest(url: checkoutUrl)) ``` * **Apple Pay** renders inside a `WKWebView` on **iOS 16+** (Apple Pay on the Web is supported in `WKWebView`, but **not** in `SFSafariViewController` — use a `WKWebView`). On older iOS the user pays with Google Pay or card. No domain verification is required on your side; the checkout runs on our Apple-registered domain and pops the native Apple Pay sheet in-app. * **Google Pay** works in a modern Android WebView; **card** is always available as a fallback. * **Completion:** the page navigates to **`/fund/success`** when the payment completes — observe that navigation to close your WebView — and the [status endpoint](/api-reference/wallet/fund-status) is the authoritative confirmation. * **Wallet-only sheet:** append `&only=apple_pay` (or `&only=google_pay`) to the `checkout_url` fragment to present just that wallet button with no card form. ### Mint on demand, not per render Every embedded session creates a real payment order the moment you call the endpoint. Mint one only when the user has actually initiated payment (tapped "Add funds"), render it immediately, and create a fresh session for the next attempt if the link lapses. Don't mint on page render or in retry loops — the API refuses excess pending sessions for the same user with `too_many_pending_sessions`. * **Never relay an embedded link** through chat or email; link unfurlers can consume it and leave the user a dead page. Server → WebView, immediately, is the only safe path. * The embedded `checkout_url` appears only on the create response; the [status endpoint](/api-reference/wallet/fund-status) never re-serves it. If it lapsed, create a new session. * **Test with sandbox-mode credentials** — sandbox clients create TEST orders (never charged), so you can exercise the full WebView flow end to end before switching to live keys. * On a physical device, cards must be in the platform wallet; simulators cannot show the Apple Pay sheet. # Get a funding session Source: https://docs.agentcard.sh/api-reference/wallet/fund-status openapi.json GET /api/v2/wallet/fund/{session_id} Poll a funding session until it is `completed` — the payment status is refreshed from the provider on every read. ## Status values | Status | Meaning | What to do | | ------------ | ------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | | `pending` | The session can still complete: the link can still be opened, or a started payment is inside its grace. | Show the user the link you have (hosted: `checkout_url`; embedded: the link you rendered). No link to show? Wait, or create a new session (either is fine). | | `processing` | Paid — the deposit is settling. | Wait; poll again. | | `completed` | Funds are in the wallet. | Done. | | `failed` | The payment failed (`failure_reason` says why). | Create a new session. | | `expired` | The link was never opened within 30 minutes, or a started payment was abandoned. | Create a new session. | One policy covers every `pending` case, so you never need to diagnose them: surface the freshest link you hold, and whenever the user wants to retry, create a new session immediately, at any time. Sessions are independent; an unpaid one never charges, holds no funds, and needs no canceling (there is no cancel endpoint because none is needed). Hosted links are single-use: once the user opens the page and starts the payment sheet, that link is spent, even if they close it without paying, and a session whose started payment was abandoned reads `expired` on its own within about ten minutes of the attempt. `checkout_url` is present only while a hosted link can still be opened; embedded sessions never carry it here (the link appears only on the create response). `expires_at` always reflects the session's 30-minute funding window. ## Fees `fee_cents` is the payment provider's fee when known (`null` = unknown yet, never "free"). **Agentcard covers it** — the wallet is credited the full `amount_cents`; don't gross up. `fees_covered` reports the outcome: `true` (fee absorbed by Agentcard), `false` (rare anomalous fee — the wallet received the net amount), `null` (fee not known yet). # Get the user's wallet Source: https://docs.agentcard.sh/api-reference/wallet/get openapi.json GET /api/v2/wallet The connected user's wallet and current balance — render it in your own wallet UI. Provisions the wallet on first read. ## Notes * The wallet is provisioned automatically on first read — there is no separate provision call. * `balance_usdc` is the current balance as a decimal string (e.g. `"25.00"`). * If `balance_unavailable` is present and `true`, the balance could not be read right now — treat it as "unknown", not "\$0". # Wallet Source: https://docs.agentcard.sh/api-reference/wallet/overview A connected user's balance, and how to fund it from your own UI. The **wallet** is a connected user's Agentcard balance. It is provisioned on first read. To fund it you request a payment link (Apple Pay / Google Pay), show it in your UI, and poll the funding session until the money lands. Funding requires a phone verification fresh within 60 days; you relay that code through your UI the same way as the connect code. ## The wallet object | Field | Type | Description | | --------------------- | ------- | ----------------------------------------------------------------------------------------------------------- | | `object` | string | `wallet` | | `user_id` | string | | | `address` | string | The wallet's on-chain address (USDC on Base). | | `balance_usdc` | string | Current balance in USD, as a decimal string. | | `balance_unavailable` | boolean | Present and true when the balance could not be read right now. Distinguish "no funds" from "couldn't read". | | `status` | string | | ```json theme={null} { "object": "wallet", "user_id": "usr_123", "address": "0xabc…", "balance_usdc": "25.00", "status": "active" } ``` ## The funding session object | Field | Type | Description | | ------------------------------------------ | -------------- | ------------------------------------------------------------------------------------------------- | | `id`, `user_id` | string | | | `status` | string | `pending`, `processing`, `completed`, `failed`, `expired`. | | `amount_cents`, `currency` | | What the wallet is credited. | | `payment_method` | string | `apple_pay` or `google_pay`. | | `checkout_url` | string | The payment link to show the user. | | `link_type` | string | `hosted` (openable for 30 minutes) or `embedded` (single use, \~5 minutes). Create response only. | | `fee_cents`, `fees_covered` | | The provider fee and whether Agentcard absorbs it. Do not gross up the amount. | | `failure_reason` | string or null | `region_not_supported`, `provider_error`. | | `expires_at`, `completed_at`, `created_at` | string | | ## Endpoints | Endpoint | | | -------------------------------------- | ----------------------------------------------------------------------------------------- | | `GET /api/v2/wallet` | [Get the user's wallet](/api-reference/wallet/get) | | `POST /api/v2/wallet/fund` | [Create a funding session](/api-reference/wallet/fund): single use, expires in 30 minutes | | `GET /api/v2/wallet/fund/{session_id}` | [Get a funding session](/api-reference/wallet/fund-status) | | `POST /api/v2/wallet/phone/start` | [Start phone verification](/api-reference/wallet/phone-start) | | `POST /api/v2/wallet/phone/verify` | [Verify the phone code](/api-reference/wallet/phone-verify) | # Start phone verification Source: https://docs.agentcard.sh/api-reference/wallet/phone-start openapi.json POST /api/v2/wallet/phone/start Sends the user a one-time code. Relay it through your UI — the user reads it back to you, same pattern as the connect code. A verification stays fresh for 60 days. Provide `phone_number` only when the user has no phone on file (any E.164 number outside the prohibited-countries list). ## How it works Some flows need the user's phone OTP-verified — for example, adding a card lists `phone_number` under `user_info_required`. Same embedded pattern as [connect](/api-reference/connections/start): we send the code, your UI collects it, you [verify it](/api-reference/wallet/phone-verify) server-to-server. * If the user already has a verified phone that's still fresh, the response is `already_verified` — nothing more to collect. * Pass `phone_number` only when the user has no phone on file. Any E.164 number works (e.g. `+14155550123`, `+4915123456789`). Numbers from [prohibited countries](https://legal.raincards.xyz/legal/prohibitions) return `country_not_supported`, unless Agentcard serves that country through a partner issuing program (Israel is supported this way). * International numbers with an email on file get the code over SMS **and** email at once (`channel: "sms_and_email"`) — carrier delays can outlive the code's 10-minute life, so either message verifies and the user types whichever arrives first. * A verification stays fresh for **60 days**; after that, run this flow again when a phone is required. # Verify the phone code Source: https://docs.agentcard.sh/api-reference/wallet/phone-verify openapi.json POST /api/v2/wallet/phone/verify Checks the code the user read back. On success the verification stays fresh for 60 days and funding sessions can be created. ## Notes * `phone_number` is **required when the user had no phone on file at [start](/api-reference/wallet/phone-start)** (e.g. a fresh connection before KYC) — the code was sent to the number you supplied, can only be checked against it, and there's no stored number to fall back on, so a call without it returns `phone_number_required`. Keep passing that **same** number on verify until the user is verified: the code is only ever valid against the number it was sent to, so don't switch to a stored number that shows up mid-flight (a KYC backfill between start and verify). Omit `phone_number` only when start sent the code to a number already on file. It's optional in the schema only because that stored-number case exists. * On `verified`, the user can fund immediately — the verification stays fresh for 60 days. * `invalid_code` carries a `reason` (`incorrect`, `expired`, `too_many_attempts`, or `no_code`) so you can decide between "try again" and "send a new code". # Create a webhook endpoint Source: https://docs.agentcard.sh/api-reference/webhook-endpoints/create POST https://api.agentcard.sh/api/v2/webhook_endpoints Register a URL and the events it receives. The signing secret is returned once. An HTTPS URL you control. Event types or wildcards, at least one. Unknown types are rejected. Up to 255 characters. ```bash cURL theme={null} curl -X POST https://api.agentcard.sh/api/v2/webhook_endpoints \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"url": "https://your.app/agentcard/webhooks", "enabled_events": ["vault.card_stored", "checkout_authorization.*"], "description": "Production checkout events"}' ``` ```json 201 theme={null} { "id": "we_7h2k9p4m", "object": "webhook_endpoint", "url": "https://your.app/agentcard/webhooks", "enabled_events": ["vault.card_stored", "checkout_authorization.*"], "status": "active", "description": "Production checkout events", "secret": "whsec_…" } ``` Store `secret` now. It is not returned again except through [Get the signing secret](/api-reference/webhook-endpoints/secret). The token decides the endpoint's mode, never the body. # Delete a webhook endpoint Source: https://docs.agentcard.sh/api-reference/webhook-endpoints/delete DELETE https://api.agentcard.sh/api/v2/webhook_endpoints/{id} Remove an endpoint. Deliveries stop immediately. The endpoint id. ```bash cURL theme={null} curl -X DELETE https://api.agentcard.sh/api/v2/webhook_endpoints/we_7h2k9p4m \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json 200 theme={null} { "id": "we_7h2k9p4m", "object": "webhook_endpoint", "deleted": true } ``` # List recent deliveries Source: https://docs.agentcard.sh/api-reference/webhook-endpoints/deliveries GET https://api.agentcard.sh/api/v2/webhook_endpoints/{id}/deliveries Recent delivery attempts for an endpoint, for debugging. The endpoint id. ```bash cURL theme={null} curl https://api.agentcard.sh/api/v2/webhook_endpoints/we_7h2k9p4m/deliveries \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json 200 theme={null} { "object": "list", "data": [ { "id": "whd_1a2b3c", "event_id": "evt_9f8e7d", "event_type": "vault.card_stored", "status": "succeeded", "response_status": 200, "attempted_at": "2026-09-07T17:05:12Z" } ] } ``` Failed deliveries are retried with backoff. A run of failures on one endpoint is the first thing to check when a webhook consumer seems silent. # Get a webhook endpoint Source: https://docs.agentcard.sh/api-reference/webhook-endpoints/get GET https://api.agentcard.sh/api/v2/webhook_endpoints/{id} One endpoint, without its secret. The endpoint id. ```bash cURL theme={null} curl https://api.agentcard.sh/api/v2/webhook_endpoints/we_7h2k9p4m \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json theme={null} { "id": "we_7h2k9p4m", "object": "webhook_endpoint", "url": "https://your.app/agentcard/webhooks", "enabled_events": ["vault.card_stored", "checkout_authorization.*"], "status": "active", "description": "Production checkout events", "created_at": "2026-09-07T17:00:00Z" } ``` # List webhook endpoints Source: https://docs.agentcard.sh/api-reference/webhook-endpoints/list GET https://api.agentcard.sh/api/v2/webhook_endpoints The endpoints registered in the mode of your token. ```bash cURL theme={null} curl https://api.agentcard.sh/api/v2/webhook_endpoints \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json 200 theme={null} { "object": "list", "data": [ { "id": "we_7h2k9p4m", "object": "webhook_endpoint", "url": "https://your.app/agentcard/webhooks", "enabled_events": ["vault.card_stored", "checkout_authorization.*"], "status": "active", "description": "Production checkout events" } ] } ``` Secrets are never included in list or get responses. # Webhook endpoints Source: https://docs.agentcard.sh/api-reference/webhook-endpoints/overview Register the URLs Agentcard delivers events to, choose the events, and rotate signing secrets. A **webhook endpoint** is a URL you own plus the list of events it should receive. Agentcard signs every delivery with the endpoint's secret, which is returned once at creation and can be rotated. Endpoints are mode-scoped: a sandbox token manages sandbox endpoints, a production token manages production ones. `enabled_events` accepts concrete event types (`vault.card_stored`) or wildcards (`checkout_authorization.*`). Events emitted today: `connection.created`, `wallet_link.opened`, `vault.session_linked`, `vault.card_stored`, `checkout_authorization.approved|submitted|declined|expired|amount_mismatch`, `order.placed|failed|confirmed`, `identity.verification.updated`, `connected_card.updated`, `card.created|updated|closed`, `transaction.authorized|cleared|declined|voided`, `approval.requested`. ## The webhook endpoint object | Field | Type | Description | | ---------------- | -------------- | --------------------------------------------------------------------- | | `object` | string | `webhook_endpoint` | | `id` | string | `we_…` | | `url` | string | Where events are delivered. HTTPS. | | `enabled_events` | string\[] | Event types or wildcards (`checkout_authorization.*`). | | `status` | string | `active` or `disabled`. | | `description` | string or null | | | `secret` | string | Only on the create response and `GET …/secret`. Signs every delivery. | ```json theme={null} { "id": "we_7h2k9p4m", "object": "webhook_endpoint", "url": "https://your.app/agentcard/webhooks", "enabled_events": ["vault.card_stored", "checkout_authorization.*"], "status": "active", "description": "Production checkout events" } ``` ## Endpoints | Endpoint | | | ------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | `GET /api/v2/webhook_endpoints` | [List webhook endpoints](/api-reference/webhook-endpoints/list) | | `POST /api/v2/webhook_endpoints` | [Create a webhook endpoint](/api-reference/webhook-endpoints/create): the secret is returned once | | `GET /api/v2/webhook_endpoints/{id}` | [Get a webhook endpoint](/api-reference/webhook-endpoints/get) | | `PATCH /api/v2/webhook_endpoints/{id}` | [Update a webhook endpoint](/api-reference/webhook-endpoints/update) | | `DELETE /api/v2/webhook_endpoints/{id}` | [Delete a webhook endpoint](/api-reference/webhook-endpoints/delete) | | `GET /api/v2/webhook_endpoints/{id}/secret` | [Get the signing secret](/api-reference/webhook-endpoints/secret) | | `POST /api/v2/webhook_endpoints/{id}/roll_secret` | [Rotate the signing secret](/api-reference/webhook-endpoints/roll-secret) | | `GET /api/v2/webhook_endpoints/{id}/deliveries` | [List recent deliveries](/api-reference/webhook-endpoints/deliveries) | The same router also answers at `/api/v1/webhook_endpoints`; both addresses are one resource. For the envelope, signature verification, and every event payload, see the [Webhooks](/webhooks/overview) tab. # Rotate the signing secret Source: https://docs.agentcard.sh/api-reference/webhook-endpoints/roll-secret POST https://api.agentcard.sh/api/v2/webhook_endpoints/{id}/roll_secret Replace the signing secret. Deliveries are signed with the new one from the next event. The endpoint id. ```bash cURL theme={null} curl -X POST https://api.agentcard.sh/api/v2/webhook_endpoints/we_7h2k9p4m/roll_secret \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json 200 theme={null} { "id": "we_7h2k9p4m", "secret": "whsec_…" } ``` Update your verifier before events start arriving signed with the new secret. # Get the signing secret Source: https://docs.agentcard.sh/api-reference/webhook-endpoints/secret GET https://api.agentcard.sh/api/v2/webhook_endpoints/{id}/secret Read the current signing secret for an endpoint. The endpoint id. ```bash cURL theme={null} curl https://api.agentcard.sh/api/v2/webhook_endpoints/we_7h2k9p4m/secret \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json 200 theme={null} { "id": "we_7h2k9p4m", "secret": "whsec_…" } ``` Use it to verify the signature header on every delivery. Reads of the secret are logged. # Update a webhook endpoint Source: https://docs.agentcard.sh/api-reference/webhook-endpoints/update PATCH https://api.agentcard.sh/api/v2/webhook_endpoints/{id} Change the URL, the events, the description, or pause deliveries. The endpoint id. A new HTTPS URL. Replaces the list. `active` or `disabled`. Disabled endpoints receive nothing until re-enabled. ```bash cURL theme={null} curl -X PATCH https://api.agentcard.sh/api/v2/webhook_endpoints/we_7h2k9p4m \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"status": "disabled"}' ``` ```json theme={null} { "id": "we_7h2k9p4m", "object": "webhook_endpoint", "url": "https://your.app/agentcard/webhooks", "enabled_events": ["vault.card_stored", "checkout_authorization.*"], "status": "disabled", "description": "Production checkout events", "created_at": "2026-09-07T17:00:00Z" } ``` # Agentic purchases explained Source: https://docs.agentcard.sh/getting-started/agentic-purchases-explained The ecosystem an agent needs to buy something online, and where Agentcard fits in. Agents can buy anything online. In practice, they need three things: (1) a browser, (2) credentials, and (3) a credit card. In the following section, we'll explain how all these parts work together and where Agentcard fits in. ## The ecosystem When an agent buys on someone's behalf, it typically touches four kinds of platforms. Most teams end up using two or three at the same time. ```mermaid theme={null} flowchart TD U[User] <-->|chat| M[Messaging platform
Linq · Photon · Blooio] M <--> A[Your agent] A --> B[Agent browser
Kernel · Browserbase] A --> E[Ecommerce API
Purchase API · Zinc · Ophelia] B --> C[Merchant checkout] E --> C AC[Agentcard
cards + credentials] -. real card at checkout .-> C AC -. passkey approval .-> U A -. asks for the card .-> AC ``` ### Agent browsers Agent browsers run a real browser in the cloud, which lets an agent visit any website, search for products, add them to a cart, and reach the checkout page. [KERNEL](https://kernel.so) and [Browserbase](https://www.browserbase.com) are the two we integrate with. They're the most general-purpose tool in the stack: if a merchant has a website, an agent browser can usually reach checkout. The trade-offs are that browsers can be slow, bot protection can get in the way, and the checkout form still needs a card number entered. That last step is where we plug in. ### Ecommerce APIs Ecommerce APIs skip the browser. Instead of clicking through a website, an agent calls an API that returns structured products, carts, and orders for the merchants it covers. Agentcard's Purchase API is our version of this. It takes a free-text request, builds the cart, and completes checkout with the user's card. Zinc and Ophelia cover other merchants in a similar way. APIs tend to be faster and more reliable than a browser, but each one covers a fixed set of merchants, so many companies use several. ### Messaging platforms Many agentic purchases start in a chat. Linq, Photon, and Blooio give an agent a phone number on iMessage or WhatsApp so users can text it. The messaging platform is also where the user typically approves a purchase before it goes through. ### Agentcard Agentcard is the payments layer underneath all of the above. It holds the user's cards and merchant credentials, determines when a card can be used, provides card details to the browser or API at the moment of checkout, and gives the user a way to approve each purchase. It can work with whichever browser, API, or messaging platform you already use. ## How we store cards and credentials A user adds a card once, through an Agentcard form that is PCI compliant. The card is encrypted on the user's device with a passkey before it's stored. Only that passkey can decrypt it, which means we never see the card number and neither would anyone who got hold of our database. Because the user's real card is what gets charged, the purchase looks like any other purchase to their bank. They keep their points and retain the right to dispute a charge. We store who approved the purchase, when, and from where, which is what a merchant typically needs to defeat a bogus dispute. ## How a purchase flows through all the parts 1. **The user talks to your agent** on iMessage, WhatsApp, or wherever it lives. They ask it to buy something. 2. **Your agent builds a cart.** It uses an agent browser to navigate a merchant site, or an ecommerce API to get there directly. 3. **The agent reaches checkout and asks Agentcard for the card.** In a browser, the agent types a placeholder card number and Agentcard intercepts the request at the network layer, with [KERNEL](https://kernel.so) and with our own SDK. Through an API, the API calls Agentcard directly. 4. **The user approves with their passkey.** Agentcard sends the user an approval request on their device, and they approve it there with their passkey or master password. The passkey that unlocks the card lives there, so nothing moves without them. 5. **Agentcard swaps in the real card.** The merchant receives the user's real card details and charges it. Your agent never sees the card number, and neither do we. 6. **The order confirms.** Your agent tells the user, and the purchase shows up on the user's statement exactly like a purchase they made themselves. ## When you need a new card instead Sometimes the right answer isn't the user's card. The agent may need a spending limit, the user may want to fund purchases from a balance, or a company may be paying. In those cases, Agentcard can issue a new card that the agent uses the same way. Read about [Issuing](/issuing/quickstart) for the details. # Getting started Source: https://docs.agentcard.sh/getting-started/index Agentcard allows your agent to buy anything online. Agentcard allows your agent to buy anything online. Agents in a chat thread, in a browser, or in your own app use Agentcard to purchase on behalf of their users. ## Enable payments for your agent Agents can buy anything online. They just need three things: (1) a browser, (2) credentials, and (3) a credit card. Agentcard offers two ways to give your agent a card: Vault, which stores and uses your users' cards, and Issuing, which creates new ones. ### Vault Agentcard stores your user's credit cards and credentials so you can use them safely with an agent, and it helps you connect with any agent browser of your choice. Vault main features: * **Every card:** Works with any card from any country—consumer, commercial, or prepaid. * **Every card network:** Works with Visa, Mastercard, American Express, Discover, and more. * **Support for every platform:** Use the Vault if you are building for web, WhatsApp, iMessage or any other platform. * **Authorize with a passkey:** Users approve payments on their own device with their passkey or master password. * **Encrypted cards:** Cards are encrypted on the user's device before they're stored. * **Integrations:** Works with the tools you already use (most agent-browsers, e-commerce APIs and messaging APIs). ### Issuing Agentcard creates a new credit card your agent can use online. Users complete KYC and can create unlimited cards. Issuing main features: * One-time or multi-use cards. * Works globally (with some restricted countries). * Credit card. * Funds held in USDC on Base. * Instant settlement. * Production access in under a week. ## Differences between Vault and Issuing As a general rule, most companies should start with Vault to store and use customers' cards. Move to Issuing only when the use case requires creating new cards. Common Issuing use cases include giving agents a card with purchase limits or enabling agents to spend from a balance held in cryptocurrencies. | | Vault | Issuing | | ----------------------- | ---------------------------------------------------------------------------- | ----------------------------------------------------- | | **Use when** | User wants to make payments using personal cards (credit, debit or prepaid). | User or agent needs a new card to complete a payment. | | **Chargebacks** | Handled by the issuer/bank (e.g. Chase). | Handled by Agentcard. | | **Points** | User gets points like with regular purchases. | User gets Agentcard points. | | **KYC** | No | Yes | | **Policies/guardrails** | Yes | Yes | ## Get started with both products Store and use your users' cards. Create a new card for your agent. # Authenticating a user Source: https://docs.agentcard.sh/issuing/authenticating-a-user Send the user a one-time code, verify it, and get the connection token that acts as them. Connecting a user is the first step of Issuing. You send them a one-time code, they read it back, and you receive a **connection token** that acts as them. That token is what your agent creates and uses cards with. Every call on this page is made by your server with your org token as the bearer (see [step 1 of the Quickstart](/issuing/quickstart#1-get-your-credentials)). ## Send the user a code By email or phone. `external_user_id` is optional: your own id for the user, returned on webhooks so you can match them up. ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v2/connect/start \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"email": "user@example.com", "external_user_id": "your-internal-id"}' ``` ```json theme={null} { "object": "connect_attempt", "connect_id": "ca_9k1m4x7d", "channel": "email" } ``` ## Verify the code In sandbox the code is always `111111`. ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v2/connect/verify \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"connect_id": "ca_9k1m4x7d", "code": "111111"}' ``` ```json theme={null} { "object": "connection", "access_token": "act_1a2b3c…", "refresh_token": "rct_4d5e6f…", "token_type": "Bearer", "expires_in": 3600, "user": { "id": "user_7g8h9i", "email": "user@example.com", "phone": null } } ``` Store all three. `user.id` is how your server names the user on `/api/v2` calls. `access_token` is the connection token your agent uses. The `connection.created` webhook fires here. ## Record consent Once per user, before any card or balance action: ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v2/connect/consent \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"user_id": "user_7g8h9i"}' ``` A `user_info_required` error later means this step was skipped. ## Refresh the connection Connection tokens expire after one hour. Rotate them with the refresh token, using your org token as the bearer: ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v2/connect/refresh \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"refresh_token": "rct_4d5e6f…"}' ``` Each refresh returns a new pair and invalidates the old one. Store what comes back. An `invalid_refresh_token` means it was already used or expired: reconnect the user. ## Users you know by phone only If your agent lives in iMessage or WhatsApp, you may not want to relay a code. Create an **onboarding attempt** instead: it returns a wallet link to text, the code fires inside our page at the user's first money action, and you exchange the attempt for the connection afterwards. See [Connections](/api-reference/connections/overview) in the API reference. ## Sandbox Sandbox sends email but not SMS, and the code is always `111111`. Sandbox users are isolated: connecting `anyone@example.com` in sandbox can never touch a real account. # Completing a KYC Source: https://docs.agentcard.sh/issuing/completing-a-kyc Verify a user's identity once so Agentcard can issue them cards. Hosted page or your own UI. Issued cards are real cards backed by real money, so the user verifies their identity once before the first one. It takes about two minutes: a government ID, a short face scan, and any details the document did not carry. There is no SSN requirement outside the US, and any national ID works from any supported country. KYC is only for Issuing. A user who pays with their own card through the [Vault](/vault/quickstart) never sees it. ## Read the status Every KYC response is the same object with exactly one `status`: ```bash theme={null} curl "https://api.agentcard.sh/api/v2/kyc?user_id=user_7g8h9i" \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json theme={null} { "object": "kyc", "status": "requires_verification", "iframe_url": "https://in.sumsub.com/websdk/p/…" } ``` | Status | Meaning | What to do | | ----------------------- | ----------------------------------- | --------------------------------------------------------------------- | | `awaiting_documents` | Waiting for the ID images. | Hand the user the `iframe_url`, or upload the images yourself. | | `needs_information` | The review asked for typed details. | Hand the user the `iframe_url`, or submit `required_fields` yourself. | | `requires_verification` | Ready for the face scan. | Hand the user the `iframe_url`. | | `pending` | Under review. | Wait. | | `approved` | Verified. | Issue cards. | | `rejected` | Not verified. | Show the `reason`. The user did not pass. | ## Option A: hosted (recommended) Whenever the status is actionable, hand the user the `iframe_url`. The hosted page collects whatever the verification still needs, documents, typed details, the face scan, and no identity data passes through your servers. Open it in a new tab, a WebView, or embed it. The link is short-lived. Always surface the one from your freshest status read or `identity.verification.updated` event rather than storing it. ## Option B: your own UI Drive the upload endpoints from your own screens and use the hosted page only for the face scan. 1. `POST /api/v2/kyc/documents/front` and `POST /api/v2/kyc/documents/back` with the ID images. The back-of-ID response is the branch point: `needs_information`, `requires_verification`, or `rejected`. It also returns `extracted` fields to prefill your form and `warnings` you can show the user. 2. `POST /api/v2/kyc/information` with the `required_fields` the review asked for. 3. At `requires_verification`, show the `iframe_url` for the face scan. Details for each call are in the [Identity verification](/api-reference/identity-verification/overview) reference. ## Learn the outcome Subscribe to `identity.verification.updated` on a [webhook endpoint](/api-reference/webhook-endpoints/overview), or poll `GET /api/v2/kyc`. Treat the webhook as the record and the conversation as a claim: the user saying "done" is not `approved`. ## Already verified them elsewhere? If you run your own KYC on Sumsub, share the applicant with a one-time token and the user skips document capture and the face scan entirely: ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v2/kyc/import \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"user_id": "user_7g8h9i", "share_token": "_act-jwt-…", "user_ip": "203.0.113.7"}' ``` The accounts must be paired first, and the import can still come back `needs_information` for a residential address. Ask us to enable sharing for your organization. ## Sandbox Sandbox verifications never reach a reviewer. They report only `requires_verification`, `pending`, `approved`, or `rejected`, and the `iframe_url` is a test-mode chooser. Drive the outcome yourself: ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v2/kyc/simulate \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"user_id": "user_7g8h9i", "outcome": "approved"}' ``` `outcome` is `approved`, `rejected`, or `requires_input` (a retryable bounce back to `requires_verification`). Re-simulating overwrites the previous outcome, so one test user can walk every path. Live tokens are refused with `403 sandbox_only`. # Issuing a card Source: https://docs.agentcard.sh/issuing/issuing-a-card Fund the user's balance, then create single-use or multi-use cards for your agent. An issued card is a virtual card Agentcard creates for the user, funded from their balance. It can never spend more than the balance behind it. Your agent creates cards through the Agentcard MCP server, connected with the user's connection token, so the user's cards and balance stay scoped to your connection. ## Connect your agent One MCP client per user, pointed at `https://mcp.agentcard.sh/mcp` with the user's connection token as the bearer. Never share a client across users: the bearer decides whose cards the agent can see. ```typescript theme={null} import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"; const transport = new StreamableHTTPClientTransport( new URL("https://mcp.agentcard.sh/mcp"), { requestInit: { headers: { Authorization: `Bearer ${user.agentcardAccessToken}` } } }, ); const client = new Client({ name: "your-app", version: "1.0.0" }); await client.connect(transport); const { tools } = await client.listTools(); ``` Register whatever `listTools()` returns rather than a hardcoded list. Tools Agentcard ships later then appear without a deploy on your side. On `401`, refresh the connection with your org token and reconnect. ## Fund the balance The balance is the user's cash. Users add it in USD with Apple Pay or Google Pay, and it is held as USDC. From the agent, `add_funds` prepares a single-use checkout link and moves no money by itself. The user opens it and pays in their own browser: ```json theme={null} { "tool": "add_funds", "arguments": { "amount_cents": 5000 } } ``` The first time, funding needs a one-time phone verification. `add_funds` sends the code and says where it went. Ask the user for it, call `verify_phone`, then call `add_funds` again. The verification stays fresh for 60 days. From your server, the same thing is `POST /api/v2/wallet/fund`, which returns a `checkout_url` to show in your UI, and `GET /api/v2/wallet/fund/{session_id}` to learn when the money landed. Agentcard covers the provider fee: send the exact amount the user should receive. `get_balance` shows what is spendable. A deposit that shows as "confirming" is already on the way. Do not ask the user to pay again. ## Create a card ```json theme={null} { "tool": "create_card", "arguments": { "source": "issued", "amount_cents": 2500 } } ``` `issued`. Draw on the user's balance. Without it, `create_card` may set up the user's own card in the Vault instead. What the card can spend, in cents. Minimum 100. Connections through your organization have no maximum. `single_use` (default) closes after the first approved charge. `multi_use` stays open until its limit is spent, for subscriptions or merchants that charge repeatedly. Optional `expires_at` auto-closes it. `ai_labs` locks the card to AI-lab merchants (OpenAI, Anthropic, Gemini). Anything else declines at authorization. Sandbox returns a test card immediately. In production, `create_card` may return one of these first: | Response | Meaning | What to do | | ------------------------- | ----------------------------------------- | -------------------------------------------------------------------- | | `kyc_required` | The user has not verified their identity. | [Complete KYC](/issuing/completing-a-kyc), then retry. | | `wallet_funding_required` | The balance is short. | `add_funds`, then retry. | | `deposit_confirming` | Money is on the way. | Wait the suggested interval, then retry. Do not fund again. | | `user_info_required` | Consent or phone missing. | Consent is recorded server-side with `POST /api/v2/connect/consent`. | Every card arrives as a `card.created` webhook. ## Or let the user do it in the wallet If you would rather not drive the flow from your agent, text or embed a [wallet link](/api-reference/wallet-links/overview). The hosted wallet runs KYC, funding and card creation itself, and you learn about each step through the same webhooks. ## Rules for your agent ```text theme={null} - Confirm with the user before creating a card. Cards are live and charged for real when used. - Create the card right before the purchase, sized to it. Don't stockpile cards. - Use multi_use only for merchants that charge repeatedly. - If create_card returns deposit_confirming, wait and retry. Never ask the user to pay twice. - A connection authorized through your SANDBOX credentials issues test cards that no real merchant accepts. ``` # Quickstart Source: https://docs.agentcard.sh/issuing/quickstart Authenticate a user, verify their identity, fund their balance, and issue a card your agent can pay with. Sandbox, about fifteen minutes. Issuing gives your agent a card number. Agentcard creates a virtual card for the user, funded from a balance they hold with us, and your agent types it into any checkout. The user verifies their identity once, then can create as many cards as they need. **The flow in one line:** authenticate the user → they complete KYC → they add funds → your agent creates a card → your agent pays with it. Steps 1 to 3 happen once per user. Steps 4 and 5 happen on every purchase. ## 1. Get your credentials You need an Agentcard organization `client_id` and `client_secret` from the [dashboard](https://app.agentcard.sh). Exchange them for an access token: ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v2/oauth/token \ -d grant_type=client_credentials \ -d client_id=$AGENTCARD_CLIENT_ID \ -d client_secret=$AGENTCARD_CLIENT_SECRET ``` Use the returned token as `$ORG_TOKEN`. Sandbox credentials create sandbox users and test cards. Start there. ## 2. Authenticate a user Send the user a one-time code, then verify it. In sandbox the code is always `111111`. ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v2/connect/start \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"email": "user@example.com"}' curl -X POST https://api.agentcard.sh/api/v2/connect/verify \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"connect_id": "CONNECT_ATTEMPT_ID", "code": "111111"}' ``` ```json theme={null} { "object": "connection", "access_token": "act_1a2b3c…", "refresh_token": "rct_4d5e6f…", "expires_in": 3600, "user": { "id": "user_7g8h9i", "email": "user@example.com" } } ``` Store all three. `user.id` names the user on every call your server makes. `access_token` is the **connection token**: it acts as the user, and it is what your agent will create and use cards with. Record consent once: ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v2/connect/consent \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"user_id": "user_7g8h9i"}' ``` [More on authenticating →](/issuing/authenticating-a-user) ## 3. Complete KYC Issued cards require identity verification. Read the status, and hand the user the hosted page it returns: ```bash theme={null} curl "https://api.agentcard.sh/api/v2/kyc?user_id=user_7g8h9i" \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json theme={null} { "object": "kyc", "status": "requires_verification", "iframe_url": "https://in.sumsub.com/websdk/p/…" } ``` The user completes document capture and a face scan on that page. You learn the outcome from `identity.verification.updated` or by reading the status again. In sandbox nothing is reviewed, so approve the test user directly: ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v2/kyc/simulate \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"user_id": "user_7g8h9i", "outcome": "approved"}' ``` [More on KYC →](/issuing/completing-a-kyc) ## 4. Fund the balance and issue a card Cards draw on the user's balance. Your agent does both steps through the Agentcard MCP server, connected with the user's connection token: ```bash theme={null} claude mcp add agentcard-user --transport http https://mcp.agentcard.sh/mcp \ --header "Authorization: Bearer act_1a2b3c…" ``` Call `add_funds` with an amount. It returns a single-use Apple Pay / Google Pay link. The user pays in their own browser. Then create the card: ```json theme={null} { "tool": "create_card", "arguments": { "source": "issued", "amount_cents": 2500 } } ``` The response carries the card id. Sandbox issues a test card immediately. In production, `create_card` may first return `kyc_required` or `wallet_funding_required`, which point back to steps 3 and 4. [More on issuing →](/issuing/issuing-a-card) ## 5. Use the card Ask for the credentials when your agent is at the checkout, not before: ```json theme={null} { "tool": "get_card_details", "arguments": { "card_id": "card_…" } } ``` You get the number, expiry, CVC and remaining balance. Type them into the merchant's form. A single-use card closes itself after its first approved charge. `transaction.authorized` tells your server money moved. [More on using cards →](/issuing/using-the-cards) ## What's next Tokens, consent, refresh, and what each credential may call. Hosted or custom verification, statuses, sandbox simulation. Funding, single-use and multi-use cards, merchant locks. Reading credentials, paying, pausing, closing, webhooks. # Set rules on a card Source: https://docs.agentcard.sh/issuing/set-rules-on-a-card Presets are optional rules for the cards you issue. Save one, put it on a card, and only that card is judged. Presets are optional. Without them, a card is a normal card. Presets are the rules you put on what an agent may buy with a card: a spend cap, a category, a merchant list, a place, a currency, a time window, or which of your tools may use the card. A rule never lets a card spend more than the money on it; it only narrows where, when, and on what. A preset applies to the card you put it on. Save a preset under a name of your choice, then put it where it should apply: ```bash theme={null} agent-cards cards preset save office-supplies \ --per-day 25 \ --categories meals \ --only-days weekdays \ --only-hours 11-14 \ --timezone America/Los_Angeles ``` Once a card has a preset, Agentcard judges each purchase on it. A purchase outside the rules is refused, nothing is charged, and you are told which rule refused it. A charge made straight at a merchant, outside Agentcard checkout, is judged when it settles: on a multi-use card, Agentcard pauses the card and tells you. The rules and their refusal codes are the ones a [Vault preset](/vault/set-rules-on-a-card) uses. ## Choose what to restrict Pick the rules the preset holds when you save it. A cap counts the purchases this preset covers: a per-day cap on a saved name counts every card created from that name in one window, and a total counts each card alone. | Rule | What it does | | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Total** | The most the card spends over its life, in US dollars. A charge in another currency counts at the amount the network bills the card, in dollars. | | **Rate** | A cap per rolling 24 hours, 7 days, or 30 days, in US dollars, for the purchases this preset covers. A charge in another currency counts at what the network bills the card. | | **Category** | `meals`, `groceries`, `travel`, `software`, `ai`, `wellness`, `retail`. | | **Merchant** | Names the merchant must match, such as `OPENAI`. A pattern is a case-insensitive part of the merchant's name. | | **Place** | The country or US state the merchant is in, such as `US, Canada` or `europe`. Not where your agent runs. | | **Currency** | The currencies a purchase may be in, such as `usd,eur`. Agentcard checks it; the card network does not. | | **Time window** | Days and hours, always in a named zone. UTC unless you pass `--timezone`. | | **Where the card can be used from** | The CLI, an MCP tool, the API, or the dashboard. Agentcard reads who is asking from the sign-in: your API key counts as `api`, a connected app and its MCP tools as `mcp`, the command line as `cli`, the dashboard and Slack as `browser`. | The flags, on `cards create` and `cards preset save`: | Flag | Meaning | | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `--total` | Cap on each card, over its life, in US dollars. On a `strict` preset an `--amount` above the total is refused; a preset that watches funds the card as asked and tells you when a purchase passes the total | | `--per-day` / `--per-week` / `--per-month` | Rolling caps for the purchases this preset covers, in US dollars | | `--categories` | Categories, comma-separated: `meals`, `groceries`, `travel`, `software`, `ai`, `wellness`, `retail` | | `--only-merchants` | Merchant name patterns the purchase must match, comma-separated | | `--only-in` | Places, comma-separated: a country (`US`, `Canada`), a US state (`California`, `US-CA`), or a region (`europe`, `north-america`, `apac`) | | `--currencies` | Currencies, comma-separated, by code or common name: `usd,eur` or `dollars,euros` | | `--only-days` | `mon,tue`, or `weekdays` / `weekends` | | `--only-hours` | For example `9-17`, 24-hour clock, in `--timezone` | | `--timezone` | IANA zone for `--only-days` and `--only-hours`, default `UTC` | | `--only-from` | `cli`, `mcp`, `api`, and/or `browser` | | `--mode` | What the preset does when a purchase breaks any of its rules: `strict` refuses it (the default), `watch` lets it through and tells you | Over MCP the same rules are fields on [`save_preset`](/tools/mcp/user/save_preset): `total`, `per_day`, `categories`, `mode`, and so on. Over the API, `POST /me/presets` and `POST /cards/create` take the same fields. A rule is saved only when Agentcard can check it. A name that means several currencies, a code that is both a country and a US state, or a misspelled zone is refused, and the message says what to write instead: ```text theme={null} Error: policy_invalid: "pesos" could be MXN, ARS, CLP, COP, or PHP. Write the currency code, or name the country (Mexican pesos). ``` A region such as `europe` expands to its countries when the rule is saved, and a US state next to a region narrows only the US: `north-america,US-CA` allows any Canadian or Mexican merchant and only Californian US merchants. A merchant in Paris that charges in dollars passes a `usd` rule; to restrict where the merchant is, use `--only-in`. ## Set rules on a card Put the rules on the create call, or pass a saved name. A card created with neither is a normal card. ```bash theme={null} agent-cards cards create --amount 80 --preset office-supplies -y agent-cards cards create --amount 40 --categories meals --mode watch --multi-use -y ``` ```text theme={null} Multi-use card with rules This card stays open across charges until its limit is spent — good for subscriptions. - Creating card... ✔ Virtual card issued! Card •••• 0109 Expires 09/28 Balance $40.00 ID cmtta6yaj000nbrknctlehc1l Preset Categories: Meals & restaurants. Mode: watch. Network no category allowlist on this card — Agentcard checks at checkout and settlement Run: agent-cards cards details cmtta6yaj000nbrknctlehc1l # to see full PAN/CVV The card draws on your balance when used. It stays open until its limit is spent. Manage it with `agent-cards cards pause/resume`. ``` The `Preset` line shows the rules on the card. The `Network` line says who checks them: with a category rule on a `strict` preset the card network itself declines an off-category charge wherever the card is used; every other rule is checked by Agentcard, at checkout and when a charge settles. To change what a card you already have may do from now on, point it at a saved name: ```bash theme={null} agent-cards cards preset cmtta6yaj000nbrknctlehc1l --set office-supplies ``` Agentcard updates the card's network limit when the network allows it, and the response says when the change needs a new card. Over MCP, [`set_card_preset`](/tools/mcp/user/set_card_preset) does the same and also takes inline rules. ## Read a refused purchase Agentcard checks a purchase twice: at Agentcard checkout, before the merchant sees the card, and again when the charge settles. A purchase refused at checkout answers your agent with the rule's code and the next step. A card created with `--only-from cli`, asked for its details by a connected app: ```text theme={null} Error: policy_denied: This card is CLI-only. Run the purchase from the CLI, or change the preset with `cards preset --set `. ``` A charge made straight at a merchant cannot be refused, because the merchant never asked Agentcard. It is judged when it settles. Outside a rule of a `strict` preset on a multi-use card, Agentcard pauses the card and tells you; the charge itself has already been paid, and the pause stops the next one. The card shows as `pausing` until the card network confirms, then `paused`. A single-use card closes after its first charge as usual, and the violation is recorded. A settlement that arrives without a category, a place, or a currency is not a violation. At checkout, a rule Agentcard cannot judge refuses the purchase: a merchant that operates in several countries gives a place rule nothing to judge until the order's country is known, and the purchase is refused with `geo_unknown` rather than guessed. `cards preset `, or `get_card_preset`, shows the rules in force on a card, remembered merchants included. ## Allow a refused merchant When a category or merchant rule refuses a merchant you meant to allow, one command allows it. The notice carries this command with the card id and the merchant filled in: ```bash theme={null} agent-cards cards preset allow-merchant cmtt4mw7s001fbr8zeel9tzse 'GROCERY MART' ``` From now on your agent can buy from that merchant with this card. Your other cards do not change. A card paused after settlement takes `agent-cards cards resume ` before the retry; a refusal at checkout needs nothing more. Over MCP, call [`allow_card_merchant`](/tools/mcp/user/allow_card_merchant) with `pattern` and `card_id`. A remembered merchant passes the category and merchant rules and nothing else; spend, place, currency, time, and `--only-from` rules still apply. A merchant can show up under two names, `AMAZON` at checkout and `AMZN MKTP US` on your statement; when the second name pauses the card, allow it too. A card created with a category rule on a `strict` preset keeps the category lock the card network gave it, so a purchase made directly at a remembered merchant can still be declined by the network; the response tells you when that applies, and a new card from the same preset allows the merchant everywhere. ## Replace or delete a preset Read your presets, or one card's rules: ```bash theme={null} agent-cards cards preset list agent-cards cards preset cmtta6yaj000nbrknctlehc1l ``` To replace a preset, save the same name again. Cards you create from now on get the new rules; cards you already have keep the rules they were created with. A per-day, per-week, or per-month cap counts every card created from that name in one window, and keeps counting after you allow a merchant. To delete a preset, remove it by name. You can no longer create cards from it, and cards you already have keep working: ```bash theme={null} agent-cards cards preset delete office-supplies ``` To clear a card's rules, run `cards preset --clear`. Agentcard stops checking that card, remembered merchants included; a spending limit the card network already holds stays until you create a new card. A connected app cannot change or clear a card's rules and gets `403 read_only`; you make the change from the CLI or the dashboard. Over MCP: [`list_presets`](/tools/mcp/user/list_presets), [`save_preset`](/tools/mcp/user/save_preset), [`delete_preset`](/tools/mcp/user/delete_preset). ## Relax restrictions You can relax a preset's restrictions by changing what it does when a purchase breaks a rule: a warning instead of the default refusal. Save the rules with `--mode watch`, or save the same rules under a second name with `--mode watch`: ```bash theme={null} agent-cards cards preset save weekday_meals_watch \ --categories meals --mode watch \ --only-days weekdays \ --only-hours 11-14 \ --timezone America/Los_Angeles ``` A purchase that breaks any rule of this preset goes through, and you are told; a cap that is passed says by how much. The card is never paused. Use `watch` while you learn which merchants a category really covers, and switch to `strict` once the notices go quiet. A multi-use card with a category rule on a `strict` preset cannot be created, because the card network cancels such a card after its first approved charge. Ask for one and the create is refused: ```text theme={null} Error: strict_category_multi_use_unsupported: Multi-use cards with a strict category rule are not available yet: the card network closes a category-restricted card after its first approved charge. Create a single-use card, use --mode watch for a multi-use card, or drop the category rule. ``` Use a single-use card for a category rule under `strict`, or `--mode watch` for a multi-use one. Until 2026-10-08 a multi-use `ai_labs` card can still be created, and its response carries a notice saying so; from that date it is refused like any other category rule under `strict`, and cards already created keep working. ## Receive the notices Every pause and every watched charge sends one notice, by email, or by a text to your phone if you have no email on file. Every notice names the merchant, the amount, the rule, and the exact command for the next step. A refusal at Agentcard checkout answers your agent with the same next step instead. The email for a \$5.00 charge at GROCERY MART that paused a card whose preset is `strict`, and the email for the same charge on a card whose preset watches: ```text theme={null} A $5.00 charge at GROCERY MART is outside the preset on your card ending in 7318; the card is paused. Category denied. This charge at GROCERY MART is outside Software, AI vendors. Use an allowed merchant, or allow this merchant with `cards preset allow-merchant GROCERY`. To allow this merchant and get going again, run: agent-cards cards preset allow-merchant cmtta6zne000ubrknm8imiu5n "GROCERY MART" agent-cards cards resume cmtta6zne000ubrknm8imiu5n ``` ```text theme={null} A $5.00 charge at GROCERY MART on your card ending in 7318 went through and is outside the preset. Watched charge. This charge at GROCERY MART is outside Meals & restaurants. Nothing is blocked. To stop these notices, allow this merchant with `cards preset allow-merchant GROCERY`, or change the preset with `cards preset --set `. To allow this merchant and stop these notices, run: agent-cards cards preset allow-merchant cmtta6yaj000nbrknctlehc1l "GROCERY MART" ``` A currency pause is not about a merchant, so there is no merchant to allow. The notice carries the commands that put the charge's currency on the card: save a preset with both currencies, set it on the card, resume. The email for a \$12.50 charge in euros at CAFE DE PARIS on a card that allows `usd` alone: ```text theme={null} A $12.50 charge at CAFE DE PARIS was made in EUR. This card's preset allows purchases in USD only, so the card ending in 2799 is paused. To allow EUR on this card and get going again, save a preset with the currencies you want, put it on the card, and resume it: agent-cards cards preset save usd-eur --currencies usd,eur agent-cards cards preset cmttneff4000cjpj64zb1kckl --set usd-eur agent-cards cards resume cmttneff4000cjpj64zb1kckl To be told instead of paused next time, save the preset with --currencies usd --mode watch instead. ``` A charge is judged once, in the currency it was authorized in. If it settles in another currency, you are told and the card is not paused. ## Look up a refusal code Codes from `category_denied` down are returned at Agentcard checkout or when a charge settles. The first six are returned when you create a card or save, set, or clear a preset. | Code | What it means | What to do | | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | | `policy_invalid` | The rules cannot be read: an unknown category, an ambiguous place code, an ambiguous or unknown currency, a misspelled zone, `--preset` next to rule flags, or a `--mode` other than `strict` or `watch` | Correct the rule the message names | | `strict_category_multi_use_unsupported` | A multi-use card with a category rule on a `strict` preset; the card network would cancel it after its first charge | Create it single-use, or use `--mode watch` | | `policy_denied` | The card's `--only-from` or time rule refuses the request for the card's details | Ask from the place or in the window the rule allows, or change the card's rules | | `policy_update_failed` | The card's rules changed under you, or the network refused the new limit | Read the card's rules again and retry | | `limit_exceeds_preset_total` | An amount or a new limit above the total a `strict` preset allows | Ask for less, or raise the total | | `read_only` | A connected app tried to change a card's rules or delete a saved name | Make the change from the CLI or the dashboard | | `category_denied` | The merchant's category is outside the category rule, and the preset is `strict` | Allow the merchant once, resume a paused card, retry | | `category_unknown` | The charge came with no category and Agentcard does not know the merchant | Allow the merchant once, or use a merchant Agentcard recognizes | | `merchant_denied` | The merchant matches none of the names the preset allows | Allow the merchant once, or widen the rule | | `merchant_unknown` | The merchant is unknown and the rule needs one | Retry with a named merchant | | `spend_total_exceeded` | The charge would take the card past its total | Create a card with a higher total | | `spend_rate_exceeded` | The charge would take the shared window past its cap | Wait for the window to roll, or save the preset again with a higher rate | | `spend_rate_unknown` | Agentcard could not check how much this preset has spent | Try again | | `rate_unavailable` | The dollar value of a purchase in another currency could not be worked out, because no exchange rate was available | Pay in dollars, or try again shortly | | `geo_denied` | The merchant is outside the places the rule allows | Use a merchant in an allowed place, or widen the rule | | `geo_unknown` | The merchant operates in several countries and the order's country is unknown | Use a single-country merchant, or a checkout that supplies the order's country | | `currency_denied` | The purchase is in a currency outside the currency rule, and the preset is `strict` | Buy in an allowed currency, or change the rule; resume a paused card | | `currency_unknown` | Agentcard cannot tell the currency of the purchase and the preset is `strict` | Use a checkout that states its currency, or set `--mode watch` | | `surface_denied` | The request came from a place the `--only-from` rule excludes | Run it from the CLI, an MCP tool, the API, or the dashboard, whichever the rule allows | | `surface_unknown` | Agentcard cannot tell whether the CLI, an MCP tool, the API, or the dashboard is asking | Use a signed-in CLI, a connected app, or an API key | | `time_window_denied` | Outside the allowed days or hours, in the rule's zone | Retry inside the window, or change it | Every refusal names the rule that refused and what the card allows. A category or merchant refusal carries the command that allows the merchant. # Using the cards Source: https://docs.agentcard.sh/issuing/using-the-cards Read a card's credentials at checkout, pay with it, and manage it afterwards. An issued card works like any card: your agent types the number, expiry and CVC into a merchant's checkout. What is different is what happens around it. Credentials are revealed on demand, single-use cards close themselves, and every charge reaches your server as a webhook. ## Read the credentials Ask for them when the agent is at the payment form, not before: ```json theme={null} { "tool": "get_card_details", "arguments": { "card_id": "card_…" } } ``` ```json theme={null} { "status": "details", "cardId": "card_…", "last4": "4832", "expiry": "09/29", "balanceCents": 2500, "cardStatus": "active" } ``` The full number and CVC are in the tool's text result. Never write them to logs, error reports, or analytics. Prefer `get_card_balance` when you only need the balance. If the response is `approval_required`, the user has asked to approve each reveal. Show them the prompt, they approve from their own Agentcard session or the emailed link, and your agent retries with the `approval_id`. ## Pay Type the credentials into the checkout. The card authorizes up to its `amount_cents`, and declines anything above it or outside a merchant lock. Your server receives `transaction.authorized` when money moves and `approval.requested` when a purchase needs a human first. For merchants Agentcard already covers, your agent can skip the browser: the `buy` tool on the same MCP connection runs the purchase conversationally and pays with the card. See the [Purchase API](/vault/integrations/ecommerce-apis/purchase-api). ## What happens after a charge * **Single-use cards** close themselves after the first approved charge. `closed_reason` is `used`. * **Multi-use cards** stay open until their limit is spent or you close them. * **Refunds** post back to the card that paid. The balance returns to the user. * **Tokenback:** settled spend earns tokens, 1 token per cent. `get_rewards` shows them, `redeem_rewards` turns them into spending power. ## Manage a card Multi-use cards can be managed while open: | Tool | Does | | ------------------- | --------------------------------------------------------------- | | `pause_card` | Blocks all new charges. Reversible. | | `resume_card` | Unblocks a paused card. | | `update_card_limit` | Resizes the total limit. Raising it draws on the balance. | | `close_card` | Permanent. Returns the unspent balance to the user. Idempotent. | `list_cards` shows every card the connection can see, with test cards flagged. ## Webhooks Register a [webhook endpoint](/api-reference/webhook-endpoints/overview) and subscribe to what you need: | Event | Fires when | | ------------------------------- | ----------------------------------------------- | | `card.created` | A card was issued. | | `transaction.authorized` | A charge was approved on a card. | | `approval.requested` | A purchase or a reveal is waiting for the user. | | `user_wallet.funded` | A deposit landed as spending power. | | `identity.verification.updated` | KYC status changed. | React to webhooks, not to the conversation. The agent saying it paid is a claim. `transaction.authorized` is a fact. ## Sandbox Test cards are issued instantly, carry credentials, and are not accepted by real merchants. Use them to exercise your agent's checkout code against a test storefront such as [shop.agentcard.sh](https://shop.agentcard.sh) on Stripe test mode. The reveal, close and webhook flows are identical to live. # Integrating a merchant to the Purchase API Source: https://docs.agentcard.sh/partners/integrating-a-merchant Expose a catalog and an orders endpoint, and agents on Agentcard can buy from you. The Purchase API is how agents on Agentcard buy things. An agent says what the user wants, Agentcard finds it at the merchant, shows the user an exact total, and places the order once they confirm. It works today at Amazon, Walmart, Target, DoorDash and the other merchants on the [Purchase API](/vault/integrations/ecommerce-apis/purchase-api) page. If you are a merchant, this page lists what we need you to expose so we can add your store. You do not build against Agentcard. You give us a small read API for your catalog and a small write API for orders, and we do the integration on our side. ## How to get listed Email **[founders@agentcard.sh](mailto:founders@agentcard.sh)** with: 1. The base URL of your API and a link to its docs, or the endpoints below if you are building them for us. 2. How to get us an API key, for staging first and production later. Do not paste keys in the email: a one-time secret link works, or invite [founders@agentcard.sh](mailto:founders@agentcard.sh) to your developer dashboard. 3. Which payment provider you charge through. 4. A few items we can order in staging without real inventory or money moving. We build the connector, place test orders against your staging environment with you, and list you in `GET /buy/merchants` once real orders go through cleanly. Nothing to deploy, no SDK to install, no Agentcard account needed. ## What we need you to expose Three groups: a catalog we can search, an orders endpoint we can quote and place against, and a way to pay. Field names below are a suggestion. If you already have an API that carries the same information under different names, send us that instead. The endpoint names and JSON examples below illustrate a proposed merchant API contract. We agree the final contract with you during integration. All money is an integer in the smallest unit of the currency, so `2250` is `$22.50`. Every id must be stable, so the same product returns the same id tomorrow. ## 1. Catalog The agent needs to find what the user asked for and show them the price before anything is bought. ``` GET /products?q=&page= GET /products/{id} ``` Search takes a free-text query and pages through results. Add whatever filters make sense for your catalog, such as `category`, `city`, `from` or `to`. A product: | Field | Notes | | --------------------- | ----------------------------------------------------------- | | `id` | Stable identifier. | | `name`, `description` | Shown to the user. | | `image_url`, `url` | Product image and the page on your site. | | `status` | `available`, `sold_out` or `unavailable`. | | `variants[]` | Sizes, colors, ticket types. Anything the user has to pick. | A variant: | Field | Notes | | -------------------------------- | --------------------------------------------------------------------------- | | `id` | Stable identifier. This is what we send back in an order. | | `name` | For example `Large`, `General admission`. | | `price`, `currency` | Base price in minor units. | | `fee` | Any per-unit fee you add on top, so we can show the real price. | | `available` | A quantity, or `true` / `false` if you would rather not expose stock. | | `min_per_order`, `max_per_order` | Purchase limits, if you have them. | | `sales_end` | When the variant is no longer available for purchase, if it has a deadline. | ```json theme={null} { "id": "prod_123", "name": "Colombian ground coffee", "description": "Medium roast, 16 oz bag.", "image_url": "https://shop.example.com/img/coffee.jpg", "url": "https://shop.example.com/products/colombian-ground", "status": "available", "variants": [ { "id": "var_16oz", "name": "16 oz", "price": 2250, "currency": "usd", "fee": 0, "available": 40, "min_per_order": 1, "max_per_order": 10 } ] } ``` ### Events and tickets If you sell events, expose them as events rather than products, so the agent can search by city and date and the user can see when and where it is. ``` GET /events?q=&city=&from=&to=&page= GET /events/{id} ``` An event: | Field | Notes | | ---------------------------------- | ---------------------------------------------- | | `id` | Stable identifier. | | `name`, `description` | Shown to the user. | | `starts_at`, `ends_at`, `timezone` | ISO 8601 times and the venue's IANA timezone. | | `venue` | `{ name, address, city }`. | | `image_url`, `url` | Event image and the page on your site. | | `status` | `on_sale`, `sold_out` or `cancelled`. | | `ticket_types[]` | What the user picks. Same fields as a variant. | A ticket type: | Field | Notes | | -------------------------------- | --------------------------------------------------------- | | `id` | Stable identifier. This is what we send back in an order. | | `name` | For example `General admission`, `VIP`. | | `price`, `currency` | Base price in minor units. | | `fee` | Any per-ticket fee you add on top. | | `available` | A quantity, or `true` / `false`. | | `min_per_order`, `max_per_order` | Ticket limits. | | `sales_end` | When sales close for this ticket type. | ```json theme={null} { "id": "evt_789", "name": "Sunset Sessions", "description": "Live set on the pier.", "starts_at": "2026-10-03T19:00:00-07:00", "ends_at": "2026-10-03T23:00:00-07:00", "timezone": "America/Los_Angeles", "venue": { "name": "Pier 70", "address": "420 22nd St", "city": "San Francisco" }, "image_url": "https://tickets.example.com/img/sunset.jpg", "url": "https://tickets.example.com/events/sunset-sessions", "status": "on_sale", "ticket_types": [ { "id": "tt_ga", "name": "General admission", "price": 4500, "currency": "usd", "fee": 300, "available": 120, "min_per_order": 1, "max_per_order": 6, "sales_end": "2026-10-03T18:00:00-07:00" } ] } ``` If you also sell merchandise, keep `GET /products` alongside `GET /events`. ## 2. Orders The user confirms an exact total before we place anything. So we need to quote first, then place, then read back the result. ``` POST /orders/quote POST /orders GET /orders/{id} POST /orders/{id}/cancel ``` ### Quote `POST /orders/quote` returns exact totals without committing anything. A `preview: true` flag on `POST /orders` works too. Request: | Field | Notes | | ------------------ | ------------------------------------------------------------------------------------------------------------ | | `items[]` | `{ variant_id, quantity }`, or `{ ticket_type_id, quantity }` for events. | | `event_id` | For events. The event the tickets belong to. | | `shipping_address` | For physical goods. `{ line1, line2, city, state, postal_code, country }`. Needed to price shipping and tax. | | `buyer` | Optional here. `{ first_name, last_name, email, phone }`. | Response: | Field | Notes | | ------------ | ------------------------------------------------------------------------------------------------------------- | | `subtotal` | Items before fees and tax. | | `fees` | Service, delivery and shipping fees, all together. | | `tax` | Tax on the order. | | `total` | What the card will be charged. Must equal `subtotal + fees + tax`. | | `currency` | ISO 4217, lowercase. | | `quote_id` | An id for this quote. We send it back on `POST /orders` so you can check the order matches what was approved. | | `expires_at` | Optional. How long the quote holds. | ```json theme={null} { "quote_id": "q_8f2c", "subtotal": 4500, "fees": 300, "tax": 394, "total": 5194, "currency": "usd", "expires_at": "2026-09-10T17:30:00Z" } ``` The total has to be exact and repeatable. We show it to the user, they confirm that number, and you must charge only that approved total. If the total changes between quote and order, we have to go back to the user, so include shipping, service fees and tax here rather than at order time. ### Place the order `POST /orders` with an `Idempotency-Key` header. Request: | Field | Notes | | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | | `items[]` | `{ variant_id, quantity }`, or `{ ticket_type_id, quantity }` for events. | | `event_id` | For events. | | `buyer` | `{ first_name, last_name, email, phone }`. Who the order and receipt go to. | | `shipping_address` | For physical goods. `{ line1, line2, city, state, postal_code, country }`. | | `attendees[]` | For tickets, when you need a name per ticket. `{ ticket_type_id, first_name, last_name, email }`. | | `quote_id` | The quote the user approved. | | `expected_total`, `currency` | The total the user approved. If your recalculated total differs, do not charge: reject with `total_changed` and a fresh quote. | | `payment` | See [Payment](#3-payment). | The example below shows the shared order fields. We agree the payment fields with you during integration. ```json theme={null} { "quote_id": "q_8f2c", "expected_total": 5194, "currency": "usd", "items": [{ "variant_id": "var_16oz", "quantity": 2 }], "buyer": { "first_name": "Jane", "last_name": "Doe", "email": "jane@example.com", "phone": "+14155550100" }, "shipping_address": { "line1": "1900 Jefferson St", "city": "San Francisco", "state": "CA", "postal_code": "94123", "country": "US" } } ``` Response: | Field | Notes | | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | Your order id. We store it and use it for everything after this. | | `status` | `confirmed`, `pending` or `failed`. `pending` means you are still processing and we should poll `GET /orders/{id}`. | | `totals` | `{ subtotal, fees, tax, total, currency }`, the same shape as the quote. | | `items[]` | One per line. `{ id, variant_id, quantity, url }`. For tickets, `{ id, ticket_type_id, attendee, url }` where `url` is the ticket or QR code the user presents. | | `url` | The order page on your site, if you have one. | ```json theme={null} { "id": "ord_456", "status": "confirmed", "totals": { "subtotal": 4500, "fees": 300, "tax": 394, "total": 5194, "currency": "usd" }, "items": [ { "id": "li_1", "variant_id": "var_16oz", "quantity": 2, "url": "https://shop.example.com/orders/ord_456" } ], "url": "https://shop.example.com/orders/ord_456" } ``` Two things we lean on: * Return the same order on retries. If we retry with the same `Idempotency-Key`, return the same order with its `id`, not an error. A retry after a dropped connection must never create a second order. * **Specific failures.** If something cannot be bought, say which item and why. A generic `500` makes us ask the user to try again when the answer is really "sold out". Error response: | Field | Notes | | --------- | ------------------------------------------------------------------------------------------------------------------------------ | | `error` | `items_unavailable`, `total_changed`, `invalid_address`, `payment_declined`, `limit_exceeded`, or your own code. | | `message` | Human-readable. We may show it to the user. | | `items[]` | For `items_unavailable`, the `variant_id` or `ticket_type_id` values that could not be bought. | | `quote` | For `total_changed`, a fresh quote in the same shape as `POST /orders/quote`. We take it back to the user before trying again. | ```json theme={null} { "error": "items_unavailable", "message": "16 oz is sold out.", "items": ["var_16oz"] } ``` ```json theme={null} { "error": "total_changed", "message": "Shipping went up.", "quote": { "quote_id": "q_9a11", "subtotal": 4500, "fees": 600, "tax": 394, "total": 5494, "currency": "usd" } } ``` ### Read the order `GET /orders/{id}`. We poll this after placing to confirm the order went through, and to tell the user when something ships or is ready. Response: | Field | Notes | | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- | | `id`, `status`, `totals`, `items[]`, `url` | Same as the place response. | | `status` | `confirmed`, `pending`, `failed`, `cancelled`, plus fulfillment states if you have them: `shipped`, `delivered`. | | `refund` | `{ amount, currency, status }` when any refund has been issued. `status` is `pending` or `completed`. | | `tracking` | Optional. `{ carrier, number, url, estimated_delivery }` once a package ships. | ```json theme={null} { "id": "ord_456", "status": "shipped", "totals": { "subtotal": 4500, "fees": 300, "tax": 394, "total": 5194, "currency": "usd" }, "items": [{ "id": "li_1", "variant_id": "var_16oz", "quantity": 2 }], "refund": null, "tracking": { "carrier": "USPS", "number": "9400111899223", "url": "https://tools.usps.com/go/TrackConfirmAction?tLabels=9400111899223", "estimated_delivery": "2026-09-14" } } ``` ### Cancel `POST /orders/{id}/cancel`. Optional. Cancels and refunds whatever your policy allows. If you cannot cancel through the API, tell us and we send users to your support flow instead. Request: no body. Response: | Field | Notes | | -------------- | -------------------------------------------------------------------------------------------------- | | `id`, `status` | The order, now `cancelled`. | | `refund` | `{ amount, currency, status }`. `amount` is what is coming back, which may be less than the total. | ```json theme={null} { "id": "ord_456", "status": "cancelled", "refund": { "amount": 4800, "currency": "usd", "status": "pending" } } ``` ### Webhooks Optional. Share your existing webhook and signature documentation so we can plan how order updates reach Agentcard. | Field | Notes | | ------------- | ---------------------------------------------------------------------------- | | `id` | Unique per delivery. Retries reuse the same `id`, so we can drop duplicates. | | `type` | `order.confirmed`, `order.cancelled` or `order.refunded`. | | `order_id` | The order this is about. | | `occurred_at` | ISO 8601. | | `order` | The same object `GET /orders/{id}` returns, so we never need a second call. | ```json theme={null} { "id": "evt_01j9x", "type": "order.refunded", "order_id": "ord_456", "occurred_at": "2026-09-10T17:04:12Z", "order": { "id": "ord_456", "status": "cancelled", "refund": { "amount": 4800, "currency": "usd", "status": "completed" } } } ``` We agree the receiving URL, signature verification, timestamp tolerance and retry policy with you during integration. ## 3. Payment We pay each order through your own payment provider, and you charge it like any other order. Tell us which provider you use and we handle the rest on our side. Providers we support today: * Stripe * Shopify Payments * Adyen * Braintree * Square * Recurly * Razorpay If yours is not on the list, tell us anyway and we will let you know what it takes. ## Checklist before you email us * Catalog search and product detail, with stable ids and prices in minor units. * A quote that returns the exact total including fees, tax and shipping, with a `quote_id`. * Order create checks `quote_id` and `expected_total`, and rejects with `total_changed` instead of charging a different amount. * Order create with `Idempotency-Key`, returning the order id on duplicates. * Order read, with status. * Order create charges exactly the quoted total through your payment provider. Send the base URL, your API docs or the endpoints above, how to get a staging key, your payment provider, and a couple of test items to [founders@agentcard.sh](mailto:founders@agentcard.sh). A first test order is usually placed within a few days. # CLI Source: https://docs.agentcard.sh/tools/cli The agent-cards CLI: manage your organization from the terminal, and give coding agents a tool catalog they can call. The `agent-cards` CLI does everything the dashboard does, from the terminal. Personal commands are top level. Organizations use the `companies` namespace. ## Install and sign in ```bash theme={null} npm install -g agent-cards agent-cards login ``` A sign-in link and short code appear, and you approve in your browser. For scripts and CI, `agent-cards login --email you@example.com` sends a one-time code and `--code 123456` completes it without a browser. Update any time with `agent-cards update`. Then pick the organization you work in: ```bash theme={null} agent-cards companies list agent-cards companies use ORG_ID ``` ## Organization commands All of these live under `agent-cards companies`. Sandbox or production follows the credentials in use, the same rule as the API. | Command | What it does | | ------------------------------------------------------ | ----------------------------------------------------------------------------------- | | `create` / `list` / `get` / `use` | Create an organization, list yours, pick the active one | | `credentials create` / `list` / `revoke` | Manage the OAuth clients behind your `client_id` and `client_secret` | | `env test` / `env production` | Point the CLI at sandbox or production credentials | | `balance get` / `provision` / `transfers` / `settings` | See and manage the company balance | | `balance test-fund` | Add sandbox balance so you can test issuing end to end | | `balance withdraw` | Withdraw from the company balance | | `webhooks list` / `create` / `update` / `delete` | Manage webhook endpoints | | `webhooks reveal` / `roll-secret` | Read or rotate an endpoint's signing secret | | `webhooks deliveries` / `test` | See recent deliveries, or send a test event | | `webhooks listen` | Stream events to your terminal and forward them to a local server, no tunnel needed | | `members` | Manage who is in the organization | | `subscribe` | Start the subscription that unlocks production | | `return-urls` | Set where hosted flows send users back to | | `engineer` | Ask the Agentcard engineer agent a question about your integration | Use `--help` on any command for flags: ```bash theme={null} agent-cards companies webhooks test --help ``` ## Personal commands The same CLI runs a personal Agentcard account. Useful for testing what your users will experience. | Command | What it does | | ------------------------------------------ | --------------------------------------------------------- | | `signup` / `login` / `logout` / `whoami` | Account and session | | `wallet` / `balance` / `fund` / `withdraw` | See cards and cash, add cash, withdraw | | `cards create` / `list` / `get` / `close` | Issue and manage cards | | `add` | Put your own card in the Vault | | `transactions` | Per-card or account-wide history | | `kyc` | One-time identity verification from the terminal | | `buy` | Shop and check out at supported merchants | | `approvals` | List, approve, or deny requests from connected apps | | `connections` | List or revoke third-party apps connected to your account | | `rewards` / `redeem` | Tokenback balance and promo codes | | `payment-method` / `plan` / `settings` | Saved payment methods, subscription, preferences | | `support` | Start a live support conversation | ## For coding agents Two commands turn the CLI into a tool surface an agent can drive without prompts. `agent-cards api` is the tool catalog: every account tool, with JSON on stdout and `{error, hint}` envelopes on failure. ```bash theme={null} agent-cards api --agent-help # load this once into the agent's context agent-cards api tools # every tool name agent-cards api search # find tools agent-cards api describe # a tool's input and output schema agent-cards api call '' # invoke one (pipe JSON via - for stdin) ``` `agent-cards agents add` teaches Claude Code, Codex, or Gemini to drive Agentcard by installing steering blocks that refresh themselves when the CLI updates. `agent-cards setup-mcp` configures the [MCP server](/tools/mcp) in Claude Code in one step. Most interactive commands also accept `--yes` to skip confirmations and `--json` for machine-readable output, for example `cards create --amount 25 --yes --json`. ## Rules for your agent ```text theme={null} - companies use ORG_ID scopes every later command. Check it before anything destructive, such as credentials revoke or webhooks roll-secret. - env test and env production decide which credentials the CLI uses, and sandbox or production follows from that. - In scripts and CI, sign in with login --email and --code; there's no browser to approve in. - Run webhooks test against your endpoint before going live. It's the fastest proof that signature verification works. ``` # agent-cards account link Source: https://docs.agentcard.sh/tools/cli/account-link Link or merge another account of yours (fixes "documents submitted on another Link or merge another account of yours (fixes "documents submitted on another ```bash theme={null} agent-cards account link --help ``` ```text theme={null} Usage: agent-cards account link [options] [identifier] Link or merge another account of yours (fixes "documents submitted on another profile") Options: -h, --help display help for command ``` # agent-cards agents add Source: https://docs.agentcard.sh/tools/cli/agents-add Install the Agentcard steering block into your coding agents' instruction files Install the Agentcard steering block into your coding agents' instruction files ```bash theme={null} agent-cards agents add --help ``` ```text theme={null} Usage: agent-cards agents add [options] Install the Agentcard steering block into your coding agents' instruction files Options: --agent Target one agent: claude-code | codex | gemini --all Wire every detected agent without prompting --path Write the steering block into a specific instruction file -h, --help display help for command ``` # agent-cards api Source: https://docs.agentcard.sh/tools/cli/api The Agentcard tool catalog for agents and scripts (same tools as the MCP The Agentcard tool catalog for agents and scripts (same tools as the MCP ```bash theme={null} agent-cards api --help ``` ```text theme={null} Usage: agent-cards api [options] [command] The Agentcard tool catalog for agents and scripts (same tools as the MCP server) Options: --agent-help Print the full agent guide (load it into your context) --no-fail Always exit 0 (errors still print their {error, hint} envelope) -h, --help display help for command Commands: tools [options] List tool names as a JSON array (token-cheap for agents) schema [options] [fieldPath] Drill into a field of a tool's input schema (dot notation, e.g. items.quantity) skill Published Agentcard skills for coding agents search [options] Search tools by regex over names and descriptions describe|info [options] Show a tool's description and input/output schemas call [options] [args] Invoke a tool with a JSON arguments object (or pipe JSON with -) ``` # agent-cards api call Source: https://docs.agentcard.sh/tools/cli/api-call Invoke a tool with a JSON arguments object (or pipe JSON with -) Invoke a tool with a JSON arguments object (or pipe JSON with -) ```bash theme={null} agent-cards api call --help ``` ```text theme={null} Usage: agent-cards api call [options] [args] Invoke a tool with a JSON arguments object (or pipe JSON with -) Options: --stdin Read the JSON arguments object from stdin --confirm Required for tools that move money or irreversibly change the account --dry-run Validate the arguments against the tool schema without executing -h, --help display help for command ``` # agent-cards api describe Source: https://docs.agentcard.sh/tools/cli/api-describe Show a tool's description and input/output schemas Show a tool's description and input/output schemas ```bash theme={null} agent-cards api describe --help ``` ```text theme={null} Usage: agent-cards api describe|info [options] Show a tool's description and input/output schemas Options: --json Machine-readable output -h, --help display help for command ``` # agent-cards api schema Source: https://docs.agentcard.sh/tools/cli/api-schema Drill into a field of a tool's input schema (dot notation, e.g. items.quantity) Drill into a field of a tool's input schema (dot notation, e.g. items.quantity) ```bash theme={null} agent-cards api schema --help ``` ```text theme={null} Usage: agent-cards api schema [options] [fieldPath] Drill into a field of a tool's input schema (dot notation, e.g. items.quantity) Options: --json Machine-readable output -h, --help display help for command ``` # agent-cards api search Source: https://docs.agentcard.sh/tools/cli/api-search Search tools by regex over names and descriptions Search tools by regex over names and descriptions ```bash theme={null} agent-cards api search --help ``` ```text theme={null} Usage: agent-cards api search [options] Search tools by regex over names and descriptions Options: --json Machine-readable output -h, --help display help for command ``` # agent-cards api skill Source: https://docs.agentcard.sh/tools/cli/api-skill Published Agentcard skills for coding agents Published Agentcard skills for coding agents ```bash theme={null} agent-cards api skill --help ``` ```text theme={null} Usage: agent-cards api skill [options] [command] Published Agentcard skills for coding agents Options: -h, --help display help for command Commands: list [options] List published skills install [options] Install a skill into ./.agents/skills// (sha256-verified) help [command] display help for command ``` # agent-cards api tools Source: https://docs.agentcard.sh/tools/cli/api-tools List tool names as a JSON array (token-cheap for agents) List tool names as a JSON array (token-cheap for agents) ```bash theme={null} agent-cards api tools --help ``` ```text theme={null} Usage: agent-cards api tools [options] List tool names as a JSON array (token-cheap for agents) Options: --all Include the expert shopping tools hidden by default --table Human view: boxed table with one-line descriptions -h, --help display help for command ``` # agent-cards approvals approve Source: https://docs.agentcard.sh/tools/cli/approvals-approve Approve a pending request (confirms what you are approving first) Approve a pending request (confirms what you are approving first) ```bash theme={null} agent-cards approvals approve --help ``` ```text theme={null} Usage: agent-cards approvals approve [options] Approve a pending request (confirms what you are approving first) Options: -y, --yes Skip the confirmation prompt --json Machine-readable output (requires -y) -h, --help display help for command ``` # agent-cards approvals deny Source: https://docs.agentcard.sh/tools/cli/approvals-deny Deny a pending request Deny a pending request ```bash theme={null} agent-cards approvals deny --help ``` ```text theme={null} Usage: agent-cards approvals deny [options] Deny a pending request Options: --json Machine-readable output -h, --help display help for command ``` # agent-cards approvals list Source: https://docs.agentcard.sh/tools/cli/approvals-list List pending approval requests List pending approval requests ```bash theme={null} agent-cards approvals list --help ``` ```text theme={null} Usage: agent-cards approvals list [options] List pending approval requests Options: --json Output as JSON -h, --help display help for command ``` # agent-cards attach Source: https://docs.agentcard.sh/tools/cli/attach Attach your own Visa so purchases charge it directly (no KYC, no funding) Attach your own Visa so purchases charge it directly (no KYC, no funding) ```bash theme={null} agent-cards attach --help ``` ```text theme={null} Usage: agent-cards attach [options] Attach your own Visa so purchases charge it directly (no KYC, no funding) Options: --add Attach another card alongside the current one (multi-card) --replace Remove the currently attached card first, then attach a new one --list Show all attached cards (the row marked (default) is the mint target; change it with settings default-card) --remove Remove one attached card by id (cards minted against it close) --json Machine-readable output (single POST, no browser/poll) -h, --help display help for command ``` # agent-cards balance Source: https://docs.agentcard.sh/tools/cli/balance Your cash balance (funds new cards) — or one card's balance with an id Your cash balance (funds new cards) — or one card's balance with an id ```bash theme={null} agent-cards balance --help ``` ```text theme={null} Usage: agent-cards balance [options] [id] Your cash balance (funds new cards) — or one card's balance with an id Options: --json Output as JSON (bare form only) -h, --help display help for command ``` # agent-cards buy Source: https://docs.agentcard.sh/tools/cli/buy Buy — chat to shop, or use a subcommand to link merchants, shop, and check out Buy — chat to shop, or use a subcommand to link merchants, shop, and check out ```bash theme={null} agent-cards buy --help ``` ```text theme={null} Usage: agent-cards buy [options] [command] Buy — chat to shop, or use a subcommand to link merchants, shop, and check out Options: -h, --help display help for command Commands: chat Chat in natural language to shop and check out merchants List merchants and link status link [options] Link a merchant account (rappi | goodeggs | doordash) confirm [options] Confirm a merchant link with the one-time code unlink Disconnect a merchant (drops the saved session + link) connect Link a merchant by logging in via a hosted browser (doordash) stores Find stores within a multi-store merchant (DoorDash) by name store Scope searches + the cart to one store (DoorDash) search Search a linked merchant for products cart View the cart add [options] Add a product to the cart remove Remove a product from the cart qty Set a product's quantity in the cart (0 removes it) clear Empty the cart budget [options] Set a spend budget (period: daily|weekly|monthly|total) checkout [options] Place + pay for the cart (DESTRUCTIVE — requires --yes) orders [options] View recent order history at a linked merchant reorder Re-create a cart from a past order (use the id from `buy orders`) track Show status + ETA for a placed order (use the id from `buy orders`) substitution Set out-of-stock preference for an item (itemMsid = msid from `buy search`; preference = similar|refund|contact) addresses List the delivery addresses saved on a linked merchant account set-address Set the default delivery address (addressId = the id from `buy addresses`) help [command] display help for command ``` # agent-cards buy add Source: https://docs.agentcard.sh/tools/cli/buy-add Add a product to the cart Add a product to the cart ```bash theme={null} agent-cards buy add --help ``` ```text theme={null} Usage: agent-cards buy add [options] Add a product to the cart Options: --quantity quantity (default: "1") -h, --help display help for command ``` # agent-cards buy addresses Source: https://docs.agentcard.sh/tools/cli/buy-addresses List the delivery addresses saved on a linked merchant account List the delivery addresses saved on a linked merchant account ```bash theme={null} agent-cards buy addresses --help ``` ```text theme={null} Usage: agent-cards buy addresses [options] List the delivery addresses saved on a linked merchant account Options: -h, --help display help for command ``` # agent-cards buy budget Source: https://docs.agentcard.sh/tools/cli/buy-budget Set a spend budget (period: daily|weekly|monthly|total) Set a spend budget (period: daily|weekly|monthly|total) ```bash theme={null} agent-cards buy budget --help ``` ```text theme={null} Usage: agent-cards buy budget [options] Set a spend budget (period: daily|weekly|monthly|total) Options: --timezone IANA timezone for window boundaries -h, --help display help for command ``` # agent-cards buy cart Source: https://docs.agentcard.sh/tools/cli/buy-cart View the cart View the cart ```bash theme={null} agent-cards buy cart --help ``` ```text theme={null} Usage: agent-cards buy cart [options] View the cart Options: -h, --help display help for command ``` # agent-cards buy checkout Source: https://docs.agentcard.sh/tools/cli/buy-checkout Place + pay for the cart (DESTRUCTIVE — requires --yes) Place + pay for the cart (DESTRUCTIVE — requires --yes) ```bash theme={null} agent-cards buy checkout --help ``` ```text theme={null} Usage: agent-cards buy checkout [options] Place + pay for the cart (DESTRUCTIVE — requires --yes) Options: --yes confirm placing the order --tip Dasher tip in dollars (e.g. 3.50); added to the charge + card size --schedule schedule delivery for an ISO-8601 time (e.g. 2026-06-17T16:00:00Z); default is ASAP --approval a spend approval id, if checkout returned needs_approval --idempotency-key reuse the same key on a retry so a timed-out call never double-charges -h, --help display help for command ``` # agent-cards buy clear Source: https://docs.agentcard.sh/tools/cli/buy-clear Empty the cart Empty the cart ```bash theme={null} agent-cards buy clear --help ``` ```text theme={null} Usage: agent-cards buy clear [options] Empty the cart Options: -h, --help display help for command ``` # agent-cards buy confirm Source: https://docs.agentcard.sh/tools/cli/buy-confirm Confirm a merchant link with the one-time code Confirm a merchant link with the one-time code ```bash theme={null} agent-cards buy confirm --help ``` ```text theme={null} Usage: agent-cards buy confirm [options] Confirm a merchant link with the one-time code Options: --pending --code -h, --help display help for command ``` # agent-cards buy connect Source: https://docs.agentcard.sh/tools/cli/buy-connect Link a merchant by logging in via a hosted browser (doordash) Link a merchant by logging in via a hosted browser (doordash) ```bash theme={null} agent-cards buy connect --help ``` ```text theme={null} Usage: agent-cards buy connect [options] Link a merchant by logging in via a hosted browser (doordash) Options: -h, --help display help for command ``` # agent-cards buy link Source: https://docs.agentcard.sh/tools/cli/buy-link Link a merchant account (rappi | goodeggs | doordash) Link a merchant account (rappi | goodeggs | doordash) ```bash theme={null} agent-cards buy link --help ``` ```text theme={null} Usage: agent-cards buy link [options] Link a merchant account (rappi | goodeggs | doordash) Options: --email --first-name --last-name --phone -h, --help display help for command ``` # agent-cards buy merchants Source: https://docs.agentcard.sh/tools/cli/buy-merchants List merchants and link status List merchants and link status ```bash theme={null} agent-cards buy merchants --help ``` ```text theme={null} Usage: agent-cards buy merchants [options] List merchants and link status Options: -h, --help display help for command ``` # agent-cards buy orders Source: https://docs.agentcard.sh/tools/cli/buy-orders View recent order history at a linked merchant View recent order history at a linked merchant ```bash theme={null} agent-cards buy orders --help ``` ```text theme={null} Usage: agent-cards buy orders [options] View recent order history at a linked merchant Options: --limit how many orders to show (max 50) -h, --help display help for command ``` # agent-cards buy qty Source: https://docs.agentcard.sh/tools/cli/buy-qty Set a product's quantity in the cart (0 removes it) Set a product's quantity in the cart (0 removes it) ```bash theme={null} agent-cards buy qty --help ``` ```text theme={null} Usage: agent-cards buy qty [options] Set a product's quantity in the cart (0 removes it) Options: -h, --help display help for command ``` # agent-cards buy remove Source: https://docs.agentcard.sh/tools/cli/buy-remove Remove a product from the cart Remove a product from the cart ```bash theme={null} agent-cards buy remove --help ``` ```text theme={null} Usage: agent-cards buy remove [options] Remove a product from the cart Options: -h, --help display help for command ``` # agent-cards buy reorder Source: https://docs.agentcard.sh/tools/cli/buy-reorder Re-create a cart from a past order (use the id from `buy orders`) Re-create a cart from a past order (use the id from `buy orders`) ```bash theme={null} agent-cards buy reorder --help ``` ```text theme={null} Usage: agent-cards buy reorder [options] Re-create a cart from a past order (use the id from `buy orders`) Options: -h, --help display help for command ``` # agent-cards buy search Source: https://docs.agentcard.sh/tools/cli/buy-search Search a linked merchant for products Search a linked merchant for products ```bash theme={null} agent-cards buy search --help ``` ```text theme={null} Usage: agent-cards buy search [options] Search a linked merchant for products Options: -h, --help display help for command ``` # agent-cards buy set-address Source: https://docs.agentcard.sh/tools/cli/buy-set-address Set the default delivery address (addressId = the id from `buy addresses`) Set the default delivery address (addressId = the id from `buy addresses`) ```bash theme={null} agent-cards buy set-address --help ``` ```text theme={null} Usage: agent-cards buy set-address [options] Set the default delivery address (addressId = the id from `buy addresses`) Options: -h, --help display help for command ``` # agent-cards buy store Source: https://docs.agentcard.sh/tools/cli/buy-store Scope searches + the cart to one store (DoorDash) Scope searches + the cart to one store (DoorDash) ```bash theme={null} agent-cards buy store --help ``` ```text theme={null} Usage: agent-cards buy store [options] Scope searches + the cart to one store (DoorDash) Options: -h, --help display help for command ``` # agent-cards buy stores Source: https://docs.agentcard.sh/tools/cli/buy-stores Find stores within a multi-store merchant (DoorDash) by name Find stores within a multi-store merchant (DoorDash) by name ```bash theme={null} agent-cards buy stores --help ``` ```text theme={null} Usage: agent-cards buy stores [options] Find stores within a multi-store merchant (DoorDash) by name Options: -h, --help display help for command ``` # agent-cards buy substitution Source: https://docs.agentcard.sh/tools/cli/buy-substitution Set out-of-stock preference for an item (itemMsid = msid from `buy search`; Set out-of-stock preference for an item (itemMsid = msid from `buy search`; ```bash theme={null} agent-cards buy substitution --help ``` ```text theme={null} Usage: agent-cards buy substitution [options] Set out-of-stock preference for an item (itemMsid = msid from `buy search`; preference = similar|refund|contact) Options: -h, --help display help for command ``` # agent-cards buy track Source: https://docs.agentcard.sh/tools/cli/buy-track Show status + ETA for a placed order (use the id from `buy orders`) Show status + ETA for a placed order (use the id from `buy orders`) ```bash theme={null} agent-cards buy track --help ``` ```text theme={null} Usage: agent-cards buy track [options] Show status + ETA for a placed order (use the id from `buy orders`) Options: -h, --help display help for command ``` # agent-cards buy unlink Source: https://docs.agentcard.sh/tools/cli/buy-unlink Disconnect a merchant (drops the saved session + link) Disconnect a merchant (drops the saved session + link) ```bash theme={null} agent-cards buy unlink --help ``` ```text theme={null} Usage: agent-cards buy unlink [options] Disconnect a merchant (drops the saved session + link) Options: -h, --help display help for command ``` # agent-cards cards Source: https://docs.agentcard.sh/tools/cli/cards Manage virtual cards Manage virtual cards ```bash theme={null} agent-cards cards --help ``` ```text theme={null} Usage: agent-cards cards [options] [command] Manage virtual cards Options: -h, --help display help for command Commands: add|attach [options] Add your own card to your vault so purchases charge it directly (any card, no KYC, no funding) create [options] Fund and issue a new virtual card preset [options] [card-id] Show or set account/app/card presets (limits & restrictions) list [options] List all cards details Show decrypted PAN / CVV / expiry for a card transactions [options] Show transaction history for a card pause Pause a multi-use card (blocks new charges; reversible with resume) resume Resume a paused multi-use card set-limit [options] Change a multi-use card's total spending limit close [options] Close a card (releases any held funds) help [command] display help for command ``` # agent-cards cards close Source: https://docs.agentcard.sh/tools/cli/cards-close Close a card (releases any held funds) Close a card (releases any held funds) ```bash theme={null} agent-cards cards close --help ``` ```text theme={null} Usage: agent-cards cards close [options] Close a card (releases any held funds) Options: -y, --yes Skip the confirmation prompt -h, --help display help for command ``` # agent-cards cards create Source: https://docs.agentcard.sh/tools/cli/cards-create Fund and issue a new virtual card Fund and issue a new virtual card ```bash theme={null} agent-cards cards create --help ``` ```text theme={null} Usage: agent-cards cards create [options] Fund and issue a new virtual card Options: --amount Amount in US dollars, NOT cents (e.g. 25 = $25.00) --multi-use Create a multi-use card: stays open across charges until its limit is spent (subscriptions) --preset Restrict this card (see cards preset list). Adds limits only; ai_labs implies --multi-use. --expires Auto-close the multi-use card at this ISO-8601 time (≤365 days out), e.g. 2027-01-01T00:00:00Z --from Where the money comes from: an added-card id (see add --list), or 'balance' to use your Agentcard balance even when a card is added -y, --yes Skip the confirmation prompt (for non-interactive / agent use) --json Output the result as JSON and run fully non-interactively --total Lifetime spend cap in US dollars --per-day Spend cap per rolling 24 hours, in US dollars --per-week Spend cap per rolling 7 days, in US dollars --per-month Spend cap per rolling 30 days, in US dollars --categories Restrict to categories, comma-separated: meals, groceries, travel, software, ai, wellness, retail --only-merchants Restrict to merchant name patterns, comma-separated --only-in Restrict to places, comma-separated: a country (US, Canada), a region (europe, eu, north-america, apac), a US state (California, US-CA). A region expands to its countries; a state next to a region narrows only the US, e.g. north-america,US-CA --currencies Restrict to purchase currencies, comma-separated ISO 4217 codes or names: usd,eur or dollars,euros,pounds,yen. Checked by Agentcard at checkout and settlement, not by the card network --only-days Restrict to days, comma-separated: mon,tue or weekdays/weekends --only-hours Restrict to an hour range, e.g. 9-17 or 09:00-17:00 (24-hour; defaults to UTC without --timezone) --timezone IANA timezone for --only-days/--only-hours (default UTC), e.g. America/Los_Angeles --only-from Restrict to callers, comma-separated: cli, mcp, api, browser --mode What the preset does when a purchase breaks a rule: strict refuses it (default), watch lets it through and tells you -h, --help display help for command ``` Pass `--preset ` to put a saved or built-in set of rules on the card, or spell the rules out with flags such as `--total`, `--per-day`, and `--categories`. Use one or the other; the command refuses both together. `--preset ai_labs` makes a multi-use card, and `--multi-use` beside it changes nothing. A multi-use card with a category rule on a `strict` preset is refused with `strict_category_multi_use_unsupported`, because the card network cancels such a card after its first charge. Use a single-use card, or `--categories --mode watch`. The rules are explained in [Set rules on a card](/issuing/set-rules-on-a-card). Say which currencies the card may pay in: ```bash theme={null} agent-cards cards create --amount 50 --currencies usd,eur -y ``` A charge in any other currency is refused, and you are told why. Write codes or plain names in any case, comma-separated: `usd,eur` or `dollars,euros`. If you would rather be told than refused, add `--mode watch` to the preset; pass one of the two, not both: ```bash theme={null} agent-cards cards create --amount 20 --currencies usd --mode watch --multi-use -y ``` Agentcard checks this rule at checkout and at settlement; the card network does not. Which names are refused as ambiguous, and what happens after the charge, are in [Choose what to restrict](/issuing/set-rules-on-a-card#choose-what-to-restrict). The card shows the rule on its `Preset` line, and a `Network` line says who enforces it. Captured from a local sandbox: ```text theme={null} Card •••• 4277 Expires 09/28 Balance $20.00 ID cmttoum4z0003jpk0ugxz6bkx Preset Currency: USD, EUR. Network Agentcard enforces the currency rule at checkout and settlement; the card network does not ``` A refused create writes one line to stderr, the code first, and exits 1. Captured from a local sandbox: ```text theme={null} Error: strict_category_multi_use_unsupported: Multi-use cards with a strict category rule are not available yet: the card network closes a category-restricted card after its first approved charge. Create a single-use card, use --mode watch for a multi-use card, or drop the category rule. ``` If you write a name that means several currencies, the create is refused before any card is issued, and the message lists what it could mean. `agent-cards cards create --amount 20 --currencies pesos -y` answers: ```text theme={null} Error: policy_invalid: "pesos" could be MXN, ARS, CLP, COP, or PHP. Write the currency code, or name the country (Mexican pesos). ``` Inside the deprecation window a reusable `ai_labs` card is created and carries the notice: ```text theme={null} Multi-use card with preset Preset: ai_labs This card stays open across charges until its limit is spent — good for subscriptions. - Creating card... ✔ Virtual card issued! Card •••• 4454 Expires 09/28 Balance $40.00 ID cmtta6zne000ubrknm8imiu5n Preset Categories: Software, AI vendors. Rewarded merchants: OPENAI, CHATGPT, ANTHROPIC, CLAUDE, GEMINI, GOOGLE AI. Notice From 2026-10-08 a reusable card with a category rule on a strict preset can no longer be created, this AI card included: the card network cancels such a card after its first approved charge. Cards already created keep working. For a reusable AI card after that date use --categories software,ai --mode watch; for a strict one, create a single-use card. Run: agent-cards cards details cmtta6zne000ubrknm8imiu5n # to see full PAN/CVV The card draws on your balance when used. It stays open until its limit is spent. Manage it with `agent-cards cards pause/resume`. ``` # agent-cards cards details Source: https://docs.agentcard.sh/tools/cli/cards-details Show decrypted PAN / CVV / expiry for a card Show decrypted PAN / CVV / expiry for a card ```bash theme={null} agent-cards cards details --help ``` ```text theme={null} Usage: agent-cards cards details [options] Show decrypted PAN / CVV / expiry for a card Options: -h, --help display help for command ``` # agent-cards cards list Source: https://docs.agentcard.sh/tools/cli/cards-list List all cards List all cards ```bash theme={null} agent-cards cards list --help ``` ```text theme={null} Usage: agent-cards cards list [options] List all cards Options: --json Output as JSON -h, --help display help for command ``` # agent-cards cards pause Source: https://docs.agentcard.sh/tools/cli/cards-pause Pause a multi-use card (blocks new charges; reversible with resume) Pause a multi-use card (blocks new charges; reversible with resume) ```bash theme={null} agent-cards cards pause --help ``` ```text theme={null} Usage: agent-cards cards pause [options] Pause a multi-use card (blocks new charges; reversible with resume) Options: -h, --help display help for command ``` # agent-cards cards preset Source: https://docs.agentcard.sh/tools/cli/cards-preset Show or set a card's preset (limits & restrictions) Show or set a card's preset (limits & restrictions) ```bash theme={null} agent-cards cards preset --help ``` ```text theme={null} Usage: agent-cards cards preset [options] [command] Show or set a card's preset (limits & restrictions) Arguments: card-id Card id Options: --set Preset: a saved or built-in name (see cards preset list) --clear Clear the card's preset --json Output as JSON -h, --help display help for command Commands: list [options] List built-in and saved presets save [options] Save (or update) a named preset from rule flags delete [options] Delete a saved preset allow-merchant [options] Remember a merchant on a card so the next matching charge is allowed ``` Pass a card id to see or set that card's rules. A new card takes the rules on its create call. A preset can hold spend caps, categories, merchants, places, currencies, days and hours, and where the card can be used from. Rules, built-ins, and the remember step are explained in [Set rules on a card](/issuing/set-rules-on-a-card). ```bash theme={null} agent-cards cards preset # show one card's rules, remembered merchants included agent-cards cards preset --set office-supplies # pin one card to a saved name (new version) agent-cards cards preset --clear # stop Agentcard's checks on that card ``` Clear a card and Agentcard's checks on it stop, remembered merchants included. A limit already pushed to the card network stays until you issue a new card. # agent-cards cards preset allow-merchant Source: https://docs.agentcard.sh/tools/cli/cards-preset-allow-merchant Remember a merchant so the next matching charge is allowed Remember a merchant so the next matching charge is allowed ```bash theme={null} agent-cards cards preset allow-merchant --help ``` ```text theme={null} Usage: agent-cards cards preset allow-merchant [options] Remember a merchant on a card so the next matching charge is allowed Options: --json Output as JSON -h, --help display help for command ``` Use this after a category or merchant rule refused a charge, or after a watched-charge notice. One step: no form, no support ticket, no new card, and the merchant stays allowed on that card from then on. The loop is three lines: the purchase is refused and you are told why; you run this command naming the merchant; the card resumes and the retry goes through. The pause or watch notice carries this command with the card id and merchant filled in. The pattern is a case-insensitive substring of the merchant descriptor: `starbucks` matches `STARBUCKS #123`. The rest of the preset stays in force; spend, place, currency, time, and `--only-from` rules still apply. ```bash theme={null} agent-cards cards preset allow-merchant cmtt4mw7s001fbr8zeel9tzse 'GROCERY MART' # this card only (new version of its preset) ``` If this card was created with categories on a `strict` preset, the card network still enforces the category lock it was given when the card was made, and we cannot widen it afterwards. A purchase made directly at that merchant, outside Agentcard checkout, can still be declined by the network; the output tells you when that applies. If you need both to work, create a new card from the same preset. If a multi-use card was paused after settlement: allow the merchant, run `agent-cards cards resume `, then retry. See [Allow a refused merchant](/issuing/set-rules-on-a-card#allow-a-refused-merchant). Captured from a local sandbox after a grocery charge paused a reusable `ai_labs` card: ```text theme={null} ── Merchant remembered (card) ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │ Pattern GROCERY MART │ │ Preset Categories: Software, AI vendors. Rewarded merchants: OPENAI, CHATGPT, ANTHROPIC, CLAUDE, GEMINI, GOOGLE AI. Also allow merchants: GROCERY MART. │ │ Version v2 │ │ Remembered GROCERY MART on this card. Matching charges are allowed at Agentcard checkout next time. This card keeps its network category allowlist, so a charge made directly at the merchant can still be declined there — create a new card from this preset for that. │ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ ``` # agent-cards cards preset delete Source: https://docs.agentcard.sh/tools/cli/cards-preset-delete Delete a saved preset Delete a saved preset ```bash theme={null} agent-cards cards preset delete --help ``` ```text theme={null} Usage: agent-cards cards preset delete [options] Delete a saved preset Options: --json Output as JSON -h, --help display help for command ``` Retires a saved name. The name leaves `cards preset list` and no longer works with `--preset` or `--set`. Cards you already created from it keep working exactly as they do today. Built-in names cannot be deleted. # agent-cards cards preset list Source: https://docs.agentcard.sh/tools/cli/cards-preset-list List built-in and saved presets List built-in and saved presets ```bash theme={null} agent-cards cards preset list --help ``` ```text theme={null} Usage: agent-cards cards preset list [options] List built-in and saved presets Options: --json Output as JSON -h, --help display help for command ``` Shows the built-in presets `daily`, `weekday_meals`, `cli_only`, and `ai_labs`, and every name you saved with `cards preset save`, each with a plain summary of its rules and, for saved names, the revision number you see in a card summary. Any name shown works with `cards create --preset`, `cards preset --set`, and `cards preset --set`. A deleted name drops off this list; cards you created from it keep working. # agent-cards cards preset save Source: https://docs.agentcard.sh/tools/cli/cards-preset-save Save (or update) a named preset from rule flags Save (or update) a named preset from rule flags ```bash theme={null} agent-cards cards preset save --help ``` ```text theme={null} Usage: agent-cards cards preset save [options] Save (or update) a named preset from rule flags Options: --total Lifetime spend cap in US dollars --per-day Spend cap per rolling 24 hours, in US dollars --per-week Spend cap per rolling 7 days, in US dollars --per-month Spend cap per rolling 30 days, in US dollars --categories Restrict to categories, comma-separated: meals, groceries, travel, software, ai, wellness, retail --only-merchants Restrict to merchant name patterns, comma-separated --only-in Restrict to places, comma-separated: a country (US, Canada), a region (europe, eu, north-america, apac), a US state (California, US-CA). A region expands to its countries; a state next to a region narrows only the US, e.g. north-america,US-CA --currencies Restrict to purchase currencies, comma-separated ISO 4217 codes or names: usd,eur or dollars,euros,pounds,yen. Checked by Agentcard at checkout and settlement, not by the card network --only-days Restrict to days, comma-separated: mon,tue or weekdays/weekends --only-hours Restrict to an hour range, e.g. 9-17 or 09:00-17:00 (24-hour; defaults to UTC without --timezone) --timezone IANA timezone for --only-days/--only-hours (default UTC), e.g. America/Los_Angeles --only-from Restrict to callers, comma-separated: cli, mcp, api, browser --mode What the preset does when a purchase breaks a rule: strict refuses it (default), watch lets it through and tells you --json Output as JSON -h, --help display help for command ``` Save a set of rules under a name and reuse it with `cards create --preset ` or `cards preset --set `. Save a name you already use and your change applies to the cards you create from now on; cards you already have keep the rules they were created with. The built-in names `daily`, `weekday_meals`, `cli_only`, and `ai_labs` cannot be saved over. Pass at least one rule flag. `--timezone` applies only with `--only-days` or `--only-hours` and must be a real IANA zone; a misspelled zone is refused. ```bash theme={null} agent-cards cards preset save office-supplies --per-day 25 --categories meals agent-cards cards preset save weekday_meals_watch \ --categories meals --mode watch --only-days weekdays --only-hours 11-14 \ --timezone America/Los_Angeles agent-cards cards preset save west-coast --only-in 'California, Oregon, Washington' agent-cards cards preset save euro-zone --currencies 'dollars, euros' agent-cards cards preset save euro-zone-watch --currencies usd,eur --mode watch agent-cards cards create --amount 80 --preset office-supplies -y ``` The flags mean the same as on `cards create`. Categories, `mode`, places, currencies, and time windows are explained in [Set rules on a card](/issuing/set-rules-on-a-card). Save the currencies a card may pay in: ```bash theme={null} agent-cards cards preset save euro-zone --currencies 'dollars, euros' ``` A charge in any other currency is refused, and you are told why. Write codes or plain names in any case, comma-separated. If you would rather be told than refused, add `--mode watch` to the preset. The saved rule reads `Currency: USD, EUR` in the summary. Captured from a local sandbox: ```text theme={null} ── Preset saved ──────────────── │ Preset Currency: USD, EUR. │ │ Version v1 │ │ Saved euro-zone. │ └──────────────────────────────┘ ``` If you write a name that means several currencies, the save is refused and the message lists what it could mean, so you can pick. A code that is not a currency is refused the same way. `agent-cards cards preset save euro-zone --currencies pesos` exits 1 with: ```text theme={null} "pesos" could be MXN, ARS, CLP, COP, or PHP. Write the currency code, or name the country (Mexican pesos). ``` With `--json` the same refusal is one JSON line on stdout: ```text theme={null} {"ok":false,"error":"policy_invalid","message":"\"pesos\" could be MXN, ARS, CLP, COP, or PHP. Write the currency code, or name the country (Mexican pesos)."} ``` # agent-cards cards resume Source: https://docs.agentcard.sh/tools/cli/cards-resume Resume a paused multi-use card Resume a paused multi-use card ```bash theme={null} agent-cards cards resume --help ``` ```text theme={null} Usage: agent-cards cards resume [options] Resume a paused multi-use card Options: -h, --help display help for command ``` # agent-cards cards set-limit Source: https://docs.agentcard.sh/tools/cli/cards-set-limit Change a multi-use card's total spending limit Change a multi-use card's total spending limit ```bash theme={null} agent-cards cards set-limit --help ``` ```text theme={null} Usage: agent-cards cards set-limit [options] Change a multi-use card's total spending limit Options: --amount New TOTAL limit in US dollars (e.g. 80 = $80.00) -h, --help display help for command ``` # agent-cards cards transactions Source: https://docs.agentcard.sh/tools/cli/cards-transactions Show transaction history for a card Show transaction history for a card ```bash theme={null} agent-cards cards transactions --help ``` ```text theme={null} Usage: agent-cards cards transactions [options] Show transaction history for a card Options: --limit Number of transactions (default: 20) --status Filter by status -h, --help display help for command ``` # agent-cards codes Source: https://docs.agentcard.sh/tools/cli/codes List your promo codes: used, processing, or retryable List your promo codes: used, processing, or retryable ```bash theme={null} agent-cards codes --help ``` ```text theme={null} Usage: agent-cards codes [options] List your promo codes: used, processing, or retryable Options: --json Output as JSON -h, --help display help for command ``` # agent-cards companies Source: https://docs.agentcard.sh/tools/cli/companies Agentcard for Companies — issue cards to your users' agents Agentcard for Companies — issue cards to your users' agents ```bash theme={null} agent-cards companies --help ``` ```text theme={null} Usage: agent-cards companies [options] [command] Agentcard for Companies — issue cards to your users' agents Options: -h, --help display help for command Commands: create [options] Create a new company list [options] List the companies you belong to get [org-id] Show details of a company use [company] Set the default company for companies commands (id or name; bare = pick) return-urls [options] [org-id] View or set the return-URL allowlist for hosted cardholder onboarding sessions wizard [options] Run an AI agent that implements Agentcard (OAuth + MCP) into the repo at this path subscribe [options] Subscribe to a paid plan for production access (live client credentials) env [mode] Show or switch mode for new client credentials (test/production) credentials|oauth-clients Manage client credentials — pinned OAuth clients for "Connect with Agentcard" apps members Manage company members balance|wallet Company balance — the pooled cash behind create_card's company flow webhooks Manage webhook endpoints for company events help [command] display help for command ``` # agent-cards companies balance Source: https://docs.agentcard.sh/tools/cli/companies-balance Company balance — the pooled cash behind create_card's company flow Company balance — the pooled cash behind create\_card's company flow ```bash theme={null} agent-cards companies balance --help ``` ```text theme={null} Usage: agent-cards companies balance|wallet [options] [command] Company balance — the pooled cash behind create_card's company flow Options: -h, --help display help for command Commands: get [options] Show the company balance, deposit address, and settings provision [options] Create the company balance account (one-time; admin) transfers [options] List company-funded card transfers settings [options] Update company-flow settings test-fund [options] Add TEST-MODE funds to the mock pool (never real money) withdraw [options] Withdraw company cash — to your bank via Coinbase, or USDC to a Base address help [command] display help for command ``` # agent-cards companies balance get Source: https://docs.agentcard.sh/tools/cli/companies-balance-get Show the company balance, deposit address, and settings Show the company balance, deposit address, and settings ```bash theme={null} agent-cards companies balance get --help ``` ```text theme={null} Usage: agent-cards companies balance get [options] Show the company balance, deposit address, and settings Options: --org Company ID -h, --help display help for command ``` # agent-cards companies balance provision Source: https://docs.agentcard.sh/tools/cli/companies-balance-provision Create the company balance account (one-time; admin) Create the company balance account (one-time; admin) ```bash theme={null} agent-cards companies balance provision --help ``` ```text theme={null} Usage: agent-cards companies balance provision [options] Create the company balance account (one-time; admin) Options: --org Company ID -h, --help display help for command ``` # agent-cards companies balance settings Source: https://docs.agentcard.sh/tools/cli/companies-balance-settings Update company-flow settings Update company-flow settings ```bash theme={null} agent-cards companies balance settings --help ``` ```text theme={null} Usage: agent-cards companies balance settings [options] Update company-flow settings Options: --org Company ID --ack-mode ack_required | auto_approve --ack-timeout Collection confirmation window (10-300) --default-funds-source onramp_flow | company_flow --low-balance Low-balance alert threshold in USD -h, --help display help for command ``` # agent-cards companies balance test-fund Source: https://docs.agentcard.sh/tools/cli/companies-balance-test-fund Add TEST-MODE funds to the mock pool (never real money) Add TEST-MODE funds to the mock pool (never real money) ```bash theme={null} agent-cards companies balance test-fund --help ``` ```text theme={null} Usage: agent-cards companies balance test-fund [options] Add TEST-MODE funds to the mock pool (never real money) Options: --org Company ID --amount Amount in USD -h, --help display help for command ``` # agent-cards companies balance transfers Source: https://docs.agentcard.sh/tools/cli/companies-balance-transfers List company-funded card transfers List company-funded card transfers ```bash theme={null} agent-cards companies balance transfers --help ``` ```text theme={null} Usage: agent-cards companies balance transfers [options] List company-funded card transfers Options: --org Company ID --test Show test-mode transfers instead of live -h, --help display help for command ``` # agent-cards companies balance withdraw Source: https://docs.agentcard.sh/tools/cli/companies-balance-withdraw Withdraw company cash — to your bank via Coinbase, or USDC to a Base address Withdraw company cash — to your bank via Coinbase, or USDC to a Base address ```bash theme={null} agent-cards companies balance withdraw --help ``` ```text theme={null} Usage: agent-cards companies balance withdraw [options] Withdraw company cash — to your bank via Coinbase, or USDC to a Base address Options: --org Company ID --amount Amount in USD --to
Destination 0x… address on Base (crypto rail) --bank Cash out to your bank via a hosted Coinbase confirmation --test Withdraw TEST-MODE funds from the mock pool --yes Skip the confirmation prompt -h, --help display help for command ``` # agent-cards companies create Source: https://docs.agentcard.sh/tools/cli/companies-create Create a new company Create a new company ```bash theme={null} agent-cards companies create --help ``` ```text theme={null} Usage: agent-cards companies create [options] Create a new company Options: --name Company name --email Billing email (default: the signed-in account email) -y, --yes Skip the confirmation prompt (required in non-interactive environments) -h, --help display help for command ``` # agent-cards companies credentials Source: https://docs.agentcard.sh/tools/cli/companies-credentials Manage client credentials — pinned OAuth clients for "Connect with Agentcard" Manage client credentials — pinned OAuth clients for "Connect with Agentcard" ```bash theme={null} agent-cards companies credentials --help ``` ```text theme={null} Usage: agent-cards companies credentials|oauth-clients [options] [command] Manage client credentials — pinned OAuth clients for "Connect with Agentcard" apps Options: -h, --help display help for command Commands: create [options] Register a client for an app (uses current env mode; production requires an active subscription) list [options] List a company's client credentials revoke [options] Delete a client and revoke its tokens (interactive) help [command] display help for command ``` # agent-cards companies credentials create Source: https://docs.agentcard.sh/tools/cli/companies-credentials-create Register a client for an app (uses current env mode; production requires an Register a client for an app (uses current env mode; production requires an ```bash theme={null} agent-cards companies credentials create --help ``` ```text theme={null} Usage: agent-cards companies credentials create [options] Register a client for an app (uses current env mode; production requires an active subscription) Options: --org Company ID --name App name shown on the consent screen --redirect-uri Redirect URI(s), comma-separated --public Public client (PKCE, no client_secret) instead of the default confidential client -h, --help display help for command ``` # agent-cards companies credentials list Source: https://docs.agentcard.sh/tools/cli/companies-credentials-list List a company's client credentials List a company's client credentials ```bash theme={null} agent-cards companies credentials list --help ``` ```text theme={null} Usage: agent-cards companies credentials list [options] List a company's client credentials Options: --org Company ID --json Output as JSON -h, --help display help for command ``` # agent-cards companies credentials revoke Source: https://docs.agentcard.sh/tools/cli/companies-credentials-revoke Delete a client and revoke its tokens (interactive) Delete a client and revoke its tokens (interactive) ```bash theme={null} agent-cards companies credentials revoke --help ``` ```text theme={null} Usage: agent-cards companies credentials revoke [options] Delete a client and revoke its tokens (interactive) Options: --org Company ID --client-id OAuth client ID -h, --help display help for command ``` # agent-cards companies env Source: https://docs.agentcard.sh/tools/cli/companies-env Show or switch mode for new client credentials (test/production) Show or switch mode for new client credentials (test/production) ```bash theme={null} agent-cards companies env --help ``` ```text theme={null} Usage: agent-cards companies env [options] [mode] Show or switch mode for new client credentials (test/production) Options: -h, --help display help for command ``` # agent-cards companies get Source: https://docs.agentcard.sh/tools/cli/companies-get Show details of a company Show details of a company ```bash theme={null} agent-cards companies get --help ``` ```text theme={null} Usage: agent-cards companies get [options] [org-id] Show details of a company Options: -h, --help display help for command ``` # agent-cards companies list Source: https://docs.agentcard.sh/tools/cli/companies-list List the companies you belong to List the companies you belong to ```bash theme={null} agent-cards companies list --help ``` ```text theme={null} Usage: agent-cards companies list [options] List the companies you belong to Options: --json Output as JSON -h, --help display help for command ``` # agent-cards companies members Source: https://docs.agentcard.sh/tools/cli/companies-members Manage company members Manage company members ```bash theme={null} agent-cards companies members --help ``` ```text theme={null} Usage: agent-cards companies members [options] [command] Manage company members Options: -h, --help display help for command Commands: add [options] Add a member to a company list [options] List company members remove Remove a member from a company (interactive) help [command] display help for command ``` # agent-cards companies return-urls Source: https://docs.agentcard.sh/tools/cli/companies-return-urls View or set the return-URL allowlist for hosted cardholder onboarding sessions View or set the return-URL allowlist for hosted cardholder onboarding sessions ```bash theme={null} agent-cards companies return-urls --help ``` ```text theme={null} Usage: agent-cards companies return-urls [options] [org-id] View or set the return-URL allowlist for hosted cardholder onboarding sessions Options: --url Replace the allowlist with these URLs (repeatable) --clear Remove all registered return URLs -h, --help display help for command ``` # agent-cards companies subscribe Source: https://docs.agentcard.sh/tools/cli/companies-subscribe Subscribe to a paid plan for production access (live client credentials) Subscribe to a paid plan for production access (live client credentials) ```bash theme={null} agent-cards companies subscribe --help ``` ```text theme={null} Usage: agent-cards companies subscribe [options] Subscribe to a paid plan for production access (live client credentials) Options: --org Company ID -h, --help display help for command ``` # agent-cards companies use Source: https://docs.agentcard.sh/tools/cli/companies-use Set the default company for companies commands (id or name; bare = pick) Set the default company for companies commands (id or name; bare = pick) ```bash theme={null} agent-cards companies use --help ``` ```text theme={null} Usage: agent-cards companies use [options] [company] Set the default company for companies commands (id or name; bare = pick) Options: -h, --help display help for command ``` # agent-cards companies webhooks Source: https://docs.agentcard.sh/tools/cli/companies-webhooks Manage webhook endpoints for company events Manage webhook endpoints for company events ```bash theme={null} agent-cards companies webhooks --help ``` ```text theme={null} Usage: agent-cards companies webhooks [options] [command] Manage webhook endpoints for company events Options: -h, --help display help for command Commands: list [options] List webhook endpoints create [options] Create a webhook endpoint (prints the signing secret once) update [options] Update a webhook endpoint delete [options] Delete a webhook endpoint and its delivery history reveal [options] Show the signing secret for a webhook endpoint roll-secret [options] Rotate the signing secret for a webhook endpoint deliveries [options] List recent deliveries for a webhook endpoint test [options] Send a test event to a webhook endpoint help [command] display help for command ``` # agent-cards companies webhooks create Source: https://docs.agentcard.sh/tools/cli/companies-webhooks-create Create a webhook endpoint (prints the signing secret once) Create a webhook endpoint (prints the signing secret once) ```bash theme={null} agent-cards companies webhooks create --help ``` ```text theme={null} Usage: agent-cards companies webhooks create [options] Create a webhook endpoint (prints the signing secret once) Options: --org Company ID --url Endpoint URL (https) --events Comma-separated event names (default '*') --description Description -h, --help display help for command ``` # agent-cards companies webhooks delete Source: https://docs.agentcard.sh/tools/cli/companies-webhooks-delete Delete a webhook endpoint and its delivery history Delete a webhook endpoint and its delivery history ```bash theme={null} agent-cards companies webhooks delete --help ``` ```text theme={null} Usage: agent-cards companies webhooks delete [options] Delete a webhook endpoint and its delivery history Options: --org Company ID -y, --yes Skip the confirmation prompt -h, --help display help for command ``` # agent-cards companies webhooks deliveries Source: https://docs.agentcard.sh/tools/cli/companies-webhooks-deliveries List recent deliveries for a webhook endpoint List recent deliveries for a webhook endpoint ```bash theme={null} agent-cards companies webhooks deliveries --help ``` ```text theme={null} Usage: agent-cards companies webhooks deliveries [options] List recent deliveries for a webhook endpoint Options: --org Company ID --limit Max deliveries to show (default 20) -h, --help display help for command ``` # agent-cards companies webhooks list Source: https://docs.agentcard.sh/tools/cli/companies-webhooks-list List webhook endpoints List webhook endpoints ```bash theme={null} agent-cards companies webhooks list --help ``` ```text theme={null} Usage: agent-cards companies webhooks list [options] List webhook endpoints Options: --org Company ID --json Output as JSON -h, --help display help for command ``` # agent-cards companies webhooks listen Source: https://docs.agentcard.sh/tools/cli/companies-webhooks-listen Manage webhook endpoints for company events Manage webhook endpoints for company events ```bash theme={null} agent-cards companies webhooks listen --help ``` ```text theme={null} Usage: agent-cards companies webhooks [options] [command] Manage webhook endpoints for company events Options: -h, --help display help for command Commands: list [options] List webhook endpoints create [options] Create a webhook endpoint (prints the signing secret once) update [options] Update a webhook endpoint delete [options] Delete a webhook endpoint and its delivery history reveal [options] Show the signing secret for a webhook endpoint roll-secret [options] Rotate the signing secret for a webhook endpoint deliveries [options] List recent deliveries for a webhook endpoint test [options] Send a test event to a webhook endpoint help [command] display help for command ``` # agent-cards companies webhooks reveal Source: https://docs.agentcard.sh/tools/cli/companies-webhooks-reveal Show the signing secret for a webhook endpoint Show the signing secret for a webhook endpoint ```bash theme={null} agent-cards companies webhooks reveal --help ``` ```text theme={null} Usage: agent-cards companies webhooks reveal [options] Show the signing secret for a webhook endpoint Options: --org Company ID -h, --help display help for command ``` # agent-cards companies webhooks roll-secret Source: https://docs.agentcard.sh/tools/cli/companies-webhooks-roll-secret Rotate the signing secret for a webhook endpoint Rotate the signing secret for a webhook endpoint ```bash theme={null} agent-cards companies webhooks roll-secret --help ``` ```text theme={null} Usage: agent-cards companies webhooks roll-secret [options] Rotate the signing secret for a webhook endpoint Options: --org Company ID -y, --yes Skip the confirmation prompt -h, --help display help for command ``` # agent-cards companies webhooks test Source: https://docs.agentcard.sh/tools/cli/companies-webhooks-test Send a test event to a webhook endpoint Send a test event to a webhook endpoint ```bash theme={null} agent-cards companies webhooks test --help ``` ```text theme={null} Usage: agent-cards companies webhooks test [options] Send a test event to a webhook endpoint Options: --org Company ID --event Concrete event type to send (default: first enabled event) -h, --help display help for command ``` # agent-cards companies webhooks update Source: https://docs.agentcard.sh/tools/cli/companies-webhooks-update Update a webhook endpoint Update a webhook endpoint ```bash theme={null} agent-cards companies webhooks update --help ``` ```text theme={null} Usage: agent-cards companies webhooks update [options] Update a webhook endpoint Options: --org Company ID --url New endpoint URL --events Comma-separated event names --status enabled | disabled --description Description -h, --help display help for command ``` # agent-cards companies wizard Source: https://docs.agentcard.sh/tools/cli/companies-wizard Run an AI agent that implements Agentcard (OAuth + MCP) into the repo at this Run an AI agent that implements Agentcard (OAuth + MCP) into the repo at this ```bash theme={null} agent-cards companies wizard --help ``` ```text theme={null} Usage: agent-cards companies wizard [options] Run an AI agent that implements Agentcard (OAuth + MCP) into the repo at this path Options: --path Target repo directory (defaults to the current directory) -y, --yes Skip the consent prompt (required in agent mode: explicit consent to modify files) --agent Non-interactive agent mode: no prompts, plain streaming output, machine-readable result line (auto-enabled under CLAUDECODE/CI or without a TTY) --email Email for sign-in when no session exists (interactive: prefills the sign-in prompt) --code Agent mode: sign-in code from the email (only for backends on code sign-in, after a code_required exit; interactive runs prompt for the code) --org Company to provision under (agent mode: required when the account has several; interactive: skips the picker) --app-url Your app's base URL for the OAuth callback (default http://localhost:3000) --app-name Name for the company (when created) and OAuth client (default: the repo directory name) --verbose Include tool inputs and outputs in the stream --engineer Route Agentcard uncertainty to the LIVE forward-deployed engineer instead of guessing from the static playbook (needs `engineer init` + a running `engineer connect` for this repo) -h, --help display help for command Agent mode (for AI agents / CI): agent-cards companies wizard --agent --yes [--email you@co.com] [--org ] [--app-url http://localhost:3000] (also reachable as: npx agent-cards-admin wizard --agent --yes — the old name forwards here) - auto-enabled without --agent when CLAUDECODE or CI is set, or a TTY is missing on either side; AGENT_CARDS_WIZARD_MODE=agent|interactive overrides auto-detection - never prompts; anything it needs and doesn't have exits 2 — the result line's "hint" names the flag to re-run with and what to ask your user when the value isn't derivable (the emailed sign-in code, which company, the app's base URL) - sign-in: prints "magic link sent to " and polls up to 15 minutes (env AGENT_CARDS_WIZARD_LOGIN_TIMEOUT_MS overrides); re-runs RESUME the pending sign-in instead of re-emailing. Backends on code sign-in exit 2 with code_required — finish with --email --code - runs take 5-20 minutes end to end: use a generous timeout or run in background - streams plain progress lines (add --verbose for tool detail); if a connect link needs a user tap it appears in the stream — open it to let the run continue - the LAST line is machine-readable: AGENTCARD_WIZARD_RESULT {"ok":true,...} - exit codes: 0 success · 1 integration/unexpected error · 2 missing input/consent error codes: consent_required, login_required, code_required, invalid_email, invalid_path, invalid_app_url, invalid_app_name, org_ambiguous, org_not_found, root_unsupported, integration_agent_error, unexpected_error - --engineer additionally requires a live engagement; missing pieces exit 2 with engineer_engagement_required, engineer_engagement_not_active, or engineer_daemon_not_running (the hint names the command a human must run) ``` # agent-cards connections list Source: https://docs.agentcard.sh/tools/cli/connections-list List connected apps List connected apps ```bash theme={null} agent-cards connections list --help ``` ```text theme={null} Usage: agent-cards connections list [options] List connected apps Options: --json Output as JSON -h, --help display help for command ``` # agent-cards connections revoke Source: https://docs.agentcard.sh/tools/cli/connections-revoke Revoke an app's access to your account Revoke an app's access to your account ```bash theme={null} agent-cards connections revoke --help ``` ```text theme={null} Usage: agent-cards connections revoke [options] Revoke an app's access to your account Options: -y, --yes Skip confirmation -h, --help display help for command ``` # agent-cards engineer ask Source: https://docs.agentcard.sh/tools/cli/engineer-ask Ask the AgentCard engineer a question and BLOCK for the answer (for coding Ask the AgentCard engineer a question and BLOCK for the answer (for coding ```bash theme={null} agent-cards engineer ask --help ``` ```text theme={null} Usage: agent-cards engineer ask [options] Ask the AgentCard engineer a question and BLOCK for the answer (for coding agents) Options: --repo Repo root (default: current directory) --question The question to ask --snippet File(s) to attach as code snippets (each capped at 8000 chars) --timeout Seconds to wait for the answer (default 480) --resume Keep waiting on a previously asked question instead of asking a new one --json Machine-readable output (one JSON line on stdout) -h, --help display help for command For AI agents: run with a generous shell timeout (the command blocks up to --timeout seconds). A timeout exits 0 with {"ok":false,"timedOut":true, "questionId":"env_…"} — proceed with your best judgment and optionally re-run with --resume later; the answer also arrives in the shared Slack channel. Requires the daemon (agent-cards engineer connect) to be running. Never include secrets (API keys, tokens, client secrets) in a question. ``` # agent-cards engineer connect Source: https://docs.agentcard.sh/tools/cli/engineer-connect Run the daemon: bridge proposals from the AgentCard engineer into your coding Run the daemon: bridge proposals from the AgentCard engineer into your coding ```bash theme={null} agent-cards engineer connect --help ``` ```text theme={null} Usage: agent-cards engineer connect [options] Run the daemon: bridge proposals from the AgentCard engineer into your coding agent Options: --repo Repo root (default: current directory) --adapter claude-code | codex | paste (default: auto-detect) --permission-mode acceptEdits (default) | bypassPermissions --accept-version Re-pin the stored version to the running CLI version --background, --detach Start the daemon detached, confirm the link, and return (for coding agents — one shell) --stop Stop a background daemon started with --background -h, --help display help for command ``` # agent-cards engineer disconnect Source: https://docs.agentcard.sh/tools/cli/engineer-disconnect Close the engagement and remove the daemon token, queue, and repo snippet Close the engagement and remove the daemon token, queue, and repo snippet ```bash theme={null} agent-cards engineer disconnect --help ``` ```text theme={null} Usage: agent-cards engineer disconnect [options] Close the engagement and remove the daemon token, queue, and repo snippet Options: --repo Repo root (default: current directory) --keep-snippet Leave the CLAUDE.md/AGENTS.md snippet in place -h, --help display help for command ``` # agent-cards engineer init Source: https://docs.agentcard.sh/tools/cli/engineer-init Provision an engineer engagement for this repo (device login, Slack channel, Provision an engineer engagement for this repo (device login, Slack channel, ```bash theme={null} agent-cards engineer init --help ``` ```text theme={null} Usage: agent-cards engineer init [options] Provision an engineer engagement for this repo (device login, Slack channel, daemon token) Options: --org Company to open the engagement for (default: active company or picker) --company-name Create a company with this name if you have none (for non-interactive/agent runs) --repo Repo root (default: current directory) --json Machine-readable output -h, --help display help for command ``` # agent-cards engineer report Source: https://docs.agentcard.sh/tools/cli/engineer-report Report an AgentCard issue/question to the engineer (for coding agents; queues Report an AgentCard issue/question to the engineer (for coding agents; queues ```bash theme={null} agent-cards engineer report --help ``` ```text theme={null} Usage: agent-cards engineer report [options] Report an AgentCard issue/question to the engineer (for coding agents; queues via the daemon) Options: --repo Repo root (default: current directory) --title Short issue title --summary <summary> What you were doing, what happened, what you expected --environment <env> sandbox | production (default: sandbox) --error-message <message> The error message you saw --error-code <code> Machine error code, if any --http-status <status> HTTP status code, if any --request-id <id> Request id from the response, if any --endpoint <endpoint> The API endpoint involved (e.g. "POST /api/v2/cards") --sdk <sdk> SDK/library in use --agent <agent> claude-code | codex | other --snippet <path...> File(s) to attach as code snippets (each capped at 8000 chars) --question <text> Ask a plain question instead of filing an issue --json-stdin Read the full issue-report JSON body from stdin --json Machine-readable output -h, --help display help for command ``` # agent-cards engineer status Source: https://docs.agentcard.sh/tools/cli/engineer-status Show the engagement, daemon, and report-queue status Show the engagement, daemon, and report-queue status ```bash theme={null} agent-cards engineer status --help ``` ```text theme={null} Usage: agent-cards engineer status [options] Show the engagement, daemon, and report-queue status Options: --repo <path> Repo root (default: current directory) --json Machine-readable output -h, --help display help for command ``` # agent-cards fund Source: https://docs.agentcard.sh/tools/cli/fund Add cash to your balance via Apple Pay / Google Pay Add cash to your balance via Apple Pay / Google Pay ```bash theme={null} agent-cards fund --help ``` ```text theme={null} Usage: agent-cards fund [options] Add cash to your balance via Apple Pay / Google Pay Options: --amount <dollars> Amount in dollars (e.g. 50) --method <method> Payment method: apple_pay | google_pay (default: "apple_pay") -h, --help display help for command ``` # agent-cards kyc Source: https://docs.agentcard.sh/tools/cli/kyc Verify your identity (ID photo → auto-read details → quick face scan) Verify your identity (ID photo → auto-read details → quick face scan) ```bash theme={null} agent-cards kyc --help ``` ```text theme={null} Usage: agent-cards kyc [options] Verify your identity (ID photo → auto-read details → quick face scan) Options: -h, --help display help for command ``` # agent-cards login Source: https://docs.agentcard.sh/tools/cli/login Log in with an emailed code (same as signup) Log in with an emailed code (same as signup) ```bash theme={null} agent-cards login --help ``` ```text theme={null} Usage: agent-cards login [options] Log in with an emailed code (same as signup) Options: --email <email> Non-interactive: start sign-in for this email (a code is emailed) --code <code> Non-interactive: finish sign-in with the emailed code -h, --help display help for command ``` # agent-cards logout Source: https://docs.agentcard.sh/tools/cli/logout Log out and clear stored credentials Log out and clear stored credentials ```bash theme={null} agent-cards logout --help ``` ```text theme={null} Usage: agent-cards logout [options] Log out and clear stored credentials Options: -h, --help display help for command ``` # agent-cards payment-method default Source: https://docs.agentcard.sh/tools/cli/payment-method-default Set your default payment method (prompts if no id given) Set your default payment method (prompts if no id given) ```bash theme={null} agent-cards payment-method default --help ``` ```text theme={null} Usage: agent-cards payment-method default [options] [id] Set your default payment method (prompts if no id given) Options: -h, --help display help for command ``` # agent-cards payment-method list Source: https://docs.agentcard.sh/tools/cli/payment-method-list List your saved payment methods List your saved payment methods ```bash theme={null} agent-cards payment-method list --help ``` ```text theme={null} Usage: agent-cards payment-method list [options] List your saved payment methods Options: -h, --help display help for command ``` # agent-cards payment-method remove Source: https://docs.agentcard.sh/tools/cli/payment-method-remove Remove a saved payment method Remove a saved payment method ```bash theme={null} agent-cards payment-method remove --help ``` ```text theme={null} Usage: agent-cards payment-method remove [options] Remove a saved payment method Options: --id <paymentMethodId> Payment method ID to remove -h, --help display help for command ``` # agent-cards payment-method setup Source: https://docs.agentcard.sh/tools/cli/payment-method-setup Save a payment method for future card creation Save a payment method for future card creation ```bash theme={null} agent-cards payment-method setup --help ``` ```text theme={null} Usage: agent-cards payment-method setup [options] Save a payment method for future card creation Options: -h, --help display help for command ``` # agent-cards plan Source: https://docs.agentcard.sh/tools/cli/plan View and manage your subscription plan View and manage your subscription plan ```bash theme={null} agent-cards plan --help ``` ```text theme={null} Usage: agent-cards plan [options] [command] View and manage your subscription plan Options: -h, --help display help for command Commands: upgrade [plan] Upgrade to a paid plan (basic or pro) cancel Cancel your subscription ``` # agent-cards plan cancel Source: https://docs.agentcard.sh/tools/cli/plan-cancel Cancel your subscription Cancel your subscription ```bash theme={null} agent-cards plan cancel --help ``` ```text theme={null} Usage: agent-cards plan cancel [options] Cancel your subscription Options: -h, --help display help for command ``` # agent-cards plan upgrade Source: https://docs.agentcard.sh/tools/cli/plan-upgrade Upgrade to a paid plan (basic or pro) Upgrade to a paid plan (basic or pro) ```bash theme={null} agent-cards plan upgrade --help ``` ```text theme={null} Usage: agent-cards plan upgrade [options] [plan] Upgrade to a paid plan (basic or pro) Arguments: plan Plan to upgrade to: 'basic' ($15/mo) or 'pro' ($100/mo) (default: "basic") Options: -h, --help display help for command ``` # agent-cards redeem Source: https://docs.agentcard.sh/tools/cli/redeem Redeem a promo code; the credit lands in your balance Redeem a promo code; the credit lands in your balance ```bash theme={null} agent-cards redeem --help ``` ```text theme={null} Usage: agent-cards redeem [options] <code> Redeem a promo code; the credit lands in your balance Options: --json Output as JSON -h, --help display help for command ``` # agent-cards rewards redeem Source: https://docs.agentcard.sh/tools/cli/rewards-redeem Redeem tokenback as balance credit (defaults to the full balance) Redeem tokenback as balance credit (defaults to the full balance) ```bash theme={null} agent-cards rewards redeem --help ``` ```text theme={null} Usage: agent-cards rewards redeem [options] Redeem tokenback as balance credit (defaults to the full balance) Options: --tokens <n> Tokens to redeem (1 token = 1 cent); omit to redeem the full balance -y, --yes Skip the confirmation prompt -h, --help display help for command ``` # agent-cards rewards show Source: https://docs.agentcard.sh/tools/cli/rewards-show Show the tokenback balance and recent activity Show the tokenback balance and recent activity ```bash theme={null} agent-cards rewards show --help ``` ```text theme={null} Usage: agent-cards rewards show [options] Show the tokenback balance and recent activity Options: -h, --help display help for command ``` Tokenback pays tokens on settled card spend, and 1 token is 1¢ of credit. The boosted rate is earned on an AI card, one created with the `ai_labs` preset or a software and AI rule in either mode, and only on its charges at software and AI vendors. Every other charge on a personal card earns the normal rate. Cards funded by a company earn no tokenback from Agentcard; the company shares its own earnings with its users instead. Redeem with `agent-cards rewards redeem`. # agent-cards settings Source: https://docs.agentcard.sh/tools/cli/settings Manage notification, delivery address, and authorization preferences Manage notification, delivery address, and authorization preferences ```bash theme={null} agent-cards settings --help ``` ```text theme={null} Usage: agent-cards settings [options] [command] Manage notification, delivery address, and authorization preferences Options: -h, --help display help for command Commands: notifications Configure email notifications default-card [options] Pick the default payment agents charge: wallet balance or an attached card address [options] Set the default delivery address agents ship to authorization View authorization status (always enabled) ``` # agent-cards settings address Source: https://docs.agentcard.sh/tools/cli/settings-address Set the default delivery address agents ship to Set the default delivery address agents ship to ```bash theme={null} agent-cards settings address --help ``` ```text theme={null} Usage: agent-cards settings address [options] Set the default delivery address agents ship to Options: --clear Remove the saved default delivery address -h, --help display help for command ``` # agent-cards settings authorization Source: https://docs.agentcard.sh/tools/cli/settings-authorization View authorization status (always enabled) View authorization status (always enabled) ```bash theme={null} agent-cards settings authorization --help ``` ```text theme={null} Usage: agent-cards settings authorization [options] View authorization status (always enabled) Options: -h, --help display help for command ``` # agent-cards settings default-card Source: https://docs.agentcard.sh/tools/cli/settings-default-card Pick the default payment agents charge: wallet balance or an attached card Pick the default payment agents charge: wallet balance or an attached card ```bash theme={null} agent-cards settings default-card --help ``` ```text theme={null} Usage: agent-cards settings default-card [options] Pick the default payment agents charge: wallet balance or an attached card Options: --clear Reset to auto (attached card wins, else balance) -h, --help display help for command ``` # agent-cards settings notifications Source: https://docs.agentcard.sh/tools/cli/settings-notifications Configure email notifications Configure email notifications ```bash theme={null} agent-cards settings notifications --help ``` ```text theme={null} Usage: agent-cards settings notifications [options] Configure email notifications Options: -h, --help display help for command ``` # agent-cards setup-mcp Source: https://docs.agentcard.sh/tools/cli/setup-mcp Configure the AgentCard MCP server in Claude Code Configure the AgentCard MCP server in Claude Code ```bash theme={null} agent-cards setup-mcp --help ``` ```text theme={null} Usage: agent-cards setup-mcp [options] Configure the AgentCard MCP server in Claude Code Options: -h, --help display help for command ``` # agent-cards signup Source: https://docs.agentcard.sh/tools/cli/signup Sign up or sign in with an emailed code Sign up or sign in with an emailed code ```bash theme={null} agent-cards signup --help ``` ```text theme={null} Usage: agent-cards signup [options] Sign up or sign in with an emailed code Options: --email <email> Non-interactive: start sign-in for this email (a code is emailed) --code <code> Non-interactive: finish sign-in with the emailed code -h, --help display help for command ``` # agent-cards support Source: https://docs.agentcard.sh/tools/cli/support Start a live support conversation Start a live support conversation ```bash theme={null} agent-cards support --help ``` ```text theme={null} Usage: agent-cards support [options] Start a live support conversation Options: --resume <id> Resume an existing conversation -h, --help display help for command ``` # agent-cards transactions Source: https://docs.agentcard.sh/tools/cli/transactions Show transactions across all your cards (or a single card if an id is given) Show transactions across all your cards (or a single card if an id is given) ```bash theme={null} agent-cards transactions --help ``` ```text theme={null} Usage: agent-cards transactions [options] [id] Show transactions across all your cards (or a single card if an id is given) Options: --limit <n> Number of transactions (default: 20) --offset <n> Number of transactions to skip (account-wide only) --status <status> Filter by status --json Output as JSON (account-wide only) -h, --help display help for command ``` # agent-cards update Source: https://docs.agentcard.sh/tools/cli/update Update CLI to the latest version Update CLI to the latest version ```bash theme={null} agent-cards update --help ``` ```text theme={null} Usage: agent-cards update [options] Update CLI to the latest version Options: -h, --help display help for command ``` # agent-cards wallet Source: https://docs.agentcard.sh/tools/cli/wallet Your wallet — the cards it holds, plus your balance Your wallet — the cards it holds, plus your balance ```bash theme={null} agent-cards wallet --help ``` ```text theme={null} Usage: agent-cards wallet [options] [command] Your wallet — the cards it holds, plus your balance Options: --json Output the balance as JSON -h, --help display help for command Commands: fund [options] Alias of `agent-cards fund` — add cash to your balance withdraw [options] Alias of `agent-cards withdraw` — withdraw cash from your balance ``` # agent-cards whoami Source: https://docs.agentcard.sh/tools/cli/whoami Show the currently logged-in user email Show the currently logged-in user email ```bash theme={null} agent-cards whoami --help ``` ```text theme={null} Usage: agent-cards whoami [options] Show the currently logged-in user email Options: --json Output as JSON -h, --help display help for command ``` # agent-cards withdraw Source: https://docs.agentcard.sh/tools/cli/withdraw Withdraw cash to your bank, or USDC on Base with --to (processed manually, 1-3 Withdraw cash to your bank, or USDC on Base with --to (processed manually, 1-3 ```bash theme={null} agent-cards withdraw --help ``` ```text theme={null} Usage: agent-cards withdraw [options] Withdraw cash to your bank, or USDC on Base with --to (processed manually, 1-3 business days) Options: --amount <dollars> Amount in dollars (e.g. 25) --to <address> Send USDC on Base to this 0x address instead of a bank account -h, --help display help for command ``` # MCP Source: https://docs.agentcard.sh/tools/mcp One Agentcard MCP server, three toolsets: your organization's, your users', and your own. There is one Agentcard MCP server, at `https://mcp.agentcard.sh/mcp`. What it exposes depends on the credential you connect with: your organization, one of your users, or your own personal account. Connecting with the wrong credential gives you the wrong toolset, not an error. ## Install ```bash theme={null} npx -y agent-cards setup-mcp ``` One command for Claude Code. A browser sign-in appears the first time a tool runs. For any other MCP client, add the URL and an `Authorization` header to its config. ## Connect as your organization Run your whole integration from your coding agent, with the same credentials you use for the API: ```bash theme={null} claude mcp add agentcard --transport http https://mcp.agentcard.sh/mcp \ --header "Authorization: Bearer YOUR_CLIENT_SECRET" ``` Sandbox or production follows the credential, like everywhere else. ### Organization tools | Area | Tools | | --------------- | -------------------------------------------------------------------------------------------------------------------- | | Users | `create_cardholder` · `list_cardholders` · `get_cardholder` · `create_onboarding_session` · `get_onboarding_session` | | Identity | `start_cardholder_kyc` · `get_cardholder_kyc_status` | | Cards | `create_card` · `list_cards` · `get_card` · `get_card_details` · `close_card` | | Payment methods | `setup_cardholder_payment_method` · `get_cardholder_payment_method_status` | | Company balance | `get_company_wallet` · `list_transfers` · `confirm_collection` · `recover_funds` · `list_recoveries` | | Testing | `test_charge` simulates a full sandbox charge: authorization, settlement, and every webhook | | Support | `ask_agentcard_engineer` · `get_engineer_reply` · `report_agentcard_issue` | | Session | `whoami` · `mint_buy_token` | When something breaks during your integration, connect this server and ask your agent to debug it. It reads the same state we see. ## Connect as one of your users Your users' agents connect to the same URL with the user's connection `access_token`, the token your server stored in [Authenticating a user](/issuing/authenticating-a-user). One client per user, never shared: the bearer decides whose cards and purchases the agent can see. ```typescript theme={null} import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"; const transport = new StreamableHTTPClientTransport( new URL("https://mcp.agentcard.sh/mcp"), { requestInit: { headers: { Authorization: `Bearer ${user.agentcardAccessToken}` } } }, ); const client = new Client({ name: "your-app", version: "1.0.0" }); await client.connect(transport); const { tools } = await client.listTools(); ``` Register whatever `listTools()` returns rather than a hardcoded list, so tools Agentcard ships later appear without a deploy on your side. ### User tools | Area | Tools | | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Shopping | `buy` is the whole purchase loop. `buy_list_merchants`, `buy_connect` and `buy_connect_status` handle merchants that need the user to link an account first. `buy_track_order`, `buy_order_history`, `buy_return_order` and `buy_return_status` cover what happens after. | | Cards | `create_card` · `list_cards` · `get_card_details` · `get_card_balance` · `pause_card` · `resume_card` · `update_card_limit` · `close_card` | | Vault | `get_wallet_link` with `purpose: "add_card"` mints the link that puts the user's own card in the Vault. `list_added_cards` · `remove_added_card` | | Balance | `get_balance` · `add_funds` · `start_phone_verification` · `verify_phone` | | Identity | `start_kyc` · `submit_kyc_document` · `check_kyc_document` · `submit_kyc_fields` · `get_kyc_status` | | Rewards | `get_rewards` · `redeem_rewards` · `redeem_code` · `list_codes` | | Transactions | `list_transactions` · `list_transactions_by_payment_method` · `list_all_transactions` | | Session | `whoami` · `get_instructions` · `get_settings` · `update_settings` · `get_plan` | Approvals are deliberately absent. An approval is the user's own consent, so `list_pending_approvals` and `approve_request` answer `personal_surface_only` to a connected session. The user resolves it from the emailed link or their own Agentcard session, and your agent retries with the `approval_id`. ## Rules for your agent ```text theme={null} - The credential decides the server. Your org credential gets the organization tools; a user's connection token gets that user's tools, including buy. - Keep the client secret in your own MCP config, on your machine or server. Never in a browser or a shared config. - One client per user, never shared. - Call get_instructions once before the first buy; it carries the current usage guide. - On 401, refresh the connection with your org token (POST /api/v2/connect/refresh), replace both stored tokens, and reconnect the client. - Never write card numbers or CVVs to logs, error reports, or analytics. ``` # ask_agentcard_engineer Source: https://docs.agentcard.sh/tools/mcp/org/ask_agentcard_engineer Ask AgentCard's forward-deployed engineer a question about integrating or debugging AgentCard. Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). ## What it does Ask AgentCard's forward-deployed engineer a question about integrating or debugging AgentCard. Your question goes into a live, human-supervised support engagement where an AgentCard engineer agent investigates using your organization's actual logs and the real AgentCard codebase. Asynchronous: you get an envelope\_id back immediately — poll get\_engineer\_reply with it. Requires an active engineer engagement for your organization (a human admin runs `agent-cards engineer init` once); if there is none, this tool tells you so. Prefer report\_agentcard\_issue for concrete failures with error details. ## Inputs | Field | Type | Description | | ----------------------- | ------ | ----------------------------------------------------------------------------------- | | `question` *(required)* | string | The question, as specific as possible (≤4000 chars). | | `snippets` | array | Optional code snippets giving the engineer context (each ≤8000 chars). | | `in_reply_to` | string | Envelope id of an earlier exchange to continue that thread. | | `idempotency_key` | string | Optional stable key (letters/digits/\_/-, ≤64) so a retried call is not sent twice. | ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable confirmation. | | `envelope_id` | string | Poll get\_engineer\_reply with this id. | | `engagement_id` | string | The engagement the question entered. | | `status` | string | "sent", or "no\_engagement"/"rate\_limited"/"engagement\_frozen" when not accepted. | ## Example call ```json theme={null} { "tool": "ask_agentcard_engineer", "arguments": { "question": "\u2026" } } ``` # close_card Source: https://docs.agentcard.sh/tools/mcp/org/close_card Close a card and release any unspent hold. Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). **Behavior:** destructive. ## What it does Close a card and release any unspent hold. Irreversible; idempotent on an already-closed card. ## Inputs | Field | Type | Description | | ---------------------- | ------ | -------------------- | | `card_id` *(required)* | string | The card id to close | ## Returns | Field | Type | Description | | ---------------------- | ------ | ---------------------------- | | `message` *(required)* | string | Human-readable confirmation. | | `cardId` | string | The closed card id. | | `status` | string | Always "CLOSED" on success. | ## Example call ```json theme={null} { "tool": "close_card", "arguments": { "card_id": "\u2026" } } ``` # confirm_collection Source: https://docs.agentcard.sh/tools/mcp/org/confirm_collection Report your collection outcome for a company-wallet transfer awaiting it (the card_flow.started webhook is your cue): "succeeded" when you've secured payment f… Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). ## What it does Report your collection outcome for a company-wallet transfer awaiting it (the card\_flow\.started webhook is your cue): "succeeded" when you've secured payment from your own customer (the transfer proceeds and the card is created), "failed" to release the reservation. Idempotent per outcome. ## Inputs | Field | Type | Description | | -------------------------- | ------------------------------ | ------------------------ | | `transfer_id` *(required)* | string | The transfer id (owt\_…) | | `outcome` *(required)* | string: `succeeded` · `failed` | Your collection result | ## Returns | Field | Type | Description | | ---------------------- | ------ | ---------------------------------- | | `message` *(required)* | string | Human-readable outcome. | | `transfer` | object | The transfer after the transition. | ## Example call ```json theme={null} { "tool": "confirm_collection", "arguments": { "transfer_id": "\u2026", "outcome": "\u2026" } } ``` # create_card Source: https://docs.agentcard.sh/tools/mcp/org/create_card Issue a virtual card for a cardholder, holding an exact amount in cents (2500 = $25.00). Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). ## What it does Issue a virtual card for a cardholder, holding an exact amount in cents (2500 = \$25.00). Default is one-time-use: the first approved charge spends it and the card closes itself. Pass type "multi\_use" for a reusable card that survives repeated charges until its balance is spent (or expires\_at passes). In sandbox this issues a test card (mock, never charged). If the cardholder is not ready, the error says exactly which gate to clear: kyc\_required (run start\_cardholder\_kyc), wallet\_funding\_required or deposit\_confirming (the user's wallet), payment\_method\_required, or org\_wallet\_funding\_required (your company wallet, with funds\_source "company\_flow"). ## Inputs | Field | Type | Description | | ---------------------------- | -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cardholder_id` *(required)* | string | Which cardholder the card is for | | `amount_cents` *(required)* | number | Exact amount in cents, minimum 100 (\$1.00) | | `funds_source` | string: `onramp_flow` · `company_flow` | onramp\_flow (default): the user's own wallet pays. company\_flow: your pooled company wallet pays. | | `type` | string: `single_use` · `multi_use` | single\_use (default): closes after the first approved charge. multi\_use: reusable until the balance is spent. | | `expires_at` | string | Multi-use only: ISO-8601 expiry in the future, at most 365 days out. The card closes then and any unused balance is released. | | `idempotency_key` | string | Stable key for THIS card intent (e.g. your order id). Always pass one with company\_flow: retries then attach to the in-flight funding instead of double-funding, and a funding\_in\_progress retry must reuse the same key. | ## Returns | Field | Type | Description | | ---------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `message` *(required)* | string | Human-readable outcome. | | `status` | string | "created", "funding\_in\_progress", or a readiness gate: kyc\_required \| wallet\_funding\_required \| deposit\_confirming \| payment\_method\_required \| org\_wallet\_funding\_required. | | `cardId` | string | Present when created. | | `last4` | string | Present when created. | | `verificationUrl` | string | Present on kyc\_required when a verification link exists. | | `retryAfterSeconds` | number | Present on funding\_in\_progress / deposit\_confirming — retry after this many seconds. | ## Example call ```json theme={null} { "tool": "create_card", "arguments": { "cardholder_id": "\u2026", "amount_cents": "\u2026" } } ``` # create_cardholder Source: https://docs.agentcard.sh/tools/mcp/org/create_cardholder Create a cardholder: one of YOUR users, as Agentcard knows them. Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). ## What it does Create a cardholder: one of YOUR users, as Agentcard knows them. Cards are issued in the cardholder's own name, so their real name and date of birth are required (identity verification needs them), plus at least one of email or phone number. On messaging surfaces, ask the user for these in conversation first. The cardholder is created in this connection's mode. ## Inputs | Field | Type | Description | | ---------------------------- | ------ | -------------------------------------------------------------------------------- | | `first_name` *(required)* | string | The user's legal first name | | `last_name` *(required)* | string | The user's legal last name | | `date_of_birth` *(required)* | string | Date of birth, e.g. "1990-01-15" | | `email` | string | Email (unique within your org per mode). One of email/phone\_number is required. | | `phone_number` | string | Phone in E.164, e.g. "+14155550123". One of email/phone\_number is required. | ## Returns | Field | Type | Description | | ---------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `message` *(required)* | string | Human-readable confirmation. | | `cardholderId` | string | The new cardholder id — store it keyed to your user. | | `identityMismatch` | boolean | Present (true) when a cardholder with this email already exists but its name/date of birth do not match the request — the existing id was NOT reused; do not store it for this user. | ## Example call ```json theme={null} { "tool": "create_cardholder", "arguments": { "first_name": "\u2026", "last_name": "\u2026", "date_of_birth": "\u2026" } } ``` # create_onboarding_session Source: https://docs.agentcard.sh/tools/mcp/org/create_onboarding_session Create a hosted onboarding session: Agentcard collects the user's details, verifies their email with an emailed code, takes consent, and hands you a finished c… Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). ## What it does Create a hosted onboarding session: Agentcard collects the user's details, verifies their email with an emailed code, takes consent, and hands you a finished cardholder — use it when you'd rather not collect names and birthdates in your own UI. Send the user to the returned url (expires in 60 minutes); we redirect them to your registered return\_url with ?session\_id= when done. Subscribe to the cardholder\_onboarding\_session.completed webhook or poll get\_onboarding\_session. ## Inputs | Field | Type | Description | | ------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------- | | `return_url` *(required)* | string | Where we send the user afterward. Must match a URL registered with `agent-cards-admin orgs onboarding-return-urls`. | | `email` | string | Prefill only — the flow verifies whatever address the user proves. | | `external_user_id` | string | Your id for this user; echoed on reads and the completion webhook. | | `cardholder_id` | string | An existing cardholder to claim instead of creating a new one. | | `state` | string | Opaque string (max 512 chars) echoed on the final redirect. | ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable next step. | | `sessionId` | string | The session id (cos\_…). | | `url` | string | Send the user here. Embeds a secret token — treat like a password-reset link. | | `expiresAt` | string | ISO 8601 expiry (60 minutes). | ## Example call ```json theme={null} { "tool": "create_onboarding_session", "arguments": { "return_url": "\u2026" } } ``` # get_card Source: https://docs.agentcard.sh/tools/mcp/org/get_card Get one card's summary (no card number): balance, status, expiry, cardholder. Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). **Behavior:** read-only. ## What it does Get one card's summary (no card number): balance, status, expiry, cardholder. ## Inputs | Field | Type | Description | | ---------------------- | ------ | ----------- | | `card_id` *(required)* | string | The card id | ## Returns | Field | Type | Description | | ---------------------- | ------ | ---------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable summary. | | `card` | object | id, cardholderId, last4, expiry, spendLimitCents, balanceCents, status, createdAt. | ## Example call ```json theme={null} { "tool": "get_card", "arguments": { "card_id": "\u2026" } } ``` # get_card_details Source: https://docs.agentcard.sh/tools/mcp/org/get_card_details Reveal a card's full number, expiry, and CVC for checkout. Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). **Behavior:** read-only. ## What it does Reveal a card's full number, expiry, and CVC for checkout. This is the live credential — pass it to the paying agent at payment time; never log or store it. Each access is recorded in your org's audit trail. ## Inputs | Field | Type | Description | | ---------------------- | ------ | ----------- | | `card_id` *(required)* | string | The card id | ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | The card credentials, human-readable. Raw credentials are deliberately NOT advertised as structured fields. | | `last4` | string | Last four digits. | | `expiry` | string | MM/YY. | | `balanceCents` | number | Remaining balance in cents. | ## Example call ```json theme={null} { "tool": "get_card_details", "arguments": { "card_id": "\u2026" } } ``` # get_cardholder Source: https://docs.agentcard.sh/tools/mcp/org/get_cardholder Get one cardholder by id (must belong to your org, in this mode). Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). **Behavior:** read-only. ## What it does Get one cardholder by id (must belong to your org, in this mode). ## Inputs | Field | Type | Description | | ---------------------------- | ------ | ----------------- | | `cardholder_id` *(required)* | string | The cardholder id | ## Returns | Field | Type | Description | | ---------------------- | ------ | ------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable summary. | | `cardholder` | object | id, firstName, lastName, email, phoneNumber, dateOfBirth, createdAt, updatedAt. | ## Example call ```json theme={null} { "tool": "get_cardholder", "arguments": { "cardholder_id": "\u2026" } } ``` # get_cardholder_kyc_status Source: https://docs.agentcard.sh/tools/mcp/org/get_cardholder_kyc_status Check a cardholder's identity verification status: not_started, pending (review usually takes about a minute), requires_input (the user must redo something — r… Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). **Behavior:** read-only. ## What it does Check a cardholder's identity verification status: not\_started, pending (review usually takes about a minute), requires\_input (the user must redo something — reason says what), verified (cards can be issued), or rejected. ## Inputs | Field | Type | Description | | ---------------------------- | ------ | ----------------- | | `cardholder_id` *(required)* | string | The cardholder id | ## Returns | Field | Type | Description | | ---------------------- | ------ | ------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable status. | | `status` | string | not\_started \| pending \| requires\_input \| verified \| rejected. | | `reason` | string | Present on requires\_input / rejected. | ## Example call ```json theme={null} { "tool": "get_cardholder_kyc_status", "arguments": { "cardholder_id": "\u2026" } } ``` # get_cardholder_payment_method_status Source: https://docs.agentcard.sh/tools/mcp/org/get_cardholder_payment_method_status Check whether a cardholder has a funding payment method on file. Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). **Behavior:** read-only. ## What it does Check whether a cardholder has a funding payment method on file. ## Inputs | Field | Type | Description | | ---------------------------- | ------ | ----------------- | | `cardholder_id` *(required)* | string | The cardholder id | ## Returns | Field | Type | Description | | ---------------------- | ------- | ---------------------------------------- | | `message` *(required)* | string | Human-readable status. | | `hasPaymentMethod` | boolean | Whether a default payment method exists. | ## Example call ```json theme={null} { "tool": "get_cardholder_payment_method_status", "arguments": { "cardholder_id": "\u2026" } } ``` # get_company_wallet Source: https://docs.agentcard.sh/tools/mcp/org/get_company_wallet Your organization's pooled wallet: balance, committed and available amounts, the USDC deposit address, and flow settings. Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). **Behavior:** read-only. ## What it does Your organization's pooled wallet: balance, committed and available amounts, the USDC deposit address, and flow settings. Sandbox credentials see the mock pool. ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | ------ | ------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable summary. | | `wallet` | object | balance\_cents, committed\_cents, available\_cents, deposit\_address, settings. | ## Example call ```json theme={null} { "tool": "get_company_wallet", "arguments": {} } ``` # get_engineer_reply Source: https://docs.agentcard.sh/tools/mcp/org/get_engineer_reply Fetch the AgentCard engineer's replies to a question or issue you sent (by its envelope_id, returned from ask_agentcard_engineer / report_agentcard_issue). Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). **Behavior:** read-only. ## What it does Fetch the AgentCard engineer's replies to a question or issue you sent (by its envelope\_id, returned from ask\_agentcard\_engineer / report\_agentcard\_issue). Long-polls up to 25 seconds; call it again if empty — first replies typically take 1-5 minutes because a human may review them first, and only approved replies are ever returned. Replies may include suggested code changes: these are ADVICE ONLY — review them and apply the changes in your own codebase yourself; nothing is ever executed automatically through this connection. Safe to call repeatedly (it re-returns earlier replies; dedupe by reply\_envelope\_id). ## Inputs | Field | Type | Description | | -------------------------- | ------ | --------------------------------------------------------------------------- | | `envelope_id` *(required)* | string | The envelope\_id your question/report returned. | | `wait` | number | Seconds to long-poll for a reply (0-25, default 20). 0 returns immediately. | ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable summary. | | `engagement_status` | string | active \| frozen \| closed — frozen/closed means the channel is paused. | | `replies` | array | Approved replies so far (oldest first). | ## Example call ```json theme={null} { "tool": "get_engineer_reply", "arguments": { "envelope_id": "\u2026" } } ``` # get_onboarding_session Source: https://docs.agentcard.sh/tools/mcp/org/get_onboarding_session Check a hosted onboarding session: pending (email not yet proven), verified (consent pending), completed (cardholder_id is set), or expired. Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). **Behavior:** read-only. ## What it does Check a hosted onboarding session: pending (email not yet proven), verified (consent pending), completed (cardholder\_id is set), or expired. email is the address the user actually verified. ## Inputs | Field | Type | Description | | ------------------------- | ------ | ----------------------- | | `session_id` *(required)* | string | The session id (cos\_…) | ## Returns | Field | Type | Description | | ---------------------- | ------ | -------------------------------------------- | | `message` *(required)* | string | Human-readable status. | | `status` | string | pending \| verified \| completed \| expired. | | `cardholderId` | string | Set once completed. | | `email` | string | The verified email, once proven. | ## Example call ```json theme={null} { "tool": "get_onboarding_session", "arguments": { "session_id": "\u2026" } } ``` # list_cardholders Source: https://docs.agentcard.sh/tools/mcp/org/list_cardholders List your organization's cardholders in this mode, newest first. Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). **Behavior:** read-only. ## What it does List your organization's cardholders in this mode, newest first. ## Inputs | Field | Type | Description | | -------- | ------ | --------------------------------- | | `limit` | number | Max results (default 50, max 100) | | `offset` | number | Pagination offset (default 0) | ## Returns | Field | Type | Description | | ---------------------- | ------ | --------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable summary. | | `cardholders` | array | Cardholder objects: id, firstName, lastName, email, phoneNumber, createdAt. | | `total` | number | Total cardholders in this mode. | ## Example call ```json theme={null} { "tool": "list_cardholders", "arguments": {} } ``` # list_cards Source: https://docs.agentcard.sh/tools/mcp/org/list_cards List your organization's cards in this mode, newest first. Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). **Behavior:** read-only. ## What it does List your organization's cards in this mode, newest first. Filter by cardholder or status (OPEN, IN\_USE, CLOSED, PAUSED, PAUSING, CLOSING). A card shows PAUSING or CLOSING from the moment a charge pauses or spends it until the card network confirms, then PAUSED or CLOSED; it finishes on its own. ## Inputs | Field | Type | Description | | --------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | | `cardholder_id` | string | Only this cardholder's cards | | `status` | string: `OPEN` · `IN_USE` · `CLOSED` · `PAUSED` · `PAUSING` · `CLOSING` | Only cards in this status. `PAUSING` and `CLOSING`: the change is recorded and the card network has not confirmed it yet. | | `limit` | number | Max results (default 50, max 100) | | `offset` | number | Pagination offset | ## Returns | Field | Type | Description | | ---------------------- | ------ | ---------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable summary. | | `cards` | array | Card objects: `id`, `cardholderId`, `last4`, `expiry`, `spendLimitCents`, `balanceCents`, `status`, `createdAt`. | | `total` | number | Total cards matching the filter. | ## Example call ```json theme={null} { "tool": "list_cards", "arguments": {} } ``` # list_recoveries Source: https://docs.agentcard.sh/tools/mcp/org/list_recoveries List headroom recoveries (residual cardholder spending power pulled back into the company wallet), newest first. Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). **Behavior:** read-only. ## What it does List headroom recoveries (residual cardholder spending power pulled back into the company wallet), newest first. Filter by status: requested, processing, completed, rejected. ## Inputs | Field | Type | Description | | -------- | ------------------------------------------------------------- | --------------------------------- | | `status` | string: `requested` · `processing` · `completed` · `rejected` | Status filter | | `limit` | number | Max results (default 25, max 100) | ## Returns | Field | Type | Description | | ---------------------- | ------- | ------------------------------------------------------------------ | | `message` *(required)* | string | Human-readable summary. | | `recoveries` | array | Recovery objects (id, status, amount\_cents, cardholder\_id, ...). | | `hasMore` | boolean | Whether more pages exist. | ## Example call ```json theme={null} { "tool": "list_recoveries", "arguments": {} } ``` # list_transfers Source: https://docs.agentcard.sh/tools/mcp/org/list_transfers List company-wallet transfers (pool → user funding for cards), newest first. Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). **Behavior:** read-only. ## What it does List company-wallet transfers (pool → user funding for cards), newest first. Filter by public status: pending, funded, consumed, reclaimed, failed. ## Inputs | Field | Type | Description | | -------- | ------------------------------------------------------------------ | --------------------------------- | | `status` | string: `pending` · `funded` · `consumed` · `reclaimed` · `failed` | Public status filter | | `limit` | number | Max results (default 25, max 100) | ## Returns | Field | Type | Description | | ---------------------- | ------- | ----------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable summary. | | `transfers` | array | Transfer objects (id, status, substatus, amount\_cents, cardholder\_id, ...). | | `hasMore` | boolean | Whether more pages exist. | ## Example call ```json theme={null} { "tool": "list_transfers", "arguments": {} } ``` # mint_buy_token Source: https://docs.agentcard.sh/tools/mcp/org/mint_buy_token Create a scoped 30-day token that lets this cardholder's agent act as THAT ONE USER — add balance to their wallet, complete verification, and shop through the… Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). ## What it does Create a scoped 30-day token that lets this cardholder's agent act as THAT ONE USER — add balance to their wallet, complete verification, and shop through the buy agent — with no browser OAuth. The pattern for messaging surfaces (iMessage, SMS, WhatsApp): store the token keyed by your user and reuse it; create a fresh one any time. ## Inputs | Field | Type | Description | | ---------------------------- | ------ | ----------------- | | `cardholder_id` *(required)* | string | The cardholder id | ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------------------- | | `message` *(required)* | string | Human-readable summary. | | `buyToken` | string | Bearer token for the user's agent (30-day TTL). | | `agentcardUserId` | string | The linked end-user id. | | `expiresAt` | string | ISO 8601 expiry. | ## Example call ```json theme={null} { "tool": "mint_buy_token", "arguments": { "cardholder_id": "\u2026" } } ``` # recover_funds Source: https://docs.agentcard.sh/tools/mcp/org/recover_funds Recover a cardholder's residual company-funded spending power back into your company wallet — for users you won't fund again (for everyone else, closed-card ba… Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). ## What it does Recover a cardholder's residual company-funded spending power back into your company wallet — for users you won't fund again (for everyone else, closed-card balances net automatically against their next card). Omit amount\_cents to recover the full current headroom. Live recoveries are fulfilled by the AgentCard team and complete asynchronously (recovery.completed webhook); sandbox completes instantly. Supports an idempotency\_key. ## Inputs | Field | Type | Description | | ---------------------------- | ------ | ---------------------------------------------------------- | | `cardholder_id` *(required)* | string | The cardholder whose headroom to recover | | `amount_cents` | number | Amount in cents; omit to recover the full current headroom | | `idempotency_key` | string | Optional key making retries safe (Stripe semantics) | ## Returns | Field | Type | Description | | ---------------------- | ------ | -------------------------------------------------------------- | | `message` *(required)* | string | Human-readable outcome. | | `recovery` | object | The recovery (id, status, amount\_cents, cardholder\_id, ...). | ## Example call ```json theme={null} { "tool": "recover_funds", "arguments": { "cardholder_id": "\u2026" } } ``` # report_agentcard_issue Source: https://docs.agentcard.sh/tools/mcp/org/report_agentcard_issue Report a concrete AgentCard integration failure (an API error, an unexpected response, broken behavior) to AgentCard's forward-deployed engineer as a structure… Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). ## What it does Report a concrete AgentCard integration failure (an API error, an unexpected response, broken behavior) to AgentCard's forward-deployed engineer as a structured issue report. Include the request\_id from the failing API response whenever you have one — it lets the engineer find the exact request in the logs. Asynchronous like ask\_agentcard\_engineer: poll get\_engineer\_reply with the returned envelope\_id. Requires an active engineer engagement (a human admin runs `agent-cards engineer init` once). ## Inputs | Field | Type | Description | | -------------------------- | -------------------------------- | ----------------------------------------------------------------------------------- | | `title` *(required)* | string | One-line summary of the issue (≤200 chars). | | `summary` *(required)* | string | What you were doing, what happened, what you expected (≤4000 chars). | | `environment` *(required)* | string: `sandbox` · `production` | Where it happened. | | `error` | object | The failure itself, when there is a concrete error. | | `context` | object | What was calling AgentCard. | | `snippets` | array | Optional code snippets giving the engineer context (each ≤8000 chars). | | `idempotency_key` | string | Optional stable key (letters/digits/\_/-, ≤64) so a retried call is not sent twice. | ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable confirmation. | | `envelope_id` | string | Poll get\_engineer\_reply with this id. | | `engagement_id` | string | The engagement the report entered. | | `status` | string | "sent", or "no\_engagement"/"rate\_limited"/"engagement\_frozen" when not accepted. | ## Example call ```json theme={null} { "tool": "report_agentcard_issue", "arguments": { "title": "\u2026", "summary": "\u2026", "environment": "\u2026" } } ``` # setup_cardholder_payment_method Source: https://docs.agentcard.sh/tools/mcp/org/setup_cardholder_payment_method Set up a funding payment method for a cardholder — needed when create_card answers payment_method_required. Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). ## What it does Set up a funding payment method for a cardholder — needed when create\_card answers payment\_method\_required. In sandbox this adds a simulated Visa instantly. Live returns a checkout\_url: send the user there to enter their card on the hosted page, then poll get\_cardholder\_payment\_method\_status. ## Inputs | Field | Type | Description | | ---------------------------- | ------ | ----------------- | | `cardholder_id` *(required)* | string | The cardholder id | ## Returns | Field | Type | Description | | ---------------------- | ------ | ------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable next step. | | `status` | string | "attached" (sandbox, instant) or "requires\_action" (live — user must finish on the hosted page). | | `checkoutUrl` | string | Present on requires\_action — send the user here. | ## Example call ```json theme={null} { "tool": "setup_cardholder_payment_method", "arguments": { "cardholder_id": "\u2026" } } ``` # start_cardholder_kyc Source: https://docs.agentcard.sh/tools/mcp/org/start_cardholder_kyc Start (or resume) identity verification for a cardholder. Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). ## What it does Start (or resume) identity verification for a cardholder. You initiate it; only the user themself completes it. In sandbox this approves instantly. Live returns a verification\_url — hand it to the user; they upload their ID and take a face scan there. Poll get\_cardholder\_kyc\_status afterward. ## Inputs | Field | Type | Description | | ---------------------------- | ------ | ----------------- | | `cardholder_id` *(required)* | string | The cardholder id | ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable next step. | | `status` | string | "verified", "pending", or "kyc\_rejected". | | `verificationUrl` | string | Present when the user must complete verification — give them this link. | ## Example call ```json theme={null} { "tool": "start_cardholder_kyc", "arguments": { "cardholder_id": "\u2026" } } ``` # test_charge Source: https://docs.agentcard.sh/tools/mcp/org/test_charge Sandbox only: simulate a merchant charging a test card, driving the exact settlement a real charge does — authorization, clearing, the one-time-use auto-close,… Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). **Behavior:** destructive. ## What it does Sandbox only: simulate a merchant charging a test card, driving the exact settlement a real charge does — authorization, clearing, the one-time-use auto-close, and the same webhooks (transaction.authorized, transaction.cleared, card.closed). Use it to prove an integration end to end without real money. ## Inputs | Field | Type | Description | | ---------------------- | ------ | --------------------------------------------------------------------------------------------------------------------- | | `card_id` *(required)* | string | The sandbox card id | | `amount` | number | Charge amount, an integer in the currency's smallest unit: 675 for \$6.75 (default \$6.75 capped at the card balance) | | `merchant` | string | Merchant descriptor (default "COFFEE SHOP #42 SAN FRANCISCO") | ## Returns | Field | Type | Description | | ---------------------- | ------ | ---------------------------------------------------------- | | `message` *(required)* | string | Human-readable outcome. | | `paymentId` | string | The settled payment id. | | `cardStatus` | string | Post-charge card status (CLOSED — cards are one-time-use). | | `events` | array | Webhook events this charge emitted. | ## Example call ```json theme={null} { "tool": "test_charge", "arguments": { "card_id": "\u2026" } } ``` # whoami Source: https://docs.agentcard.sh/tools/mcp/org/whoami Confirm which organization this connection acts as, and whether it is in sandbox (test cards, no real money) or production mode. Connect to `https://mcp.agentcard.sh/mcp` with your **organization credential** (`client_id` + `client_secret`, or the org access token). **Behavior:** read-only. ## What it does Confirm which organization this connection acts as, and whether it is in sandbox (test cards, no real money) or production mode. Call this first when unsure what you are connected to. ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | ------ | -------------------------- | | `message` *(required)* | string | Human-readable summary. | | `organizationId` | string | The organization id. | | `name` | string | The organization name. | | `mode` | string | "sandbox" or "production". | ## Example call ```json theme={null} { "tool": "whoami", "arguments": {} } ``` # add_funds Source: https://docs.agentcard.sh/tools/mcp/user/add_funds Generate a secure checkout link the user opens to add cash to their own balance (the money that funds new cards) via Apple Pay or Google Pay, in USD. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Generate a secure checkout link the user opens to add cash to their own balance (the money that funds new cards) via Apple Pay or Google Pay, in USD. Calling this tool moves NO money and initiates NO transfer: it only prepares a single-use hosted payment page — the exact equivalent of the user clicking 'Add funds' in the dashboard. The user personally reviews, authorizes, and completes (or abandons) the payment in their own browser with their own payment method; you never see or handle payment credentials. If a one-time phone verification is needed first, this tool automatically sends the user a code and tells you where it went: ask the user for the code, call verify\_phone with it, then call add\_funds again. ## Inputs | Field | Type | Description | | --------------------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `amount_cents` *(required)* | number | Amount to add in cents (e.g. 5000 = \$50.00). Typical range: \$20.00 to \$10,000.00 (2000 to 1000000 cents); the exact range depends on the active funding provider and is returned by the API when the amount is invalid. | | `payment_method` | string: `apple_pay` · `google_pay` | Payment method for the checkout. Defaults to apple\_pay. | ## Returns | Field | Type | Description | | ---------------------- | ------ | ---------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable result or next step. | | `checkoutUrl` | string | Single-use payment link to hand the user verbatim (present when a checkout was created). | | `amountUsd` | string | Amount of the created checkout in USD. | ## Example call ```json theme={null} { "tool": "add_funds", "arguments": { "amount_cents": "\u2026" } } ``` # allow_card_merchant Source: https://docs.agentcard.sh/tools/mcp/user/allow_card_merchant Remember a merchant so the next charge there passes the card's category and merchant rules. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Remember a merchant so the next charge there passes the card's category and merchant rules. One tool call: no form, no support ticket, no new card, and the merchant stays allowed on that card from then on. The loop is three lines: the purchase is refused and the agent is told why; the agent calls this tool naming the merchant; the card resumes and the retry goes through. The pause or watch notice names the card id and the merchant pattern to pass. Pass `card_id` to remember it on that card, the default. The rest of the preset stays in force: spend, place, currency, time, and `only_from` rules still apply. The pattern is a case-insensitive substring of the merchant descriptor. If a multi-use card was paused after settlement, remember the merchant, call resume\_card, then retry. See [Allow a refused merchant](/issuing/set-rules-on-a-card#allow-a-refused-merchant). ## Inputs | Field | Type | Description | | ---------------------- | ------ | ------------------------------------------------------------------------ | | `pattern` *(required)* | string | Merchant name pattern to remember, e.g. `STARBUCKS` or `BRAXTER'S DELI`. | | `card_id` *(required)* | string | Card id (from list\_cards). | ## Returns | Field | Type | Description | | ---------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable result or guidance for the next step. | | `pattern` | string | The normalized pattern that was remembered. | | `summary` | string | Plain-English summary of the rules now in force. | | `policyVersion` | number | The new preset version. | | `needsNewCard` | boolean | True when the card keeps a network category allowlist the remember cannot widen. | | `messages` | array | Plain-English notes on where the remember is enforced. | | `preset` | object | Preset summary, or null when unrestricted: `id`, `name` (null for an anonymous preset), `version`, and a plain-English `summary` of the rules, remembered merchants included. | ## Example call ```json theme={null} { "tool": "allow_card_merchant", "arguments": { "card_id": "cmtt4mw7s001fbr8zeel9tzse", "pattern": "GROCERY MART" } } ``` # approve_request Source: https://docs.agentcard.sh/tools/mcp/user/approve_request Resolve a pending approval request (approve or deny) once the USER has decided. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Resolve a pending approval request (approve or deny) once the USER has decided. Use this after get\_card\_details or create\_card returns a 202 requiring approval, or for a row from list\_pending\_approvals. For card\_details and transaction, approval automatically completes the follow-up action and returns the result. For cross\_app actions (asks from another app: close/pause/resume a card, change a limit, view details), approval records the user's consent and the REQUESTING app completes the action from its side when it retries with the approval id. ## Inputs | Field | Type | Description | | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | | `approval_id` *(required)* | string | The approval request ID | | `decision` *(required)* | string: `approved` · `denied` | Whether to approve or deny the request | | `action` *(required)* | string: `card_details` · `transaction` · `cross_app:details` · `cross_app:close` · `cross_app:pause` · `cross_app:resume` · `cross_app:update` | The original action type from the approval prompt (list\_pending\_approvals rows carry it as action). | | `resource_id` *(required)* | string | Card ID (for card\_details and cross\_app actions) or approval ID (for transaction) | ## Returns | Field | Type | Description | | ---------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable summary of the approval outcome and any follow-up action. | | `status` | string | Outcome of the request: 'denied', 'card\_details', 'card\_created', 'resolved' (cross\_app approvals: consent recorded, the requesting app completes the action), 'personal\_surface\_only' (company-connected session; the user resolves personally), or 'unknown\_action'. | | `decision` | string | The decision that was applied: 'approved' or 'denied'. | | `action` | string | The original action type from the approval prompt: 'card\_details' or 'transaction'. | | `card` | object | The card resource returned by the approved follow-up action, when applicable. | ## Example call ```json theme={null} { "tool": "approve_request", "arguments": { "approval_id": "\u2026", "decision": "\u2026", "action": "\u2026", "resource_id": "\u2026" } } ``` # buy Source: https://docs.agentcard.sh/tools/mcp/user/buy Shop and check out, in natural language, across the merchants the user has linked (DoorDash, etc.). Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** destructive. ## What it does Shop and check out, in natural language, across the merchants the user has linked (DoorDash, etc.). Pass the whole ask as `request` — e.g. "order a caesar salad from Zuni on DoorDash" — and this tool runs the shopping flow for you. It is CONVERSATIONAL: this tool RETURNS a `conversation_id`; pass that SAME `conversation_id` back on every follow-up (your reply to a question, "add a coke", "yes, check out") so it continues the SAME order. Omit it (or set new\_order=true) only to start a fresh order. It will ask for the delivery address and have you confirm the cart and total. CHECKOUT (which charges a one-time card) happens ONLY after the user explicitly confirms in a later message — relay the confirmation through `request` ("yes, place the order") on the SAME conversation\_id. RELAY REPLIES VERBATIM: when the user answers a question from this tool ("yes", "the 16 oz one", "use my other card"), pass their reply through `request` as-is on the same conversation\_id — do NOT rewrite it into a fresh full order command; a rewritten command reads as a NEW ask and the confirmation never lands. NEVER use new\_order (or drop the conversation\_id) to recover from an error or a refused checkout — that discards the cart and any pending confirmation. Stay on the same conversation\_id and follow the error's instruction instead; new\_order is ONLY for the user starting an unrelated order. If it hands out a merchant login link (hosted connect), just reply on the SAME conversation\_id once the user finishes (e.g. "done — I logged in") and it verifies the link itself. Logins started here have no pending\_id, so the buy\_connect / buy\_connect\_status pair does not apply to them. Call get\_instructions FIRST for the current usage guide before your first buy. ## Inputs | Field | Type | Description | | ---------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | `request` *(required)* | string | The natural-language ask or follow-up, e.g. "order a caesar salad from Zuni on DoorDash", "deliver to 123 Main St", or "yes, place the order". | | `conversation_id` | string | The conversation\_id returned by a previous buy call. Pass it to continue the SAME order (keeps the cart + confirmation). Omit to start a new order. | | `new_order` | boolean | Start a fresh shopping conversation instead of continuing the current one. Use when beginning an unrelated order (ignores any conversation\_id). | ## Returns | Field | Type | Description | | ---------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | The assistant's conversational turn (it may ask for the delivery address, show the cart + total, confirm, or report a placed order), or an error explanation. | | `status` | string: `assistant_turn` · `conversation_start_failed` · `request_failed` | Discriminator for the outcome. 'assistant\_turn' when the buy loop replied; 'conversation\_start\_failed' or 'request\_failed' on errors. | | `conversation_id` | string | The conversation id to thread back as conversation\_id on the next buy call to continue the SAME order. Present on a successful assistant turn. | | `messages` | array | The same turn split into ordered messages for multi-bubble surfaces (each narration segment, then the final reply/confirmation). `message` is the same content consolidated; clients that show one bubble should use `message` and ignore this. | ## Example call ```json theme={null} { "tool": "buy", "arguments": { "request": "\u2026" } } ``` # buy_add_items Source: https://docs.agentcard.sh/tools/mcp/user/buy_add_items Add SEVERAL items to the cart in ONE call — use this instead of repeated buy_add_to_cart whenever the user wants a multi-item order (e.g. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Add SEVERAL items to the cart in ONE call — use this instead of repeated buy\_add\_to\_cart whenever the user wants a multi-item order (e.g. "two pizzas, a drink, and breadsticks"). Building the whole cart at once is REQUIRED for a guest (not-yet-linked) DoorDash cart, which can otherwise hold only one item. Each item is \{ product\_id, quantity?, options? } exactly like buy\_add\_to\_cart (for any item flagged hasOptions, call buy\_get\_item\_options first and pass the chosen ids). Returns the updated cart with subtotal; any item DoorDash rejected is listed under droppedLines so you can tell the user. ## Inputs | Field | Type | Description | | ----------------------- | ------ | ----------------------------- | | `merchant` *(required)* | string | | | `items` *(required)* | array | the items to add, in one shot | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_add_items", "arguments": { "merchant": "\u2026", "items": "\u2026" } } ``` # buy_add_to_cart Source: https://docs.agentcard.sh/tools/mcp/user/buy_add_to_cart Add a product (by id from buy_search_products or the menu digest) to the cart. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Add a product (by id from buy\_search\_products or the menu digest) to the cart. Returns the updated cart with subtotal. For a RESTAURANT item flagged (has options), FIRST call buy\_get\_item\_options, have the user choose, and pass the chosen ids here as `options` — a required option group must be satisfied or the add is rejected with options\_required (then fetch options and re-add with selections; a persistent options\_required usually means a required NESTED sub-choice is still missing). Grocery items and no-option restaurant items need no options. ## Inputs | Field | Type | Description | | ------------------------- | ------ | ---------------------------------------------------------------------- | | `merchant` *(required)* | string | | | `product_id` *(required)* | string | | | `quantity` | number | default 1 | | `options` | array | restaurant items only: the chosen options from buy\_get\_item\_options | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_add_to_cart", "arguments": { "merchant": "\u2026", "product_id": "\u2026" } } ``` # buy_addresses Source: https://docs.agentcard.sh/tools/mcp/user/buy_addresses List the delivery addresses saved on a linked merchant account. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does List the delivery addresses saved on a linked merchant account. The one marked "(default)" is where checkout will ship unless changed — lead with it (confirm it in your reply rather than asking the user to pick or type an address); "(last used)" is the best guess when the default is unknown. ## Inputs | Field | Type | Description | | ----------------------- | ------ | ---------------------------------------------------- | | `merchant` *(required)* | string | Merchant slug to list addresses for (e.g. doordash). | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_addresses", "arguments": { "merchant": "\u2026" } } ``` # buy_cancel_flight Source: https://docs.agentcard.sh/tools/mcp/user/buy_cancel_flight Cancel a flight the user previously booked, and refund them. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** destructive. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Cancel a flight the user previously booked, and refund them. TWO STEPS, like checkout: FIRST call with confirm:false (or omitted) to get the refund QUOTE — the airline's fare rules decide the refund (full, partial, or \$0 for non-refundable fares); the booking service fee is NOT refunded. SHOW the user the exact refund amount and get an explicit yes. THEN, in a LATER message, call again with confirm:true to actually cancel + refund. Cancels the most recent booked flight by default; pass `pnr` to target a specific one. ## Inputs | Field | Type | Description | | --------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `confirm` | boolean | Omit/false = refund quote only (no cancellation). true = cancel for real + refund — ONLY after the user has seen the refund amount and agreed in a later message. | | `pnr` | string | Optional booking reference (PNR) to cancel a specific flight. Omit for the most recent booked flight. | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_cancel_flight", "arguments": {} } ``` # buy_checkout Source: https://docs.agentcard.sh/tools/mcp/user/buy_checkout DESTRUCTIVE: place + pay for the current cart. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** destructive. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does DESTRUCTIVE: place + pay for the current cart. Runs the spend gate, creates a one-time card sized to the cart total, tokenizes at the merchant, and places the order. Confirm the cart total with the user first. Returns needs\_approval if a spend approval is required. May also return denied with an account gate — kyc\_required (run start\_kyc), user\_info\_required (run submit\_user\_info), wallet\_funding\_required (run add\_funds) — each reply names the tool to run before retrying with the same idempotency\_key. To make retries SAFE (e.g. after a timeout), pass the SAME idempotency\_key on every retry of one purchase — the backend then reuses the single reservation/card instead of charging twice. Use a fresh key only for a genuinely new purchase. ## Inputs | Field | Type | Description | | ----------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `merchant` *(required)* | string | | | `expected_total_cents` | number | the FINAL total in cents you showed the user and they confirmed — cart total PLUS any tip\_cents you pass. The server re-reads the live cart and rejects the checkout (409 cart\_total\_changed) if it no longer adds up, so an amount the user never saw can never be charged. Always pass it when you showed a total. | | `expected_address_id` | string | the id (from buy\_addresses / the one you passed to buy\_set\_default\_address) of the delivery address the user confirmed. The server re-asserts it as the merchant default and rejects the checkout (409 address\_changed) if it can't, so the order can never ship to a stale/other address. Always pass it once a delivery address is set. | | `tip_cents` | number | optional Dasher tip in cents; added to the charge and the created card size | | `delivery_time` | string | optional ISO-8601 time to SCHEDULE delivery for (e.g. "2026-06-17T23:00:00Z"); omit for ASAP | | `approval_id` | string | a previously-issued spend approval id, if checkout returned needs\_approval | | `idempotency_key` | string | a stable key for this purchase; reuse it on every retry so a timed-out/retried call never double-charges | | `cart_rebuilt` | boolean | pass true ONLY after a pos\_cart\_validation rejection AND after you actually re-added the item with corrected option selections — it overrides the server's block on re-checking-out a cart it saw the restaurant's register reject. Never pass it on a cart you haven't changed. | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_checkout", "arguments": { "merchant": "\u2026" } } ``` # buy_clear_cart Source: https://docs.agentcard.sh/tools/mcp/user/buy_clear_cart Empty the cart at a linked merchant. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Empty the cart at a linked merchant. ## Inputs | Field | Type | Description | | ----------------------- | ------ | -------------------------------------------------- | | `merchant` *(required)* | string | Merchant slug whose cart to empty (e.g. doordash). | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_clear_cart", "arguments": { "merchant": "\u2026" } } ``` # buy_confirm_merchant Source: https://docs.agentcard.sh/tools/mcp/user/buy_confirm_merchant Complete linking a cooperative merchant (Rappi) by submitting the one-time code from buy_link_merchant. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Complete linking a cooperative merchant (Rappi) by submitting the one-time code from buy\_link\_merchant. ## Inputs | Field | Type | Description | | ------------------------- | ------ | ------------------------------------------------------ | | `merchant` *(required)* | string | Merchant slug being linked (e.g. rappi). | | `pending_id` *(required)* | string | The pending\_id returned by buy\_link\_merchant. | | `code` *(required)* | string | The one-time code the user received from the merchant. | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_confirm_merchant", "arguments": { "merchant": "\u2026", "pending_id": "\u2026", "code": "\u2026" } } ``` # buy_connect Source: https://docs.agentcard.sh/tools/mcp/user/buy_connect Connect a merchant for shopping. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Connect a merchant for shopping. For merchants that need a real login (e.g. DoorDash) this opens a secure hosted browser session and returns a URL the user opens to log in; after they finish, call buy\_connect\_status with the pending\_id to confirm. Merchants that need no login (e.g. Agentcard Flights) come back ready immediately. Use this instead of buy\_link\_merchant for hosted-login merchants. This tool pairs only with buy\_connect\_status and only tracks logins it started itself; a login link handed out by the conversational `buy` tool has no pending\_id and is verified inside that same buy conversation (the user replies there, e.g. "done — I logged in"). ## Inputs | Field | Type | Description | | ----------------------- | ------ | ----------------------------- | | `merchant` *(required)* | string | merchant slug (e.g. doordash) | ## Returns | Field | Type | Description | | ---------------------- | ------ | --------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable next step. | | `status` | string | Outcome: 'pending' (hosted login started), 'ready'/'linked' (auto-link merchant — no login needed), or 'error'. | | `loginUrl` | string | URL the user must open to log in to the merchant. Absent for auto-link merchants. | | `pendingId` | string | Session id to pass to buy\_connect\_status. Absent for auto-link merchants. | | `merchant` | string | The merchant slug, present when an auto-link merchant needs no login. | ## Example call ```json theme={null} { "tool": "buy_connect", "arguments": { "merchant": "\u2026" } } ``` # buy_connect_status Source: https://docs.agentcard.sh/tools/mcp/user/buy_connect_status Check the status of a hosted merchant login started with buy_connect. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does Check the status of a hosted merchant login started with buy\_connect. Returns linking (still in progress — call again in a few seconds), linked (success — the merchant is ready to shop), expired, or error. Pass the merchant and the pending\_id from buy\_connect. ONLY for logins started by the buy\_connect tool: a login link handed out by the conversational `buy` tool has no pending\_id — for those, reply to the same `buy` conversation ("done — I logged in") instead of calling this. ## Inputs | Field | Type | Description | | ------------------------- | ------ | ----------------------------------------- | | `merchant` *(required)* | string | merchant slug (e.g. doordash) | | `pending_id` *(required)* | string | The pending\_id returned by buy\_connect. | ## Returns | Field | Type | Description | | ---------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `message` *(required)* | string | Human-readable status / next step. | | `status` | string | Connect state: 'linking', 'linked', 'expired', or 'error'. | | `merchant` | string | The merchant slug, present when linked. | | `cart_carried_over` | boolean | True when a cart built anonymously before linking was moved onto the linked account — re-show it (buy\_view\_cart) and re-confirm the total before checkout. | ## Example call ```json theme={null} { "tool": "buy_connect_status", "arguments": { "merchant": "\u2026", "pending_id": "\u2026" } } ``` # buy_get_budget Source: https://docs.agentcard.sh/tools/mcp/user/buy_get_budget Show the user's spending budgets: the daily/weekly/monthly/total caps the spend gate enforces before any checkout, each with its limit, spent, and remaining am… Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Show the user's spending budgets: the daily/weekly/monthly/total caps the spend gate enforces before any checkout, each with its limit, spent, and remaining amounts. Set or change one with buy\_set\_budget. ## Inputs None. ## Returns None. ## Example call ```json theme={null} { "tool": "buy_get_budget", "arguments": {} } ``` # buy_get_item_options Source: https://docs.agentcard.sh/tools/mcp/user/buy_get_item_options For a restaurant item where buy_search_products reported hasOptions=true, or the user asked to customize/modify an item, or buy_add_to_cart failed with options… Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does For a restaurant item where buy\_search\_products reported hasOptions=true, or the user asked to customize/modify an item, or buy\_add\_to\_cart failed with options\_required: fetch its customization option groups (e.g. "Choose Your Filling" — required, pick 1 of N) so the user can choose before adding. Returns groups \[\{id, name, min, max, required, options:\[\{id, name, priceCents, nested}]}] — an option can carry its OWN required `nested` groups (a combo side's size, a drink's flavor); every required group AND required nested group needs a selection. Pass the chosen option ids to buy\_add\_to\_cart as `options`. Not for grocery items. ## Inputs | Field | Type | Description | | ------------------------- | ------ | -------------------------------------------------------------------------------- | | `merchant` *(required)* | string | Merchant slug, e.g. 'doordash'. | | `product_id` *(required)* | string | Product id from buy\_search\_products. | | `store_id` | string | Store id (from buy\_search\_stores) when the item was found at a specific store. | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_get_item_options", "arguments": { "merchant": "\u2026", "product_id": "\u2026" } } ``` # buy_link_merchant Source: https://docs.agentcard.sh/tools/mcp/user/buy_link_merchant Link a merchant account so the agent can shop + check out there. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Link a merchant account so the agent can shop + check out there. Cooperative merchants (Rappi) reply that a one-time code was sent — then call buy\_confirm\_merchant with it. Learned merchants (Good Eggs, DoorDash) link in one step. DoorDash needs the user's captured browser session. ## Inputs | Field | Type | Description | | ------------------------- | ------ | --------------------------------------------- | | `merchant` *(required)* | string | merchant slug (rappi \| goodeggs \| doordash) | | `email` *(required)* | string | | | `first_name` *(required)* | string | | | `last_name` *(required)* | string | | | `phone` *(required)* | string | | | `captured_session` | object | DoorDash only: cookies captured client-side | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_link_merchant", "arguments": { "merchant": "\u2026", "email": "\u2026", "first_name": "\u2026", "last_name": "\u2026", "phone": "\u2026" } } ``` # buy_list_merchants Source: https://docs.agentcard.sh/tools/mcp/user/buy_list_merchants List merchants available for agent commerce (Rappi, Good Eggs, DoorDash) and whether this user has linked each one. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does List merchants available for agent commerce (Rappi, Good Eggs, DoorDash) and whether this user has linked each one. Link a merchant before shopping it. ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | ------ | ------------------------------------------------------------------ | | `message` *(required)* | string | Human-readable merchant list (or an error / empty note). | | `status` | string | Outcome: 'ok', 'empty', or 'error'. | | `count` | number | Number of merchants returned. | | `merchants` | array | Available commerce merchants and this user's link status for each. | ## Example call ```json theme={null} { "tool": "buy_list_merchants", "arguments": {} } ``` # buy_order_history Source: https://docs.agentcard.sh/tools/mcp/user/buy_order_history List recent orders at a linked merchant. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does List recent orders at a linked merchant. ## Inputs | Field | Type | Description | | ----------------------- | ------ | ------------------------------- | | `merchant` *(required)* | string | | | `limit` | number | max orders (default 10, max 50) | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_order_history", "arguments": { "merchant": "\u2026" } } ``` # buy_remove_from_cart Source: https://docs.agentcard.sh/tools/mcp/user/buy_remove_from_cart Remove a product (by id) from the cart at a linked merchant. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Remove a product (by id) from the cart at a linked merchant. ## Inputs | Field | Type | Description | | ------------------------- | ------ | ----------- | | `merchant` *(required)* | string | | | `product_id` *(required)* | string | | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_remove_from_cart", "arguments": { "merchant": "\u2026", "product_id": "\u2026" } } ``` # buy_reorder Source: https://docs.agentcard.sh/tools/mcp/user/buy_reorder Re-create a cart from a past order (use the order id from buy_order_history), making it the active cart. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Re-create a cart from a past order (use the order id from buy\_order\_history), making it the active cart. Review with buy\_view\_cart, then buy\_checkout. ## Inputs | Field | Type | Description | | ----------------------- | ------ | ------------------------------------- | | `merchant` *(required)* | string | | | `order_id` *(required)* | string | the order id from buy\_order\_history | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_reorder", "arguments": { "merchant": "\u2026", "order_id": "\u2026" } } ``` # buy_request_merchant Source: https://docs.agentcard.sh/tools/mcp/user/buy_request_merchant Log a feature request when the user asks to shop at a merchant/provider Agentcard does NOT support (anything not in buy_list_merchants — e.g. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Log a feature request when the user asks to shop at a merchant/provider Agentcard does NOT support (anything not in buy\_list\_merchants — e.g. Instacart, Uber Eats, Amazon). Call it once per merchant the user asks for, then tell the user plainly that the merchant isn't supported yet and that their request has been passed to the team. Do NOT promise a timeline. ## Inputs | Field | Type | Description | | ----------------------- | ------ | ----------------------------------------------------------------------------- | | `merchant` *(required)* | string | The merchant/provider the user asked for, as they said it (e.g. 'Instacart'). | | `details` | string | Optional: what they wanted to buy or do there, in one short sentence. | ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------------------- | | `message` *(required)* | string | Human-readable confirmation (or an error note). | | `status` | string | Outcome: 'logged' or 'error'. | | `merchant` | string | The merchant the request was logged for. | ## Example call ```json theme={null} { "tool": "buy_request_merchant", "arguments": { "merchant": "\u2026" } } ``` # buy_return_order Source: https://docs.agentcard.sh/tools/mcp/user/buy_return_order Start a return for a placed retail order (Amazon/Walmart lane) — use the order id from buy_order_history / the placement confirmation. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** destructive. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Start a return for a placed retail order (Amazon/Walmart lane) — use the order id from buy\_order\_history / the placement confirmation. Returns the WHOLE order unless product\_ids narrows it. reason must be one of the listed codes (pick the closest to the user's words; use 'other' + notes when none fits). The refund is automatic once the merchant receives the items: it posts back to the card that paid. Return labels are issued asynchronously — the create response usually has none yet; poll buy\_return\_status and relay the label URLs when they appear. ## Inputs | Field | Type | Description | | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | | `merchant` *(required)* | string | merchant slug (e.g. retail) | | `order_id` *(required)* | string | the placed order id (from buy\_order\_history or the placement confirmation) | | `reason` *(required)* | string: `damaged` · `not_delivered` · `empty_box` · `wrong_item` · `defective` · `not_as_described` · `wrong_size` · `no_longer_needed` · `other` | why the user is returning — closest code to their words; 'other' needs notes | | `notes` | string | extra context in the user's words (recommended; required in spirit for reason 'other') | | `product_ids` | array | return only these products (ids from the order); omit to return every item | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_return_order", "arguments": { "merchant": "\u2026", "order_id": "\u2026", "reason": "\u2026" } } ``` # buy_return_status Source: https://docs.agentcard.sh/tools/mcp/user/buy_return_status Status + return-label URLs for a return started with buy_return_order (by its return_id). Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Status + return-label URLs for a return started with buy\_return\_order (by its return\_id). Statuses: open (being processed), approved (labels issued — relay them), denied (see resolution notes), credited (refund issued). ## Inputs | Field | Type | Description | | ------------------------ | ------ | -------------------------------------- | | `merchant` *(required)* | string | | | `return_id` *(required)* | string | the return\_id from buy\_return\_order | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_return_status", "arguments": { "merchant": "\u2026", "return_id": "\u2026" } } ``` # buy_save_traveler Source: https://docs.agentcard.sh/tools/mcp/user/buy_save_traveler Save the traveller (passenger) details a flight booking needs: legal first + last name (as on their government ID), date of birth (YYYY-MM-DD), gender, contact… Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Save the traveller (passenger) details a flight booking needs: legal first + last name (as on their government ID), date of birth (YYYY-MM-DD), gender, contact email, and phone. REQUIRED once before booking a flight — collect these from the user, confirm them back, then call this. Stored securely (DOB encrypted at rest) and reused for future bookings; saving again overwrites. Not needed for food/grocery merchants. ## Inputs | Field | Type | Description | | -------------------------- | ----------------- | -------------------------------------------------------------------------------- | | `given_name` *(required)* | string | Traveller's legal first name, exactly as on their ID. | | `family_name` *(required)* | string | Traveller's legal last name, exactly as on their ID. | | `born_on` *(required)* | string | Date of birth in YYYY-MM-DD. | | `gender` *(required)* | string: `m` · `f` | Gender as shown on the traveller's ID: 'm' or 'f' (a Secure Flight requirement). | | `email` *(required)* | string | Contact email for the booking. | | `phone` *(required)* | string | Contact phone in E.164 format, e.g. +14155550100. | | `title` | string | Optional title: mr, ms, mrs, miss, or dr. | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_save_traveler", "arguments": { "given_name": "\u2026", "family_name": "\u2026", "born_on": "\u2026", "gender": "\u2026", "email": "\u2026", "phone": "\u2026" } } ``` # buy_search_products Source: https://docs.agentcard.sh/tools/mcp/user/buy_search_products Search a linked merchant for products by keyword. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Search a linked merchant for products by keyword. For the retail merchant the store ids are FIXED — amazon, walmart — so skip buy\_search\_stores/buy\_select\_store entirely and pass store\_id directly on the first search. For DoorDash, select a store first (buy\_select\_store) and then PASS store\_id ON EVERY SEARCH — the server-side store scope is volatile, and omitting it silently falls back to the nearest grocery store. ## Inputs | Field | Type | Description | | ----------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | `merchant` *(required)* | string | | | `query` *(required)* | string | | | `store_id` | string | multi-store merchants (DoorDash): the selected store's id from buy\_select\_store. Required after selecting a store — it pins the search to that store. | | `store_kind` | string | the selected store's kind from buy\_search\_stores (e.g. 'restaurant' \| 'grocery'), when known | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_search_products", "arguments": { "merchant": "\u2026", "query": "\u2026" } } ``` # buy_search_stores Source: https://docs.agentcard.sh/tools/mcp/user/buy_search_stores Find orderable stores within a multi-store merchant (DoorDash) by name. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Find orderable stores within a multi-store merchant (DoorDash) by name. Pick one with buy\_select\_store before searching products. Single-store merchants (Rappi region, Good Eggs) don't need this. NEVER needed for the retail merchant: its store ids are fixed (amazon, walmart) — pass one straight to buy\_search\_products as store\_id. ## Inputs | Field | Type | Description | | ----------------------- | ------ | ----------- | | `merchant` *(required)* | string | | | `query` *(required)* | string | | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_search_stores", "arguments": { "merchant": "\u2026", "query": "\u2026" } } ``` # buy_select_store Source: https://docs.agentcard.sh/tools/mcp/user/buy_select_store Scope subsequent searches and the cart to one store within a multi-store merchant (DoorDash). Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Scope subsequent searches and the cart to one store within a multi-store merchant (DoorDash). Not needed for the retail merchant (amazon, walmart): pass the fixed store\_id straight to buy\_search\_products instead. ## Inputs | Field | Type | Description | | ----------------------- | ------ | ----------- | | `merchant` *(required)* | string | | | `store_id` *(required)* | string | | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_select_store", "arguments": { "merchant": "\u2026", "store_id": "\u2026" } } ``` # buy_set_budget Source: https://docs.agentcard.sh/tools/mcp/user/buy_set_budget Set a spending budget that the spend gate enforces before any checkout creates a card. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Set a spending budget that the spend gate enforces before any checkout creates a card. Period is daily | weekly | monthly | total. ## Inputs | Field | Type | Description | | -------------------------- | ------------------------------------------------ | ------------------------------------------- | | `period` *(required)* | string: `daily` · `weekly` · `monthly` · `total` | | | `limit_cents` *(required)* | number | budget cap in cents | | `timezone` | string | IANA tz for window boundaries (default UTC) | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_set_budget", "arguments": { "period": "\u2026", "limit_cents": "\u2026" } } ``` # buy_set_default_address Source: https://docs.agentcard.sh/tools/mcp/user/buy_set_default_address Set the default delivery address on a linked merchant account. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Set the default delivery address on a linked merchant account. address\_id is the id from buy\_addresses; new orders default to it. ## Inputs | Field | Type | Description | | ------------------------- | ------ | -------------------------- | | `merchant` *(required)* | string | | | `address_id` *(required)* | string | the id from buy\_addresses | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_set_default_address", "arguments": { "merchant": "\u2026", "address_id": "\u2026" } } ``` # buy_set_delivery_address Source: https://docs.agentcard.sh/tools/mcp/user/buy_set_delivery_address Set a NEW delivery address by its raw parts (street, city, state, zip) for merchants with NO saved addresses to choose from (e.g. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Set a NEW delivery address by its raw parts (street, city, state, zip) for merchants with NO saved addresses to choose from (e.g. Good Eggs, or DoorDash while browsing anonymously). Use this INSTEAD of buy\_set\_default\_address in that case. Confirm the address with the user, and call it BEFORE buy\_search\_products — delivery routing and item availability depend on it. ## Inputs | Field | Type | Description | | ----------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | `merchant` *(required)* | string | Merchant slug, e.g. 'goodeggs'. | | `street` *(required)* | string | Street address, e.g. "2261 Market St". | | `city` *(required)* | string | City, e.g. "San Francisco". | | `state` *(required)* | string | Two-letter state/province code, e.g. "CA" or "BC". | | `zip` *(required)* | string | US ZIP or Canadian postal code, e.g. "94114" or "V3J 0T1". | | `address2` | string | Optional apartment / suite / floor. | | `phone` | string | Recipient phone number, e.g. +14155550100. Required for retail shipping merchants (their carriers demand one); delivery merchants ignore it. | | `name` | string | Recipient full name for the shipping label. Pass it when you know it; delivery merchants ignore it. | | `can_leave_at_door` | boolean | Whether the courier may leave the order at the door (merchant-dependent). Pass it when the user (or their saved address) states a preference. | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_set_delivery_address", "arguments": { "merchant": "\u2026", "street": "\u2026", "city": "\u2026", "state": "\u2026", "zip": "\u2026" } } ``` # buy_set_gift_recipient Source: https://docs.agentcard.sh/tools/mcp/user/buy_set_gift_recipient DoorDash only: send this order as a GIFT — marks the cart as a gift for a recipient identified by their first name + phone (DoorDash texts them). Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does DoorDash only: send this order as a GIFT — marks the cart as a gift for a recipient identified by their first name + phone (DoorDash texts them). Call AFTER items are in the cart and BEFORE buy\_checkout. BY DEFAULT the RECIPIENT chooses where it's delivered: DoorDash texts them a link to enter their own address, so you do NOT set a delivery address. ONLY when the user explicitly gives a specific destination address should you set it first (buy\_set\_default\_address) and pass recipient\_schedules\_address=false. Then buy\_view\_cart, confirm the total, and buy\_checkout as usual. Confirm the recipient's name + phone with the user before checkout. ## Inputs | Field | Type | Description | | ----------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | `merchant` *(required)* | string | Merchant slug — gifting is DoorDash-only today, so 'doordash'. | | `recipient_first_name` *(required)* | string | Gift recipient's first name. | | `recipient_phone` *(required)* | string | Recipient mobile number — DoorDash texts them the gift, e.g. +14155550100. | | `sender_name` *(required)* | string | Required. Who the gift is from, shown on the gift card (DoorDash rejects a gift with no sender). | | `recipient_last_name` | string | Recipient's last name (optional). | | `recipient_email` | string | Recipient email for the gift notification (optional). | | `message` | string | Short personal gift message (optional). | | `recipient_schedules_address` | boolean | omit/true (DEFAULT) = the recipient gets a link to enter their OWN delivery address. false = deliver to the already-set address and just notify them. | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_set_gift_recipient", "arguments": { "merchant": "\u2026", "recipient_first_name": "\u2026", "recipient_phone": "\u2026", "sender_name": "\u2026" } } ``` # buy_set_item_quantity Source: https://docs.agentcard.sh/tools/mcp/user/buy_set_item_quantity Set a product's quantity in the cart (0 removes it). Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Set a product's quantity in the cart (0 removes it). ## Inputs | Field | Type | Description | | ------------------------- | ------ | -------------------------------- | | `merchant` *(required)* | string | | | `product_id` *(required)* | string | | | `quantity` *(required)* | number | new quantity; 0 removes the item | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_set_item_quantity", "arguments": { "merchant": "\u2026", "product_id": "\u2026", "quantity": "\u2026" } } ``` # buy_set_substitution Source: https://docs.agentcard.sh/tools/mcp/user/buy_set_substitution Set the out-of-stock preference for one item in a placed order. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Set the out-of-stock preference for one item in a placed order. item\_msid is the item's msid from buy\_search\_products; preference is similar (any similar item), refund, or contact. ## Inputs | Field | Type | Description | | ------------------------- | ---------------------------------------- | ---------------------------------------- | | `merchant` *(required)* | string | | | `order_id` *(required)* | string | the order id from buy\_order\_history | | `item_msid` *(required)* | string | the item msid from buy\_search\_products | | `preference` *(required)* | string: `similar` · `refund` · `contact` | | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_set_substitution", "arguments": { "merchant": "\u2026", "order_id": "\u2026", "item_msid": "\u2026", "preference": "\u2026" } } ``` # buy_track_order Source: https://docs.agentcard.sh/tools/mcp/user/buy_track_order Status of a placed order (order id from buy_order_history or the placement confirmation): retail orders carry the retailer's own order number, its quoted deliv… Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Status of a placed order (order id from buy\_order\_history or the placement confirmation): retail orders carry the retailer's own order number, its quoted delivery window and final total once it confirms, and carrier tracking once shipped. ## Inputs | Field | Type | Description | | ----------------------- | ------ | ------------------------------------- | | `merchant` *(required)* | string | | | `order_id` *(required)* | string | the order id from buy\_order\_history | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_track_order", "arguments": { "merchant": "\u2026", "order_id": "\u2026" } } ``` # buy_unlink_merchant Source: https://docs.agentcard.sh/tools/mcp/user/buy_unlink_merchant Disconnect a merchant — drops the saved session + link. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** destructive, idempotent. ## What it does Disconnect a merchant — drops the saved session + link. The user must re-link (e.g. hosted connect) before shopping it again. ## Inputs | Field | Type | Description | | ----------------------- | ------ | -------------------------------------------- | | `merchant` *(required)* | string | Merchant slug to disconnect (e.g. doordash). | ## Returns | Field | Type | Description | | ---------------------- | ------ | --------------------------------------------------- | | `message` *(required)* | string | Human-readable unlink outcome. | | `status` | string | Outcome: 'unlinked', 'not\_linked', or 'error'. | | `merchant` | string | The merchant slug that was unlinked (or attempted). | ## Example call ```json theme={null} { "tool": "buy_unlink_merchant", "arguments": { "merchant": "\u2026" } } ``` # buy_view_cart Source: https://docs.agentcard.sh/tools/mcp/user/buy_view_cart View the current cart (items + totals) at a linked merchant. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does View the current cart (items + totals) at a linked merchant. Use this to build the itemized confirmation before checkout. If the user wants to TIP, pass that same tip as tip\_cents here so the total you show them (cart + tip) is the exact amount checkout will charge — then pass the SAME tip\_cents and that shown total (as expected\_total\_cents) to buy\_checkout. ## Inputs | Field | Type | Description | | ----------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------- | | `merchant` *(required)* | string | | | `tip_cents` | number | optional tip (cents) the user asked for, to include in the shown total. Pass the SAME value to buy\_checkout. Omit if no tip. | ## Returns None. ## Example call ```json theme={null} { "tool": "buy_view_cart", "arguments": { "merchant": "\u2026" } } ``` # cancel_plan Source: https://docs.agentcard.sh/tools/mcp/user/cancel_plan Cancel the active paid subscription, reverting to the free plan. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** destructive. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Cancel the active paid subscription, reverting to the free plan. Use get\_plan first to check the current plan. This is the counterpart to upgrade\_plan. ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | ------------------- | ------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable summary of the cancellation result. | | `status` | string: `cancelled` | Discriminator for the outcome. 'cancelled' when the cancellation was processed. | ## Example call ```json theme={null} { "tool": "cancel_plan", "arguments": {} } ``` # check_kyc_document Source: https://docs.agentcard.sh/tools/mcp/user/check_kyc_document Check the conversational verification state — use after the user uploads their ID via the browser upload link (or any time you need to re-orient). Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does Check the conversational verification state — use after the user uploads their ID via the browser upload link (or any time you need to re-orient). Returns the current step and the fields still missing. ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | ----------- | ----------- | | `message` *(required)* | string | | | `nextStep` | string/null | | | `missingFields` | array | | | `uploadUrl` | string | | | `verificationUrl` | string | | ## Example call ```json theme={null} { "tool": "check_kyc_document", "arguments": {} } ``` # close_card Source: https://docs.agentcard.sh/tools/mcp/user/close_card Permanently close a virtual card. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** destructive. ## What it does Permanently close a virtual card. This is irreversible — the card cannot be reopened. Safe to call on an already-closed card (idempotent). The user's rewards card (the card their tokenback redeems onto) is close-protected: closing it returns its balance to the wallet but retires the card number the user may have on file at AI labs, so it requires confirm\_rewards\_card — set it ONLY after the user explicitly confirms they want the rewards card closed. ## Inputs | Field | Type | Description | | ---------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `card_id` *(required)* | string | The card ID to close | | `confirm_rewards_card` | boolean | Required to close the rewards card. Only set after the user explicitly confirms; never set it preemptively. | | `approval_id` | string | Approval id from a prior approval\_required response, once the user has approved. Only for cards created through ANOTHER app: first call without it (the user is emailed an approve link), then retry with it. | ## Returns | Field | Type | Description | | ---------------------- | ------ | ------------------------------------------------------------------------------------------------ | | `message` *(required)* | string | Human-readable confirmation that the card was closed. | | `approvalId` | string | Present when status is approval\_required: pass it back as approval\_id after the user approves. | | `cardId` | string | The ID of the card that was closed. | | `status` | string | Outcome discriminator; always "closed" on success. | ## Example call ```json theme={null} { "tool": "close_card", "arguments": { "card_id": "\u2026" } } ``` # complete_kyc_transfer Source: https://docs.agentcard.sh/tools/mcp/user/complete_kyc_transfer One-time transfer for users verified under the LEGACY hosted KYC flow (verified before July 2026): carries their existing, approved verification into the curre… Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does One-time transfer for users verified under the LEGACY hosted KYC flow (verified before July 2026): carries their existing, approved verification into the current identity system so funding checkouts can reuse it and skip re-verification. NOT a new KYC — no documents, no face scan. Ask the user for their SSN (required; sent to the identity provider, never stored) and, only if the API reports missing fields, the specific fields it lists (name, date of birth, or address). Users verified under the current flow don't need this (the tool returns already\_transferred). ## Inputs | Field | Type | Description | | --------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `ssn` *(required)* | string | The user's 9-digit Social Security Number, any formatting. Forwarded to the identity provider only — never stored or logged. | | `first_name` | string | Legal first name — only when the API reported it missing. | | `last_name` | string | Legal last name — only when the API reported it missing. | | `date_of_birth` | string | YYYY-MM-DD — only when the API reported it missing. | | `address_line1` | string | Street address — only when the API reported address missing. | | `address_line2` | string | Apt/suite (optional). | | `address_city` | string | | | `address_region` | string | State, e.g. DE. | | `address_postal_code` | string | | | `accepts_crossmint_privacy` | boolean | Set true ONLY after showing the user this line: "By continuing you agree to Crossmint's privacy policy (crossmint.com/legal/privacy-policy)." It lets the transferred verification be registered with the funding provider immediately, so the user's next funding attempt skips the review wait. Omit if the disclosure was not shown — funding then handles it at checkout time. | ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------- | | `message` *(required)* | string | Human-readable result or next step. | ## Example call ```json theme={null} { "tool": "complete_kyc_transfer", "arguments": { "ssn": "\u2026" } } ``` # create_card Source: https://docs.agentcard.sh/tools/mcp/user/create_card The one card tool: get the user a virtual debit card for a purchase. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does The one card tool: get the user a virtual debit card for a purchase. Cards are live and charged for real when used. For a FIRST-TIME user it starts by putting the user's OWN card in their Agentcard vault (any Visa, Mastercard, Amex, or Discover from any country, no identity verification (KYC), no balance funding): the call returns a secure link (vault\_started); send it to the user (they type the card once and lock it with their passkey or master password; Agentcard never sees the number). A vaulted card pays through the buy tool, where the user approves each purchase on their device with their passkey or master password; it never becomes a card number you type, so after vault\_started (or vault\_ready, when a card is already in the vault) use buy for purchases instead of calling create\_card again. If the user specifically needs a card NUMBER, that is an Agentcard funded from their cash balance, which requires KYC the first time: only after the user agrees, call create\_card with source "issued". Established users: the saved default decides (get\_settings default\_payment: their chosen added card, or the wallet balance); with no saved default, an active ADDED card wins, otherwise the cash balance. Per-call overrides: connected\_card\_id issues against a specific added card, source "issued" forces the cash balance, restart\_setup mints a fresh vault link. If the balance is short on the issued path, top up with add\_funds. Connections through a company OAuth client have NO card count or amount limits; only first-party personal accounts have per-plan caps. Call get\_plan for the limits in effect. ## Inputs | Field | Type | Description | | --------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `amount_cents` *(required)* | number | Card funding amount in CENTS, not dollars (minimum 100). 100 = \$1.00 and 2500 = \$25.00; a value like 25 would be \$0.25. Company-governed connections have no maximum; personal accounts are capped by their plan — call get\_plan for the limits in effect. | | `connected_card_id` | string | Multi-card: issue against a SPECIFIC added card (an id from the user's added cards, see list\_added\_cards) instead of the newest active one. Omit for the default. | | `source` | string: `issued` | Force the card to be funded from the user's cash balance (the issued path: KYC + wallet funding) even when they have an added or vaulted card or would otherwise be offered the vault. Use it only after the user explicitly picks the balance option. Omit for the default (an active added card wins; first-time users get the vault link). | | `restart_setup` | boolean | Set true ONLY when the user lost or never received a vault link, it expired (about 15 minutes), or they want to add ANOTHER card. Never needed on the first call or for normal retries. | | `funds_source` | string: `onramp_flow` · `company_flow` | Where the card funds come from. OMIT unless instructed: the server applies the right default (company-connected accounts use the company wallet automatically when the company enables it). company\_flow = the company's wallet funds the card; onramp\_flow = the user's own wallet. | | `type` | string: `single_use` · `multi_use` | Card behavior. 'single\_use' (default) closes after its first approved charge — right for one-off purchases. 'multi\_use' stays open across charges until its total limit is spent — right for subscriptions and recurring merchants. Multi-use cards can be paused (pause\_card), resumed (resume\_card), and resized (update\_card\_limit). | | `expires_at` | string | Optional hard expiry for a multi-use card (ISO-8601 with timezone, e.g. "2027-01-01T00:00:00Z"). Must be in the future, at most 365 days out. The card closes automatically when it passes. | | `preset` | string · object | Rules for this card: a built-in name (ai\_labs, weekday\_meals, cli\_only, daily), a comma-separated list of built-ins, a saved name or id from list\_presets, inline JSON privileges, or `{ name?, privileges }`. Rules only tighten. Inline, a currency rule is `{ "kind": "currency", "currencies": ["USD"] }`, with `"mode": "watch"` on the object to watch instead of refuse. Omit it for a normal card without rules. See [Set rules on a card](/issuing/set-rules-on-a-card). | | `scope_preset` | string: `ai_labs` | Older spelling of `preset: "ai_labs"`: a multi-use card for AI vendors (OpenAI, Anthropic, Gemini). The card network declines charges anywhere else. Charges at software and AI vendors on this card earn the boosted tokenback rate; other charges on it earn the normal rate. Requires type 'multi\_use'; with single\_use the call is refused with `scope_preset_requires_multi_use`. Prefer `preset`. | ## Returns | Field | Type | Description | | ---------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `message` *(required)* | string | Human-readable result or guidance for the next step. | | `status` | string | Outcome discriminator: "created" (card issued), "vault\_started" (first-time setup: send vaultUrl to the user; once their card is in the vault, purchases go through buy, not create\_card), "vault\_ready" (the user's own card is already in their vault: use buy; only source "issued" produces a card number), "attach\_started" / "attach\_pending" (an older add-card enrollment still in flight: send attachUrl or wait, then call again with the same arguments), "issuing\_suggested" (legacy servers only: offer the balance-funded fallback, noting it requires KYC, and only then call again with source "issued"), "approval\_required" (human approval needed), "approval\_pending" (added-card passkey approval: send approvalUrl to the user, then retry with the same arguments in \~10s), "kyc\_required" (issued path only), "user\_info\_required" (check missingFields: phone/terms go through submit\_user\_info; consent must be recorded by the connecting platform), "beta\_capacity\_reached", "issuing\_balance\_insufficient" (issued path only), "payment\_method\_declined", "limit\_reached", "funding\_in\_progress" (company wallet funding underway: retry with the same arguments in \~10s), "funding\_not\_approved", "org\_wallet\_funding\_required", "org\_wallet\_unavailable" (the company wallet backing this account is not active: the company must finish setup; do not retry immediately), or "rate\_limited" (wait \~1 minute, then retry). | | `cardId` | string | The new card ID. Present only when status is "created". | | `last4` | string | Last four digits of the new card. Present only when status is "created". | | `expiry` | string | Card expiry (MM/YY). Present only when status is "created". | | `balanceCents` | number | Card balance in cents. Present only when status is "created". | | `balanceDollars` | string | Card balance formatted as USD dollars, e.g. "12.50". Present only when status is "created". | | `cardStatus` | string | Card status, e.g. "active". Present only when status is "created". | | `preset` | object | The rules on the new card: `id`, `name`, `version`, `summary`. Null when the card is unrestricted. Present only when status is "created". | | `approvalId` | string | The approval request ID to pass to approve\_request. Present only when status is "approval\_required". | | `approvalUrl` | string | The passkey approval link to send to the user. Present only when status is "approval\_pending". | | `vaultUrl` | string | The secure link the user opens to put their card in their vault. Present only when status is "vault\_started". | | `vaultCards` | number | How many cards the user already holds in their vault. Present only when status is "vault\_ready". | | `attachUrl` | string | The secure link the user opens to finish an older add-card enrollment. Present only when status is "attach\_started". | | `expiresAt` | string | When the link expires (ISO 8601). Present when status is "vault\_started" or "attach\_started". | | `source` | string | "connected" when the card was created against the user's added card. Absent for wallet-funded cards. | | `reason` | string | On "issuing\_suggested" (legacy servers only; current servers route every first-time user to the vault instead): why the card could not be added. On "kyc\_required": why the previous identity-verification attempt failed (e.g. "document\_unverified\_other"), present only when a prior attempt was rejected. | | `missingFields` | array | What is missing when status is "user\_info\_required" (e.g. "termsAccepted", "consent"). | ## Example call ```json theme={null} { "tool": "create_card", "arguments": { "amount_cents": "\u2026" } } ``` A card with a currency rule says who enforces it. `create_card` with `"preset": { "privileges": [{ "kind": "currency", "currencies": ["USD", "EUR"] }] }` on a sandbox connection, captured from a local run; `structuredContent.preset.agentcardOnly` lists `currency`: ```text theme={null} TEST card created (sandbox connection). Card ID: cmttouxtv000hjpk0bp7mbvzs Last 4: 8549 Expiry: 09/28 Balance: $20.00 Status: OPEN Preset: Currency: USD, EUR. (Agentcard enforces the currency rule at checkout and settlement; the card network does not) This is a TEST card: no real charge, not usable at real merchants. Tell the user it is a test card before they try to spend it. ``` ## Example error `scope_preset: "ai_labs"` with `type: "single_use"`, captured from a local sandbox. `isError` is set and `structuredContent.status` carries the code: ```json theme={null} { "content": [ { "type": "text", "text": "Scoped (AI) cards are always multi-use — omit type or pass multi_use." } ], "structuredContent": { "message": "Scoped (AI) cards are always multi-use — omit type or pass multi_use.", "status": "scope_preset_requires_multi_use" }, "isError": true } ``` A `preset` with a currency Agentcard cannot read answers the same way, with `policy_invalid`. `create_card` with `"preset": { "privileges": [{ "kind": "currency", "currencies": ["ZZZ"] }] }`, captured from a local run: ```json theme={null} { "content": [ { "type": "text", "text": "ZZZ is not a currency code. Use an ISO 4217 code (USD, EUR, GBP, JPY) or a common name (dollars, euros, pounds, yen)." } ], "structuredContent": { "message": "ZZZ is not a currency code. Use an ISO 4217 code (USD, EUR, GBP, JPY) or a common name (dollars, euros, pounds, yen).", "status": "policy_invalid" }, "isError": true } ``` # create_withdrawal_recipient Source: https://docs.agentcard.sh/tools/mcp/user/create_withdrawal_recipient Save a bank account as a withdrawal destination for the user's cash balance. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Save a bank account as a withdrawal destination for the user's cash balance. Supports US bank accounts (ACH: routing + account number) and international bank accounts (SWIFT wire: IBAN + BIC). Ask the user for their bank details conversationally, then call this once. After saving, use withdraw to request a payout. ## Inputs | Field | Type | Description | | ------------------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `type` *(required)* | string: `ach` · `international_wire` | ach for US bank accounts; international\_wire (SWIFT) for everywhere else. | | `beneficiary_name` *(required)* | string | The account holder's full legal name, exactly as the bank knows it. | | `country_code` *(required)* | string | Two-letter country code of the account holder (e.g. 'US', 'DE'). | | `routing_number` | string | ACH only: 9-digit US routing number. | | `account_number` | string | ACH only: US account number (4-17 digits). | | `account_type` | string: `checking` · `savings` | ACH only: account type. | | `iban` | string | International only: IBAN (e.g. DE89370400440532013000). | | `swift_code` | string | International only: 8 or 11 character SWIFT/BIC. | | `bank_name` | string | The recipient bank's name (recommended). | | `nickname` | string | A label for this account (e.g. 'My checking'). | | `country_specific` | object | Extra banking fields some countries require: \{"ifsc": "..."} for India, \{"clabe": "..."} for Mexico, \{"bsb": "..."} for Australia. Required for those countries; the validation error names the missing key. | ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------- | | `message` *(required)* | string | Human-readable result or next step. | ## Example call ```json theme={null} { "tool": "create_withdrawal_recipient", "arguments": { "type": "\u2026", "beneficiary_name": "\u2026", "country_code": "\u2026" } } ``` # delete_preset Source: https://docs.agentcard.sh/tools/mcp/user/delete_preset Retire a saved preset name. Cards already issued keep their rules. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Retire a saved name. Cards already issued keep their rules; the name stops appearing in list\_presets and no longer works as `preset`. Built-in names are refused, because there is nothing to delete. Over a connected app's own credential this returns `read_only`. The account owner deletes saved names from the CLI or the dashboard. ## Inputs | Field | Type | Description | | ------------------- | ------ | -------------------------------- | | `name` *(required)* | string | The saved preset name to delete. | ## Returns | Field | Type | Description | | ---------------------- | ------- | ---------------------------------------------------- | | `message` *(required)* | string | Human-readable result or guidance for the next step. | | `deleted` | boolean | true when the name was retired. | ## Example call ```json theme={null} { "tool": "delete_preset", "arguments": { "name": "office-supplies" } } ``` # get_balance Source: https://docs.agentcard.sh/tools/mcp/user/get_balance The user's cash balance: the money that funds new cards. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. ## What it does The user's cash balance: the money that funds new cards. Provisions the balance account on first use. Users add cash with Apple Pay or Google Pay in USD; funds are held as USDC. (Their wallet, meaning the cards themselves, is list\_cards.) ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | ------ | ------------------------------------------------------------------------ | | `message` *(required)* | string | Human-readable balance summary. | | `balanceUsd` | string | Spendable cash balance in USD (string decimal). | | `status` | string | Balance account status. | | `confirmingUsd` | string | Deposit clearing on-chain, not yet spendable (present only mid-deposit). | ## Example call ```json theme={null} { "tool": "get_balance", "arguments": {} } ``` # get_card_balance Source: https://docs.agentcard.sh/tools/mcp/user/get_card_balance The live balance of ONE virtual card (the user's overall cash balance is get_balance). Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does The live balance of ONE virtual card (the user's overall cash balance is get\_balance). Prefer this over get\_card\_details when you only need to verify available funds: it is faster and does not expose sensitive card credentials. ## Inputs | Field | Type | Description | | ---------------------- | ------ | ----------- | | `card_id` *(required)* | string | The card ID | ## Returns | Field | Type | Description | | ---------------------- | ------- | --------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable balance summary. | | `balanceCents` | number | Available balance in cents. | | `balanceDollars` | string | Available balance formatted as USD dollars, e.g. "12.50". | | `cached` | boolean | Whether the balance was served from a short-lived cache rather than fetched live. | ## Example call ```json theme={null} { "tool": "get_card_balance", "arguments": { "card_id": "\u2026" } } ``` # get_card_details Source: https://docs.agentcard.sh/tools/mcp/user/get_card_details Get decrypted PAN, CVV, expiry, and current balance for a specific card. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does Get decrypted PAN, CVV, expiry, and current balance for a specific card. Use this only when you need to fill in a payment form — prefer get\_card\_balance if you only need the balance. May require human approval before returning credentials. If approval is required, prompt the user and then call approve\_request. Card details are encrypted at rest with AES-256-GCM. ## Inputs | Field | Type | Description | | ---------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `card_id` *(required)* | string | The card ID | | `approval_id` | string | Approval id from a prior approval\_required response, once the user has approved. Only for cards created through ANOTHER app: first call without it (the user is emailed an approve link), then retry with it. | ## Returns | Field | Type | Description | | ---------------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable card details (or an approval-required prompt). | | `status` | string | Outcome discriminator: "details" when credentials were returned, "approval\_required" when human approval is needed first, "not\_accessible" when the card exists outside this connection's scope, "policy\_denied" when the card's rules refuse the reveal, with the reason in the message, for example a CLI-only card read from MCP, "managed\_by\_organization" for org-issued read-only cards. | | `cardId` | string | The card ID. | | `expiry` | string | Card expiry (MM/YY). Present only when status is "details". | | `last4` | string | Last four digits of the card number. Present only when status is "details". | | `balanceCents` | number | Card balance in cents. Present only when status is "details". | | `balanceDollars` | string | Card balance formatted as USD dollars, e.g. "12.50". Present only when status is "details". | | `cardStatus` | string | Card status, e.g. "active" or "closed". Present only when status is "details". | | `approvalId` | string | The approval request ID to pass to approve\_request. Present only when status is "approval\_required". | ## Example call ```json theme={null} { "tool": "get_card_details", "arguments": { "card_id": "\u2026" } } ``` # get_card_preset Source: https://docs.agentcard.sh/tools/mcp/user/get_card_preset Read the rules on a card as a plain summary. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does Read the rules on a card as a plain summary: spend caps, rates, categories, merchants, places, currencies, time windows, where the card can be used from, and any remembered merchants. A currency rule reads `Currency: USD, EUR`, and a preset that watches ends with `Mode: watch`. A card, app, or account without a preset is unrestricted, and the tool says so. The rules are explained in [Set rules on a card](/issuing/set-rules-on-a-card). ## Inputs | Field | Type | Description | | ---------------------- | ------ | ------------------------------- | | `card_id` *(required)* | string | The card id (from list\_cards). | ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable result or guidance for the next step. | | `cardId` | string | The card id, when one was passed. | | `preset` | object | Preset summary, or null when unrestricted: `id`, `name` (null for an anonymous preset), `version`, and a plain-English `summary` of the rules, remembered merchants included. | ## Example call ```json theme={null} { "tool": "get_card_preset", "arguments": { "card_id": "…" } } ``` # get_instructions Source: https://docs.agentcard.sh/tools/mcp/user/get_instructions Call this FIRST; returns the latest usage guide for shopping with `buy` AND for operating the Agentcard account tools (cards, funding, your own card, KYC, supp… Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does Call this FIRST; returns the latest usage guide for shopping with `buy` AND for operating the Agentcard account tools (cards, funding, your own card, KYC, support). ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------------------- | | `message` *(required)* | string | The latest buy usage guide / instructions text. | ## Example call ```json theme={null} { "tool": "get_instructions", "arguments": {} } ``` # get_kyc_status Source: https://docs.agentcard.sh/tools/mcp/user/get_kyc_status Check the user's identity verification (KYC) status. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does Check the user's identity verification (KYC) status. Returns whether they are verified and, if not, the current state plus the conversational next step. Use this to poll after the user does the face scan, or any time create\_card reports kyc\_required. ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable status / next step. | | `verified` | boolean | True when identity verification has passed. | | `status` | string/null | Raw KYC state: "verified", "pending", "requires\_input", "duplicate\_identity", "canceled", or null if never started. | | `reason` | string/null | Failure reason from the verification provider when one exists. | | `nextStep` | string/null | Conversational next step when the flow is in progress. | | `missingFields` | array | | | `verificationUrl` | string | | ## Example call ```json theme={null} { "tool": "get_kyc_status", "arguments": {} } ``` # get_plan Source: https://docs.agentcard.sh/tools/mcp/user/get_plan Show the user's current subscription plan, card limits, and this month's usage. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does Show the user's current subscription plan, card limits, and this month's usage. Call this before create\_card when you need the per-card amount cap or remaining monthly quota, or whenever the user asks about their plan, limits, billing, or upgrading. To cancel a paid plan, the gated tool cancel\_plan also exists; call it by name even though it isn't in the tools list. ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable plan + usage summary. | | `plan` | string | Raw plan id, e.g. 'free', 'basic', or 'pro'. | | `planName` | string | Display label of the plan, e.g. "Basic (\$15/mo)". | | `cardsThisMonth` | number | Number of cards created this month. | | `maxCardsPerMonth` | number/null | Max cards allowed per month; null means unlimited (connections through a company OAuth client or organization have no card limits). | | `cardsRemaining` | number/null | Cards remaining this month; null means unlimited. | | `maxCardAmountCents` | number/null | Maximum funding per card, in cents; null means no per-card cap. | | `maxCardAmountDollars` | string/null | Maximum funding per card, formatted as USD dollars, e.g. "500.00"; null means no per-card cap. | | `ordersPlaced` | number | Orders placed (counts toward the free-order quota on Free). | | `maxLifetimeOrders` | number/null | Lifetime free-order quota; null means unlimited (paid plans). | | `subscriptionStatus` | string/null | Stripe subscription status (e.g. 'active', 'past\_due'), or null on Free / when unavailable. | | `cancelAtPeriodEnd` | boolean | Whether the subscription cancels at the end of the current billing period. | | `currentPeriodEnd` | string/null | ISO date the current billing period ends, or null. | ## Example call ```json theme={null} { "tool": "get_plan", "arguments": {} } ``` # get_rewards Source: https://docs.agentcard.sh/tools/mcp/user/get_rewards Show the user's tokenback: balance, lifetime earned, and recent activity. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does Show the user's tokenback: balance, lifetime earned, and recent activity. Tokenback pays tokens (1 token = 1¢ of credit value) on settled card spend. The boosted rate is earned on an AI card, one created with the `ai_labs` preset or a software and AI rule in either mode, and only on its charges at software and AI vendors. Every other charge on a personal card earns the normal rate. Cards funded by a company earn no tokenback from Agentcard; the company shares its own earnings with its users instead. Redeem with redeem\_rewards. ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------------- | | `message` *(required)* | string | Human-readable summary. | | `balanceTokens` | number | Current token balance (1 token = 1 cent). | | `lifetimeEarnedTokens` | number | Tokens earned all-time. | | `redeemedTokens` | number | Tokens redeemed all-time. | | `minRedeemTokens` | number | Minimum tokens per redemption. | ## Example call ```json theme={null} { "tool": "get_rewards", "arguments": {} } ``` # get_settings Source: https://docs.agentcard.sh/tools/mcp/user/get_settings View the user's notification preferences (which email alerts they receive), their default payment source (which card or balance agents charge — check it before… Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does View the user's notification preferences (which email alerts they receive), their default payment source (which card or balance agents charge — check it before picking a funding source for them), their default delivery address (the wallet-level shipping address to use when buying physical goods for them — check it before asking them to dictate an address), and authorization settings (whether viewing card details or making transactions requires explicit approval). Authorization settings are read-only here; change the rest with the gated tool update\_settings, calling it by name even though it isn't in the tools list. ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable settings summary. | | `notifications` | object | Email notification preferences. | | `authorization` | object | Authorization (approval) settings — read-only. | | `delivery_address` | object/null | The wallet-level default delivery address (street/city/state/zip + optional address2/phone/name), or null when unset. | | `default_payment` | object/null | The wallet-level default payment source: \{ source: 'balance' } or \{ source: 'connected', connected\_card\_id }. null = auto (an active added card wins, else the balance). | ## Example call ```json theme={null} { "tool": "get_settings", "arguments": {} } ``` # get_wallet_link Source: https://docs.agentcard.sh/tools/mcp/user/get_wallet_link The user's hosted wallet, as one shareable URL. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does The user's hosted wallet, as one shareable URL. Opens their Agentcard wallet in the browser: every card in one place, apply for an Agentcard card (identity verification runs right in the page). Mint it whenever the user needs a browser step (seeing cards, finishing verification when in-chat photos fail) and send them the URL. To ADD the user's own card, pass purpose "add\_card": the link then opens their Agentcard vault card form directly (any card, typed once, locked with their passkey or master password, never seen by Agentcard) and works on personal logins too. Pass merchant + amount\_cents to open the wallet ON the payment-approval sheet (the user picks a card and approves that exact charge) instead of the card list. Multi-use but short-lived (about 15 minutes — the exact moment is in expiresAt); mint a fresh one when it expires. The wallet link only works for app connections (OAuth). ## Inputs | Field | Type | Description | | -------------- | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | | `purpose` | string: `wallet` · `add_card` | "wallet" (default) opens the hosted wallet. "add\_card" opens the vault card form so the user can put their own card on file; single-use, about 15 minutes. | | `merchant` | string | Merchant name shown on the payment-approval sheet (with amount\_cents). | | `amount_cents` | integer | Amount in cents. When present, the link opens on the payment-approval sheet for this charge. | ## Returns | Field | Type | Description | | ---------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Ready-to-send sentence containing the URL. | | `url` | string | The hosted wallet URL to share with the user. | | `kind` | string | purpose add\_card only: how the vault link signs the user in. "connected" = a one-time code to their own phone or email; "handoff" = directly; "open" = passkey setup or passkey sign-in. | | `expiresAt` | string | ISO time the link stops working. | | `sandbox` | boolean | True when the connection is in test mode. | ## Example call ```json theme={null} { "tool": "get_wallet_link", "arguments": {} } ``` # link_account Source: https://docs.agentcard.sh/tools/mcp/user/link_account Link or merge another Agentcard account that belongs to the same person. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** destructive. ## What it does Link or merge another Agentcard account that belongs to the same person. Use when the user says they already have an account under a DIFFERENT email or phone number — most often after identity verification (KYC) is rejected as a duplicate, which means that person already verified on another account. Two steps: (1) call with \{ type, identifier } to send a one-time code to that email/phone; (2) call again with the \{ ticket, code } to verify. If the identifier belongs to a different account, the two accounts are MERGED (the identity-verified account survives and gains the other's email/phone, so both sign in to one account); if no account has it, it is simply added to the current account. ## Inputs | Field | Type | Description | | ------------ | ------------------------- | ------------------------------------------------------------------------- | | `type` | string: `email` · `phone` | Step 1: which kind of identifier the OTHER account uses. | | `identifier` | string | Step 1: the email address or phone number of the other account to verify. | | `ticket` | string | Step 2: the ticket returned by step 1. | | `code` | string | Step 2: the one-time code the user received. | ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------- | | `message` *(required)* | string | Human-readable result or next step. | ## Example call ```json theme={null} { "tool": "link_account", "arguments": {} } ``` # list_added_cards Source: https://docs.agentcard.sh/tools/mcp/user/list_added_cards List the user's ADDED cards (their own Visa/Mastercard cards enrolled via create_card's add-card flow — the funding source that charges their own card), with i… Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does List the user's ADDED cards (their own Visa/Mastercard cards enrolled via create\_card's add-card flow — the funding source that charges their own card), with ids, brand, last4, expiry, and status. The row marked isDefault is what create\_card charges when no connected\_card\_id is given — the user's chosen default card (set with update\_settings default\_payment), falling back to the newest active one. Not the same as list\_cards (the virtual cards Agentcard issues). ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable list (or an empty-state note). | | `count` | number | Number of non-revoked added cards. | | `attachedCards` | array | Added-card enrollments, newest first. The row with isDefault true is the default for new cards; none is marked when the default payment is the wallet balance. | ## Example call ```json theme={null} { "tool": "list_added_cards", "arguments": {} } ``` # list_all_transactions Source: https://docs.agentcard.sh/tools/mcp/user/list_all_transactions Advanced/legacy: use list_transactions WITHOUT a card_id for the all-cards view instead. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Advanced/legacy: use list\_transactions WITHOUT a card\_id for the all-cards view instead. List transactions across ALL of your cards in one flat list, newest first. Each transaction is tagged with the card it belongs to (card id + last4) so you can tell which card was charged. This is the account-wide view; use list\_transactions when you only want one specific card. Use limit, offset (pagination), and status to filter results. ## Inputs | Field | Type | Description | | -------- | ------ | ------------------------------------------------------------------------------------------- | | `limit` | number | Max number of transactions to return (default 20, max 100) | | `offset` | number | Number of transactions to skip, for pagination (default 0) | | `status` | string | Filter by transaction status (e.g. PENDING, SETTLED, DECLINED, REVERSED, EXPIRED, REFUNDED) | ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable list of transactions across all cards (or a "no transactions" note). | | `count` | number | Number of transactions returned. | | `transactions` | array | Transactions across all of the account's cards, newest first. | ## Example call ```json theme={null} { "tool": "list_all_transactions", "arguments": {} } ``` # list_cards Source: https://docs.agentcard.sh/tools/mcp/user/list_cards The user's wallet: every live card they hold, with IDs, last four digits, expiry, balance, and status, plus `vaultCards`: the user's OWN cards stored in their… Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does The user's wallet: every live card they hold, with IDs, last four digits, expiry, balance, and status, plus `vaultCards`: the user's OWN cards stored in their Agentcard vault (display fields only; a vaulted card pays through buy with an approval on the user's device (their passkey or master password) and never exposes a number). Start here to find available cards; if none are returned, call create\_card. When the shared wallet is enabled, `wallet` lists every card across all connected apps and companies, each tagged with its source (kind personal/company, the issuing app, and the company where applicable); cards created by another app or company are read-only from this session: get\_card\_details and close\_card will not work on them. ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable list of cards (or an empty-state message). | | `count` | number | Total number of cards across the user's own cards and any connected-account cards. | | `cards` | array | The user's own virtual cards. | | `wallet` | array | One-wallet view (present when the shared wallet is enabled): every LIVE card across personal and company sources, each tagged with its provenance. Closed cards are excluded; transactions carry history. | | `vaultCards` | array | The user's own cards stored in their Agentcard vault. Display fields only; they pay through buy with an approval on the user's device (their passkey or master password) and never expose a card number. | | `connectedAccounts` | array | Read-only cards issued and managed by an organization the user is linked to. | ## Example call ```json theme={null} { "tool": "list_cards", "arguments": {} } ``` # list_codes Source: https://docs.agentcard.sh/tools/mcp/user/list_codes List the user's promo (coupon) codes: every code they have redeemed or attempted, with its amount and state — used (credit already sent), awaiting_verification… Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does List the user's promo (coupon) codes: every code they have redeemed or attempted, with its amount and state — used (credit already sent), awaiting\_verification (claimed and reserved; pays out automatically once the user passes KYC — offer start\_kyc), processing (mid-transfer), available (a failed attempt they can retry with redeem\_code), or expired. Codes the user has never presented cannot be listed; they only enter the history via redeem\_code. ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | ------ | --------------------------------------------------------------- | | `message` *(required)* | string | Human-readable list of the user's codes (or a "no codes" note). | | `count` | number | Number of codes returned. | | `codes` | array | The user's promo-code history, newest first. | ## Example call ```json theme={null} { "tool": "list_codes", "arguments": {} } ``` # list_connections Source: https://docs.agentcard.sh/tools/mcp/user/list_connections List the third-party apps the user has connected to their Agentcard account via OAuth (e.g. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does List the third-party apps the user has connected to their Agentcard account via OAuth (e.g. Kilo), including when each was connected and whether it is still active. Read-only. To revoke an app, call revoke\_connection with its clientId. ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | ------ | ------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable summary of the connected apps. | | `status` | string | Result status: "no\_connections" when none are connected, otherwise "ok". | | `count` | number | Number of connected apps. | | `connections` | array | The third-party apps connected to the user's account via OAuth. | ## Example call ```json theme={null} { "tool": "list_connections", "arguments": {} } ``` # list_payment_methods Source: https://docs.agentcard.sh/tools/mcp/user/list_payment_methods List the saved payment methods (used only to pay for flight bookings, not for cards or adding funds). Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does List the saved payment methods (used only to pay for flight bookings, not for cards or adding funds). Returns each method with its id, brand, last 4 digits, and expiry, and marks the default one. Use setup\_payment\_method to add a new one. The gated tools set\_default\_payment\_method and remove\_payment\_method also exist; call them by name even though they aren't in the tools list. ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | -------------------------------------- | ------------------------------------------------------- | | `message` *(required)* | string | Human-readable summary of the saved payment methods. | | `status` | string: `listed` · `no_payment_method` | Whether any payment methods are saved. | | `count` | number | Number of saved payment methods. | | `defaultId` | string | The id of the payment method marked as default, if any. | | `paymentMethods` | array | The saved payment methods. | ## Example call ```json theme={null} { "tool": "list_payment_methods", "arguments": {} } ``` # list_pending_approvals Source: https://docs.agentcard.sh/tools/mcp/user/list_pending_approvals List the user's PENDING approval requests: asks from connected apps (create a card, view full card details, close/pause/resume a card, change a limit) waiting… Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does List the user's PENDING approval requests: asks from connected apps (create a card, view full card details, close/pause/resume a card, change a limit) waiting on the user's decision. Surface each one to the user and let THEM decide; after the user answers, resolve with approve\_request. NEVER approve or deny on your own — an approval is the user's consent, not yours. Personal sessions only; company-connected sessions have no personal inbox. ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | ------ | ---------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable list of pending approvals (or an empty-state note). | | `status` | string | Present only when the list is unavailable: "personal\_surface\_only" for company-connected sessions. | | `count` | number | Number of pending approvals. | | `approvals` | array | Pending, unexpired approval requests, newest first. Each is waiting on the user's decision. | ## Example call ```json theme={null} { "tool": "list_pending_approvals", "arguments": {} } ``` # list_presets Source: https://docs.agentcard.sh/tools/mcp/user/list_presets List every preset the user can pass by name, built-in and saved, each with a plain summary. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does List every preset the user can pass by name: the built-ins `ai_labs`, `weekday_meals`, `cli_only`, and `daily`, and every name they saved, each with a plain summary of its rules. Pass any `key` as `preset` to create\_card or set\_card\_preset. A deleted name is not listed; cards created from it keep working. ## Inputs | Field | Type | Description | | -------- | ---- | ----------------------------- | | *(none)* | | This tool takes no arguments. | ## Returns | Field | Type | Description | | ---------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable result or guidance for the next step. | | `presets` | array | One entry per preset: `key` (the name to pass elsewhere as `preset`), `builtin`, `version` (saved names only), `summary`. | ## Example call ```json theme={null} { "tool": "list_presets", "arguments": {} } ``` # list_transactions Source: https://docs.agentcard.sh/tools/mcp/user/list_transactions Transactions with amount, merchant, status, and timestamps. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does Transactions with amount, merchant, status, and timestamps. Pass card\_id for one card's transactions; OMIT it for every card in the account (newest first, each row tagged with its card). Use limit and status to filter. The gated views list\_all\_transactions and list\_transactions\_by\_payment\_method also exist; call them by name even though they aren't in the tools list. ## Inputs | Field | Type | Description | | --------- | ------ | ------------------------------------------------------------------------------------------- | | `card_id` | string | A card ID for that card's transactions; omit for all cards in the account. | | `limit` | number | Max number of transactions to return (default 20) | | `offset` | number | Skip this many (all-cards view pagination; ignored for a single card). | | `status` | string | Filter by transaction status (e.g. PENDING, SETTLED, DECLINED, REVERSED, EXPIRED, REFUNDED) | ## Returns | Field | Type | Description | | ---------------------- | ------ | ------------------------------------------------------------------ | | `message` *(required)* | string | Human-readable list of transactions (or a "no transactions" note). | | `count` | number | Number of transactions returned. | | `transactions` | array | The transactions for the card, newest first. | ## Example call ```json theme={null} { "tool": "list_transactions", "arguments": {} } ``` # list_transactions_by_payment_method Source: https://docs.agentcard.sh/tools/mcp/user/list_transactions_by_payment_method List transactions across the whole account GROUPED by payment method: wallet (USDC collateral) card spend, legacy saved-card-on-file spend, sandbox/test card s… Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does List transactions across the whole account GROUPED by payment method: wallet (USDC collateral) card spend, legacy saved-card-on-file spend, sandbox/test card spend, and wallet-funding deposits grouped by Apple Pay / Google Pay. Each group carries all-time totals; each transaction row carries its card (id + last4), merchant name + MCC, and — for purchases made through the buy flow — the merchant order behind the charge (merchant, order id, order total). Use this for "what did I spend, and how did I pay" style questions; use list\_all\_transactions for a flat ungrouped list, or buy\_order\_history for line-level items of a specific merchant's orders. limit/offset paginate the underlying newest-first transaction stream (groups repeat across pages); status filters card spend (e.g. SETTLED, DECLINED). ## Inputs | Field | Type | Description | | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | | `limit` | number | Max number of transactions across all groups per page (default 50, max 100) | | `offset` | number | Number of transactions to skip, for pagination (default 0) | | `status` | string | Filter card spend by transaction status (e.g. PENDING, SETTLED, DECLINED, REVERSED, EXPIRED, REFUNDED). Wallet-funding deposit groups are omitted when set. | ## Returns | Field | Type | Description | | ---------------------- | ------ | ---------------------------------------------------------------- | | `message` *(required)* | string | Human-readable report of transactions grouped by payment method. | | `groupCount` | number | Number of payment-method groups returned. | | `returned` | number | Number of transactions returned in this page across all groups. | | `groups` | array | One entry per payment method that has activity. | ## Example call ```json theme={null} { "tool": "list_transactions_by_payment_method", "arguments": {} } ``` # list_withdrawal_recipients Source: https://docs.agentcard.sh/tools/mcp/user/list_withdrawal_recipients List the user's saved bank accounts for withdrawals, masked (bank name and last four only). Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does List the user's saved bank accounts for withdrawals, masked (bank name and last four only). Use a recipient's id as recipient\_id with withdraw. If the list is empty, collect the user's bank details and call create\_withdrawal\_recipient first. ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | ------ | --------------------------------------------- | | `message` *(required)* | string | Human-readable list (or an empty-state note). | | `count` | number | Number of saved bank destinations. | | `recipients` | array | Saved bank destinations, masked. | ## Example call ```json theme={null} { "tool": "list_withdrawal_recipients", "arguments": {} } ``` # manage_subscription Source: https://docs.agentcard.sh/tools/mcp/user/manage_subscription Manage a recurring meal/grocery SUBSCRIPTION (e.g. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Manage a recurring meal/grocery SUBSCRIPTION (e.g. Locale) — NOT a one-time purchase, and no payment is taken (the subscription auto-bills the card on file at the merchant). action: 'menu\_search' (browse the recurring menu; items flagged inPlan are covered by the plan), 'get\_skip\_dates' (list skipped/paused deliveries), 'skip'/'unskip' (one upcoming delivery date), 'set\_skip\_dates' (replace the full skip set; \[] resumes all), 'update\_setting' (change a setting). Locale settings: subscription\_size (meals, e.g. 8), calorie\_preference (low\_calorie|both|moderate), diets (array), longevity\_allergens (array), ingredient\_allergies (array), default\_window ('9am - 6pm'|'3pm - 7pm'|'9am - 12pm'), delivery\_instructions (text). Link the merchant first. ## Inputs | Field | Type | Description | | ----------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | | `merchant` *(required)* | string | merchant slug (e.g. locale) | | `action` *(required)* | string: `menu_search` · `get_skip_dates` · `skip` · `unskip` · `set_skip_dates` · `update_setting` | the management action | | `query` | string | menu\_search: term over the recurring menu (e.g. 'salmon'); '' lists everything | | `limit` | number | menu\_search: max items | | `date` | string | skip/unskip: one ISO delivery date (YYYY-MM-DD) | | `dates` | array | set\_skip\_dates: FULL set of ISO dates to skip (\[] resumes all) | | `setting` | string | update\_setting: the setting key (see description) | | `value` | object | update\_setting: the new value (number, string, or array of strings) | ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------- | | `message` *(required)* | string | Human-readable result or next step. | ## Example call ```json theme={null} { "tool": "manage_subscription", "arguments": { "merchant": "\u2026", "action": "\u2026" } } ``` # pause_card Source: https://docs.agentcard.sh/tools/mcp/user/pause_card Pause a multi-use card: temporarily blocks ALL new charges (reversible — use resume_card to unblock). Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. ## What it does Pause a multi-use card: temporarily blocks ALL new charges (reversible — use resume\_card to unblock). Right for "stop this subscription for now" or a card the user suspects is compromised but is not sure. Only multi-use cards can be paused; single-use cards close after one charge and cannot be paused. ## Inputs | Field | Type | Description | | ---------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `card_id` *(required)* | string | The card ID to pause (from list\_cards or create\_card). | | `approval_id` | string | Approval id from a prior approval\_required response, once the user has approved. Only for cards created through ANOTHER app: first call without it (the user is emailed an approve link), then retry with it. | ## Returns | Field | Type | Description | | ---------------------- | ------ | ------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable result. | | `status` | string | "paused" on success; an error discriminator otherwise (e.g. "not\_multi\_use", "card\_not\_updatable"). | | `cardId` | string | The card ID. | ## Example call ```json theme={null} { "tool": "pause_card", "arguments": { "card_id": "\u2026" } } ``` # read_support_chat Source: https://docs.agentcard.sh/tools/mcp/user/read_support_chat Read the message history of a support conversation Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does Read the message history of a support conversation ## Inputs | Field | Type | Description | | ------------------------------ | ------ | ------------------- | | `conversation_id` *(required)* | string | The conversation ID | ## Returns | Field | Type | Description | | ---------------------- | ------ | ---------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable rendering of the conversation history. | | `status` | string | Outcome of the read: 'empty' when there are no messages yet, 'ok' when messages were returned. | | `messages` | array | The messages in the conversation, oldest first. | | `count` | number | Number of messages returned. | ## Example call ```json theme={null} { "tool": "read_support_chat", "arguments": { "conversation_id": "\u2026" } } ``` # redeem_code Source: https://docs.agentcard.sh/tools/mcp/user/redeem_code Redeem a promo code that adds money to the user's cash balance. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. ## What it does Redeem a promo code that adds money to the user's cash balance. Each code works once per user; the credit lands in the balance and becomes spendable within a minute or two. Some codes hold the money until the user verifies their identity — the claim still locks the code to this user instantly, and the credit lands automatically once KYC is approved (start\_kyc begins verification). The gated tool list\_codes shows the user's code history; call it by name even though it isn't in the tools list. ## Inputs | Field | Type | Description | | ------------------- | ------ | ------------------------------------------------------------------------------ | | `code` *(required)* | string | The promo code exactly as the user provided it (case and dashes are forgiven). | ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------- | | `message` *(required)* | string | Human-readable result or next step. | ## Example call ```json theme={null} { "tool": "redeem_code", "arguments": { "code": "\u2026" } } ``` # redeem_rewards Source: https://docs.agentcard.sh/tools/mcp/user/redeem_rewards Redeem tokenback: the tokens' cash value (1 token = 1¢) lands on the user's rewards card as spending power. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Redeem tokenback: the tokens' cash value (1 token = 1¢) lands on the user's rewards card as spending power. The rewards card is permanent and locked to AI-lab merchants (OpenAI, Anthropic, Gemini) — created on first redemption, topped up after. Check get\_rewards first for the balance and the minimum. Ask the user before redeeming. ## Inputs | Field | Type | Description | | --------------------- | ------ | -------------------------------------------------------------------------------------- | | `tokens` *(required)* | number | How many tokens to redeem (1 token = 1 cent, so 500 tokens = \$5.00 of wallet credit). | ## Returns | Field | Type | Description | | ---------------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable result. | | `status` | string | "redeemed" on success; an error discriminator otherwise (e.g. "below\_minimum", "insufficient\_tokens", "redemption\_in\_progress"). | | `redemptionId` | string | The redemption ID. Present when status is "redeemed". | | `amountCents` | number | Wallet credit in cents. Present when status is "redeemed". | | `deliveredCardId` | string | Rewards card the value landed on, when delivery completed inline. Absent = the value sits as wallet credit (it reaches the rewards card within a few minutes when delivery is enabled). | | `deliveredCardLast4` | string | Last 4 digits of the rewards card, when delivered inline. | ## Example call ```json theme={null} { "tool": "redeem_rewards", "arguments": { "tokens": "\u2026" } } ``` # remove_added_card Source: https://docs.agentcard.sh/tools/mcp/user/remove_added_card Remove (unenroll) one of the user's added cards. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** destructive. ## What it does Remove (unenroll) one of the user's added cards. Irreversible for that enrollment: any virtual cards created against it are closed first, then the card is unenrolled at the network. ALWAYS confirm with the user before calling. Get ids from list\_added\_cards. The user can add the same card again later (create\_card with restart\_setup: true). ## Inputs | Field | Type | Description | | ------------------------------- | ------ | ------------------------------------------------------------- | | `attached_card_id` *(required)* | string | The id of the added card to remove (from list\_added\_cards). | ## Returns | Field | Type | Description | | ---------------------- | ------ | ------------------------------------------------------ | | `message` *(required)* | string | Human-readable confirmation or guidance. | | `id` | string | The id of the removed card. | | `status` | string | "revoked" on success. | | `closedCards` | number | How many virtual cards created against it were closed. | ## Example call ```json theme={null} { "tool": "remove_added_card", "arguments": { "attached_card_id": "\u2026" } } ``` # remove_payment_method Source: https://docs.agentcard.sh/tools/mcp/user/remove_payment_method Remove a saved payment method. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** destructive. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Remove a saved payment method. This detaches it permanently. Use list\_payment\_methods or the list from setup\_payment\_method status to find the payment\_method\_id. ## Inputs | Field | Type | Description | | -------------------------------- | ------ | ---------------------------------------------- | | `payment_method_id` *(required)* | string | The payment method ID to remove (e.g. pm\_xxx) | ## Returns | Field | Type | Description | | ---------------------- | ----------------- | ------------------------------------------------------ | | `message` *(required)* | string | Human-readable summary of the result. | | `paymentMethodId` | string | The payment method ID that was removed (e.g. pm\_xxx). | | `status` | string: `removed` | Outcome of the operation. | ## Example call ```json theme={null} { "tool": "remove_payment_method", "arguments": { "payment_method_id": "\u2026" } } ``` # resume_card Source: https://docs.agentcard.sh/tools/mcp/user/resume_card Resume a paused multi-use card so it accepts charges again. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. ## What it does Resume a paused multi-use card so it accepts charges again. The inverse of pause\_card. ## Inputs | Field | Type | Description | | ---------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `card_id` *(required)* | string | The paused card ID to resume. | | `approval_id` | string | Approval id from a prior approval\_required response, once the user has approved. Only for cards created through ANOTHER app: first call without it (the user is emailed an approve link), then retry with it. | ## Returns | Field | Type | Description | | ---------------------- | ------ | --------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable result. | | `status` | string | "active" on success; an error discriminator otherwise (e.g. "card\_not\_paused"). | | `cardId` | string | The card ID. | ## Example call ```json theme={null} { "tool": "resume_card", "arguments": { "card_id": "\u2026" } } ``` # revoke_connection Source: https://docs.agentcard.sh/tools/mcp/user/revoke_connection Revoke a third-party app's access to the user's Agentcard account. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** destructive, idempotent. ## What it does Revoke a third-party app's access to the user's Agentcard account. Disconnects the app and invalidates its OAuth tokens; it must reconnect via OAuth to regain access. Pass the clientId shown by list\_connections. ## Inputs | Field | Type | Description | | ------------------------ | ------ | ------------------------------------------------------------------ | | `client_id` *(required)* | string | The OAuth client ID of the app to revoke (from list\_connections). | ## Returns | Field | Type | Description | | ---------------------- | ------ | ---------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable outcome. | | `status` | string | Result status: "revoked" when tokens were invalidated, "not\_connected" when the app had no active access. | | `revoked` | number | Number of OAuth tokens that were revoked. | | `clientId` | string | The client ID that was revoked. | ## Example call ```json theme={null} { "tool": "revoke_connection", "arguments": { "client_id": "\u2026" } } ``` # save_preset Source: https://docs.agentcard.sh/tools/mcp/user/save_preset Save a set of rules under a name so the user can reuse it in create_card or set_card_preset. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Save a set of rules under a name so the user can reuse it in create\_card or set\_card\_preset. Save a name that already exists and the change applies to cards created from now on; cards the user already has keep their rules. The built-in names `ai_labs`, `weekday_meals`, `cli_only`, and `daily` cannot be saved over. Pass the rule fields below, or a raw `privileges` array. The fields mean the same as the flags on [`cards preset save`](/tools/cli/cards-preset-save). Categories, `mode`, places, currencies, and time windows are explained in [Set rules on a card](/issuing/set-rules-on-a-card). ## Inputs | Field | Type | Description | | ------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` *(required)* | string | A name for this preset, e.g. `meals-only`. | | `total` | number | Lifetime spend cap, in US dollars. | | `per_day` | number | Spend cap per rolling 24 hours, in US dollars. | | `per_week` | number | Spend cap per rolling 7 days, in US dollars. | | `per_month` | number | Spend cap per rolling 30 days, in US dollars. | | `categories` | string | Comma-separated spend categories to allow, e.g. `meals,groceries` (`meals`, `groceries`, `travel`, `software`, `ai`, `wellness`, `retail`). | | `only_merchants` | string | Comma-separated merchant name patterns to allow, e.g. `openai,anthropic`. | | `only_in` | string | Comma-separated places to allow charges from, e.g. `US,California` (a country or a US state). | | `currencies` | string | The currencies the card may pay in, comma-separated, as codes or plain names in any case: `usd,eur` or `dollars,euros`. A charge in any other currency is refused and the user is told. A name that means several currencies, such as `pesos`, is refused when you save. Agentcard checks this rule; the card network does not. | | `only_days` | string | Comma-separated days to allow, e.g. `mon,tue,wed` or `weekdays`/`weekends`. | | `only_hours` | string | An hour range to allow, e.g. `9-17` (24-hour clock; defaults to UTC without timezone). | | `timezone` | string | IANA timezone for only\_days/only\_hours (default UTC), e.g. `America/Los_Angeles`. Always shown in summaries. Unknown zones are refused. | | `only_from` | string | Comma-separated callers to allow, e.g. `cli,mcp` (`cli`, `mcp`, `api`, `browser`). | | `mode` | string | What the preset does when a purchase breaks any of its rules: `strict` refuses it (the default), `watch` lets it through and tells the user once. | | `privileges` | array | Advanced: raw privilege objects instead of the rule fields above. | ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------------------------- | | `message` *(required)* | string | Human-readable result or guidance for the next step. | | `preset` | object | The saved preset: `id`, `name`, `version`, `summary`. | ## Example call ```json theme={null} { "tool": "save_preset", "arguments": { "name": "office-supplies", "per_day": 25, "categories": "meals" } } ``` A preset that keeps purchases in dollars or euros. Codes or names, any case; the summary reads `Currency: USD, EUR`: ```json theme={null} { "tool": "save_preset", "arguments": { "name": "euro-zone", "currencies": "usd, euros" } } ``` ## Example error An unknown category, captured from a local sandbox. `isError` is set and `structuredContent.status` carries the code: ```json theme={null} { "content": [ { "type": "text", "text": "Unknown category \"crypto\". Use meals, groceries, travel, software, ai, wellness, or retail." } ], "structuredContent": { "message": "Unknown category \"crypto\". Use meals, groceries, travel, software, ai, wellness, or retail.", "status": "policy_invalid" }, "isError": true } ``` A currency Agentcard cannot read answers the same way. `save_preset` with `"currencies": "pesos"`, captured from a local run: ```json theme={null} { "content": [ { "type": "text", "text": "\"pesos\" could be MXN, ARS, CLP, COP, or PHP. Write the currency code, or name the country (Mexican pesos)." } ], "structuredContent": { "message": "\"pesos\" could be MXN, ARS, CLP, COP, or PHP. Write the currency code, or name the country (Mexican pesos).", "status": "policy_invalid" }, "isError": true } ``` # send_support_message Source: https://docs.agentcard.sh/tools/mcp/user/send_support_message Send a message in an existing support conversation Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Send a message in an existing support conversation ## Inputs | Field | Type | Description | | ------------------------------ | ------ | ------------------- | | `conversation_id` *(required)* | string | The conversation ID | | `message` *(required)* | string | Your message | ## Returns | Field | Type | Description | | ---------------------- | ------ | ------------------------------------------------------ | | `message` *(required)* | string | Human-readable confirmation that the message was sent. | | `conversationId` | string | The ID of the conversation the message was sent to. | ## Example call ```json theme={null} { "tool": "send_support_message", "arguments": { "conversation_id": "\u2026", "message": "\u2026" } } ``` # set_card_preset Source: https://docs.agentcard.sh/tools/mcp/user/set_card_preset Put rules on a card. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Put rules on a card. Pass a built-in name, `ai_labs`, `weekday_meals`, `cli_only`, or `daily`; a saved name from list\_presets; a comma-separated list of built-ins; or inline JSON privileges as `{ name?, privileges }`. Pass null or "" with `card_id` to clear a card's rules: Agentcard stops checking that card, and a spending limit the card network already holds stays. For a card, the response says what applies from now on, whether the card's spending limit changed, and whether the change needs a new card. The rules are explained in [Set rules on a card](/issuing/set-rules-on-a-card). Over a connected app's own credential this returns `read_only`. Presets are the owner's rules on the app, so the app cannot change them. The app can still read them and remember a merchant with `allow_card_merchant`. ## Inputs | Field | Type | Description | | ---------------------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `card_id` *(required)* | string | The card id (from list\_cards). | | `preset` *(required)* | string · null · object | Template name (`ai_labs`, `weekday_meals`, `cli_only`, `daily`), comma-separated templates, a saved name, inline JSON privileges, or `{ name?, privileges }`. Pass null or "" to clear the card's preset. Any category accepts `"enforcement": "watch"` inside a `category` privilege. A currency rule is `{ "kind": "currency", "currencies": ["USD", "EUR"] }`, codes or common names in any case, with `"mode": "watch"` on the object to watch instead of refuse; Agentcard enforces it and the card network does not. | ## Returns | Field | Type | Description | | ---------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable result or guidance for the next step. | | `preset` | object | Preset summary, or null when unrestricted: `id`, `name` (null for an anonymous preset), `version`, and a plain-English `summary` of the rules, remembered merchants included. | | `policyId` | string | Card edits only: the id of the new preset version now bound to the card. | | `policyVersion` | number | Card edits only: the new version number. | | `summary` | string | Card edits only: plain-English summary of the rules now in force. | | `pushed` | array | Card edits only: rule kinds that were also updated on the card network (for example the spend limit). | | `agentcardOnly` | array | Card edits only: rule kinds enforced on Agentcard only; the network limit was not changed. | | `needsNewCard` | boolean | Card edits only: true when the change cannot be applied to this card and a new card is needed. | | `messages` | array | Card edits only: plain-English honesty notes about what landed where. | ## Example call ```json theme={null} { "tool": "set_card_preset", "arguments": { "card_id": "…", "preset": "office-supplies" } } ``` # set_default_payment_method Source: https://docs.agentcard.sh/tools/mcp/user/set_default_payment_method Set which saved payment method is the default charged for flight bookings. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Set which saved payment method is the default charged for flight bookings. Use list\_payment\_methods to find the payment\_method\_id. ## Inputs | Field | Type | Description | | -------------------------------- | ------ | -------------------------------------------------------- | | `payment_method_id` *(required)* | string | The payment method ID to make the default (e.g. pm\_xxx) | ## Returns | Field | Type | Description | | ---------------------- | --------------------- | -------------------------------------------------------- | | `message` *(required)* | string | Human-readable summary of the result. | | `paymentMethodId` | string | The payment method ID now set as default (e.g. pm\_xxx). | | `status` | string: `set_default` | Outcome of the operation. | ## Example call ```json theme={null} { "tool": "set_default_payment_method", "arguments": { "payment_method_id": "\u2026" } } ``` # setup_payment_method Source: https://docs.agentcard.sh/tools/mcp/user/setup_payment_method Save a payment method used ONLY to pay for flight bookings (the fare is charged to it via a hold at booking; no virtual card is created for flights). Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Save a payment method used ONLY to pay for flight bookings (the fare is charged to it via a hold at booking; no virtual card is created for flights). It does NOT fund cards or the cash balance — cards are funded from the balance (see add\_funds). Returns a secure checkout URL the user must open to save their card details. ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | ------ | --------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable summary of the result. | | `checkoutUrl` | string | Secure Stripe checkout URL the user must open to save their payment method. | | `stripeSessionId` | string | Identifier of the Stripe Checkout session created for the setup. | ## Example call ```json theme={null} { "tool": "setup_payment_method", "arguments": {} } ``` # start_kyc Source: https://docs.agentcard.sh/tools/mcp/user/start_kyc Begin (or resume) identity verification. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. ## What it does Begin (or resume) identity verification. Verification is CONVERSATIONAL: it starts with a photo of the user's government ID — the backend reads the printed details automatically and the user confirms every value. Only fields the ID does not carry are asked (like the SSN for US documents, or the national ID number for non-US ones); occupation/income questions are never asked. The only browser step is a short face scan at the end. Relay each step to the user as ONE SHORT message (one or two sentences — the current ask only, never the whole flow, never an unrequested link). Returns the next step, ID-photo upload options, and (for legacy hosted-flow accounts) a hosted verification URL instead. ## Inputs | Field | Type | Description | | --------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `terms_accepted` | boolean | DEPRECATED — use agreements\_accepted. Pass true once the user has explicitly agreed to the card issuer's cardholder terms in the conversation. | | `agreements_accepted` | array | Keys of the User Agreements the user explicitly accepted, one by one (the full required set from the agreements list — e.g. e\_sign, account\_opening\_privacy, card\_terms, accuracy, non\_solicitation). Only pass after presenting each agreement verbatim and getting a yes covering all of them. | ## Returns | Field | Type | Description | | ---------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable summary / next step. | | `status` | string | "started", "verified", "rejected", or "unknown". | | `nextStep` | string/null | Conversational step: id\_document \| fields \| terms \| face\_verification \| review\_pending \| verified \| rejected. | | `missingFields` | array | Fields still needed from the user. | | `uploadUrl` | string | Browser upload page for the ID photo (1h validity). | | `verificationUrl` | string | Face-scan page (conversational flow) or hosted verification URL (legacy flow), 48h validity. | | `reason` | string/null | Provider reason on rejection. | ## Example call ```json theme={null} { "tool": "start_kyc", "arguments": {} } ``` # start_phone_verification Source: https://docs.agentcard.sh/tools/mcp/user/start_phone_verification Send (or re-send) the user's one-time funding verification code (the provider verifies the phone on the user's Agentcard identity, valid 60 days). Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Send (or re-send) the user's one-time funding verification code (the provider verifies the phone on the user's Agentcard identity, valid 60 days). add\_funds already sends this code automatically when verification is needed — call this tool only to RE-send when the code never arrived (any unexpired code still works; sends are rate-limited). Returns the masked destination (text or email) and whether a code was sent; if the phone is already verified it says so and you go straight to add\_funds. After the user reads back the code, call verify\_phone. ## Inputs None. ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------- | | `message` *(required)* | string | Human-readable result or next step. | ## Example call ```json theme={null} { "tool": "start_phone_verification", "arguments": {} } ``` # start_support_chat Source: https://docs.agentcard.sh/tools/mcp/user/start_support_chat Start a new support conversation and send the first message Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. ## What it does Start a new support conversation and send the first message ## Inputs | Field | Type | Description | | ---------------------- | ------ | ---------------------------- | | `message` *(required)* | string | Your initial support message | ## Returns | Field | Type | Description | | ---------------------- | ------ | ------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable summary confirming the conversation was started. | | `conversationId` | string | The ID of the newly created support conversation. Pass this to send\_support\_message or read\_support\_chat. | ## Example call ```json theme={null} { "tool": "start_support_chat", "arguments": { "message": "\u2026" } } ``` # submit_funding_profile Source: https://docs.agentcard.sh/tools/mcp/user/submit_funding_profile Save the user's one-time funding profile — five multiple-choice compliance answers (employment status, source of funds, industry, income band, expected yearly… Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Save the user's one-time funding profile — five multiple-choice compliance answers (employment status, source of funds, industry, income band, expected yearly funding volume). With a profile on file, wallet funding checkouts can skip the payment provider's own identity questionnaire (the user's existing KYC is reused). Ask the user each question conversationally and submit their answers; this is NOT a re-verification and no documents are involved. Answers can be updated any time by calling this again. ## Inputs | Field | Type | Description | | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `employment_status` *(required)* | string: `full-time` · `part-time` · `contractual` · `self-employed` · `student` · `retired` · `unemployed` | The user's employment status. | | `source_of_funds` *(required)* | string: `salary-disbursement` · `business-dividends-profits` · `investment-returns` · `property-sale` · `inheritance-distribution` · `savings-personal-funds` · `loan-disbursement` · `government-benefits` | Where the money they fund with primarily comes from. | | `industry` *(required)* | string: `accommodation-food-services` · `administrative-support-waste-management-remediation-services` · `adult-entertainment` · `agriculture-forestry-fishing-hunting` · `arts-entertainment-recreation` · `auctions` · `automobiles` · `professional-scientific-technical-services` · `blockchain` · `construction` · `crypto` · `e-commerce` · `educational-services` · `export-import` · `financial-institution` · `gambling` · `health-care-social-assistance` · `hedge-fund` · `insurance` · `registered-investment-advisor` · `investment` · `management-of-companies-enterprises` · `manufacturing` · `market-maker` · `mining` · `money-service-business` · `non-profit` · `drugs` · `precious-metals` · `public-administration` · `real-estate-rental-leasing` · `retail-trade` · `shell-bank` · `sto-issuer` · `information` · `transportation-warehousing` · `travel-transport` · `utilities` · `weapons` · `wholesale-trade` · `other-services` | The industry the user works in (pick the closest; 'other-services' when nothing fits). | | `estimated_yearly_income` *(required)* | string: `income-0-50k` · `income-50k-100k` · `income-100k-250k` · `income-250k-500k` · `income-500k-750k` · `income-750k-1mil` · `income-above-1mil` | Estimated yearly income band (USD). | | `expected_yearly_volume` | string: `volume-0-25k` · `volume-25k-75k` · `volume-75k-150k` · `volume-above-150k` | How much they expect to fund per year (USD). Defaults to the lowest band when omitted. | | `accepts_crossmint_privacy` | boolean | Set true ONLY after showing the user this line: "By continuing you agree to Crossmint's privacy policy (crossmint.com/legal/privacy-policy)." It lets the profile be registered with the funding provider immediately, so the user's next funding attempt skips the review wait. Omit if the disclosure was not shown — funding then handles it at checkout time. | ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------- | | `message` *(required)* | string | Human-readable result or next step. | ## Example call ```json theme={null} { "tool": "submit_funding_profile", "arguments": { "employment_status": "\u2026", "source_of_funds": "\u2026", "industry": "\u2026", "estimated_yearly_income": "\u2026" } } ``` # submit_kyc_document Source: https://docs.agentcard.sh/tools/mcp/user/submit_kyc_document Submit the user's ID photo for identity verification. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Submit the user's ID photo for identity verification. Ways in: (a) image data you hold programmatically (e.g. the user sent the photo in this chat and your platform exposes its bytes) — pass front\_base64 (and back\_base64 for a license back; its barcode reads most accurately); (b) local (stdio) mode — pass file\_path/back\_file\_path and the file is read from disk; (c) neither — you get a secure upload link to hand the user. Do NOT ask the user what kind of document it is or where it was issued — the type and country are detected automatically from the photo; only relay a question if the result says the type could not be determined. Returns the fields read off the document — SHOW THEM TO THE USER for confirmation before continuing — plus whatever is still missing. If the result says NO identity details could be read, the image did not read as an ID at all: never insist to the user that it was their ID. Supported: JPEG/PNG/WebP up to 12MB (convert iPhone HEIC first). ## Inputs | Field | Type | Description | | ----------------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `front_base64` | string | Base64 image bytes of the ID front (or passport photo page). ONLY pass base64 you received programmatically from your platform (e.g. an injected chat attachment) — never type or reconstruct image bytes yourself. | | `back_base64` | string | Base64 image bytes of the license back (optional, recommended — the barcode reads most accurately). Same rule: programmatically sourced only. | | `front_mime_type` | string | MIME type of front\_base64 (image/jpeg, image/png, image/webp). Defaults to image/jpeg. | | `back_mime_type` | string | MIME type of back\_base64. Defaults to image/jpeg. | | `file_path` | string | Local path to the ID photo (front of license, or passport photo page). Local/stdio connections only — remote connections without image data receive an upload link instead. | | `back_file_path` | string | Local path to the back of the license (optional, recommended). Local/stdio connections only. | | `document_type` | string: `drivers_license` · `state_id` · `passport` | ONLY pass this when the user themselves said what the document is ("here's my license") — otherwise omit it; the type is detected from the photo. Never ask up front. | | `issuing_country` | string | 2-letter ISO country that issued the document (e.g. US, AR). ONLY when the user volunteered it — otherwise omit; it is detected from the photo. Never ask up front. | ## Returns | Field | Type | Description | | ---------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | | | `status` | string | processed \| document\_expired \| upload\_failed \| upload\_link\_provided | | `extracted` | object | Fields read from the document (confirm with the user). | | `unreadable` | boolean | True when the image was received but NO identity fields could be read from it — it did not read as an ID; never assert to the user that it was one. | | `missingFields` | array | | | `nextStep` | string/null | | | `uploadUrl` | string | | | `verificationUrl` | string | | ## Example call ```json theme={null} { "tool": "submit_kyc_document", "arguments": {} } ``` # submit_kyc_fields Source: https://docs.agentcard.sh/tools/mcp/user/submit_kyc_fields Submit identity fields for verification: the ones the ID photo didn't carry (listed by missingFields — the tax/ID number always has to be asked since IDs don't… Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Submit identity fields for verification: the ones the ID photo didn't carry (listed by missingFields — the tax/ID number always has to be asked since IDs don't print it; call it "SSN" only for US documents and "national ID number" otherwise), corrections to extracted values the user flagged, and the User Agreements acceptance (agreements\_accepted, after presenting each agreement verbatim). That number is forwarded directly to the verification provider and never stored by Agentcard. NEVER ask about occupation, income, spending volume, or account purpose — those are filled automatically and must not be asked. ## Inputs | Field | Type | Description | | ---------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `first_name` | string | Legal first name, exactly as printed on the ID document. | | `last_name` | string | Legal last name, exactly as printed on the ID document. | | `date_of_birth` | string | YYYY-MM-DD | | `ssn` | string | US documents: 9-digit SSN, dashes optional. Non-US documents: the national ID / tax number printed on the ID. Forward-only — never stored. | | `address_line1` | string | Residential street address, line 1 (e.g. 123 Main St). | | `address_line2` | string | Residential street address, line 2 — apartment, suite, or unit. Omit if none. | | `address_city` | string | City of the residential address. | | `address_region` | string | 2-letter state code for US (e.g. CA). | | `address_postal_code` | string | Postal / ZIP code of the residential address. | | `address_country_code` | string | 2-letter ISO country code (e.g. US). | | `phone_number` | string | E.164 with country code, e.g. +14155551234. | | `terms_accepted` | boolean | DEPRECATED — use agreements\_accepted. true once the user explicitly accepted the card issuer's cardholder terms. | | `agreements_accepted` | array | Keys of the User Agreements the user explicitly accepted, one by one — the FULL required set from the agreements list in the previous step's result. Only pass after presenting each agreement verbatim and getting an explicit yes covering all of them. | ## Returns | Field | Type | Description | | ---------------------- | ----------- | ----------------------------------------------------- | | `message` *(required)* | string | | | `nextStep` | string/null | | | `missingFields` | array | | | `verificationUrl` | string | Face-scan link, present once everything is collected. | ## Example call ```json theme={null} { "tool": "submit_kyc_fields", "arguments": {} } ``` # submit_user_info Source: https://docs.agentcard.sh/tools/mcp/user/submit_user_info Submit the user's phone number and terms acceptance for a virtual card. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Submit the user's phone number and terms acceptance for a virtual card. Call this after create\_card returns user\_info\_required. Do NOT ask the user for occupation, income, or account purpose — those are never asked. Identity fields (name, date of birth, SSN / national ID, address) belong to the KYC flow: create\_card tells you whether it runs conversationally (start\_kyc → ID photo → face scan) or via a hosted verification\_url. After phone + terms are saved, retry create\_card. ## Inputs | Field | Type | Description | | ----------------------------- | ------- | ------------------------------------------------------------------------------------------------------------- | | `phone_number` *(required)* | string | User's phone number in international E.164 format with a country code (e.g. +1 555 123 4567, +44 7911 123456) | | `terms_accepted` *(required)* | boolean | Must be true — the user accepted the AgentCard cardholder terms of service | ## Returns | Field | Type | Description | | ---------------------- | ------ | ------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable confirmation that the user information was saved. | | `status` | string | Outcome of the submission: 'saved' when the user information was stored successfully. | ## Example call ```json theme={null} { "tool": "submit_user_info", "arguments": { "phone_number": "\u2026", "terms_accepted": "\u2026" } } ``` # surprise_me Source: https://docs.agentcard.sh/tools/mcp/user/surprise_me Buy the user something totally unexpected and very silly/stupid-fun under a small dollar cap (default $10, hard max $25). Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Buy the user something totally unexpected and very silly/stupid-fun under a small dollar cap (default \$10, hard max \$25). Great when the user cannot decide what to order (from DoorDash etc.) or just wants a fun surprise. It kicks off a shopping conversation that FIRST brainstorms deliberately stupid ideas, picks ONE genuinely unexpected item, builds the cart, and shows the item + exact total. It NEVER checks out by itself: the reply includes a conversation\_id — relay the user's explicit confirmation ("yes, place it") through the `buy` tool on that SAME conversation\_id, exactly like a normal order. Each surprise\_me call starts a fresh surprise; use `buy` for all follow-ups (answers, tweaks, the confirmation). ## Inputs | Field | Type | Description | | ------------- | ------ | --------------------------------------------------------------------------------------------------------- | | `max_dollars` | number | Hard spend cap in dollars, total including fees. Optional; default 10, values above 25 are clamped to 25. | | `merchant` | string | Optional merchant hint the surprise should come from, e.g. 'doordash'. Omit to let the agent pick. | | `vibe` | string | Optional notes/vibe from the user, e.g. "make it food", "something for my desk", "they love ducks". | ## Returns | Field | Type | Description | | ---------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | The assistant's conversational turn (it may ask for the delivery address, show the cart + total, confirm, or report a placed order), or an error explanation. | | `status` | string: `assistant_turn` · `conversation_start_failed` · `request_failed` | Discriminator for the outcome. 'assistant\_turn' when the buy loop replied; 'conversation\_start\_failed' or 'request\_failed' on errors. | | `conversation_id` | string | The conversation id to thread back as conversation\_id on the next buy call to continue the SAME order. Present on a successful assistant turn. | | `messages` | array | The same turn split into ordered messages for multi-bubble surfaces (each narration segment, then the final reply/confirmation). `message` is the same content consolidated; clients that show one bubble should use `message` and ignore this. | ## Example call ```json theme={null} { "tool": "surprise_me", "arguments": {} } ``` # update_card_limit Source: https://docs.agentcard.sh/tools/mcp/user/update_card_limit Change a multi-use card's total spending limit. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. ## What it does Change a multi-use card's total spending limit. Raising it reserves the extra amount from the user's cash balance (top up with add\_funds if short); lowering it frees the difference, but the new limit can never go below what the card has already spent. Single-use cards cannot be resized. ## Inputs | Field | Type | Description | | ---------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `card_id` *(required)* | string | The multi-use card ID to resize. | | `approval_id` | string | Approval id from a prior approval\_required response, once the user has approved. Only for cards created through ANOTHER app: first call without it (the user is emailed an approve link), then retry with it. | | `spend_limit_cents` | number | The new TOTAL spending limit in cents (minimum 100). This is the lifetime cap, not a delta: a card that spent \$20 of a \$50 limit, resized to 8000, can spend \$60 more. | | `new_limit_cents` | number | Deprecated alias for spend\_limit\_cents. Prefer spend\_limit\_cents (matches the docs and the REST API). | ## Returns | Field | Type | Description | | ---------------------- | ------ | ---------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable result. | | `status` | string | "updated" on success; an error discriminator otherwise (e.g. "limit\_below\_spent", "insufficient\_collateral"). | | `cardId` | string | The card ID. | | `spendLimitCents` | number | The new total limit in cents. | | `balanceCents` | number | The remaining spendable balance in cents. | ## Example call ```json theme={null} { "tool": "update_card_limit", "arguments": { "card_id": "\u2026" } } ``` # update_settings Source: https://docs.agentcard.sh/tools/mcp/user/update_settings Update the user's email notification preferences, their default delivery address (the wallet-level shipping address agents use when buying physical goods for t… Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** idempotent. <Note>Not in the default `tools/list`. It is still callable by exact name, and appears when the client sends the `x-expert-tools: 1` header.</Note> ## What it does Update the user's email notification preferences, their default delivery address (the wallet-level shipping address agents use when buying physical goods for them), and/or their default payment source (which card or balance agents charge). Pass only the fields to change. Confirm a new delivery address or default payment with the user before saving it. Authorization (approval) settings cannot be changed here — they are managed in the dashboard. ## Inputs | Field | Type | Description | | ----------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `card_details_accessed` | boolean | Email when a card's full details (PAN/CVV) are accessed. | | `card_created` | boolean | Email when a new card is created. | | `transaction` | boolean | Email on each card transaction. | | `card_closed` | boolean | Email when a card is closed. | | `low_balance` | boolean | Email when a card balance drops below the low-balance threshold. | | `support_activity` | boolean | Copy the user on support-chat activity: messages sent to Agentcard support on their behalf and replies from support (email, or a text message when they have no email). | | `low_balance_threshold_cents` | number | Low-balance alert threshold in cents (e.g. 500 = \$5.00). | | `delivery_address` | object | Set the default delivery address (full replace — pass every field each time). Confirm it with the user first. | | `clear_delivery_address` | boolean | true = remove the saved default delivery address. Do not combine with delivery\_address. | | `default_payment` | object | Set the wallet-level default payment source agents charge. \{ source: 'balance' } = always create single-use cards from the wallet; \{ source: 'connected', connected\_card\_id } = always charge that added card (ids from list\_added\_cards). Confirm with the user first. | | `clear_default_payment` | boolean | true = back to auto (an active added card wins, else the balance). Do not combine with default\_payment. | ## Returns | Field | Type | Description | | ---------------------- | ----------- | ------------------------------------------------------------------ | | `message` *(required)* | string | Human-readable summary of the updated settings. | | `status` | string | Result status: "ok", or "noop" when no fields were provided. | | `notifications` | object | The updated email notification preferences. | | `authorization` | object | Authorization (approval) settings — read-only. | | `delivery_address` | object/null | The saved default delivery address after the update, or null. | | `default_payment` | object/null | The saved default payment source after the update, or null (auto). | ## Example call ```json theme={null} { "tool": "update_settings", "arguments": {} } ``` # upgrade_plan Source: https://docs.agentcard.sh/tools/mcp/user/upgrade_plan Start a paid-plan upgrade. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Start a paid-plan upgrade. Choose the target plan: 'basic' (\$15/mo — 15 cards/month, up to \$500 per card) or 'pro' (\$100/mo — 50 cards/month, up to \$1,000 per card). Defaults to 'basic' if omitted. Returns a Stripe Checkout URL the user must open in their browser to complete payment. After they finish checkout, the plan updates automatically; verify with get\_plan. Use only when the user explicitly wants to upgrade. To cancel a paid plan instead, the gated tool cancel\_plan also exists; call it by name even though it isn't in the tools list. ## Inputs | Field | Type | Description | | ------ | ----------------------- | ---------------------------------------------- | | `plan` | string: `basic` · `pro` | Which plan to upgrade to. Defaults to 'basic'. | ## Returns | Field | Type | Description | | ---------------------- | -------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable summary of the upgrade outcome. | | `status` | string: `swapped` · `checkout_required` · `already_on_plan` · `waitlisted` · `unavailable` · `checkout_failed` | Discriminator for the outcome branch. | | `plan` | string | Display label of the target plan, e.g. 'Basic' or 'Pro'. Present when the requested plan is known. | | `checkoutUrl` | string | Stripe Checkout URL the user must open to complete payment. Present only when status is checkout\_required. | ## Example call ```json theme={null} { "tool": "upgrade_plan", "arguments": {} } ``` # verify_phone Source: https://docs.agentcard.sh/tools/mcp/user/verify_phone Check the one-time code the user received from start_phone_verification. Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Check the one-time code the user received from start\_phone\_verification. On success the balance is unlocked for funding (the verification stays fresh for 60 days) — call add\_funds next. A wrong or expired code returns a recoverable status so you can ask the user to re-check it, or call start\_phone\_verification to resend. ## Inputs | Field | Type | Description | | ------------------- | ------ | ------------------------------------------------------------------------------------------------------- | | `code` *(required)* | string | The one-time code the user received, as a string (keep any leading zeros — do not send it as a number). | ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------- | | `message` *(required)* | string | Human-readable result or next step. | ## Example call ```json theme={null} { "tool": "verify_phone", "arguments": { "code": "\u2026" } } ``` # whoami Source: https://docs.agentcard.sh/tools/mcp/user/whoami Show who you are operating as: the authenticated AgentCard account's email, user id, name, plan, KYC + account status, member-since date, and how this session… Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). **Behavior:** read-only, idempotent. ## What it does Show who you are operating as: the authenticated AgentCard account's email, user id, name, plan, KYC + account status, member-since date, and how this session is connected (personal login vs a third-party OAuth app connection, with the app name). Call this when the user asks "who am I" / "which account is this", or before money-moving actions when you need to confirm the account. Read-only. KYC shown here is the stored snapshot — use get\_kyc\_status when you need the live, provider-checked state. ## Inputs None. ## Returns | Field | Type | Description | | -------------------------- | --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `message` *(required)* | string | Human-readable identity summary. | | `email` | string/null | Email of the authenticated account, or null for a phone-first account (e.g. signed up by text message). | | `userId` | string | AgentCard user id of the authenticated account. | | `name` | string/null | Cardholder name ("First Last"), or null before KYC info is submitted. | | `plan` | string | Subscription plan id, e.g. 'free', 'basic', or 'pro'. | | `subscriptionStatus` | string/null | Stripe subscription status (e.g. 'active', 'past\_due'), or null on the free plan. | | `accountStatus` | string | Account standing: 'active' or 'suspended'. | | `kycVerified` | boolean | Whether identity verification (KYC) has passed (stored snapshot). | | `kycStatus` | string/null | Raw stored KYC state (e.g. approved, pending, requires\_input), or null if never started. | | `memberSince` | string | ISO timestamp the account was created. | | `connectionType` | string: `oauth` · `personal` · `organization` | How this session authenticates: 'oauth' (third-party app connection), 'personal' (CLI/dashboard login), or 'organization' (a company's Agentcard integration acting for its end user). | | `connectionClientId` | string/null | OAuth client id of the connected app, when connectionType is oauth. | | `connectionClientName` | string/null | Display name of the connected OAuth app (e.g. "Claude"), when known. | | `connectionOrganizationId` | string/null | Organization id, when connectionType is organization. | ## Example call ```json theme={null} { "tool": "whoami", "arguments": {} } ``` # withdraw Source: https://docs.agentcard.sh/tools/mcp/user/withdraw Withdraw cash from the user's balance, either to their saved bank account or to a crypto address on Base (USDC). Connect to `https://mcp.agentcard.sh/mcp` with the **user's connection token** (or a `buy_token` for org-owned accounts). ## What it does Withdraw cash from the user's balance, either to their saved bank account or to a crypto address on Base (USDC). Transfers are processed manually by the Agentcard team, usually within 1-3 business days; the user is emailed when it's sent. For a bank withdrawal, if the user has no saved bank account yet, call create\_withdrawal\_recipient first. For a crypto withdrawal, pass destination\_address (a 0x Base address). ALWAYS confirm the amount and destination with the user before calling this. ## Inputs | Field | Type | Description | | --------------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------- | | `amount_cents` *(required)* | number | Amount to withdraw in cents (e.g. 2500 = \$25.00). Range: \$2.00 to \$10,000.00. | | `recipient_id` | string | Bank rail: the saved bank account to pay (wrec\_...). Omit to be shown the saved accounts. | | `destination_address` | string | Crypto rail: a 0x-prefixed address on Base to receive USDC. When set, the withdrawal goes on-chain instead of to a bank account. | ## Returns | Field | Type | Description | | ---------------------- | ------ | ----------------------------------------------- | | `message` *(required)* | string | Human-readable result or next step. | | `withdrawalId` | string | Reference id of the created withdrawal request. | | `amountUsd` | string | Requested amount in USD. | ## Example call ```json theme={null} { "tool": "withdraw", "arguments": { "amount_cents": "\u2026" } } ``` # Adding a card to the Vault Source: https://docs.agentcard.sh/vault/adding-a-card Create a vault session, send the user one link, and get back a user id you can charge against. A user adds a card to the Vault once. After that, any agent you run can pay with it, and the user only needs to approve each purchase. You don't build a card form. Instead, you create a **vault session**, send the user its link, and Agentcard handles the rest: the page, the passkey, and the encryption. The page carries your branding. Set a display name and upload a logo in the dashboard under **Settings → General → Branding**, and every link you mint shows them in the header and tab title. The address, the passkey, and the "Powered by Agentcard" footer stay Agentcard's; for a fully dedicated domain, [talk to us](mailto:karen@agentcard.sh). ## Create a vault session ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v2/vault_sessions \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{}' ``` ```json theme={null} { "object": "vault_session", "id": "vs_2q9d1x8f3k2m4t7w", "user_id": null, "url": "https://vault.agentcard.sh/v?vs=vs_2q9d1x8f3k2m4t7w.3k1v…", "expires_at": "2026-08-28T21:00:00Z", "poll_interval": 3, "test_mode": false } ``` <ParamField type="string"> Omit this for a new user. The session is **open**: Agentcard creates the user during enrollment and returns their id. If you pass an id you already have, the session is **connected**: opening the link sends a one-time code to the contact on that account, and verifying it signs the user in. </ParamField> <ParamField type="number"> Lifetime in seconds (60 to 172,800). Defaults to 24 hours. Each session is single use. </ParamField> `$ORG_TOKEN` must be a client-credentials access token. API keys are rejected with `400 client_credentials_required`. Open sessions are limited to 200 per organization per rolling 24 hours. ## Send the link Deliver `url` to the user in the thread or app you already use with them. Each link is for a single enrollment, so send it to one person and associate the resulting `user_id` with whoever you sent it to. What the user sees: a page where they enter their card details and save. A passkey and a master password lock the card, with fingerprint or face unlock on Android and Face ID or Touch ID on iPhone and Mac, and the card is encrypted on their device before it's stored. No account to create first, and no code to enter. **Returning users** choose "Unlock with your passkey" instead of entering a card. The passkey signs them in, and the session links to their existing account. ## Learn when the card is stored You have two options. ### Option A: webhooks (recommended) | Event | When | | ---------------------- | ---------------------------------------------------------------- | | `vault.session_linked` | The session got its user. Carries the `user_id` to store. | | `vault.card_stored` | A card landed in the vault. Carries `card_id`, `brand`, `last4`. | ```json vault.session_linked theme={null} { "type": "vault.session_linked", "data": { "vault_session_id": "vs_2q9d1x8f3k2m4t7w", "user_id": "usr_8f3k2m" } } ``` A connected session already named its user, so it does not send `vault.session_linked`. It still sends `vault.card_stored`. ### Option B: poll the session For a CLI or an agent with no public endpoint, read the session until it finishes. Use the `id` from the create response, never the token inside `url`. ```bash theme={null} curl https://api.agentcard.sh/api/v2/vault_sessions/vs_2q9d1x8f3k2m4t7w \ -H "Authorization: Bearer $ORG_TOKEN" ``` | `status` | Meaning | What to do | | --------- | ------------------------------ | ----------------------------------------- | | `pending` | The user has not finished yet. | Wait `poll_interval` seconds, read again. | | `linked` | Done. `user_id` is set. | Store it. Stop polling. | | `expired` | The link died unused. | Create a new session. | Honor `poll_interval` and you will never hit the read budget (40 reads a minute per session). ## Check for an existing card Before sending a returning user through enrollment again, check what they already have: ```bash theme={null} curl "https://api.agentcard.sh/api/v2/vault_cards?user_id=usr_8f3k2m" \ -H "Authorization: Bearer $ORG_TOKEN" ``` Returns display fields only: `id`, `brand`, `last4`, expiry. Never card data. Pass a card's `id` as `cardId` on a checkout when the user should pay with a specific card. ## Test mode A sandbox token creates a sandbox session. The passkey ceremony is real in the browser, and the user it creates is a sandbox user. On a connected session no code is delivered; `111111` verifies. Store a test card, any of [Stripe's published test cards](https://docs.stripe.com/testing), so the purchase flow works against test-mode storefronts. # Completing a purchase Source: https://docs.agentcard.sh/vault/completing-a-purchase The agent submits a placeholder card, the user approves with their passkey, the real card pays, and you confirm the order. Once the SDK is attached and the cart is built, the purchase is four moments: submit, approve, pay, confirm. ## 1. The agent submits a placeholder card Have your agent fill the checkout form with placeholder card data and submit it: any of [Stripe's published test cards](https://docs.stripe.com/testing), any future expiry, any CVC. The real card never enters the browser. When the page sends that card to a recognized payment processor, the SDK intercepts the request and pauses it. `onApprovalUrl` fires with an approval link. ## 2. The user approves with their passkey Send the approval link to the user. They open it on their own device, see the merchant and the amount you passed, and confirm with fingerprint or face unlock on Android, Face ID or Touch ID on iPhone and Mac, or their master password. Their passkey decrypts the vaulted card on the device. The user can also decline. Nobody approving within 15 minutes expires the authorization. ## 3. The user's device pays The device sends the real card to the payment processor directly and reports the processor's response back. The SDK replays that response into the paused request, and your browser continues as if it had sent the real card itself. Your agent never sees the card number, and neither does Agentcard. Your agent stays in control of the browser. If the merchant asks for a bank challenge or a redirect, surface it to the user. ## 4. Confirm the order Approval is not a purchase. Read the merchant's order result before you tell the user anything or run post-payment steps. ```ts theme={null} const checkout = await attachToPlaywright(page, { // ...as in Creating a cart requireMerchantResult: true, resolveMerchantResult: (state) => readMerchantOrder(page, state), }); await runAgentCheckout(page); const result = await checkout.reconcile(); switch (result.status) { case 'completed': await notifyUser(`Order ${result.orderId} confirmed`); break; case 'pending': case 'unknown': case 'requires_user_action': await keepBrowserForFollowUp(page, result); // don't retry the payment break; case 'failed': await notifyUser('The merchant did not complete the order'); break; } ``` `resolveMerchantResult` is yours: read the confirmation page, an order id, or the merchant's API. A missing receipt is not proof of failure, so never retry a payment automatically. Retry only after the merchant confirms it failed. ## Webhooks Your server learns the outcome through the same signed webhooks as every other Agentcard event. | Event | Fires when | | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `checkout_authorization.approved` | The user approved with their passkey. Carries what the processor said it charged (`charged_amount`, `charged_kind`, `amount_verified`). | | `checkout_authorization.declined` | The user said no, the amount changed before the card was sent, one of your presets refused it right before the card was sent, or the processor refused the card (`reason`, `psp_error_code`). | | `checkout_authorization.expired` | Nobody approved within 15 minutes. | | `checkout_authorization.refused` | One of your presets refused the purchase before anyone was asked. No authorization exists. | | `checkout_authorization.watched` | The purchase went through and broke a rule one of your presets watches. Nothing is blocked. | ```json checkout_authorization.approved theme={null} { "type": "checkout_authorization.approved", "data": { "authorization_id": "cauth_2q9d1x8f3k2m4t7w", "user_id": "usr_8f3k2m", "merchant": "shop.example.com", "amount": 2306, "currency": "usd", "amount_display": "$23.06", "psp": "stripe", "amount_verified": true, "charged_amount": 2306, "charged_kind": "captured" } } ``` None of these confirms a merchant order. Only the merchant does. ## Set rules on a card Presets are optional rules for Vault purchases: a spend cap, a merchant list, a currency, a time window. Nothing is filtered until you attach one to one of a user's cards; then a purchase outside the rules is refused before anyone is asked to approve it, and again right before the card is sent, and you are told each time. See [Set rules on a card](/vault/set-rules-on-a-card). ## Amount protection The processor's own amount is the authority: Agentcard reads it from the paused payment request where the processor puts it there (Tranzila, Razorpay, Nuvei, Paysafe, Adyen), or from the Stripe intent the request names, right before the device sends the card. Caps use the amount the processor charges. Send `amount` to have a purchase judged the moment your agent opens it. A hint more than one smallest unit away from the processor's amount declines the authorization before the card is sent, and nothing is charged. A charge that differs after the fact is recorded and reported on the `approved` webhook as `amount_verified: false`. Every authorization and every webhook carries `amount` (an integer in the currency's smallest unit), `currency`, `amount_display` (the human form, `$23.06`), and `amount_authority`: `processor`, `agent`, `page`, or `none`. On a processor whose request names no amount, your `amount` is the authority, and a purchase with none at all is refused only when a preset caps spending (`amount_unknown`). ## Supported processors | | | | -------------------------- | ------------------------------------------------------------------------- | | **Global** | Stripe · Shopify · Square · Recurly · Razorpay | | **Client-side encryption** | Adyen (the card is encrypted on the device with the merchant's Adyen key) | | **Hosted form** | Tranzila (the device submits Tranzila's own form) | The live list is `GET /v2/checkout/recognizers`. `syncRegistry()` reads it on every run, so new processors reach your agents without an SDK update. Validate each merchant you care about end to end before launch: reaching a recognized processor is not the same as a confirmed order. ## Without the SDK If you run your own interception, make the authorization call yourself with the processor request your automation captured: ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v2/checkout/authorizations \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "user": "usr_8f3k2m", "merchant": "shop.example.com", "amount": 2306, "currency": "usd", "psp": "stripe", "request": { "url": "https://api.stripe.com/v1/tokens", "method": "POST", "headers": { "content-type": "application/x-www-form-urlencoded" }, "body": "card[number]=<card number>&..." } }' ``` The response carries `approvalUrl` to send the user and an `id` to read back with `GET /v2/checkout/authorizations/:id`. When you fulfill the paused request with the approved response, add the CORS headers the page expects (`access-control-allow-origin` echoing the request's `Origin`). The SDK's `withCorsHeaders` helper does this for you. ## Test it Test mode follows your credential. The pause, approval, and replay are identical to live. Rehearse against [shop.agentcard.sh](https://shop.agentcard.sh), a demo store on Stripe test mode: store one of [Stripe's published test cards](https://docs.stripe.com/testing) in the vault, attach the SDK, add a product, submit the placeholder card, approve on the device that holds your passkey, and the order completes. # Creating a cart Source: https://docs.agentcard.sh/vault/creating-a-cart Attach Agentcard to the browser your agent already uses, then let it shop. Your agent builds the cart the way it already does: in a real browser, on the merchant's own website. Agentcard does not change how the agent shops. It attaches to the browser and waits for the moment the checkout form sends the card to the payment processor. There is one rule: **attach before the agent reaches the payment form.** The SDK has to be watching when the page tries to send the card. ## Choose a browser The SDK attaches to any Playwright Chromium page, which means it works with: * **[KERNEL](https://kernel.so)**: connect over `cdp_ws_url`. KERNEL also ships a [native Agentcard integration](https://www.kernel.sh/docs/integrations/payments/agentcard) that needs no SDK. Pick one per checkout. * **[Browserbase](https://www.browserbase.com)**: connect over the session's `connectUrl`. * **Any CDP browser**: supply its CDP URL. Your agent keeps control of the browser during approval and afterward. ## Install ```bash theme={null} npm i @agent-cards/checkout@0.3.0 playwright-core # plus your browser provider, e.g. @onkernel/sdk ``` You need your Agentcard `client_id` and `client_secret` on your server, and the `user_id` of the person whose card will pay (from [Adding a card](/vault/adding-a-card)). ## Attach to the page ```ts theme={null} import { chromium } from 'playwright-core'; import { VaultClient, attachToPlaywright } from '@agent-cards/checkout'; const vault = new VaultClient({ clientId: process.env.AGENTCARD_CLIENT_ID!, clientSecret: process.env.AGENTCARD_CLIENT_SECRET!, }); await vault.syncRegistry(); // pulls the current processor list; safe on every run const browser = await chromium.connectOverCDP(CDP_URL); const context = browser.contexts()[0] ?? (await browser.newContext({ serviceWorkers: 'block' })); const page = context.pages()[0] ?? (await context.newPage()); const checkout = await attachToPlaywright(page, { vault, user: 'usr_8f3k2m', merchant: 'shop.example.com', amount: 2306, currency: 'usd', onApprovalUrl: (url) => sendToUser(url), }); // Now let the agent shop. await page.goto('https://shop.example.com'); await runAgentShopping(page); ``` <ParamField type="string"> The Agentcard user whose vaulted card pays. </ParamField> <ParamField type="string"> Shown on the approval screen. Pass what the user would recognize. </ParamField> <ParamField type="number | string"> Your hint at the amount: an integer in the currency's smallest unit (2306 for \$23.06), or a decimal string in normal units (`"23.06"`). Pass with `currency`. Caps use the amount the processor charges. Send `amount` to have a purchase judged the moment your agent opens it. </ParamField> <ParamField type="string"> ISO 4217 code for `amount`. Required with it. </ParamField> <ParamField type="function"> Called with the approval link the moment the payment pauses. Deliver it to the user in your own thread or app. </ParamField> ## Two things that break attachment * **Service workers.** Use a context with `serviceWorkers: 'block'`. Playwright cannot intercept requests from an already-active service worker, so the SDK refuses to attach to one. * **Attaching too late.** If the agent has already submitted the payment form, there is nothing to pause. Attach right after you get the page, before navigation. ## Don't want a browser? Agentcard's [Purchase API](/vault/integrations/ecommerce-apis/purchase-api) builds the cart and completes the checkout for you on the merchants it covers (Amazon, Walmart, Target, DoorDash, and more). No browser to run, same passkey approval for the user. # Browserbase Source: https://docs.agentcard.sh/vault/integrations/agent-browsers/browserbase Use Agentcard with Browserbase to let your agent make purchases with your users' cards. [Browserbase](https://www.browserbase.com) runs the browser your agent shops in. The Agentcard SDK attaches to it through Playwright over the session's `connectUrl`, the same way it attaches to any CDP browser. You need a user with a card in the Vault first. See [Adding a card](/vault/adding-a-card). ## Install ```bash theme={null} npm i @agent-cards/checkout@0.3.0 @browserbasehq/sdk playwright-core ``` ## Connect and attach ```ts theme={null} import Browserbase from '@browserbasehq/sdk'; import { chromium } from 'playwright-core'; import { VaultClient, attachToPlaywright } from '@agent-cards/checkout'; const bb = new Browserbase({ apiKey: process.env.BROWSERBASE_API_KEY! }); const session = await bb.sessions.create({ projectId: process.env.BROWSERBASE_PROJECT_ID! }); const browser = await chromium.connectOverCDP(session.connectUrl); // Reuse the default context and page so the session recording stays intact. const context = browser.contexts()[0]; const page = context.pages()[0]; const vault = new VaultClient({ clientId: process.env.AGENTCARD_CLIENT_ID!, clientSecret: process.env.AGENTCARD_CLIENT_SECRET!, }); await vault.syncRegistry(); const checkout = await attachToPlaywright(page, { vault, user: 'usr_8f3k2m', merchant: 'shop.example.com', amount: 2306, currency: 'usd', onApprovalUrl: (url) => sendToUser(url), }); // Now let the agent shop. await page.goto('https://shop.example.com'); ``` Attach before the agent reaches the payment form. Browserbase's default context does not block service workers, so if the SDK refuses to attach, create the session's browser context with `serviceWorkers: 'block'` or check the merchant's site for an active service worker. After the run, the session recording is at `https://browserbase.com/sessions/${session.id}`, which is useful for reviewing a checkout that needed a human. ## Next The rest of the flow is identical to any Vault purchase: placeholder card, passkey approval, real card swapped in, confirm with the merchant. Follow the [Vault Quickstart](/vault/quickstart) from step 4, or read [Completing a purchase](/vault/completing-a-purchase). # Kernel Source: https://docs.agentcard.sh/vault/integrations/agent-browsers/kernel Use Agentcard with KERNEL to let your agent make purchases with your users' cards. [KERNEL](https://kernel.so) runs the browser your agent shops in. There are two ways to connect it to the Vault. Pick one per checkout. | | Native integration | Agentcard SDK | | --------------------------- | ------------------------------------- | ------------------------------------------- | | **Who intercepts the card** | KERNEL, at its network edge | Agentcard's SDK, over CDP in Playwright | | **Extra dependency** | None | `@agent-cards/checkout` + `playwright-core` | | **Good for** | Agents built on the KERNEL SDK or MCP | Agents that already drive Playwright | Both need a user with a card in the Vault first. See [Adding a card](/vault/adding-a-card). ## Option A: KERNEL's native integration KERNEL stores an Agentcard wallet in its vault and swaps the card in at checkout itself. Full reference: [KERNEL docs](https://www.kernel.sh/docs/integrations/payments/agentcard). Set `AGENTCARD_MODE` to `sandbox` or `live` to match your credentials. ```ts theme={null} import Kernel from '@onkernel/sdk'; const kernel = new Kernel({ projectID: process.env.KERNEL_PROJECT_ID! }); // 1. One vault per user, one Agentcard wallet inside it. const vault = await kernel.vaults.upsert({ name: 'user-12345' }); const wallet = await kernel.vaults.items.upsert('agentcard-wallet', { id_or_name: vault.id, type: 'wallet', spec: { provider: 'agentcard' }, }); // First time: show wallet's enrollment action to the user, wait for status "connected". // 2. A card item per purchase, with what the user will approve. const card = await kernel.vaults.items.upsert('notebook-order', { id_or_name: vault.id, type: 'card', spec: { provider: 'agentcard', wallet: wallet.key, merchant: 'shop.example.com', amount: 2306, // minor units currency: 'usd', }, }); // 3. A browser with the vault attached. The agent shops and submits the card aliases. const browser = await kernel.browsers.create({ vaults: [{ id: vault.id }], headless: false, timeout_seconds: 1800, }); ``` When the agent submits the checkout form, KERNEL pauses the processor request and the card item's `state.authorization` fills in. Serve its `action.url` to the user through your own signed-in thread or app, never to the agent. The user approves with their passkey, the request resumes, and you confirm the order with the merchant before reporting success. ## Option B: Agentcard SDK over CDP Connect Playwright to the KERNEL browser and attach Agentcard the same way as any CDP browser. ```bash theme={null} npm i @agent-cards/checkout@0.3.0 @onkernel/sdk playwright-core ``` ```ts theme={null} import Kernel from '@onkernel/sdk'; import { chromium } from 'playwright-core'; import { VaultClient, attachToPlaywright } from '@agent-cards/checkout'; const kernel = new Kernel({ apiKey: process.env.KERNEL_API_KEY! }); const kernelBrowser = await kernel.browsers.create({ stealth: true }); const browser = await chromium.connectOverCDP(kernelBrowser.cdp_ws_url); const context = browser.contexts()[0] ?? (await browser.newContext({ serviceWorkers: 'block' })); const page = context.pages()[0] ?? (await context.newPage()); const vault = new VaultClient({ clientId: process.env.AGENTCARD_CLIENT_ID!, clientSecret: process.env.AGENTCARD_CLIENT_SECRET!, }); await vault.syncRegistry(); const checkout = await attachToPlaywright(page, { vault, user: 'usr_8f3k2m', merchant: 'shop.example.com', amount: 2306, currency: 'usd', onApprovalUrl: (url) => sendToUser(url), }); ``` Attach before the agent reaches the payment form. A KERNEL session bills until deleted, so call `kernel.browsers.deleteByID(kernelBrowser.session_id)` once the order is confirmed. ## Next The rest of the flow is identical to any Vault purchase: placeholder card, passkey approval, real card swapped in, confirm with the merchant. Follow the [Vault Quickstart](/vault/quickstart) from step 4, or read [Completing a purchase](/vault/completing-a-purchase). # Your own browser Source: https://docs.agentcard.sh/vault/integrations/agent-browsers/your-own Use Agentcard with a browser you run yourself to let your agent make purchases with your users' cards. You don't need a browser provider. If your agent drives its own Chromium, locally or on your infrastructure, the Vault attaches to it the same way it attaches to KERNEL or Browserbase. There are three levels, depending on how much of the browser you control. You need a user with a card in the Vault first. See [Adding a card](/vault/adding-a-card). ## Level 1: You use Playwright Attach to your Playwright page. This is the same code as every other browser, with your own launch instead of a provider's. ```bash theme={null} npm i @agent-cards/checkout@0.3.0 playwright ``` ```ts theme={null} import { chromium } from 'playwright'; import { VaultClient, attachToPlaywright } from '@agent-cards/checkout'; const browser = await chromium.launch({ headless: true }); const context = await browser.newContext({ serviceWorkers: 'block' }); const page = await context.newPage(); const vault = new VaultClient({ clientId: process.env.AGENTCARD_CLIENT_ID!, clientSecret: process.env.AGENTCARD_CLIENT_SECRET!, }); await vault.syncRegistry(); const checkout = await attachToPlaywright(page, { vault, user: 'usr_8f3k2m', merchant: 'shop.example.com', amount: 2306, currency: 'usd', onApprovalUrl: (url) => sendToUser(url), }); // Now let the agent shop. await page.goto('https://shop.example.com'); ``` A remote Chromium works too: replace `chromium.launch()` with `chromium.connectOverCDP(yourCdpUrl)`. ## Level 2: You speak CDP directly Not on Playwright? The SDK also exposes `attachToCdp`. Give it a browser-level, session-aware CDP connection wrapped in its two-method `CdpLike` shape (send a command, subscribe to events). The SDK needs the browser level, not a single page session, because card fields live in cross-origin iframes that are separate CDP targets and it attaches to each one. ```ts theme={null} import { VaultClient, attachToCdp } from '@agent-cards/checkout'; const checkout = await attachToCdp(myCdpConnection, { vault, user: 'usr_8f3k2m', merchant: 'shop.example.com', amount: 2306, currency: 'usd', onApprovalUrl: (url) => sendToUser(url), }); ``` ## Level 3: You do your own interception If you already intercept network requests in your browser, skip the SDK and make the authorization call yourself. When your agent submits the placeholder card and you see the request to the payment processor, pause it and send it to Agentcard: ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v2/checkout/authorizations \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "user": "usr_8f3k2m", "merchant": "shop.example.com", "amount": 2306, "currency": "usd", "psp": "stripe", "request": { "url": "https://api.stripe.com/v1/tokens", "method": "POST", "headers": { "content-type": "application/x-www-form-urlencoded" }, "body": "card[number]=<card number>&..." } }' ``` The response carries `approvalUrl` to send the user. Poll `GET /v2/checkout/authorizations/:id` until it is `approved`, then fulfill the paused request with the processor `response` from the authorization. Two things to get right: * **CORS.** Stripe and most processors are called cross-origin. Your fulfilled response must carry `access-control-allow-origin` set to the paused request's own `Origin` header, plus `access-control-allow-credentials: true`, or the page rejects it. The SDK exports `withCorsHeaders` for this. * **Recognized processors only.** `GET /v2/checkout/recognizers` lists the processor endpoints Agentcard can complete. Pause those, and leave everything else untouched. ## Next Whichever level you pick, the rest of the flow is identical: placeholder card, passkey approval, real card swapped in, confirm with the merchant. Follow the [Vault Quickstart](/vault/quickstart) from step 4, or read [Completing a purchase](/vault/completing-a-purchase). # Ophelia Source: https://docs.agentcard.sh/vault/integrations/ecommerce-apis/ophelia \[tbd] # Agentcard's Purchase API Source: https://docs.agentcard.sh/vault/integrations/ecommerce-apis/purchase-api Let your agent buy online without building merchant integrations or running an agent browser. Use Agentcard's Purchase API to let your agent buy things online without building merchant integrations or using an agent browser. Merchants supported today include Amazon, Walmart, Target, Best Buy, and many more. ## Where agents can buy Here are a few examples of merchants supported today: <div> <div> <img alt="Amazon logo" /> <span>Amazon</span> </div> <div> <img alt="Walmart logo" /> <span>Walmart</span> </div> <div> <img alt="Target logo" /> <span>Target</span> </div> <div> <img alt="Best Buy logo" /> <span>Best Buy</span> </div> <div> <img alt="Home Depot logo" /> <span>Home Depot</span> </div> <div> <img alt="Lowe's logo" /> <span>Lowe's</span> </div> <div> <img alt="Macy's logo" /> <span>Macy's</span> </div> <div> <img alt="Wayfair logo" /> <span>Wayfair</span> </div> <div> <img alt="Staples logo" /> <span>Staples</span> </div> <div> <img alt="Kohl's logo" /> <span>Kohl's</span> </div> <div> <img alt="B&H Photo logo" /> <span>B\&H Photo</span> </div> <div> <img alt="DoorDash logo" /> <span>DoorDash</span> </div> <div> <img alt="Good Eggs logo" /> <span>Good Eggs</span> </div> <div> <img alt="Locale logo" /> <span>Locale</span> </div> <div> <Icon icon="plane" /> <span>Flights</span> </div> </div> For the live list, call `GET /buy/merchants` with the same bearer token you send to `/buy`. ## What you need 1. **A user with a card in the Vault** ([Adding a card](/vault/adding-a-card)). 2. **A user-scoped bearer token.** * `/buy` always runs as a single user, so org tokens are rejected. * Use the user's connection `access_token`, or mint a `buy_token` for a cardholder you own: ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v1/cardholders/CARDHOLDER_ID/buy_token \ -H "Authorization: Bearer $ORG_TOKEN" ``` **Recommended:** set a client timeout of at least 120 seconds. Each turn runs against a live merchant. ## Quickstart Every call is a `POST /buy`. A single purchase follows a turn-based loop, tied together by `conversation_id`. ### 1) Start (send an ask) ```bash theme={null} curl -X POST https://api.agentcard.sh/buy \ -H "Authorization: Bearer $USER_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{"ask": "a 16 oz bag of Colombian ground coffee from Amazon, ship it to 1900 Jefferson St, San Francisco"}' ``` ### 2) Loop: reply → ask (until a cart is ready) If the API needs more info, it responds with `status: "needs_input"` and a natural-language `reply`. Show `reply` to the user, then send the user's answer back as the next `ask` with the same `conversation_id`: ```bash theme={null} curl -X POST https://api.agentcard.sh/buy \ -H "Authorization: Bearer $USER_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{"conversation_id": "cmsq18x2m00a1", "ask": "the Cafe Mesa one"}' ``` Repeat this loop as needed. Nothing can be charged during it. ### 3) Read the cart (use structured fields) Once the API has enough details, the response includes a `cart` and a `cart.hash`. Use these structured fields (not the prose) to show the user exactly what will be purchased. ```json theme={null} { "conversation_id": "cmsq18x2m00a1", "status": "needs_input", "reply": "Found it. Cafe Mesa de los Santos Colombian Ground Coffee, 16 oz, at $22.50. Total $23.06 shipping to 1900 Jefferson St. Want me to place it?", "cart": { "merchant": "retail", "merchant_name": "Amazon", "items": [ { "name": "Cafe Mesa de los Santos Colombian Ground Coffee, 16 oz", "qty": 1, "priceCents": 2250, "product_id": "https://www.amazon.com/dp/B07ZQ5C4RB" } ], "totalCents": 2306, "hash": "9f2c4a1b8e3d5f07" }, "unmatched": [] } ``` Notes: * `unmatched` lists anything requested that didn't make it into the cart (plus a reason). Show it instead of guessing from the prose. * The status can still be `needs_input` here, because the API is asking for confirmation. * If the user wants a change (for example, "make it two bags"), send that as another `ask`. You'll get an updated cart with a new `hash`. ### 4) Confirm the cart hash (and choose a payment source) When the user wants to proceed, confirm the exact cart you showed by sending the `cart.hash` (not a free-form "yes"). To pay with the user's own card, pass `payment_source: "vault"`. ```bash theme={null} curl -X POST https://api.agentcard.sh/buy \ -H "Authorization: Bearer $USER_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{"conversation_id": "cmsq18x2m00a1", "confirm": "9f2c4a1b8e3d5f07", "payment_source": "vault"}' ``` ### 5) If approval is required: send the approval URL, then retry confirm A confirm may pause while the user approves: ```json theme={null} { "conversation_id": "cmsq18x2m00a1", "status": "declined", "decline_code": "vault_approval_required", "approval_url": "https://vault.agentcard.sh/authorize?id=cauth_2q9d1x8f3k2m4t7w", "charge_status": "none" } ``` This is a pause, not a verdict. Nothing was charged. Send `approval_url` to the user. After they approve with their passkey, repeat the same confirm call from step 4. When the purchase is placed: ```json theme={null} { "conversation_id": "cmsq18x2m00a1", "status": "order_placed", "reply": "Order placed at Amazon. Charged $23.06 to your Visa ending 4832.", "order_id": "3f9a8c1b-7d2e-4c5a-9b1f-2e8d4a6c0b17", "payment_source": { "source": "vault", "brand": "visa", "last4": "4832" }, "charge_status": "settled" } ``` ## The fields you branch on | Field | Values | Use it to | | --------------- | ------------------------------------------------------------- | ------------------------------------------------ | | `status` | `needs_input`, `order_placed`, `partially_placed`, `declined` | Decide what to do next. Never branch on `reply`. | | `cart.hash` | string | Confirm exactly this cart. | | `decline_code` | `vault_approval_required`, `items_unavailable`, … | Tell an approval pause from a real decline. | | `approval_url` | string or null | Send to the user when the confirm paused. | | `charge_status` | `none`, `confirming`, `settled`, `unknown` | Tell the user whether money moved. | | `order_id` | string or null | Reconcile and track. | ## Edge cases ### If the price changed A confirm authorizes one cart at one price. If anything drifted since the cart was shown, confirm returns `409` with a fresh cart and a new `hash`. Show the user the new total, then confirm the new hash. ### Track the order Retail orders confirm asynchronously (often \~1 minute after placement). ```bash theme={null} curl "https://api.agentcard.sh/buy/v1/merchants/retail/orders/ORDER_ID/track" \ -H "Authorization: Bearer $USER_ACCESS_TOKEN" ``` This returns the retailer's order number, delivery window, final total, and shipments once a package ships. Or listen for the `order.placed` and `order.confirmed` webhooks instead of polling. ### If a confirm times out Don't resend. First, read the conversation: ```bash theme={null} curl https://api.agentcard.sh/buy/conversations/CONVERSATION_ID \ -H "Authorization: Bearer $USER_ACCESS_TOKEN" ``` Wait for `turn_in_progress` to clear, then check `orders`. A duplicate confirm while a turn is running returns `409 turn_in_progress`, so the same cart can never place twice. ## Over MCP The same loop is available as the `buy` tool on `https://mcp.agentcard.sh/mcp`, using the same bearer. The agent relays each turn, the user confirms in words, and the tool places the order. ## Sandbox Sandbox runs the real loop against real merchants up to the confirm. The confirm returns `declined` with `decline_code: "sandbox_mode"` by design, because sandbox cards can't pay a real merchant. Everything before it (conversation, cart, hash) is identical to production. # Zinc Source: https://docs.agentcard.sh/vault/integrations/ecommerce-apis/zinc \[tbd] # Blooio Source: https://docs.agentcard.sh/vault/integrations/imessage-providers/blooio Use Agentcard with Blooio to let your iMessage agent make payments with your users' cards. \[tbd] # Linq Source: https://docs.agentcard.sh/vault/integrations/imessage-providers/linq Use Agentcard with Linq to let your iMessage agent make payments with your users' cards. [Linq](https://linqapp.com) gives your agent a phone number on iMessage. Agentcard gives it a way to pay. Linq ships a native Agentcard integration, so the card enrollment and the payment approval render as native bubbles in the thread, and your agent gets a card to check out with. Full reference on Linq's side: [Agentcard guide](https://docs.linqapp.com/channel/imessage/guides/agentcard/). ## How it fits together 1. Your agent receives a text through a Linq webhook (`message.received`). 2. The first time, your agent asks Linq to connect the user to Agentcard. Linq texts them a native card; they add their card and approve with their passkey: fingerprint or face unlock on Android, Face ID or Touch ID on iPhone, or their master password. 3. When the user wants to buy, your agent creates a payment through Linq. Linq asks the user to approve, then hands your agent card credentials scoped to that purchase. 4. Your agent checks out with those credentials, in a browser or through an ecommerce API. ## Integrate ### 1. Connect your Linq account to Agentcard Once per Linq account. Linq returns a hosted flow where you sign in with your Agentcard organization. ```bash theme={null} curl -X POST https://api.linqapp.com/api/partner/v3/payments/providers/agentcard/connect \ -H "Authorization: Bearer $LINQ_API_TOKEN" ``` ### 2. Connect a user Once per user, by their phone number (`handle`). Linq texts them the enrollment bubble. Wait for the `connection.created` webhook before creating payments. ```bash theme={null} curl -X POST "https://api.linqapp.com/api/partner/v3/payments/handles/+15551234567/connect" \ -H "Authorization: Bearer $LINQ_API_TOKEN" ``` ### 3. Create a payment When the cart is ready, create a payment with what the user will approve. Linq sends the approval bubble. ```bash theme={null} curl -X POST https://api.linqapp.com/api/partner/v3/payments \ -H "Authorization: Bearer $LINQ_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "handle": "+15551234567", "amount": 2306, "currency": "usd", "merchant": "shop.example.com" }' ``` ### 4. Get the card and check out When the payment's status is `ready` (webhook `payment.authorized`), fetch the credentials and complete the checkout. ```bash theme={null} curl https://api.linqapp.com/api/partner/v3/payments/PAYMENT_ID/credentials \ -H "Authorization: Bearer $LINQ_API_TOKEN" ``` Subscribe to `payment.authorized`, `payment.declined`, `connection.created` and `connection.revoked` so your agent reacts to facts, not to the conversation. ## Prefer to run Agentcard yourself? You can also treat Linq as plain text messaging: create an Agentcard [vault session](/vault/adding-a-card) or approval link on your server and text the URL as a normal message. ```bash theme={null} curl -X POST https://api.linqapp.com/api/partner/v3/chats \ -H "Authorization: Bearer $LINQ_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "from": "'"$LINQ_PHONE_NUMBER"'", "to": ["+15551234567"], "message": { "parts": [{ "type": "text", "value": "Add a card so I can buy for you: '"$VAULT_URL"'" }] } }' ``` The rest of the flow is then the standard one. Follow the [Vault Quickstart](/vault/quickstart) from step 2. # Photon Source: https://docs.agentcard.sh/vault/integrations/imessage-providers/photon Use Agentcard with Photon to let your iMessage agent make payments with your users' cards. \[tbd] # Open your cards on another device Source: https://docs.agentcard.sh/vault/open-your-cards-on-another-device Approve a new computer from the phone that holds your key, and it opens your cards from then on without your master password. Save a card on your phone, then open an approval on your laptop. The laptop shows a code. Scan it with your phone, unlock the way you do for any payment, and the laptop opens your card. The laptop then offers to set up its own unlock, Face ID or Touch ID on a Mac, Windows Hello on Windows, and stops asking. Your master password keeps working everywhere it did before. ## Approve a computer from your phone On the computer, open the approval link or your cards. Where the page cannot reach your key, it shows a square code and eight characters, and says which phone holds the key. ```text theme={null} Your card's key is on your iPhone (Safari). Approve this Mac from it. Or unlock with your master password. ``` Point your phone's camera at the code. Your phone opens a page that names the computer and how long ago it asked, and one button. ```text theme={null} Chrome on a Mac wants to open your cards. Requested just now. Approve only if that is your computer, in front of you now. ``` Tap Approve. Your phone asks for its own unlock, Face ID or Touch ID on an iPhone, fingerprint or face unlock on an Android phone, or your master password where that is how the phone opens the vault. The computer unlocks within a few seconds. If the computer was signed out when it asked, your phone shows six digits after you approve. Type them on the computer to finish. The digits are what stop a code someone sent you from signing their computer in: only a person looking at your phone's screen has them. ## Compare the code instead of scanning If the computer is signed in, its request also appears on your phone's own vault page, with no camera needed. Open your cards on the phone, choose the request, and check that the eight characters your phone shows match the eight on the computer before you approve. If they do not match, do not approve: the request is not the one on your screen. ## Turn on this computer's unlock Right after the computer opens your card, it offers to use its own Face ID, Touch ID or Windows Hello next time. Accept, and your next visit is a look, not a code. Decline, and nothing changes; the offer comes back after your next unlock. ## Know what a code cannot do A code expires ten minutes after the computer asks. A request you did not make can be ignored; it approves nothing on its own. Approving a computer lets it open your cards; it does not let it change any autopilot spending rules, which you allow separately, per device, from a device that already can. ## Let a computer change spending rules A computer you approved opens your cards. Changing autopilot's spending rules is a second thing you allow, per computer, from a device that already can: open your cards there, choose Your devices, and allow the computer. Until then the computer sees your rules and changes nothing, and its autopilot panel says so. ```text theme={null} This computer can see your spending rules. To change them, allow it from a device that already can. ``` Autopilot turns on only once your account has a master password, because that is the one way to open your cards if you lose the device that holds them. The panel asks for one first if you have none. ## Remove a computer Open your cards on any device that opens them, choose Your devices, and remove the one you no longer hold. It cannot open your cards after that, and anything it was signed in to is signed out on its next request. Spending rules that computer already approved keep running until they expire, because a rule belongs to the account and not to the computer that approved it. The screen names each one, with its card, what is left of its budget and when it ends. From a device that manages your spending rules you can turn them all off as you remove the computer; from any other device the screen says where to do that. ```text theme={null} Spending rules already approved keep running until they expire: card ending in 7315, \$120.00 left, ends October 3. ``` ## If you lose the phone that holds your key Sign in on any device with the code sent to your email. Because your key is on a device you no longer hold, your master password does not work there straight away: the screen says so and offers a wait. Start it, and a day later the password works on that device. A device you approve from a phone that still opens your cards skips the wait. ```text theme={null} Your master password works on this computer after a day's wait, which you can start below. To unlock now, approve this computer from a device that opens your cards. ``` You get a notice when the wait starts, naming the device, and another when it ends. If the sign-in was not you, the first notice's stop link ends the wait, and the password stays off that device. Nothing else changes; from a device that opens your cards, choose Your devices and remove any you do not recognise. Once the wait ends, that device offers to turn on its own unlock, as an approved computer does. Accounts with no passkey are never made to wait: their master password is the only key, and it works everywhere at once. # Quickstart Source: https://docs.agentcard.sh/vault/quickstart Store a user's card once, then complete a first purchase from an agent browser in about fifteen minutes. This guide takes you from zero to a first purchase with the Vault. You will store a test card, attach Agentcard to an agent browser, and let the user approve a payment with their passkey. **The flow in one line:** the user stores a card once → your agent shops in a browser and submits a placeholder card → Agentcard pauses the payment → the user approves on their device → that device pays with the real card → your agent confirms the order. Step 1 happens once per user. Steps 2 to 4 happen on every purchase. Presets are optional: once it works, you can [attach a preset](/vault/set-rules-on-a-card) to one of a user's cards, and only that card's purchases are filtered. ## 1. Get your credentials You need an Agentcard organization `client_id` and `client_secret`. Create them in the [dashboard](https://app.agentcard.sh) and exchange them for an access token: ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v2/oauth/token \ -d grant_type=client_credentials \ -d client_id=$AGENTCARD_CLIENT_ID \ -d client_secret=$AGENTCARD_CLIENT_SECRET ``` Use the returned token as `$ORG_TOKEN` below. Sandbox credentials create sandbox sessions and sandbox authorizations, so start there. ## 2. Store a card Create a vault session and send the user the link wherever you already talk to them: iMessage, WhatsApp, your app. ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v2/vault_sessions \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{}' ``` ```json theme={null} { "id": "vs_2q9d1x8f3k2m4t7w", "url": "https://vault.agentcard.sh/v?vs=vs_2q9d1x8f3k2m4t7w.3k1v…", "poll_interval": 3, "expires_at": "2026-08-28T21:00:00Z" } ``` The user opens the link, types their card, and saves it with a passkey and a master password. The card is encrypted on their device before it leaves. When they finish, you receive a `vault.session_linked` webhook with their `user_id`, or you poll the session until its `status` is `linked`. Store that `user_id`, you need it on every purchase. For a test run, store a test card: any of [Stripe's published test cards](https://docs.stripe.com/testing), any future expiry, any CVC. [More on adding cards →](/vault/adding-a-card) ## 3. Attach Agentcard to your browser Install the SDK next to your browser provider. This example uses KERNEL; Browserbase and any CDP browser work the same way. ```bash theme={null} npm i @agent-cards/checkout@0.3.0 @onkernel/sdk playwright-core ``` Attach **before** your agent reaches the payment form. The SDK watches the page for the payment processor's request. ```ts theme={null} import Kernel from '@onkernel/sdk'; import { chromium } from 'playwright-core'; import { VaultClient, attachToPlaywright } from '@agent-cards/checkout'; const vault = new VaultClient({ clientId: process.env.AGENTCARD_CLIENT_ID!, clientSecret: process.env.AGENTCARD_CLIENT_SECRET!, }); await vault.syncRegistry(); const kernel = new Kernel({ apiKey: process.env.KERNEL_API_KEY! }); const kernelBrowser = await kernel.browsers.create({ stealth: true }); const browser = await chromium.connectOverCDP(kernelBrowser.cdp_ws_url); const context = browser.contexts()[0] ?? (await browser.newContext({ serviceWorkers: 'block' })); const page = context.pages()[0] ?? (await context.newPage()); const checkout = await attachToPlaywright(page, { vault, user: 'usr_8f3k2m', // from step 2 merchant: 'shop.agentcard.sh', // what the user sees on the approval screen amount: 2306, currency: 'usd', onApprovalUrl: (url) => sendToUser(url), // deliver over your channel }); ``` [More on creating a cart →](/vault/creating-a-cart) ## 4. Complete the purchase Let your agent shop as usual. At checkout it should fill the card form with placeholder data, any of [Stripe's published test cards](https://docs.stripe.com/testing), and submit. The Agentcard SDK intercepts the processor request and pauses it. `onApprovalUrl` fires with a link; send it to the user. They approve with their passkey, their device sends the real card to the processor, and the paused request resumes with the real response. Then confirm the order with the merchant before you tell the user anything: ```ts theme={null} await page.goto('https://shop.agentcard.sh'); await runAgentCheckout(page); // your agent: add to cart, fill the form, submit const result = await checkout.reconcile(); if (result.status === 'completed') { await notifyUser(`Order ${result.orderId} confirmed`); } ``` [More on completing a purchase →](/vault/completing-a-purchase) ## Try it against a store that always works [shop.agentcard.sh](https://shop.agentcard.sh) is a demo store on Stripe test mode, kept running for exactly this rehearsal. Add a product, submit the card form with the placeholder card, approve on the device that holds your passkey, and the order completes with a real test-mode charge. ## Keep going <CardGroup> <Card title="Adding a card" href="/vault/adding-a-card"> Open vs connected sessions, webhooks vs polling, returning users. </Card> <Card title="Creating a cart" href="/vault/creating-a-cart"> Browsers, SDK options, and the Purchase API alternative. </Card> <Card title="Completing a purchase" href="/vault/completing-a-purchase"> Approval, reconciliation, webhooks, supported processors. </Card> <Card title="Set rules on a card" href="/vault/set-rules-on-a-card"> Optional rules for one of a user's cards: a spend cap, a merchant list, a currency, a time window. </Card> </CardGroup> # Set rules on a card Source: https://docs.agentcard.sh/vault/set-rules-on-a-card Presets are optional rules for Vault purchases. Save one, attach it to a stored card, and only the purchases paid with that card are judged. Presets are optional. Without them, every Vault purchase goes through as usual. Presets are the rules you put on what an agent may buy: a spend cap, a merchant list, a currency, a time window. A preset can apply to one of a user's stored cards. Save a preset under a name of your choice, then attach it where it should apply. ```bash theme={null} curl -X PUT https://api.agentcard.sh/api/v2/vault/presets/office-supplies \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"per_day": 50, "only_merchants": "EXAMPLE SHOP,ACME", "currencies": "usd"}' ``` Once you attach a preset, Agentcard judges each purchase it covers. A purchase made outside of the preset rules is refused, nothing is charged, and you are told which preset and which rule(s) refused it. Attach a preset when you want a purchase-level restriction, guarding against how much a particular agent or set of agents should spend in a day, for example. You can also use presets while you build: set a tight preset to test your work before shipping to production. The rules and their refusal codes are the ones a [card preset](/issuing/set-rules-on-a-card) uses. ## Choose what to restrict Pick the rules the preset holds when you save it. Caps count separately for each card the preset is attached to. Caps use the amount the processor charges. Send `amount` to have a purchase judged the moment your agent opens it. | Rule | What it does | | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Total** | The most the purchases this preset covers spend in all, in US dollars. | | **Rate** | A cap per rolling 24 hours, 7 days, or 30 days, in US dollars, for the purchases this preset covers. | | **Category** | `meals`, `groceries`, `travel`, `software`, `ai`, `wellness`, `retail`. Judged on the merchant Agentcard names from the checkout page, never on the text your agent sends. | | **Merchant** | Names the merchant must match, such as `EXAMPLE SHOP` or `shop.example.com`. A pattern is a case-insensitive part of the merchant's name or checkout host as Agentcard names them. | | **Place** | The country the merchant is in, such as `US, Canada` or `europe`. Not where your agent runs. | | **Currency** | The currencies a purchase may be in, such as `usd,eur`. | | **Time window** | Days and hours, always in a named zone. UTC unless you pass `timezone`. | | **Where the purchase comes from** | A Vault purchase always comes from your agent through the API, which counts as `api`. A rule that allows only `cli` refuses every one of them. | Available preset parameters: | Field | Meaning | | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | | `total` | Cap on the purchases this preset covers, over all time, in US dollars | | `per_day` / `per_week` / `per_month` | Rolling caps for the purchases this preset covers, in US dollars | | `categories` | Categories, comma-separated: `meals`, `groceries`, `travel`, `software`, `ai`, `wellness`, `retail` | | `only_merchants` | Merchant name or host patterns the purchase must match, comma-separated | | `only_in` | Places, comma-separated: a country (`US`, `Canada`), a US state (`California`, `US-CA`), or a region (`europe`, `north-america`, `apac`) | | `currencies` | The currencies a purchase may be in, comma-separated, by code or common name: `usd,eur` or `dollars,euros` | | `only_days` | Days, comma-separated: `mon,tue,wed`, or `weekdays` / `weekends` | | `only_hours` | For example `9-17`, 24-hour clock, in `timezone` | | `timezone` | IANA zone for `only_days` and `only_hours`, default `UTC` | | `only_from` | Where purchases may come from. A Vault purchase is always `api` | | `mode` | What the preset does when a purchase breaks any of its rules: `strict` refuses it (the default), `watch` lets it through and tells you | Caps are in US dollars. A purchase in another currency counts at that day's exchange rate plus a small cushion, so a purchase near the cap is refused rather than let through on a rate we cannot know yet. A purchase whose processor names no amount, with no `amount` from your agent, is refused right before the card is sent with `amount_unknown`. ## Attach to a card Attach a preset to one of a user's stored cards, and every purchase paid with that card follows it. Read the card id from the user's stored cards, or from the `id` in the `vault.card_stored` event: ```bash theme={null} curl "https://api.agentcard.sh/api/v2/vault_cards?user_id=cmtvwbbz80002jpcctuianq78" \ -H "Authorization: Bearer $ORG_TOKEN" ``` ```json theme={null} { "object": "list", "data": [ { "object": "vault_card", "id": "cmtvwbbzj0006jpccycjrkqy4", "brand": "visa", "last4": "7318", "expiry_month": 12, "expiry_year": 2030, "created_at": "2026-09-10T17:36:29.700Z" } ] } ``` Attach the preset to that card: ```bash theme={null} curl -X PUT https://api.agentcard.sh/api/v2/vault/presets/office-supplies/attachments \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"kind": "card", "target_id": "cmtvwbbzj0006jpccycjrkqy4"}' ``` ```json theme={null} { "object": "vault_preset", "name": "office-supplies", "id": "cmtvwbc0g000bjpcc88yiyx8z", "version": 1, "summary": "Up to $50.00 per day. Merchants: EXAMPLE SHOP, ACME. Currency: USD.", "attachments": [ { "kind": "card", "target_id": "cmtvwbbzj0006jpccycjrkqy4", "last4": "7318" } ] } ``` A card id that is not one of your users' cards is refused: ```json theme={null} { "error": { "code": "card_not_found", "message": "No stored card with that id belongs to one of your users. List a user's cards at GET /api/v2/vault_cards?user_id=…, or read the id from the vault.card_stored event.", "docs": "https://docs.agentcard.sh" } } ``` From now on `office-supplies` judges every purchase paid with that card. Your agent opens a purchase on the card by sending `card_id` on the checkout authorization; at a merchant the preset does not allow, the call answers HTTP 403 and no authorization exists: ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v2/checkout/authorizations \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"user": "cmtvwbbz80002jpcctuianq78", "merchant": "Braxter'\''s Deli", "checkout_origin": "https://www.braxters-deli.example", "amount": 2306, "currency": "usd", "psp": "shopify", "card_id": "cmtvwbbzj0006jpccycjrkqy4", "request": { "url": "https://checkout.pci.shopifyinc.com/sessions", "method": "POST", "headers": {}, "body": "..." }}' ``` ```json theme={null} { "error": { "code": "merchant_denied", "message": "Preset \"office-supplies\", attached to the card ending in 7318: merchant denied. This purchase is at braxters-deli.example. The preset allows EXAMPLE SHOP and ACME. Add the merchant to the preset with PUT /api/v2/vault/presets/office-supplies, or buy from an allowed merchant.", "docs": "https://docs.agentcard.sh", "preset": { "id": "cmtvwbc0g000bjpcc88yiyx8z", "version": 1, "name": "office-supplies" }, "attachment": { "kind": "card", "target_id": "cmtvwbbzj0006jpccycjrkqy4", "last4": "7318" }, "rule": "merchant", "stage": "create", "refusals": [ { "preset": { "id": "cmtvwbc0g000bjpcc88yiyx8z", "version": 1, "name": "office-supplies" }, "attachment": { "kind": "card", "target_id": "cmtvwbbzj0006jpccycjrkqy4", "last4": "7318" }, "rule": "merchant", "reason": "merchant_denied", "message": "Preset \"office-supplies\", attached to the card ending in 7318: merchant denied. This purchase is at braxters-deli.example. The preset allows EXAMPLE SHOP and ACME. Add the merchant to the preset with PUT /api/v2/vault/presets/office-supplies, or buy from an allowed merchant." } ] } } ``` Send `card_id`, or leave the user with exactly one stored card, and Agentcard judges the card's presets the moment your agent opens the purchase; otherwise it judges them right before the card is sent, once the user has chosen and unlocked a card. To stop using the preset on that card, detach it with the same body: ```bash theme={null} curl -X DELETE https://api.agentcard.sh/api/v2/vault/presets/office-supplies/attachments \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"kind": "card", "target_id": "cmtvwbbzj0006jpccycjrkqy4"}' ``` ```json theme={null} { "object": "vault_preset", "name": "office-supplies", "id": "cmtvwbc0g000bjpcc88yiyx8z", "version": 1, "summary": "Up to $50.00 per day. Merchants: EXAMPLE SHOP, ACME. Currency: USD.", "attachments": [] } ``` A per-day cap attached to a card counts that card's purchases alone. Attach the same preset to two cards and each has its own \$50 a day. ## Combine several presets When one or more presets apply to a purchase, the purchase must satisfy all of them. Agentcard judges each purchase against every attached preset, and any that would cause a refusal are named in the response. ## Read a refused purchase Agentcard checks a purchase twice: when your agent opens it, and again right before the card is sent, after the user approves. If a preset refuses at the second check, the user sees: ```text theme={null} This purchase was refused The company that set up this checkout has rules on its purchases, and this one is outside them. Your card was not sent. Nothing was charged. Ask your agent, or the company, before trying again. ``` Your agent reads the same outcome when it reads the authorization back: `status` is `declined`, with the preset and the rule named. A purchase every attached preset allows is approved and paid like any other. ## Replace or delete a preset Read your presets, or one preset and where it is attached: ```bash theme={null} curl https://api.agentcard.sh/api/v2/vault/presets \ -H "Authorization: Bearer $ORG_TOKEN" curl https://api.agentcard.sh/api/v2/vault/presets/office-supplies \ -H "Authorization: Bearer $ORG_TOKEN" ``` To replace a preset, save the same name again. The new rules apply everywhere it is attached. Purchases already counted toward a cap stay counted, so tightening a rate at noon does not reset the day. To delete a preset, remove it by name. It stops judging every purchase it was attached to: ```bash theme={null} curl -X DELETE https://api.agentcard.sh/api/v2/vault/presets/office-supplies \ -H "Authorization: Bearer $ORG_TOKEN" ``` Save the same name again later and its caps start from zero. ## Relax restrictions You can relax a preset's restrictions by changing what it does when a purchase breaks a rule: a warning instead of the default refusal. Set `"mode": "watch"` on the preset, or save the same rules under a second preset with `"mode": "watch"`. For example, a currency rule: ```bash theme={null} curl -X PUT https://api.agentcard.sh/api/v2/vault/presets/watch-eur \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"currencies": "eur", "mode": "watch"}' ``` Attach it, and a purchase in another currency goes through. Once the charge is recorded you are told, with the preset and where it is attached named: ```text theme={null} Watched purchase: $23.06 at Example Shop Bought by cmtvwbbz80002jpcctuianq78. Preset "watch-eur", attached to the card ending in 7318: a $23.06 purchase at example-shop.example went through. It is in USD, and this preset allows EUR only. Nothing is blocked. To stop these notices, change the preset with PUT /api/v2/vault/presets/watch-eur. ``` Every rule relaxes the same way. A watched cap says by how much the purchase went over it. ## Receive the notices Every refusal and every watched purchase sends one notice, three ways: an event to your webhook, an email to your billing contact and your account's owners and admins, and a post in your Slack conversation with Agentcard once you have connected it. A test-mode purchase sends the webhook only. Every notice names the preset, where it is attached, the rule, and what to do next. A refusal when your agent opens the purchase is a `checkout_authorization.refused` event. It has no authorization id, because none was created: ```json theme={null} { "authorization_id": null, "user_id": "cmtvwbbz80002jpcctuianq78", "external_user_id": "cmtvwbbz80002jpcctuianq78", "merchant": "Braxter's Deli", "amount": 2306, "currency": "usd", "amount_display": "$23.06", "psp": "shopify", "mode": "token", "stage": "create", "reason": "merchant_denied", "rule": "merchant", "message": "Preset \"office-supplies\", attached to the card ending in 7318: merchant denied. This purchase is at braxters-deli.example. The preset allows EXAMPLE SHOP and ACME. Add the merchant to the preset with PUT /api/v2/vault/presets/office-supplies, or buy from an allowed merchant.", "preset": { "id": "cmtvwbc0g000bjpcc88yiyx8z", "name": "office-supplies", "version": 1 }, "attachment": { "kind": "card", "last4": "7318", "target_id": "cmtvwbbzj0006jpccycjrkqy4" }, "refusals": [ { "rule": "merchant", "preset": { "id": "cmtvwbc0g000bjpcc88yiyx8z", "name": "office-supplies", "version": 1 }, "reason": "merchant_denied", "message": "Preset \"office-supplies\", attached to the card ending in 7318: merchant denied. This purchase is at braxters-deli.example. The preset allows EXAMPLE SHOP and ACME. Add the merchant to the preset with PUT /api/v2/vault/presets/office-supplies, or buy from an allowed merchant.", "attachment": { "kind": "card", "last4": "7318", "target_id": "cmtvwbbzj0006jpccycjrkqy4" } } ] } ``` A refusal right before the card is sent is a `checkout_authorization.declined` event with the same fields. A watched purchase is a `checkout_authorization.watched` event, sent after `approved`. See [Checkout authorization events](/webhooks/checkout-authorizations/overview). The email for the refusal above: ```text theme={null} Purchase refused: $23.06 at Braxter's Deli Your preset refused a $23.06 purchase at Braxter's Deli for cmtvwbbz80002jpcctuianq78. Nobody was asked to approve it, and nothing was charged. Preset "office-supplies", attached to the card ending in 7318: merchant denied. This purchase is at braxters-deli.example. The preset allows EXAMPLE SHOP and ACME. Add the merchant to the preset with PUT /api/v2/vault/presets/office-supplies, or buy from an allowed merchant. ``` The Slack post for the same refusal: ```text theme={null} ⛔ $23.06 at Braxter's Deli for cmtvwbbz80002jpcctuianq78 refused by your preset. Nobody was asked to approve it, and nothing was charged. Preset "office-supplies", attached to the card ending in 7318: merchant denied. This purchase is at braxters-deli.example. The preset allows EXAMPLE SHOP and ACME. Add the merchant to the preset with PUT /api/v2/vault/presets/office-supplies, or buy from an allowed merchant. ``` ## Look up a refusal code Codes from `merchant_denied` down are returned when your agent opens the purchase or right before the card is sent. The first three are returned when you save or attach. | Code | What it means | What to do | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | | `policy_invalid` | The rules cannot be read: an unknown category, an ambiguous place code, an unknown built-in, an ambiguous currency, a misspelled zone, a bad name, or a mode other than `strict` or `watch` | Correct the rule the message names | | `preset_not_found` | No preset of that name is saved | Save it, or list your presets | | `card_not_found` | The card id is not a card one of your users stored | Use the id from the stored-cards list or the `vault.card_stored` event | | `merchant_denied` | The merchant's name and checkout host match none of the patterns the preset allows | Add the merchant, or buy from an allowed one | | `merchant_unknown` | The purchase carries no checkout origin, so there is no merchant to match | Update the checkout SDK, or send `checkout_origin` on the authorization | | `category_denied` | The merchant's category is outside the category rule, and the preset is `strict` | Buy from an allowed merchant, or allow this one with a `merchant_allow` rule on its host | | `category_unknown` | Agentcard does not know the merchant, or the purchase carries no checkout origin, so the category is unknown | Buy from a merchant Agentcard knows, allow this one with a `merchant_allow` rule on its host, or send `checkout_origin` | | `geo_denied` | The merchant is outside the places the rule allows | Buy from a merchant in an allowed place, or widen the rule | | `geo_unknown` | Agentcard does not know where the merchant is: an unknown merchant, or one that sells in several countries | Buy from a merchant in an allowed place, or drop the place rule | | `spend_total_exceeded` | The purchase would take this preset past its total | Raise the total | | `spend_rate_exceeded` | The purchase would take this preset's rolling window past its cap | Wait for the window to roll, or raise the cap | | `spend_rate_unknown` | Agentcard could not check how much this preset has spent | Try again | | `rate_unavailable` | The dollar value of a purchase in another currency could not be worked out, because no exchange rate was available | Pay in dollars, or try again shortly | | `amount_unknown` | The preset caps spending, and right before the card was sent no authority named an amount: the processor's request carries none and your agent sent none | Send `amount` with `currency` on the authorization | | `currency_denied` | The currency is outside the currency rule, and the preset is `strict` | Buy in an allowed currency, or change the rule | | `currency_unknown` | No currency on the purchase, and the preset is `strict` | Send `currency`, or set `mode` to `watch` | | `time_window_denied` | Outside the allowed days or hours, in the rule's zone | Retry inside the window, or change it | | `surface_denied` | The preset allows purchases from somewhere other than the API; every Vault purchase comes through the API | Allow `api` in `only_from`, or drop the rule | Every refusal names the preset that refused and the card it is attached to, with its last four digits. When several presets refuse the same purchase, `refusals` lists each one, and the top-level fields are the first. # balance.low Source: https://docs.agentcard.sh/webhooks/cards/balance-low A card's remaining balance dropped below its threshold. A card's remaining balance dropped below its threshold. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "balance.low", "created": 1757264400, "livemode": false, "data": { "card_id": "card_7h2k", "last4": "7318", "balance_cents": 120 } } ``` # card.closed Source: https://docs.agentcard.sh/webhooks/cards/card-closed The card closed. The card closed. `reason` is `one_time_use` after its first approved charge, or `canceled`, `expired`, `declined`. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "card.closed", "created": 1757264400, "livemode": false, "data": { "id": "card_7h2k", "last4": "7318", "status": "CLOSED", "reason": "one_time_use" } } ``` # card.created Source: https://docs.agentcard.sh/webhooks/cards/card-created A one-time virtual card was created. A one-time virtual card was created. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "card.created", "created": 1757264400, "livemode": false, "data": { "id": "card_7h2k", "last4": "7318", "balance_cents": 1000, "status": "OPEN" } } ``` # card.updated Source: https://docs.agentcard.sh/webhooks/cards/card-updated The card's balance or status changed, for example after its first authorization. The card's balance or status changed, for example after its first authorization. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "card.updated", "created": 1757264400, "livemode": false, "data": { "id": "card_7h2k", "last4": "7318", "balance_cents": 325, "status": "IN_USE" } } ``` # Card and transaction events Source: https://docs.agentcard.sh/webhooks/cards/overview Lifecycle of a one-time virtual card and every authorization on it. Filter: `card.*`, `transaction.*`, `balance.*`. | Event | Fires when | | ------------------------------------------------------------------ | -------------------------------------------------------------------------------- | | [`card.created`](/webhooks/cards/card-created) | A one-time virtual card was created. | | [`card.updated`](/webhooks/cards/card-updated) | The card's balance or status changed, for example after its first authorization. | | [`card.closed`](/webhooks/cards/card-closed) | The card closed. | | [`transaction.authorized`](/webhooks/cards/transaction-authorized) | A merchant authorized a charge on the card. | | [`transaction.cleared`](/webhooks/cards/transaction-cleared) | The authorization settled. | | [`transaction.declined`](/webhooks/cards/transaction-declined) | A charge was declined. | | [`transaction.voided`](/webhooks/cards/transaction-voided) | A pending authorization was reversed by the merchant. | | [`balance.low`](/webhooks/cards/balance-low) | A card's remaining balance dropped below its threshold. | # transaction.authorized Source: https://docs.agentcard.sh/webhooks/cards/transaction-authorized A merchant authorized a charge on the card. A merchant authorized a charge on the card. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "transaction.authorized", "created": 1757264400, "livemode": false, "data": { "id": "txn_3f9a", "card_id": "card_7h2k", "last4": "7318", "amount": 675, "currency": "usd", "amount_display": "$6.75", "merchant": "COFFEE SHOP #42 SAN FRANCISCO", "status": "PENDING", "balance_cents": 325 } } ``` # transaction.cleared Source: https://docs.agentcard.sh/webhooks/cards/transaction-cleared The authorization settled. The authorization settled. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "transaction.cleared", "created": 1757264400, "livemode": false, "data": { "id": "txn_3f9a", "card_id": "card_7h2k", "last4": "7318", "amount": 675, "currency": "usd", "amount_display": "$6.75", "merchant": "COFFEE SHOP #42 SAN FRANCISCO", "status": "SETTLED", "balance_cents": 325 } } ``` # transaction.declined Source: https://docs.agentcard.sh/webhooks/cards/transaction-declined A charge was declined. A charge was declined. `decline_reason` says why. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "transaction.declined", "created": 1757264400, "livemode": false, "data": { "id": "txn_3f9a", "card_id": "card_7h2k", "last4": "7318", "amount": 675, "currency": "usd", "amount_display": "$6.75", "merchant": "COFFEE SHOP #42 SAN FRANCISCO", "status": "DECLINED", "decline_reason": "insufficient_funds" } } ``` # transaction.voided Source: https://docs.agentcard.sh/webhooks/cards/transaction-voided A pending authorization was reversed by the merchant. A pending authorization was reversed by the merchant. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "transaction.voided", "created": 1757264400, "livemode": false, "data": { "id": "txn_3f9a", "card_id": "card_7h2k", "last4": "7318", "amount": 675, "currency": "usd", "amount_display": "$6.75", "merchant": "COFFEE SHOP #42 SAN FRANCISCO", "status": "VOIDED" } } ``` # checkout_authorization.amount_mismatch Source: https://docs.agentcard.sh/webhooks/checkout-authorizations/checkout_authorization-amount_mismatch Fires after `approved` for the same authorization when the charge disagreed with the approval. Fires after `approved` for the same authorization when the charge disagreed with the approval. `reason` is `amount_mismatch` (a different amount or currency) or `intent_mismatch` (the device confirmed a different Stripe intent than the paused request named). The approval stands; by then the money has moved. Record it and reconcile with the merchant. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "checkout_authorization.amount_mismatch", "created": 1757264400, "livemode": false, "data": { "authorization_id": "cauth_2q9d1x8f3k2m4t7w", "user_id": "usr_8f3k2m", "external_user_id": "usr_8f3k2m", "merchant": "shop.example.com", "psp": "stripe", "mode": "token", "stage": "post_replay", "reason": "amount_mismatch", "expected_cents": 2306, "actual_cents": 2599, "currency": "usd", "actual_currency": "usd", "expected_intent_id": "pi_3Qxample", "actual_intent_id": "pi_3Qxample", "charged_kind": "captured", "charged_status": "succeeded" } } ``` # checkout_authorization.approved Source: https://docs.agentcard.sh/webhooks/checkout-authorizations/checkout_authorization-approved The user approved with their passkey and the processor answered (`token` and `cse` only). The user approved with their passkey and the processor answered (`token` and `cse` only). Carries the post-charge reconciliation: `amount_verified`, `charged_amount`, `charged_kind` (`captured`, `authorized`, `none`, or null). On `cse` the charged facts are null because Adyen answers the browser, not Agentcard. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "checkout_authorization.approved", "created": 1757264400, "livemode": false, "data": { "authorization_id": "cauth_2q9d1x8f3k2m4t7w", "user_id": "usr_8f3k2m", "external_user_id": "usr_8f3k2m", "merchant": "shop.example.com", "amount": 2306, "currency": "usd", "amount_display": "$23.06", "amount_authority": "processor", "psp": "stripe", "mode": "token", "submitted_at": null, "amount_verified": true, "charged_amount": 2306, "charged_currency": "usd", "charged_kind": "captured" } } ``` # checkout_authorization.declined Source: https://docs.agentcard.sh/webhooks/checkout-authorizations/checkout_authorization-declined The user said no, a pre-replay check refused it, the processor rejected the request, or your runtime cancelled it. The user said no, a pre-replay check refused it, the processor rejected the request, or your runtime cancelled it. `reason` is `user_declined`, `amount_mismatch` (with `expected_cents`, `actual_cents`), `intent_not_confirmable` (with `intent_status`), `processor_refused` (with `psp_error_code`), `merchant_request_aborted`, or the code of a rule on one of your [attached presets](/vault/set-rules-on-a-card) that refused the purchase right before the card was sent (`merchant_denied`, `currency_denied`, `spend_rate_exceeded`, and the others listed there; with `preset`, `attachment`, `rule`, `message`, `stage: "verify"`, and `refusals`, every preset that refused). `replay_attempted` says whether a device may already have sent the card. Razorpay processor refusals can include `processor_error` with bounded `reason`, `source`, `step`, `payment_id`, and `order_id` identifiers. Generic codes such as `BAD_REQUEST_ERROR` do not establish issuer decline or prove that nothing was charged. Reconcile the merchant payment before another attempt. The event never includes the raw processor response or free-form description; older records may lack structured details. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "checkout_authorization.declined", "created": 1757264400, "livemode": false, "data": { "authorization_id": "cauth_2q9d1x8f3k2m4t7w", "user_id": "usr_8f3k2m", "external_user_id": "usr_8f3k2m", "merchant": "shop.example.com", "amount": 2306, "currency": "usd", "amount_display": "$23.06", "amount_authority": "agent", "psp": "shopify", "mode": "token", "reason": "user_declined", "replay_attempted": false, "psp_error_code": null } } ``` # checkout_authorization.expired Source: https://docs.agentcard.sh/webhooks/checkout-authorizations/checkout_authorization-expired Nobody approved within 15 minutes. Nobody approved within 15 minutes. `replay_attempted: true` means a device passed the pre-replay check and may have sent the card without reporting back: the outcome is unknown, check the processor. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "checkout_authorization.expired", "created": 1757264400, "livemode": false, "data": { "authorization_id": "cauth_2q9d1x8f3k2m4t7w", "user_id": "usr_8f3k2m", "external_user_id": "usr_8f3k2m", "merchant": "shop.example.com", "amount": 2306, "currency": "usd", "amount_display": "$23.06", "amount_authority": "agent", "psp": "shopify", "mode": "token", "replay_attempted": false } } ``` # checkout_authorization.refused Source: https://docs.agentcard.sh/webhooks/checkout-authorizations/checkout_authorization-refused One of your presets refused a purchase before anyone was asked to approve it. No authorization exists and nothing was charged. One of your presets refused a purchase when your agent tried to open it. No authorization was created, so `authorization_id` is null, nobody was asked to approve, and nothing was charged. `reason` is the rule's code, the same code a card preset produces: `merchant_denied`, `currency_denied`, `currency_unknown`, `spend_total_exceeded`, `spend_rate_exceeded`, `spend_rate_unknown`, `time_window_denied`, or `surface_denied`. `preset` names the preset and version that refused, `attachment` says which card it is attached to (`card` with the card id and its last four digits), `rule` names the kind of rule, and `message` says what the rule allows and your next step. `refusals` lists every preset that refused, each with its `preset`, `attachment`, `rule`, `reason`, and `message`; the fields above are its first entry. A refusal right before the card was sent fires [`checkout_authorization.declined`](/webhooks/checkout-authorizations/checkout_authorization-declined) instead, with the same `reason`, `preset`, `attachment`, `rule`, `message`, and `refusals` fields, because an authorization exists there. See [Set rules on a card](/vault/set-rules-on-a-card). ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "checkout_authorization.refused", "created": 1757264400, "livemode": false, "data": { "authorization_id": null, "user_id": "cmtvwbbz80002jpcctuianq78", "external_user_id": "cmtvwbbz80002jpcctuianq78", "merchant": "Braxter's Deli", "amount": 2306, "currency": "usd", "amount_display": "$23.06", "psp": "shopify", "mode": "token", "stage": "create", "reason": "merchant_denied", "rule": "merchant", "message": "Preset \"office-supplies\", attached to the card ending in 7318: merchant denied. This purchase is at braxters-deli.example. The preset allows EXAMPLE SHOP and ACME. Add the merchant to the preset with PUT /api/v2/vault/presets/office-supplies, or buy from an allowed merchant.", "preset": { "id": "cmtvwbc0g000bjpcc88yiyx8z", "name": "office-supplies", "version": 1 }, "attachment": { "kind": "card", "last4": "7318", "target_id": "cmtvwbbzj0006jpccycjrkqy4" }, "refusals": [ { "rule": "merchant", "preset": { "id": "cmtvwbc0g000bjpcc88yiyx8z", "name": "office-supplies", "version": 1 }, "reason": "merchant_denied", "message": "Preset \"office-supplies\", attached to the card ending in 7318: merchant denied. This purchase is at braxters-deli.example. The preset allows EXAMPLE SHOP and ACME. Add the merchant to the preset with PUT /api/v2/vault/presets/office-supplies, or buy from an allowed merchant.", "attachment": { "kind": "card", "last4": "7318", "target_id": "cmtvwbbzj0006jpccycjrkqy4" } } ] } } ``` # checkout_authorization.submitted Source: https://docs.agentcard.sh/webhooks/checkout-authorizations/checkout_authorization-submitted Hosted-form processors only, instead of `approved`: the user's device attested that it submitted the processor's form. Hosted-form processors only, instead of `approved`: the user's device attested that it submitted the processor's form. No processor evidence exists, so `outcome` is `unverified` and there are no charged facts. Confirm the order with the merchant before treating it as paid. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "checkout_authorization.submitted", "created": 1757264400, "livemode": false, "data": { "authorization_id": "cauth_9k1m4x7d", "user_id": "usr_8f3k2m", "external_user_id": "usr_8f3k2m", "merchant": "order.example.com", "amount": 15000, "currency": "ils", "amount_display": "₪150.00", "amount_authority": "processor", "psp": "tranzila", "mode": "hosted_form", "submitted_at": "2026-09-02T10:42:07Z", "outcome": "unverified", "attested_by": "cardholder_device" } } ``` # checkout_authorization.watched Source: https://docs.agentcard.sh/webhooks/checkout-authorizations/checkout_authorization-watched A finished purchase broke a rule one of your presets watches. Nothing is blocked; you are being told. A purchase went through, and once the charge was recorded it turned out to break a rule of an attached preset whose `mode` is `watch`. Nothing is blocked and the money has moved; this event is the notice. Fires once, after [`checkout_authorization.approved`](/webhooks/checkout-authorizations/checkout_authorization-approved) or `checkout_authorization.submitted` for the same authorization. `outcome` is `watched` when the preset's `mode` is `watch`, or `violated` when a rule of a `strict` preset was broken only by what the processor charged, after the purchase had already been judged and allowed on the approved amount and currency. `preset` names the preset and version that judged it, `attachment` where it is attached, `rule` the kind of rule, and `message` says what the rule watches and how to stop the notices. `charged_amount` and `charged_currency` carry what the processor reported, when the user's device reported a charge. See [Set rules on a card](/vault/set-rules-on-a-card). ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "checkout_authorization.watched", "created": 1757264400, "livemode": false, "data": { "authorization_id": "cauth_f272e5eb1e27ad26fd243916", "user_id": "cmtvwbbz80002jpcctuianq78", "external_user_id": "cmtvwbbz80002jpcctuianq78", "merchant": "Example Shop", "amount": 2306, "currency": "usd", "amount_display": "$23.06", "psp": "shopify", "mode": "token", "charged_amount": null, "charged_currency": null, "outcome": "watched", "reason": "currency_watched", "rule": "currency", "message": "Preset \"watch-eur\", attached to the card ending in 7318: a $23.06 purchase at example-shop.example went through. It is in USD, and this preset allows EUR only. Nothing is blocked. To stop these notices, change the preset with PUT /api/v2/vault/presets/watch-eur.", "preset": { "id": "cmtvwbc30000tjpccm3jyui0s", "name": "watch-eur", "version": 1 }, "attachment": { "kind": "card", "target_id": "cmtvwbbzj0006jpccycjrkqy4", "last4": "7318" } } } ``` # Checkout authorization events Source: https://docs.agentcard.sh/webhooks/checkout-authorizations/overview What happened to a paused checkout: approved, submitted, declined, refused by your rules, expired, watched, or charged a different amount. Filter: `checkout_authorization.*`. Every payload carries `mode`: `token` (the device sent the card and the processor answered), `cse` (the device encrypted it for Adyen and the browser sent it), or `hosted_form` (the device submitted Tranzila's own form). None of these events confirms a merchant order. Only the merchant does. | Event | Fires when | | -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | [`checkout_authorization.approved`](/webhooks/checkout-authorizations/checkout_authorization-approved) | The user approved with their passkey and the processor answered (`token` and `cse` only). | | [`checkout_authorization.submitted`](/webhooks/checkout-authorizations/checkout_authorization-submitted) | Hosted-form processors only, instead of `approved`: the user's device attested that it submitted the processor's form. | | [`checkout_authorization.declined`](/webhooks/checkout-authorizations/checkout_authorization-declined) | The user said no, a pre-replay check or one of your presets refused it, the processor refused the card, or your runtime cancelled it. | | [`checkout_authorization.expired`](/webhooks/checkout-authorizations/checkout_authorization-expired) | Nobody approved within 15 minutes. | | [`checkout_authorization.amount_mismatch`](/webhooks/checkout-authorizations/checkout_authorization-amount_mismatch) | Fires after `approved` for the same authorization when the charge disagreed with the approval. | | [`checkout_authorization.refused`](/webhooks/checkout-authorizations/checkout_authorization-refused) | One of your presets refused the purchase before anyone was asked to approve it. No authorization exists. | | [`checkout_authorization.watched`](/webhooks/checkout-authorizations/checkout_authorization-watched) | Fires after `approved` for the same authorization when the purchase broke a rule one of your presets watches. Nothing is blocked. | # card_flow.failed Source: https://docs.agentcard.sh/webhooks/company-wallet/card_flow-failed The mint did not complete. The mint did not complete. `funds_status` says where the money went (`released_to_headroom`). ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "card_flow.failed", "created": 1757264400, "livemode": false, "data": { "transfer_id": "owt_1f2e", "cardholder_id": "ch_2b3c", "amount_cents": 2500, "reason": "mint_failed", "funds_status": "released_to_headroom" } } ``` # card_flow.started Source: https://docs.agentcard.sh/webhooks/company-wallet/card_flow-started A company-funded card mint started: a transfer from the company balance to the cardholder is about to happen. A company-funded card mint started: a transfer from the company balance to the cardholder is about to happen. When `ack_required` is true, approve the transfer before `ack_deadline` or it fails. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "card_flow.started", "created": 1757264400, "livemode": false, "data": { "transfer_id": "owt_1f2e", "cardholder_id": "ch_2b3c", "external_user_id": "your_user_42", "amount_cents": 2500, "fee_cents": 0, "transfer_cents": 2500, "ack_required": true, "ack_deadline": "2026-09-07T17:06:00Z", "client_id": "client_a1b2c3" } } ``` # cardholder.created Source: https://docs.agentcard.sh/webhooks/company-wallet/cardholder-created A cardholder was created for your organization. A cardholder was created for your organization. `cardholder.updated` fires with the same shape when their KYC status or details change. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "cardholder.created", "created": 1757264400, "livemode": false, "data": { "id": "ch_2b3c", "first_name": "Ada", "last_name": "Lovelace", "kyc_status": "approved" } } ``` # cardholder_onboarding_session.completed Source: https://docs.agentcard.sh/webhooks/company-wallet/cardholder_onboarding_session-completed A hosted onboarding session finished and the cardholder exists. A hosted onboarding session finished and the cardholder exists. `external_user_id` is the id you passed. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "cardholder_onboarding_session.completed", "created": 1757264400, "livemode": false, "data": { "id": "cos_8d9e", "cardholder_id": "ch_2b3c", "external_user_id": "your_user_42" } } ``` # Company wallet events Source: https://docs.agentcard.sh/webhooks/company-wallet/overview Events for organizations that fund cards from a company balance: cardholders, card flows, transfers, recoveries. These belong to the company-funded card flow, where your organization allocates spending power to cardholders from its own balance. Filter: `cardholder.*`, `cardholder_onboarding_session.*`, `card_flow.*`, `transfer.*`, `recovery.*`, `wallet.*`. | Event | Fires when | | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | | [`cardholder.created`](/webhooks/company-wallet/cardholder-created) | A cardholder was created for your organization. | | [`cardholder_onboarding_session.completed`](/webhooks/company-wallet/cardholder_onboarding_session-completed) | A hosted onboarding session finished and the cardholder exists. | | [`card_flow.started`](/webhooks/company-wallet/card_flow-started) | A company-funded card mint started: a transfer from the company balance to the cardholder is about to happen. | | [`card_flow.failed`](/webhooks/company-wallet/card_flow-failed) | The mint did not complete. | | [`transfer.approved`](/webhooks/company-wallet/transfer-approved) | The transfer was approved (by API or in the dashboard). | | [`transfer.completed`](/webhooks/company-wallet/transfer-completed) | The funds reached the cardholder. | | [`recovery.requested`](/webhooks/company-wallet/recovery-requested) | Residual spending power on a cardholder is being recovered back to the company pool. | | [`wallet.funded`](/webhooks/company-wallet/wallet-funded) | The company balance received funds. | | [`wallet.balance.low`](/webhooks/company-wallet/wallet-balance-low) | The company balance dropped below the threshold you set, accounting for committed funds. | # recovery.requested Source: https://docs.agentcard.sh/webhooks/company-wallet/recovery-requested Residual spending power on a cardholder is being recovered back to the company pool. Residual spending power on a cardholder is being recovered back to the company pool. `recovery.completed` and `recovery.rejected` (with `failure_reason`) follow. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "recovery.requested", "created": 1757264400, "livemode": false, "data": { "recovery_id": "rcv_7a8b", "cardholder_id": "ch_2b3c", "external_user_id": "your_user_42", "amount_cents": 1200 } } ``` # transfer.approved Source: https://docs.agentcard.sh/webhooks/company-wallet/transfer-approved The transfer was approved (by API or in the dashboard). The transfer was approved (by API or in the dashboard). `transfer.initiated`, `transfer.completed`, `transfer.failed`, and `transfer.released` follow the same shape with `transferred_cents`, `tx_hash`, or `reason` as the stage requires. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "transfer.approved", "created": 1757264400, "livemode": false, "data": { "transfer_id": "owt_1f2e", "cardholder_id": "ch_2b3c", "amount_cents": 2500, "approved_via": "api" } } ``` # transfer.completed Source: https://docs.agentcard.sh/webhooks/company-wallet/transfer-completed The funds reached the cardholder. The funds reached the cardholder. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "transfer.completed", "created": 1757264400, "livemode": false, "data": { "transfer_id": "owt_1f2e", "cardholder_id": "ch_2b3c", "amount_cents": 2500, "transferred_cents": 2500, "tx_hash": "0xabab…" } } ``` # wallet.balance.low Source: https://docs.agentcard.sh/webhooks/company-wallet/wallet-balance-low The company balance dropped below the threshold you set, accounting for committed funds. The company balance dropped below the threshold you set, accounting for committed funds. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "wallet.balance.low", "created": 1757264400, "livemode": false, "data": { "balance_cents": 4000, "threshold_cents": 50000, "committed_cents": 2500 } } ``` # wallet.funded Source: https://docs.agentcard.sh/webhooks/company-wallet/wallet-funded The company balance received funds. The company balance received funds. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "wallet.funded", "created": 1757264400, "livemode": false, "data": { "amount_cents": 100000, "balance_cents": 250000 } } ``` # approval.requested Source: https://docs.agentcard.sh/webhooks/connections/approval-requested An action on this user's card needs their approval, for example another connected app asking to close a card. An action on this user's card needs their approval, for example another connected app asking to close a card. Show them `action` and wait; the request expires at `expires_at`. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "approval.requested", "created": 1757264400, "livemode": false, "data": { "approval_id": "appr_4d5e6f", "action": "cross_app:close", "card_id": "card_7h2k", "last4": "7318", "requested_by": { "client_id": "client_x9y8z7", "name": "Sample App" }, "expires_at": "2026-09-07T17:15:00Z", "connection": { "client_id": "client_a1b2c3", "scope": "user_connection" } } } ``` # connection.created Source: https://docs.agentcard.sh/webhooks/connections/connection-created A user finished connecting to your platform: they verified the code on `/connect/verify`, or completed attested onboarding. A user finished connecting to your platform: they verified the code on `/connect/verify`, or completed attested onboarding. Carries `onboarding_attempt_id` in the latter case, so you know to exchange the attempt for the connection. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "connection.created", "created": 1757264400, "livemode": false, "data": { "user_id": "user_7g8h9i", "channel": "phone", "external_user_id": "partner_u_123", "client_id": "client_a1b2c3" } } ``` # Connection events Source: https://docs.agentcard.sh/webhooks/connections/overview A user connected to your platform, opened their wallet link, or an action needs their approval. Filter: `connection.*`, `wallet_link.*`, `approval.*`. | Event | Fires when | | ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | | [`connection.created`](/webhooks/connections/connection-created) | A user finished connecting to your platform: they verified the code on `/connect/verify`, or completed attested onboarding. | | [`wallet_link.opened`](/webhooks/connections/wallet_link-opened) | The user opened a wallet link you minted, the first time only. | | [`approval.requested`](/webhooks/connections/approval-requested) | An action on this user's card needs their approval, for example another connected app asking to close a card. | # wallet_link.opened Source: https://docs.agentcard.sh/webhooks/connections/wallet_link-opened The user opened a wallet link you minted, the first time only. The user opened a wallet link you minted, the first time only. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "wallet_link.opened", "created": 1757264400, "livemode": false, "data": { "id": "wl_3k1v9d2q", "user_id": "user_7g8h9i", "opened_at": "2026-09-07T17:05:12Z" } } ``` # identity.verification.updated Source: https://docs.agentcard.sh/webhooks/identity-verification/identity-verification-updated The verification moved to a new status: `awaiting_documents`, `needs_information`, `requires_verification`, `pending`, `approved`, or `rejected`. The verification moved to a new status: `awaiting_documents`, `needs_information`, `requires_verification`, `pending`, `approved`, or `rejected`. On actionable statuses `iframe_url` is the page that collects what is still needed. Imported (reusable KYC) verifications fire the same event. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "identity.verification.updated", "created": 1757264400, "livemode": false, "data": { "user_id": "user_7g8h9i", "status": "requires_verification", "iframe_url": "https://in.sumsub.com/websdk/p/…" } } ``` # Identity verification events Source: https://docs.agentcard.sh/webhooks/identity-verification/overview A user's KYC status changed. Filter: `identity.*`. The alternative to polling `GET /api/v2/kyc`. | Event | Fires when | | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- | | [`identity.verification.updated`](/webhooks/identity-verification/identity-verification-updated) | The verification moved to a new status: `awaiting_documents`, `needs_information`, `requires_verification`, `pending`, `approved`, or `rejected`. | # order.confirmed Source: https://docs.agentcard.sh/webhooks/orders/order-confirmed Retail orders only, in addition to `order.placed`: the retailer accepted the order on its side (usually within a minute) and issued its own order number, delivery window, and final total. Retail orders only, in addition to `order.placed`: the retailer accepted the order on its side (usually within a minute) and issued its own order number, delivery window, and final total. `charged_cents` is what the paying card was finally charged. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "order.confirmed", "created": 1757264400, "livemode": false, "data": { "order_id": "3f9a8c1b-7d2e-4c5a-9b1f-2e8d4a6c0b17", "merchant": "retail", "merchant_name": "Amazon", "conversation_id": "cmsq18x2m00a1", "user_id": "usr_8f3k2m", "payment_source": { "source": "vault", "brand": "visa", "last4": "4832" }, "retailer_order_id": "112-1234567-1234567", "delivery_window": "Sat, Sep 6 - Tue, Sep 9", "final_total_cents": 2306, "charged_cents": 2306, "currency": "usd", "placed_at": "2026-09-01T21:40:11.902Z", "confirmed_at": "2026-09-01T21:41:20.114Z" } } ``` # order.failed Source: https://docs.agentcard.sh/webhooks/orders/order-failed A confirm ended without a placed order. A confirm ended without a placed order. `code` is the gate's reason (`vault_approval_required`, `byoc_approval_required`, `sandbox_mode`, `per_txn_max_exceeded`, …) or the merchant's (`items_unavailable`, `pos_cart_validation`, `address_changed`). An approval pause carries `approval_url` and `retryable: true`: show the link, then send the same confirm again. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "order.failed", "created": 1757264400, "livemode": false, "data": { "order_id": null, "merchant": "retail", "merchant_name": "Amazon", "conversation_id": "cmsq18x2m00a1", "user_id": "usr_8f3k2m", "code": "vault_approval_required", "message": "This purchase needs the cardholder's approval.", "retryable": true, "approval_url": "https://vault.agentcard.sh/authorize?id=cauth_…", "approval_id": null, "approval_expires_at": null, "total_cents": 2306, "payment_source": { "source": "vault", "brand": "visa", "last4": "4832" }, "items": null, "charge_status": "none" } } ``` # order.placed Source: https://docs.agentcard.sh/webhooks/orders/order-placed An order was placed at the merchant. An order was placed at the merchant. `charge_status` is `settled` when the charge is confirmed and `confirming` when the order is placed but the charge is still confirming. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "order.placed", "created": 1757264400, "livemode": false, "data": { "order_id": "3f9a8c1b-7d2e-4c5a-9b1f-2e8d4a6c0b17", "merchant": "retail", "merchant_name": "Amazon", "conversation_id": "cmsq18x2m00a1", "user_id": "usr_8f3k2m", "total_cents": 2306, "currency": "usd", "charge_status": "settled", "payment_source": { "source": "vault", "brand": "visa", "last4": "4832" }, "placed_at": "2026-09-01T21:40:11.902Z" } } ``` # Order events Source: https://docs.agentcard.sh/webhooks/orders/overview Every confirm on the Purchase API ends in exactly one order event, plus a confirmation when the retailer accepts. Filter: `order.*`. Every confirm on `POST /buy` produces exactly one `order.placed` or `order.failed` to the company that owns the connection. `order_id` is the same key the `/buy` envelope carries. Reconcile on it, never on amount and time. | Event | Fires when | | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [`order.placed`](/webhooks/orders/order-placed) | An order was placed at the merchant. | | [`order.confirmed`](/webhooks/orders/order-confirmed) | Retail orders only, in addition to `order.placed`: the retailer accepted the order on its side (usually within a minute) and issued its own order number, delivery window, and final total. | | [`order.failed`](/webhooks/orders/order-failed) | A confirm ended without a placed order. | # Webhooks Source: https://docs.agentcard.sh/webhooks/overview How Agentcard events reach your server: connect an endpoint, verify the signature, and handle retries. Everything that happens to your connected users reaches your server as a webhook: a card stored in the Vault, a checkout approved, an order placed, an identity check finished. SDK callbacks are UI signals. Webhooks are the record. ## Connect an endpoint Register a URL and the events it should receive. Do it once per mode: a sandbox token registers a sandbox endpoint, a production token a production one. ```bash theme={null} curl -X POST https://api.agentcard.sh/api/v2/webhook_endpoints \ -H "Authorization: Bearer $ORG_TOKEN" \ -H "Content-Type: application/json" \ -d '{"url": "https://your.app/agentcard/webhooks", "enabled_events": ["vault.*", "checkout_authorization.*", "order.*"]}' ``` The response carries the endpoint's `secret` once. Store it. `enabled_events` takes exact names, prefix wildcards like `vault.*`, or `["*"]` for everything. An endpoint receives only what it lists. Manage endpoints, read or rotate the secret, and inspect recent deliveries with the [Webhook endpoints API](/api-reference/webhook-endpoints/overview). The same is available in the dashboard under Developers → Webhooks. ## The envelope Every event has the same shape: ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "vault.card_stored", "created": 1757264400, "livemode": false, "data": { } } ``` `type` is stable and part of the API contract, so branch on it directly. `livemode: false` is sandbox. Delivery is at least once, so deduplicate on `id`. ## Verify the signature Each delivery carries an `AgentCard-Signature` header: ``` AgentCard-Signature: t=1757264400,v1=5257a869e7… ``` Take `t`, join it to the raw request body with a dot, compute HMAC-SHA256 with your endpoint's secret, and compare it to `v1` in constant time. Reject timestamps older than a few minutes to block replays. Verify against the raw bytes, never re-serialized JSON. <CodeGroup> ```javascript Node theme={null} const [t, v1] = header.split(",").map((p) => p.split("=")[1]); const expected = crypto .createHmac("sha256", process.env.AGENTCARD_WEBHOOK_SECRET) .update(`${t}.${rawBody}`) .digest("hex"); const valid = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1)); ``` ```python Python theme={null} import hmac, hashlib, os t, v1 = (part.split("=", 1)[1] for part in header.split(",")) expected = hmac.new( os.environ["AGENTCARD_WEBHOOK_SECRET"].encode(), f"{t}.{raw_body}".encode(), hashlib.sha256, ).hexdigest() valid = hmac.compare_digest(expected, v1) ``` </CodeGroup> A legacy `X-AgentCard-Signature: sha256=…` header signs the body alone. New integrations should use `AgentCard-Signature`. ## Delivery and retries Return a `2xx` quickly and do slow work afterwards. A slow handler looks like a failure. Failed deliveries retry up to five times: immediately, then after 1 minute, 5 minutes, 30 minutes, and 1 hour. Recent deliveries with payloads and response codes are on [List recent deliveries](/api-reference/webhook-endpoints/deliveries) and in the dashboard. ## Develop locally No tunnel needed. The CLI registers a listener endpoint and forwards every event to your machine, signed exactly like production: ```bash theme={null} agent-cards companies webhooks listen --forward-to localhost:4000/webhooks agent-cards companies webhooks test ``` ## Sandbox Sandbox events deliver exactly like production, with `livemode: false`. Endpoints are scoped to one mode: if your sandbox integration completes actions but nothing arrives, check that the endpoint was created with a sandbox token. ## Events by object <CardGroup> <Card title="Connections" href="/webhooks/connections/overview">`connection.created`, `wallet_link.opened`, `approval.requested`</Card> <Card title="Vault" href="/webhooks/vault/overview">`vault.session_linked`, `vault.card_stored`</Card> <Card title="Checkout authorizations" href="/webhooks/checkout-authorizations/overview">approved, submitted, declined, expired, amount\_mismatch</Card> <Card title="Orders" href="/webhooks/orders/overview">`order.placed`, `order.confirmed`, `order.failed`</Card> <Card title="Cards and transactions" href="/webhooks/cards/overview">`card.*`, `transaction.*`, `balance.low`</Card> <Card title="Identity verification" href="/webhooks/identity-verification/overview">`identity.verification.updated`</Card> <Card title="Wallet" href="/webhooks/wallet/overview">`user_wallet.funding_detected`, `user_wallet.funded`</Card> <Card title="Rewards and merchants" href="/webhooks/rewards/overview">`reward.*`, `merchant.connected`</Card> <Card title="Company wallet" href="/webhooks/company-wallet/overview">`cardholder.*`, `card_flow.*`, `transfer.*`, `recovery.*`, `wallet.*`</Card> </CardGroup> # merchant.connected Source: https://docs.agentcard.sh/webhooks/rewards/merchant-connected The user linked a merchant account (for example DoorDash) that `/buy` can now order from. The user linked a merchant account (for example DoorDash) that `/buy` can now order from. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "merchant.connected", "created": 1757264400, "livemode": false, "data": { "cardholder_id": "ch_2b3c", "merchant": "doordash" } } ``` # Reward and merchant events Source: https://docs.agentcard.sh/webhooks/rewards/overview Agentcard points earned or reversed, and a merchant account connected for the Purchase API. Filter: `reward.*`, `merchant.*`. | Event | Fires when | | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------- | | [`reward.earned`](/webhooks/rewards/reward-earned) | The user earned Agentcard points on a transaction. | | [`reward.reversed`](/webhooks/rewards/reward-reversed) | Points were reversed, for a refund or a voided transaction. | | [`merchant.connected`](/webhooks/rewards/merchant-connected) | The user linked a merchant account (for example DoorDash) that `/buy` can now order from. | # reward.earned Source: https://docs.agentcard.sh/webhooks/rewards/reward-earned The user earned Agentcard points on a transaction. The user earned Agentcard points on a transaction. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "reward.earned", "created": 1757264400, "livemode": false, "data": { "tokens": 12, "merchant": "OPENAI *CHATGPT SUBSCR", "card_id": "card_7h2k", "user_id": "user_7g8h9i", "transaction_id": "txn_3f9a" } } ``` # reward.reversed Source: https://docs.agentcard.sh/webhooks/rewards/reward-reversed Points were reversed, for a refund or a voided transaction. Points were reversed, for a refund or a voided transaction. `earn_transaction_id` names the original earn; null for a standalone refund. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "reward.reversed", "created": 1757264400, "livemode": false, "data": { "tokens": 12, "merchant": "OPENAI *CHATGPT SUBSCR", "card_id": "card_7h2k", "user_id": "user_7g8h9i", "transaction_id": "txn_5c1d", "earn_transaction_id": "txn_3f9a" } } ``` # Vault events Source: https://docs.agentcard.sh/webhooks/vault/overview A vault session linked to a user, and a card landed in their vault. Filter: `vault.*`. Both fire for vault sessions you created and for links you sent with `POST /api/v2/checkout/vault_link`. | Event | Fires when | | -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | | [`vault.session_linked`](/webhooks/vault/vault-session_linked) | An open vault session got its user: a new enrollment finished, or a returning user signed in with their passkey. | | [`vault.card_stored`](/webhooks/vault/vault-card_stored) | The user stored a card in their vault. | # vault.card_stored Source: https://docs.agentcard.sh/webhooks/vault/vault-card_stored The user stored a card in their vault. The user stored a card in their vault. The card is now available to checkout authorizations for this user. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "vault.card_stored", "created": 1757264400, "livemode": false, "data": { "user_id": "usr_8f3k2m", "card_id": "vc_9m4t2p", "brand": "visa", "last4": "4832", "vault_session_id": "vs_2q9d1x8f3k2m4t7w" } } ``` # vault.session_linked Source: https://docs.agentcard.sh/webhooks/vault/vault-session_linked An open vault session got its user: a new enrollment finished, or a returning user signed in with their passkey. An open vault session got its user: a new enrollment finished, or a returning user signed in with their passkey. Store `user_id`. A connected session already named its user, so it does not fire this event. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "vault.session_linked", "created": 1757264400, "livemode": false, "data": { "vault_session_id": "vs_2q9d1x8f3k2m4t7w", "user_id": "usr_8f3k2m" } } ``` # Wallet events Source: https://docs.agentcard.sh/webhooks/wallet/overview Funds arriving in a connected user's wallet. Filter: `user_wallet.*`. | Event | Fires when | | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | | [`user_wallet.funding_detected`](/webhooks/wallet/user_wallet-funding_detected) | A deposit to the user's wallet address was seen on chain and is confirming. | | [`user_wallet.funded`](/webhooks/wallet/user_wallet-funded) | The deposit was credited. | # user_wallet.funded Source: https://docs.agentcard.sh/webhooks/wallet/user_wallet-funded The deposit was credited. The deposit was credited. `GET /api/v2/wallet` now reflects it. Funding sessions created with `POST /api/v2/wallet/fund` end here too. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "user_wallet.funded", "created": 1757264400, "livemode": false, "data": { "user_id": "user_7g8h9i", "amount_usdc": "25.00", "wallet_address": "0xefef…", "credited_at": "2026-09-07T17:06:40Z" } } ``` # user_wallet.funding_detected Source: https://docs.agentcard.sh/webhooks/wallet/user_wallet-funding_detected A deposit to the user's wallet address was seen on chain and is confirming. A deposit to the user's wallet address was seen on chain and is confirming. ```json theme={null} { "id": "evt_9f8e7d6c5b4a", "type": "user_wallet.funding_detected", "created": 1757264400, "livemode": false, "data": { "user_id": "user_7g8h9i", "amount_usdc": "25.00", "wallet_address": "0xefef…", "detected_at": "2026-09-07T17:05:12Z" } } ```