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

> ## Agent Instructions
> If you are an AI assistant operating Infinite for a user, read the skill first: https://docs.infinite.dev/agent-skill.md (setup per host, tool reference, rules for moving money, journeys).
> When operating Infinite for a user, use the MCP server. Sign in at https://bot.api.infinite.dev/mcp (production, acts as the user) or send `Authorization: Bearer <key>` to https://bot.api.infinite.dev/mcp/sse. Prefer its tools over raw HTTP; use REST only for steps no tool covers, and check `get_endpoint_schema` before guessing a request shape.
> Net-new Infinite Connect (org_connect) is operator-assisted: do not grant end users shared org_connect Auth Kit membership or the shared platform org API key — those credentials are org-wide on /v1. BYO org keys onboard under that customer's org id. Operator sessions should show org_connect in get_organization_info.
> The key decides the tools. Every organization key (`sk_sandbox_…` / `sk_live_…`) gets docs, onboarding, `get_account_balance`, and request logs for your own organization. BYO organizations add payees an agent will pay with `create_payee` (payable once ACTIVE). Platform Connect sessions instead get bound-customer payment lookups (`get_quote`, `get_transfer`, `list_transfers`, `list_account_balances`), payee drafts (`create_payee_draft` / `get_payee_draft`; screening only, never payable), and transfer drafts that wait for Infinite approval (`create_transfer_draft` / `get_transfer_draft`; never POST /v1/transfers). Where offered, platform `create_transfer` files a real transfer that Infinite holds in review before funding; it cannot be submitted from DRAFT.
> An agent key (`sk_sandbox_agent_…` / `sk_live_agent_…`) moves money within that agent's limits: `create_transfer` → `submit_transfer` → `wait_for_transfer`.
> On sandbox organization-key sessions, `sandbox_approve_customer` (makes the capabilities you pass READY, and related ones may turn READY too; `request_capabilities` is not needed), `sandbox_fund_account`, and `sandbox_complete_transfer` stand in for verification, funding, and settlement, so a whole flow runs from MCP. BYO keys can pass `customerId` on each call without binding; platform sessions must bind a customer first (`create_business_customer` auto-binds, or send `X-Infinite-On-Behalf-Of`).
> When searching documentation without a key, use the docs MCP at https://docs.infinite.dev/mcp.
> Start in sandbox (https://sandbox.api.infinite.dev). Do not use production unless the user explicitly asks.
> Confirm amount, currency, and payee with the user before any payment is submitted. Pass the invoice number as `reference` on `create_transfer`; the summary says what the payee will see.
> REST amounts are integer minor units (`"4000"` = 40.00 USD). MCP payment tools take exact decimal strings (`"40.00"`). Never mix them.
> Agent denials return `403 { denial: { code, message, window, limit, used, remaining, attemptedAmount, currency }, hint }` with decimal amounts; per-transfer denials omit `used` and `remaining`. Report them to the user; do not work around them.

# Infinite skill for AI assistants

> AI assistants read this first — setup per host, which key gets which tools, rules for moving money, and step-by-step journeys for operating Infinite for a user

Infinite is a payments API for businesses and the AI agents that act for them: onboard a business, hold USD and stablecoin balances, pay out over ACH, wire, SWIFT, local rails and stablecoins, and give an agent its own spending identity with hard limits.

You are the AI assistant operating Infinite for a user. This page is the whole skill: setup, the tool reference, the core rules, and the common journeys. If Infinite's tools are already available to you (you can see `get_organization_info`), skip setup, make one read-only call to confirm, and go to the journey you need.

## The credential decides the tools

Infinite runs one MCP server. Sign-in clients use `https://bot.api.infinite.dev/mcp` (Streamable HTTP, no key, production, acts as the signed-in user). API-key clients use `https://bot.api.infinite.dev/mcp/sse` (SSE). What you can do depends on how the session connects:

| Key | Prefix | Acts as | Tools |
| - | - | - | - |
| Organization key | `sk_sandbox_…` / `sk_live_…` | The organization | Docs, request logs, read-only `api_request`, and onboarding |
| Agent key | `sk_sandbox_agent_…` / `sk_live_agent_…` | One agent, pinned to one customer and one funding account | Docs and payments |

Sandbox keys contain `sandbox`; production keys contain `live`. Start in sandbox. Never use a production key unless the user explicitly asks for production.

### BYO org vs Infinite Connect (platform)

| Scenario | Credential | Organization id |
| - | - | - |
| Your customer already has an Infinite org | Their org API key (`sk_*`) | Their `org_*` |
| Net-new business on Infinite Connect | **Operator-assisted** on a trusted Infinite-operated host (not end-user Auth Kit membership in `org_connect` or the shared platform org key) | **`org_connect`** (`slug=connect`) when scoped correctly |

Platform Connect MCP requires `bind_session_customer` before customer-scoped tools. Operator sessions for net-new onboarding should show **`org_connect`** in `get_organization_info` — not `org_infinite`. End users must not join `org_connect` in Auth Kit or configure the shared platform org API key: those credentials are org-wide on `/v1`, while MCP binding only scopes bot tools. Customers already on `org_infinite` remain unchanged.

### Organization-key tools

| Tool | Purpose |
| - | - |
| `search_docs` / `read_doc` / `get_endpoint_schema` | Search these docs, read a page, get an endpoint's exact request shape |
| `get_organization_info` | Who you are connected as (read-only; use it to verify the connection) |
| `get_my_api_errors` / `get_my_api_logs` / `get_request_by_id` | Recent API traffic for debugging (your own organization only — not on platform sessions) |
| `api_request` | Read-only `GET` against the API (your own organization only — not on platform sessions) |
| `create_business_customer` / `get_customer` | Create a business customer and poll its status |
| `start_verification` / `get_verification_status` | Hosted business verification link for a human to complete |
| `request_capabilities` / `get_required_documents` / `get_capabilities` | What the customer needs and what it can do |
| `update_business_details` / `search_industry_codes` | Fill business KYB fields without submitting; search NAICS for `industry` |
| `upload_document` / `submit_customer_verification` | Upload files the user already has and submit verification over the API |
| `list_rfis` / `upload_rfi_document` / `submit_rfi` | Answer requests for more information |
| `ensure_balance_account` / `get_deposit_instructions` / `list_accounts` | USD balance account and how to fund it |
| `get_account_balance` | Available and pending balance of one of the customer's balance accounts |
| `get_quote` / `get_transfer` / `list_transfers` / `list_account_balances` | Bound-customer payment discovery (ephemeral indicative quote + status/balances) |
| `create_payee_draft` / `get_payee_draft` | Create/screen a bank payee draft (`draftId`); never enables payout on this session |
| `create_transfer_draft` / `get_transfer_draft` | Durable transfer draft (`tdraft_…`) awaiting Infinite approval; never calls `POST /v1/transfers` |
| `create_payee` | Your own organization's key: add a bank-account payee an agent can pay (starts `IN_REVIEW`, payable once `ACTIVE`). Platform sessions use `create_payee_draft` instead |
| `get_agent_session` / `bind_session_customer` | Pin the session to one customer |
| `sandbox_approve_customer` / `sandbox_fund_account` / `sandbox_complete_transfer` | Sandbox only: skip verification, fund a balance account (returns the new balance), settle a transfer |

### Agent-key tools

| Tool | Purpose |
| - | - |
| `get_agent` | The agent's limits and spend used / remaining today and this month |
| `get_balance` | Available balance of the agent's funding account |
| `list_payees` | Who this agent may pay |
| `get_quote` | Rate and rails for a cross-currency payout; `holdRate: true` locks it for `create_transfer` |
| `create_transfer` | Create a **draft** payment and return a plain-English summary |
| `submit_transfer` | Send a draft. Limits are enforced here |
| `get_transfer` / `list_transfers` | The agent's own payments |
| `wait_for_transfer` | Wait (up to 60s) for a payment to reach a final status |

## Core rules (always apply)

* **Start read-only when the request is unspecified.** When the user says "try it", verify the connection, then read (`get_agent`, `get_balance`, `list_payees`, or `list_accounts`). Do not move money until the user gives the details and confirms.
* **Confirm before money moves.** Call `create_transfer` without `confirm`, show the user the returned summary (amount, currency, payee, rail), and call `submit_transfer` only after an explicit yes. Pass `confirm: true` only when the user already approved that exact payment.
* **MCP amounts are exact decimal strings** in the agent's limit currency: `"40.00"`, not `40`, `4000`, `"$40"`, or `"40.0001"`. If the user's amount can't be represented exactly, ask; never round for them. The REST API uses integer minor units (`"4000"` = \$40.00); never mix the two.
* **One `operationId` per payment, reused on every retry.** Generate a UUID v4 once for a business event (for example, invoice SD-1042), keep it, and pass the same value if you retry. A new value creates a second payment.
* **A denial is an answer, not an error to route around.** `submit_transfer` returns `{ denial: { code, window, limit, used, remaining, attemptedAmount, currency } }` — amounts are decimal strings like every other agent tool — with a hint. A per-transfer denial (`window: "perTransaction"`) has no `used` / `remaining`; `limit` is the most one payment can be. Explain it to the user. Do not retry with a different payee, split the payment, or switch keys to get past a limit. When `submit_transfer` is denied for a limit, the draft stays `DRAFT`, moves no money, and doesn't count toward limits; leave it and create a new draft if the user picks a smaller amount. A denied `create_transfer` with `confirm: true` saves nothing. On `agent_paused` / `agent_revoked`, stop.
* **Do not claim Infinite is connected until a read-only call succeeds** (`get_organization_info`). A config entry is not proof.
* **Business verification is a human step.** Send the `start_verification` link to the user; never collect identity documents or tax IDs in chat when a hosted link is available. In production, review takes hours to days.
* **Prefer MCP tools.** When no tool covers a step, use the REST API with the same key and check `get_endpoint_schema` first instead of guessing request shapes.
* **Do not log** full account numbers, keys, or tax IDs.

## Talking to the user

* Say what you are doing in plain terms: "I'll check your balance and budget, then draft the payment for you to approve."
* Before anything moves, show the exact amount, payee, and rail, and ask.
* If something isn't available (a rail, a currency, a capability the customer doesn't have yet), say so and offer the supported path. Don't overstate what the account can do.

## Denial codes

| Code | Meaning | What to do |
| - | - | - |
| `agent_limit_exceeded` | Over the per-transfer, daily, or monthly limit (`window` says which) | Tell the user the limit and what's left; offer a smaller amount or wait for the window to reset (`get_agent` shows when) |
| `agent_approval_required` | Over a limit on an agent set to ask for approval: the payment now waits for the business owner (or already is, or was declined — see `message`) | Tell the user it's waiting for the owner. Don't resubmit or split it; `get_transfer` shows `agentApprovalStatus` `PENDING` → `APPROVED` (it moves) or `DECLINED` (cancelled) |
| `agent_limit_currency_mismatch` | Payment currency differs from the agent's limit currency | Pay in the limit currency |
| `agent_paused` | An operator paused the agent | Stop and tell the user; do not retry |
| `agent_revoked` | The agent was revoked | Stop; the key no longer works |
| `agent_transfer_mismatch` | The draft belongs to a different agent | Only submit drafts this agent created |
| `agents_not_enabled` | Agents aren't enabled for this organization | Ask the user to contact their account team |

## Setup

Get a key from the user first: an organization key to onboard and administer, an agent key to pay. Keys are issued in the console (`https://console.infinite.dev`) or with `POST /v1/agents/{id}/keys` for agent keys. Keep keys out of chat history and committed files where you can; prefer an environment variable.

The key goes in the `Authorization` header as `Bearer <key>`. Use the host's native header support when it has one; otherwise bridge with `mcp-remote` and pass the key with `--header` (setting only an environment variable does not send it).

| Host | Add the server |
| - | - |
| Claude Code | Sign in: `claude mcp add --transport http infinite https://bot.api.infinite.dev/mcp`. API key: `claude mcp add --transport sse infinite https://bot.api.infinite.dev/mcp/sse --header "Authorization: Bearer $INFINITE_API_KEY"` |
| Cursor | Sign in: `{"mcpServers":{"infinite":{"url":"https://bot.api.infinite.dev/mcp"}}}` in `~/.cursor/mcp.json`. API key: same file with `"url":"https://bot.api.infinite.dev/mcp/sse"` and `"headers":{"Authorization":"Bearer <key>"}` |
| Codex | `codex mcp add infinite --env AUTH="Bearer $INFINITE_API_KEY" -- npx -y mcp-remote https://bot.api.infinite.dev/mcp/sse --transport sse-only --header 'Authorization:${AUTH}'` |
| Claude Desktop | See [MCP → Claude Desktop](/guides/mcp#claude-desktop) |
| Any other | Sign in at `https://bot.api.infinite.dev/mcp`, or point an SSE client at `https://bot.api.infinite.dev/mcp/sse` with the `Authorization` header set |

To operate as an agent alongside the organization, add a second server named `infinite-agent` with the agent key, and use only that server for payments. A signed-in session is the user, not an agent, and it uses production. Sandbox stays on an API key.

### If the tools don't show up

1. Reload or restart the host so it picks up the new server (Claude Code: start a new session and run `/mcp`; Cursor: refresh MCP tools in Settings).
2. Call `get_organization_info`. Only a successful call proves the tools are usable.
3. `401 Unauthorized` means the header didn't arrive or the key is wrong or revoked; check the header, not the URL.
4. After a reload, never re-run a payment automatically. Confirm with the user first.

## Journeys

### Onboard a business

Use a BYO org key when the business already has an Infinite organization. For **net-new** Connect, work with Infinite operators on a trusted host — do not use end-user Auth Kit membership in `org_connect` or the shared platform org API key in personal MCP config.

1. `create_business_customer` with the legal name, email, and country, and a new UUID v4 `operationId`. Keep the returned `continuationToken`.
2. `request_capabilities` for what they need (for example `USD_BALANCE`, `USD_ACH_PAYOUT`) **before** verification — a customer can only be updated while it's `DRAFT` or `NEED_ACTIONS`.
3. For API KYB (host already has facts/files): `search_industry_codes` then `update_business_details` to save business fields without submitting; upload docs and finish with `submit_customer_verification`. Prefer `start_verification` when a human can complete hosted KYB.
4. Poll `get_customer` until `ACTIVE`, then `get_capabilities` until the ones you need are `READY`.
5. `ensure_balance_account`, then `get_deposit_instructions` so the user can fund it.

On your own organization's key, pass `customerId` on each customer tool; no binding is needed. On a platform session (`get_organization_info` doesn't say `byo`), the session must be bound to one customer: if the connection drops mid-onboarding, call `bind_session_customer` with the customer ID and the saved `continuationToken` before any other customer tool.

In sandbox, skip the human steps: `sandbox_approve_customer` with the capabilities you need replaces both `request_capabilities` and verification (related capabilities may turn `READY` too), and `sandbox_fund_account` replaces the bank transfer.

### Add a payee draft (organization key, platform sessions)

To add a payee an agent will pay, use `create_payee` when it's offered. `create_payee_draft` is for platform sessions, where `create_payee` isn't available. Confirm the details with the user, then `create_payee_draft` with a new UUID v4 `operationId`. It returns a `draftId` (`eba_…`), starts `IN_REVIEW`, and runs existing account screening. Poll `get_payee_draft` for status. This does **not** enable payout — transfer approve/execute are separate steps. On BYO (non-platform) org keys, `create_payee` still creates a payee that becomes payable once `ACTIVE` for the agent-allowlist path.

### Create a transfer draft (organization key, platform sessions)

After the user confirms amount, currency, payee, and rail, call `create_transfer_draft` with a new UUID v4 `operationId`. Optionally call `get_quote` first for an indicative rate. It returns a `draftId` (`tdraft_…`) and stores amount/rail/payee/customer/actor metadata for audit. It registers the draft for platform approval and does **not** call `POST /v1/transfers` or move money — Infinite human approve/reject and execute are separate steps. Poll with `get_transfer_draft`.

### Create an agent (organization key)

No MCP tool yet — use REST with the organization key. Limits are **minor units** (cents for USD) as strings; `perTransaction` is required, and `perDay` / `perMonth` can be omitted for no cap. `allowedDestinationAccountIds` restricts who the agent may pay (up to 50); omit it to allow any of the customer's approved payees.

```bash theme={null}
curl -X POST https://sandbox.api.infinite.dev/v1/agents \
  -H "Authorization: Bearer $INFINITE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "AP Agent",
    "customerId": "cus_…",
    "sourceAccountId": "vba_…",
    "allowedDestinationAccountIds": ["eba_…"],
    "limits": { "currency": "USD", "perTransaction": "30000", "perDay": "60000", "perMonth": "500000" }
  }'
```

That's \$300 per transfer, \$600 per day, \$5,000 per month. Creating an agent isn't idempotent: if the call times out, `GET /v1/agents` before retrying so you don't create a second one. Then issue its key with `POST /v1/agents/{id}/keys` and body `{"name": "…"}`. The `secret` is returned once — hand it to the user or the runtime and don't repeat it in chat. See [Agents](/concepts/agents).

### Pay an invoice (agent key)

1. `get_agent`, `get_balance`, and `list_payees` to confirm budget, funds, and the payee.
2. `create_transfer` with the payee's `destinationAccountId`, the exact decimal `amount`, a `paymentReason` (usually `PAYMENT_FOR_GOODS_AND_SERVICES`), a UUID v4 `operationId` you keep for this invoice, and the invoice number as `reference`. The reference is always kept on the transfer (`reference` in `get_transfer`) and sent to the payee on ACH, wire, SWIFT, and RTP (not on other rails); ACH allows only 10 letters/digits, so `INV-77` goes out as `INV77`. The summary tells you exactly what the payee sees.
3. Show the returned summary and wait for approval.
4. `submit_transfer`. On success report the status (`PENDING`, then `COMPLETED`); on a denial, explain it using the table above.
5. `wait_for_transfer` to follow it to a final status (it returns `timedOut: true` if still in flight — call it again; never resubmit). Operators receive `transfer.*` webhooks, each carrying the `agentId`.

In sandbox, settle it from the organization-key session with `sandbox_complete_transfer`. Sandbox caps a single transfer at \$500.

### Check budget, balance, or status (agent key)

`get_agent` for limits and remaining spend, `get_balance` for funds, `get_transfer` / `list_transfers` for payments.

## Related

* [Agents](/concepts/agents): the model, limits, and webhooks
* [MCP](/guides/mcp): server details and per-host configuration
* [API reference](/api-reference/introduction) and the [OpenAPI spec](https://docs.infinite.dev/api-reference/openapi.json)


## Related topics

- [MCP Server](/guides/mcp.md)
- [Introduction](/introduction.md)
- [Welcome](/welcome.md)
- [Agents](/concepts/agents.md)
