> ## 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.

# Quotes and Transfers

> Learn how to get currency conversion quotes and execute transfers

## Overview

The Infinite API provides flexible options for executing currency conversions:

**Option 1: Direct Transfer (Recommended for simple flows)**

* Create a transfer with amounts and currencies
* The API automatically fetches a real-time quote and executes immediately
* Simplest approach for most use cases

**Option 2: Quote + Transfer (For locked-in rates)**

1. **Get a Quote** - Request and hold a quote to lock in an exchange rate
2. **Execute Transfer** - Use the held quote to guarantee the rate

This guide covers both approaches with practical examples.

## Currency Amount Format

<Warning>
  **All amounts in the API are in the smallest unit (unscaled)** - **Fiat
  currencies**: cents (e.g., \$100.00 = 10000 cents) - **Crypto currencies**:
  base units (e.g., 1 USDC = 1000000, 1 BTC = 100000000 satoshi) This ensures
  precision and avoids floating-point errors.
</Warning>

### Decimal Places by Currency

| Currency | Decimals | Smallest Unit | Example |
| - | - | - | - |
| USD, EUR, GBP, CAD, AUD | 2 | Cents | \$100.00 = 10000 |
| JPY | 0 | Yen | ¥1000 = 1000 |
| USDC, USDT, TRX | 6 | Base units | 1 USDC = 1000000 |
| BTC | 8 | Satoshi | 1 BTC = 100000000 |
| SOL | 9 | Lamports | 1 SOL = 1000000000 |
| ETH, DAI | 18 | Wei | 1 ETH = 1000000000000000000 |

### Converting Between Decimal and Smallest Unit

To convert from decimal amounts to smallest unit for API requests:

```javascript theme={null}
// Fiat: multiply by 10^decimals
const usdAmount = 100.5; // $100.50
const usdInCents = Math.round(usdAmount * 100); // 10050

// Crypto with 6 decimals (USDC, USDT)
const usdcAmount = 100.5; // 100.5 USDC
const usdcInBaseUnits = Math.round(usdcAmount * 1000000); // 100500000

// Crypto with 8 decimals (BTC)
const btcAmount = 0.001; // 0.001 BTC
const btcInSatoshi = Math.round(btcAmount * 100000000); // 100000
```

## Option 1: Direct Transfer (No Quote Required)

The simplest way to create a transfer is to specify amounts and currencies directly. The API will automatically fetch the current exchange rate and execute the transfer.

### Example: Direct USD to USDC Conversion

<CodeGroup>
  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.infinite.dev/v1/transfers',
      headers={
          'Authorization': 'Bearer YOUR_API_KEY',
          'Content-Type': 'application/json',
      },
      json={
          'onBehalfOf': 'cus_abc123',
          'amount': {
              'currency': 'USD',
              'rawValue': '10000',
          },
          'source': {
              'currency': 'USD',
              'paymentRail': 'ACH',
              'accountId': 'vba_source123',
          },
          'destination': {
              'currency': 'USDC',
              'paymentRail': 'ETHEREUM',
              'accountId': 'inw_dest456',
          },
          'paymentReason': 'TRADE_SETTLEMENT',
      },
  )
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch('https://api.infinite.dev/v1/transfers', {
    method: 'POST',
    headers: {
      Authorization: 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      onBehalfOf: 'cus_abc123',
      amount: {
        currency: 'USD',
        rawValue: '10000',
      },
      source: {
        currency: 'USD',
        paymentRail: 'ACH',
        accountId: 'vba_source123',
      },
      destination: {
        currency: 'USDC',
        paymentRail: 'ETHEREUM',
        accountId: 'inw_dest456',
      },
      paymentReason: 'TRADE_SETTLEMENT',
    }),
  });
  ```

  ```bash CLI theme={null}
  export INFINITE_API_KEY=YOUR_API_KEY
  infinite api POST /v1/transfers --body '{
    "onBehalfOf": "cus_abc123",
    "amount": {
      "currency": "USD",
      "rawValue": "10000"
    },
    "source": {
      "currency": "USD",
      "paymentRail": "ACH",
      "accountId": "vba_source123"
    },
    "destination": {
      "currency": "USDC",
      "paymentRail": "ETHEREUM",
      "accountId": "inw_dest456"
    },
    "paymentReason": "TRADE_SETTLEMENT"
  }'
  ```

  ```text MCP theme={null}
  Convert $100.00 from vba_source123 by ACH to USDC in inw_dest456 on Ethereum, on behalf of cus_abc123, for trade settlement.

  # With an agent key the assistant calls create_transfer (draft) then submit_transfer; with an org key run the CLI tab.
  ```

  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.infinite.dev/v1/transfers \
    --header 'Authorization: Bearer YOUR_API_KEY' \
    --header 'Content-Type: application/json' \
    --data '{
      "onBehalfOf": "cus_abc123",
      "amount": {
        "currency": "USD",
        "rawValue": "10000"
      },
      "source": {
        "currency": "USD",
        "paymentRail": "ACH",
        "accountId": "vba_source123"
      },
      "destination": {
        "currency": "USDC",
        "paymentRail": "ETHEREUM",
        "accountId": "inw_dest456"
      },
      "paymentReason": "TRADE_SETTLEMENT"
    }'
  ```
</CodeGroup>

The API will:

1. Fetch a real-time quote automatically
2. Apply the current exchange rate (inclusive of fees)
3. Execute the transfer immediately
4. Return the transfer details with actual amounts

<Tip>
  Use this approach when you don't need to show the user the exact exchange rate
  before execution, or when you're executing transfers programmatically.
</Tip>

## Option 2: Quote First (For Locked-in Rates)

If you need to show users the exact exchange rate before they confirm, or lock in a rate for a multi-step flow, use the two-step quote + transfer process.

### Step 1: Get a Quote

Request a quote to get the current exchange rate and expected destination amount.

### Quote Types

**Instant Quotes** (default): Get immediate pricing. Use for display purposes.

**Held Quotes** (with `holdQuote: true`): Lock in a rate for up to 5 minutes. Required if you want to reference the quote in a transfer.

### Example: Get an Instant Quote

<CodeGroup>
  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.infinite.dev/v1/quotes',
      headers={
          'Authorization': 'Bearer YOUR_API_KEY',
          'Content-Type': 'application/json',
      },
      json={
          'sourceAmount': {
              'currency': 'USD',
              'rawValue': '10000',
          },
          'destinationCurrency': 'USDC',
      },
  )
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch('https://api.infinite.dev/v1/quotes', {
    method: 'POST',
    headers: {
      Authorization: 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      sourceAmount: {
        currency: 'USD',
        rawValue: '10000',
      },
      destinationCurrency: 'USDC',
    }),
  });
  ```

  ```bash CLI theme={null}
  export INFINITE_API_KEY=YOUR_API_KEY
  infinite quotes create \
    --source-amount 10000 \
    --source-currency USD \
    --dest-currency USDC
  ```

  ```text MCP theme={null}
  Quote $100.00 USD to USDC.

  # With an agent key the assistant calls get_quote; with an org key run the CLI tab.
  ```

  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.infinite.dev/v1/quotes \
    --header 'Authorization: Bearer YOUR_API_KEY' \
    --header 'Content-Type: application/json' \
    --data '{
      "sourceAmount": {
        "currency": "USD",
        "rawValue": "10000"
      },
      "destinationCurrency": "USDC"
    }'
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "sourceAmount": {
    "currency": "USD",
    "exponent": 2,
    "value": "10000",
    "displayValue": "100.00"
  },
  "destinationAmount": {
    "currency": "USDC",
    "exponent": 6,
    "value": "99500000",
    "displayValue": "99.50"
  },
  "exchangeRate": "0.9950",
  "infiniteFee": {
    "fixed": null,
    "variable": null
  },
  "createdAt": "2026-09-15T10:30:00Z"
}
```

<Note>
  The `exchangeRate` is **inclusive of all fees**. You don't need to calculate
  fees separately.
</Note>

### Example: Get a Held Quote

Add `holdQuote: true` to lock in the rate:

<CodeGroup>
  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.infinite.dev/v1/quotes',
      headers={
          'Authorization': 'Bearer YOUR_API_KEY',
          'Content-Type': 'application/json',
      },
      json={
          'sourceAmount': {
              'currency': 'USD',
              'rawValue': '10000',
          },
          'destinationCurrency': 'USDC',
          'holdQuote': True,
      },
  )
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch('https://api.infinite.dev/v1/quotes', {
    method: 'POST',
    headers: {
      Authorization: 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      sourceAmount: {
        currency: 'USD',
        rawValue: '10000',
      },
      destinationCurrency: 'USDC',
      holdQuote: true,
    }),
  });
  ```

  ```bash CLI theme={null}
  export INFINITE_API_KEY=YOUR_API_KEY
  infinite quotes create \
    --source-amount 10000 \
    --source-currency USD \
    --dest-currency USDC \
    --body '{"holdQuote":true}'
  ```

  ```text MCP theme={null}
  Quote $100.00 USD to USDC and hold the rate.

  # With an agent key the assistant calls get_quote(holdRate=true) and passes the quote id as quoteId to create_transfer; with an org key run the CLI tab.
  ```

  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.infinite.dev/v1/quotes \
    --header 'Authorization: Bearer YOUR_API_KEY' \
    --header 'Content-Type: application/json' \
    --data '{
      "sourceAmount": {
        "currency": "USD",
        "rawValue": "10000"
      },
      "destinationCurrency": "USDC",
      "holdQuote": true
    }'
  ```
</CodeGroup>

**Response includes quote ID and expiration:**

```json theme={null}
{
  "id": "quote_abc123",
  "sourceAmount": {
    "currency": "USD",
    "exponent": 2,
    "value": "10000",
    "displayValue": "100.00"
  },
  "destinationAmount": {
    "currency": "USDC",
    "exponent": 6,
    "value": "99500000",
    "displayValue": "99.50"
  },
  "exchangeRate": "0.9950",
  "expiresAt": "2026-09-15T10:35:00Z",
  "createdAt": "2026-09-15T10:30:00Z"
}
```

### Quote Expiration

* **Held quotes** expire after 5 minutes
* **Instant quotes** should be used immediately as rates fluctuate
* Expired quotes cannot be used for transfers

## Step 2: Execute a Transfer

Once you have a quote, use it to create a transfer.

### Prerequisites

Before creating a transfer, ensure you have:

1. **A customer** - Create using [POST /customers/individuals](/api-reference/customers/create-a-new-individual-customer) or [POST /customers/businesses](/api-reference/customers/create-a-new-business-customer)
2. **Source account** - Virtual bank account or wallet for the customer
3. **Destination account** - External wallet or bank account

<Tip>
  See the [Accounts guide](/concepts/accounts) for details on creating accounts.
</Tip>

### Example: Execute Transfer with Instant Quote

<CodeGroup>
  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.infinite.dev/v1/transfers',
      headers={
          'Authorization': 'Bearer YOUR_API_KEY',
          'Content-Type': 'application/json',
      },
      json={
          'onBehalfOf': 'cus_abc123',
          'amount': {
              'currency': 'USD',
              'rawValue': '10000',
          },
          'source': {
              'currency': 'USD',
              'paymentRail': 'ACH',
              'accountId': 'vba_source123',
          },
          'destination': {
              'currency': 'USDC',
              'paymentRail': 'ETHEREUM',
              'accountId': 'inw_dest456',
          },
          'paymentReason': 'TRADE_SETTLEMENT',
      },
  )
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch('https://api.infinite.dev/v1/transfers', {
    method: 'POST',
    headers: {
      Authorization: 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      onBehalfOf: 'cus_abc123',
      amount: {
        currency: 'USD',
        rawValue: '10000',
      },
      source: {
        currency: 'USD',
        paymentRail: 'ACH',
        accountId: 'vba_source123',
      },
      destination: {
        currency: 'USDC',
        paymentRail: 'ETHEREUM',
        accountId: 'inw_dest456',
      },
      paymentReason: 'TRADE_SETTLEMENT',
    }),
  });
  ```

  ```bash CLI theme={null}
  export INFINITE_API_KEY=YOUR_API_KEY
  infinite api POST /v1/transfers --body '{
    "onBehalfOf": "cus_abc123",
    "amount": {
      "currency": "USD",
      "rawValue": "10000"
    },
    "source": {
      "currency": "USD",
      "paymentRail": "ACH",
      "accountId": "vba_source123"
    },
    "destination": {
      "currency": "USDC",
      "paymentRail": "ETHEREUM",
      "accountId": "inw_dest456"
    },
    "paymentReason": "TRADE_SETTLEMENT"
  }'
  ```

  ```text MCP theme={null}
  Convert $100.00 from vba_source123 by ACH to USDC in inw_dest456 on Ethereum, on behalf of cus_abc123, for trade settlement.

  # With an agent key the assistant calls create_transfer (draft) then submit_transfer; with an org key run the CLI tab.
  ```

  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.infinite.dev/v1/transfers \
    --header 'Authorization: Bearer YOUR_API_KEY' \
    --header 'Content-Type: application/json' \
    --data '{
      "onBehalfOf": "cus_abc123",
      "amount": {
        "currency": "USD",
        "rawValue": "10000"
      },
      "source": {
        "currency": "USD",
        "paymentRail": "ACH",
        "accountId": "vba_source123"
      },
      "destination": {
        "currency": "USDC",
        "paymentRail": "ETHEREUM",
        "accountId": "inw_dest456"
      },
      "paymentReason": "TRADE_SETTLEMENT"
    }'
  ```
</CodeGroup>

The API will:

1. Fetch a fresh quote automatically
2. Validate the accounts and customer
3. Initiate the transfer
4. Return the transfer details with actual exchange rate applied

**Response:**

```json theme={null}
{
  "id": "tfr_xyz789",
  "sourceCustomerId": "cus_abc123",
  "status": "PENDING",
  "source": {
    "currency": "USD",
    "paymentRail": "ACH",
    "accountId": "vba_source123"
  },
  "destination": {
    "currency": "USDC",
    "paymentRail": "ETHEREUM",
    "accountId": "inw_dest456"
  },
  "sourceAmount": {
    "currency": "USD",
    "exponent": 2,
    "value": "10000",
    "displayValue": "100.00"
  },
  "destinationAmount": {
    "currency": "USDC",
    "exponent": 6,
    "value": "99500000",
    "displayValue": "99.50"
  },
  "createdAt": "2026-09-15T10:30:00Z"
}
```

### Example: Execute Transfer with Held Quote

If you created a held quote, reference it in the transfer:

<CodeGroup>
  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.infinite.dev/v1/transfers',
      headers={
          'Authorization': 'Bearer YOUR_API_KEY',
          'Content-Type': 'application/json',
      },
      json={
          'onBehalfOf': 'cus_abc123',
          'amount': {
              'currency': 'USD',
              'rawValue': '10000',
          },
          'source': {
              'currency': 'USD',
              'paymentRail': 'ACH',
              'accountId': 'vba_source123',
          },
          'destination': {
              'currency': 'USDC',
              'paymentRail': 'ETHEREUM',
              'accountId': 'inw_dest456',
          },
          'paymentReason': 'TRADE_SETTLEMENT',
          'quoteId': 'quote_abc123',
      },
  )
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch('https://api.infinite.dev/v1/transfers', {
    method: 'POST',
    headers: {
      Authorization: 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      onBehalfOf: 'cus_abc123',
      amount: {
        currency: 'USD',
        rawValue: '10000',
      },
      source: {
        currency: 'USD',
        paymentRail: 'ACH',
        accountId: 'vba_source123',
      },
      destination: {
        currency: 'USDC',
        paymentRail: 'ETHEREUM',
        accountId: 'inw_dest456',
      },
      paymentReason: 'TRADE_SETTLEMENT',
      quoteId: 'quote_abc123',
    }),
  });
  ```

  ```bash CLI theme={null}
  export INFINITE_API_KEY=YOUR_API_KEY
  infinite api POST /v1/transfers --body '{
    "onBehalfOf": "cus_abc123",
    "amount": {
      "currency": "USD",
      "rawValue": "10000"
    },
    "source": {
      "currency": "USD",
      "paymentRail": "ACH",
      "accountId": "vba_source123"
    },
    "destination": {
      "currency": "USDC",
      "paymentRail": "ETHEREUM",
      "accountId": "inw_dest456"
    },
    "paymentReason": "TRADE_SETTLEMENT",
    "quoteId": "quote_abc123"
  }'
  ```

  ```text MCP theme={null}
  Convert $100.00 from vba_source123 by ACH to USDC in inw_dest456 on Ethereum, on behalf of cus_abc123, for trade settlement, using quote quote_abc123.

  # With an agent key the assistant calls create_transfer (draft) then submit_transfer; with an org key run the CLI tab.
  ```

  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.infinite.dev/v1/transfers \
    --header 'Authorization: Bearer YOUR_API_KEY' \
    --header 'Content-Type: application/json' \
    --data '{
      "onBehalfOf": "cus_abc123",
      "amount": {
        "currency": "USD",
        "rawValue": "10000"
      },
      "source": {
        "currency": "USD",
        "paymentRail": "ACH",
        "accountId": "vba_source123"
      },
      "destination": {
        "currency": "USDC",
        "paymentRail": "ETHEREUM",
        "accountId": "inw_dest456"
      },
      "paymentReason": "TRADE_SETTLEMENT",
      "quoteId": "quote_abc123"
    }'
  ```
</CodeGroup>

<Note>
  When using a held quote, the exchange rate from the quote is guaranteed. You
  still need to provide the full transfer details.
</Note>

## Same-asset cross-chain

To move USDC or USDT between chains without converting the asset, use the same
currency on both legs and different rails. Settlement is at par. See
[Same-asset bridging](/guides/same-asset-bridging).


## Related topics

- [Transfers](/concepts/transfers.md)
- [MCP Server](/guides/mcp.md)
- [Quote a transfer intent](/api-reference/transfers/quote-a-transfer-intent.md)
- [Confirm a transfer quote](/api-reference/transfers/confirm-a-transfer-quote.md)
- [Create a quote](/api-reference/quotes/create-a-quote.md)
