# 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