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

# Same-asset bridging

> Move USDC or USDT between chains at par with a crypto-to-crypto transfer

## Overview

Move **the same stablecoin** from one supported chain to another — for example USDT on Ethereum to USDT on Polygon, or USDC on Base to USDC on Solana.

The destination amount matches the source amount. No conversion, no FX spread. Create a normal crypto-to-crypto [transfer](/concepts/transfers) (or use the Console transfer page) with the same currency on both legs and different `paymentRail` values.

## Supported corridors

Both the source and destination networks must be in this matrix for that asset. Networks must differ.

| Asset | Networks |
| - | - |
| **USDC** | Ethereum, Solana, Arbitrum, Base, Polygon |
| **USDT** | Ethereum, Tron, Arbitrum, Polygon, Solana |

Same-chain moves (for example USDC on Base → USDC on Base) are wallet transfers, not bridges.

<Note>
  Amounts on this path support at most **4 decimal places**. Use `5.1234` USDT, not `5.123456`. In minor units that means the last two digits of a 6-decimal `rawValue` must be `00` (for example `"5000000"` for 5 USDT).
</Note>

## Prerequisites

* Verified customer (KYC/KYB completed) with same-asset bridging enabled for their account
* Distinct source and destination accounts (the same Infinite wallet cannot be both)
* Source funded on the source chain, or a deposit instruction if the customer will push funds in

## Quote (optional)

Same-asset bridges quote at **1:1**. A quote is optional; the transfer API will still settle at par.

<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={
          'onBehalfOf': 'cus_abc123',
          'sourceAmount': {'currency': 'USDT', 'rawValue': '5000000'},
          'payinMethod': 'ETHEREUM',
          'destinationCurrency': 'USDT',
          'payoutMethod': 'POLYGON',
      },
  )
  ```

  ```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({
      onBehalfOf: 'cus_abc123',
      sourceAmount: { currency: 'USDT', rawValue: '5000000' },
      payinMethod: 'ETHEREUM',
      destinationCurrency: 'USDT',
      payoutMethod: 'POLYGON',
    }),
  });
  ```

  ```bash CLI theme={null}
  export INFINITE_API_KEY=YOUR_API_KEY
  infinite api POST /v1/quotes --body '{
    "onBehalfOf": "cus_abc123",
    "sourceAmount": {"currency": "USDT", "rawValue": "5000000"},
    "payinMethod": "ETHEREUM",
    "destinationCurrency": "USDT",
    "payoutMethod": "POLYGON"
  }'
  ```

  ```text MCP theme={null}
  Quote bridging 5 USDT from Ethereum to Polygon for cus_abc123.

  # 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 '{
      "onBehalfOf": "cus_abc123",
      "sourceAmount": {
        "currency": "USDT",
        "rawValue": "5000000"
      },
      "payinMethod": "ETHEREUM",
      "destinationCurrency": "USDT",
      "payoutMethod": "POLYGON"
    }'
  ```
</CodeGroup>

## Create 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': 'USDT', 'rawValue': '5000000'},
          'source': {
              'currency': 'USDT',
              'paymentRail': 'ETHEREUM',
              'accountId': 'inw_source123',
          },
          'destination': {
              'currency': 'USDT',
              'paymentRail': 'POLYGON',
              'accountId': 'inw_dest456',
          },
          'paymentReason': 'SELF',
          'confirm': True,
      },
  )
  ```

  ```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: 'USDT', rawValue: '5000000' },
      source: {
        currency: 'USDT',
        paymentRail: 'ETHEREUM',
        accountId: 'inw_source123',
      },
      destination: {
        currency: 'USDT',
        paymentRail: 'POLYGON',
        accountId: 'inw_dest456',
      },
      paymentReason: 'SELF',
      confirm: true,
    }),
  });
  ```

  ```bash CLI theme={null}
  export INFINITE_API_KEY=YOUR_API_KEY
  infinite api POST /v1/transfers --body '{
    "onBehalfOf": "cus_abc123",
    "amount": {"currency": "USDT", "rawValue": "5000000"},
    "source": {
      "currency": "USDT",
      "paymentRail": "ETHEREUM",
      "accountId": "inw_source123"
    },
    "destination": {
      "currency": "USDT",
      "paymentRail": "POLYGON",
      "accountId": "inw_dest456"
    },
    "paymentReason": "SELF",
    "confirm": true
  }'
  ```

  ```text MCP theme={null}
  Bridge 5 USDT from inw_source123 on Ethereum to inw_dest456 on Polygon on behalf of cus_abc123, and submit it.

  # 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": "USDT",
        "rawValue": "5000000"
      },
      "source": {
        "currency": "USDT",
        "paymentRail": "ETHEREUM",
        "accountId": "inw_source123"
      },
      "destination": {
        "currency": "USDT",
        "paymentRail": "POLYGON",
        "accountId": "inw_dest456"
      },
      "paymentReason": "SELF",
      "confirm": true
    }'
  ```
</CodeGroup>

If the source is not a funded Infinite wallet, the response includes `depositInstructions` with the address and amount to send on the source chain. After the deposit confirms, Infinite delivers the same asset on the destination chain.

## Console

On the transfer page: **First Party** → pick two different treasuries or wallets → set source to `USDT · ETHEREUM` (or another supported pair) and destination to the **same asset on a different chain**. The quote should show a 1:1 rate.

## What this is not

* **USDC ↔ USDT** is a conversion, not a same-asset bridge. Use a [quote](/guides/quotes-and-transfers) for that pair.
* **USDC on Tron** and **USDT on Base** are not in the native bridge matrix above.
* Recurring inbound addresses that always sweep to another chain use a `CRYPTO_TO_CRYPTO` [fixed route](/concepts/fixed-routes) instead of a one-off transfer.


## Related topics

- [Payments](/coverage/payments.md)
- [Quotes and Transfers](/guides/quotes-and-transfers.md)
- [Transfers](/concepts/transfers.md)
- [Fixed Routes](/concepts/fixed-routes.md)
- [Overview](/coverage/overview.md)
