> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentcard.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

> Authenticated requests on behalf of your users

Every authenticated request in a company integration goes through the Agentcard MCP server, with the user's OAuth access token:

```
POST https://mcp.agentcard.sh/mcp
Authorization: Bearer <access_token>
Accept: application/json, text/event-stream
```

It's a standard MCP server over Streamable HTTP: `initialize` → `notifications/initialized` → `tools/list` → `tools/call`, echoing the `Mcp-Session-Id` header. Any spec-compliant MCP client handles this for you — point it at the URL with the token from the [OAuth flow](/companies/authentication/oauth) and the tools load automatically.

## Expose the tools dynamically

Register every tool `tools/list` returns instead of hardcoding names. Tools Agentcard ships later then appear in your integration with zero code change. If you ever need a denylist, make it config-driven and default it to empty.

### Tool gating

Two groups are hidden from the default `tools/list`. Every gated tool remains callable by name; gating trims what agents discover, not what dispatches:

* **Shopping granulars**: the `buy_*` flow tools. The conversational [buy](/companies/mcp/tools/buy) tool drives them server-side, so agents only need `buy`.
* **Advanced tools**: niche analytics, error-triggered one-offs, and companions of an advertised tool: `list_all_transactions`, `list_transactions_by_payment_method`, `submit_funding_profile`, `complete_kyc_transfer`, `list_codes`, `set_default_payment_method`, `remove_payment_method`, `cancel_plan`, and `update_settings`. A typical agent never needs to discover these to complete a core flow; each one's page carries an "Advanced tool" note.

Browse the full surface, gated tools included, with `agent-cards api tools --all`.

## Reading tool results

Two conventions worth wiring into your client up front:

* **Result fields are camelCase** (`cardId`, `spendLimitCents`, `cardStatus: "OPEN"`), while **request parameters and the REST v2 API are snake\_case** (`card_id`, `spend_limit_cents`). Don't assume one casing across both directions — send snake\_case, read camelCase.
* **`isError` flags rejected calls.** A rejected call (a validation failure, a missing or invalid resource, an operation that didn't happen) sets `isError: true`, with the reason in the text and a `status` discriminator in `structuredContent`. A successful call leaves `isError` unset, *including* one that returns a modeled next step like `approval_required` or `kyc_required` (an outcome to act on, not a failure). This flag is still rolling out across the tool surface: the card-lifecycle tools ([pause\_card](/companies/mcp/tools/pause_card), [resume\_card](/companies/mcp/tools/resume_card), [update\_card\_limit](/companies/mcp/tools/update_card_limit)) set it today and the rest are following. So treat `isError: true` as authoritative wherever you see it, but until the rollout finishes don't read its *absence* as a guaranteed success on every tool: branch on `isError` when present, then on the `status` discriminator in `structuredContent`.

## Approval gates

Sensitive calls can pause for explicit approval. When [create\_card](/companies/mcp/tools/create_card) or [get\_card\_details](/companies/mcp/tools/get_card_details) returns a status of `approval_required` with an `approval_id`, nothing has happened yet — resolve it with [approve\_request](/companies/mcp/tools/approve_request). Auto-approve when the user just asked for the action; confirm with them first before revealing card credentials.

<Warning>
  `get_card_details` returns the full card number and CVV. Never write these to logs, error reports, or analytics.
</Warning>

Whether those cards are **live or test** is set by the OAuth client your app connected with: a **sandbox** client mints test cards (no real charge), a **production** client mints live cards (which requires an active subscription). See [Production](/companies/production).

## Funding and KYC

Cards are funded from the user's Agentcard wallet. If `create_card` reports that KYC or wallet funding is needed, relay the message to the user — they complete it in their own account — then retry. If a deposit is still confirming, wait the suggested interval and retry.

## One wallet across apps

The user has one wallet, and every connected app sees it. [list\_cards](/companies/mcp/tools/list_cards) returns a `wallet` array: every live card the user holds, personal and company-funded, whatever app minted it, each row tagged with:

* `access`: `owned` (your connection minted it; full control) or `connected` (visible, but actions need the user's approval or are read-only). This field is server-authoritative and relative to *your* session: key any read-only affordances off it, never off heuristics.
* `source`: where the card came from, `{ kind: "personal" | "company", app, appName }`, plus `companyId`/`companyName` on company-funded rows.

The legacy `cards` and `connectedAccounts` fields keep their pre-shared-wallet semantics (`cards` is only what your connection created), so nothing built against them breaks.

### Acting on another app's card

Card actions on a **personal card another app minted** don't fail; they pause for the user's approval. The five gated verbs are [get\_card\_details](/companies/mcp/tools/get_card_details), [close\_card](/companies/mcp/tools/close_card), [pause\_card](/companies/mcp/tools/pause_card), [resume\_card](/companies/mcp/tools/resume_card), and [update\_card\_limit](/companies/mcp/tools/update_card_limit):

1. Call the tool as usual. If the card is `connected`, it returns `status: "approval_required"` with an `approvalId` (`kind: "cross_app"`, HTTP 202 on the REST surface); nothing has happened yet.
2. The user is emailed an approve/deny link. This gate is resolved by that link, **not** by `approve_request`.
3. Once they approve, retry the **same tool** with `approval_id` set.

Approvals are single-use, expire after 10 minutes, and bind to the exact card, action, and requesting app (and, for `update_card_limit`, the exact new limit). A consumed, expired, or mismatched approval returns `approval_not_valid`; retry without `approval_id` for a fresh one.

**Company-funded cards stay read-only** from other apps (`managed_by_organization`): the owning company manages them via its own surface.

## Card isolation

A token from your client can only **act** on the cards your app created for that user (plus cross-app actions the user explicitly approves, above). It can't touch another user's anything. A brand-new connection listing zero cards in the legacy `cards` field is expected, not a bug.

## The tools

Browse the sidebar for every tool — each has its own page with parameters, returns, and an example call. The ones you'll use most: [create\_card](/companies/mcp/tools/create_card), [get\_card\_details](/companies/mcp/tools/get_card_details), [list\_cards](/companies/mcp/tools/list_cards), [get\_card\_balance](/companies/mcp/tools/get_card_balance), [close\_card](/companies/mcp/tools/close_card), and [approve\_request](/companies/mcp/tools/approve_request).
