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

# Create a firm FX quote

> Always firm — consumes one vendor quote and persists a Quote row. Pass an `Idempotency-Key` header to make retries safe (returns the original response on replay).



## OpenAPI

````yaml post /v1/fx/quotes
openapi: 3.0.0
info:
  title: Infinite API
  description: API for Infinite
  version: '1.0'
  contact: {}
servers:
  - url: https://sandbox.api.infinite.dev
    description: Sandbox
  - url: https://api.infinite.dev
    description: Production
security: []
tags:
  - name: Accounts
    description: Virtual and external account management
  - name: Customers
    description: Customer identity management
  - name: Documents
    description: Document upload and management
  - name: Fixed Routes
    description: Fixed route management
  - name: External Bank Accounts
    description: External bank account management
  - name: External Wallets
    description: External wallet management
  - name: Infinite Wallets
    description: Infinite Wallet management
  - name: Organizations
    description: Organization management
  - name: Quotes
    description: Quote creation and management
  - name: Transfers
    description: Money movement and transaction tracking
  - name: Verification
    description: Identity verification workflows
  - name: Terms of Service
    description: Terms of Service acceptance
  - name: Health
    description: System health and monitoring
  - name: Sandbox
    description: Sandbox utilities
paths:
  /v1/fx/quotes:
    post:
      tags:
        - FX
      summary: Create a firm FX quote
      description: >-
        Always firm — consumes one vendor quote and persists a Quote row. Pass
        an `Idempotency-Key` header to make retries safe (returns the original
        response on replay).
      operationId: FxQuoteController_create_v1
      parameters:
        - name: X-API-Key
          in: header
          description: API key
          required: false
          schema:
            type: string
        - name: Idempotency-Key
          required: false
          in: header
          description: >-
            Client-supplied key to deduplicate retries (e.g. on network
            timeout). Replays return the original quote rather than burning
            another vendor quote.
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateFxQuoteDto'
      responses:
        '201':
          description: Firm quote created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FxQuoteResponseDto'
        '400':
          description: >-
            Invalid pair shape (mismatched network/rail slots), or the fiat
            source rail is not yet supported (`fx_source_rail_not_supported` —
            send `SEPA` or `SEPA_INSTANT` for EUR onramp or `FASTER_PAYMENTS`
            for GBP; slow rails such as SWIFT are not available today).
        '401':
          description: Unauthorized - Invalid or missing authentication credentials
        '403':
          description: Fiat pairs are not enabled (`fx_fiat_pairs_not_enabled`).
        '409':
          description: FX is not enabled for this organization on the given pair.
        '422':
          description: >-
            No executable quote could be produced for the pair
            (`fx_quote_capacity_exhausted`, `fx_quote_amount_too_small`,
            `fx_quote_amount_too_large`, or `fx_quote_temporarily_unavailable`).
            For the amount buckets the body includes a `hint` and, when
            available, `limits` (`sourceCurrency`, `min`, `max` in minor units)
            plus the `requested` amount. Per-corridor amount limits are
            environment-specific — sandbox uses small test limits, so amounts
            that quote in production may be rejected in sandbox.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FxNotExecutableResponseDto'
      security:
        - bearer: []
        - bearer: []
      x-codeSamples:
        - lang: bash
          label: CLI
          source: >-
            # Requires: npm i -g @infinite_dev/cli && export
            INFINITE_API_KEY=sk_sandbox_...

            # Escape hatch for any endpoint: infinite api <METHOD> <path>

            infinite api POST /v1/fx/quotes \
              --body '<request-json>'
        - lang: text
          label: MCP
          source: >-
            Create a firm FX quote.


            # Infinite MCP is read-only for this endpoint — use a dedicated MCP
            tool when one exists, otherwise run the CLI tab.
components:
  schemas:
    CreateFxQuoteDto:
      type: object
      properties:
        onBehalfOf:
          type: string
          description: Customer this quote is for (the customer who will deposit).
          example: cus_abc123
        pair:
          $ref: '#/components/schemas/FxPairDto'
        amount:
          $ref: '#/components/schemas/FxAmountDto'
        maxSlippageBps:
          type: number
          description: >-
            Per-trade max slippage tolerance on the re-quote step, in basis
            points (1 bp = 0.01%). Minimum 5, maximum 1000. Optional for stable
            sources — if omitted, the organization-level default for the pair
            applies. REQUIRED for volatile sources (e.g. BTC): a quote whose
            source can move materially across the deposit-confirmation window is
            rejected when this is omitted, so the tolerance the customer accepts
            is always explicit.
          example: 25
          minimum: 5
          maximum: 1000
      required:
        - onBehalfOf
        - pair
        - amount
    FxQuoteResponseDto:
      type: object
      properties:
        id:
          type: string
          example: quote_abc123
        pair:
          $ref: '#/components/schemas/FxPairDto'
        amount:
          $ref: '#/components/schemas/FxAmountDto'
        grossSource:
          type: string
          description: Source amount, fees included, in source-currency minor units.
          example: '10000000'
        displayedDestination:
          type: string
          description: >-
            Destination amount the customer will receive, in
            destination-currency minor units.
          example: '9998500'
        rate:
          type: string
          description: All-in customer rate (displayedDestination / grossSource).
          example: '0.9998500'
        referenceRate:
          type: string
          description: >-
            Independent reference rate used to price this quote, expressed as
            destination major units per source major unit. Present for
            benchmark-priced quotes.
          example: '1.158691536019208779'
        referenceRateAsOf:
          type: string
          description: >-
            Timestamp of the independent reference rate used to price this quote
            (ISO 8601).
          example: '2026-09-02T18:30:04.000Z'
        referenceProvider:
          type: string
          description: >-
            Independent market that published `referenceRate`. Present when
            `referenceRate` is present.
          enum:
            - XE
          example: XE
        expiresAt:
          type: string
          description: When the firm quote expires (ISO 8601).
          example: '2026-05-26T19:42:00.000Z'
        quoteBinding:
          type: string
          description: >-
            How this quote binds to a later trade. `PERSISTED`: the firm price
            is held and a trade created from this quote replays it, so accepting
            later (within `expiresAt`) is safe. `AT_ACCEPT`: pricing is
            finalized when the trade is created, so the price may move between
            quote and accept.
          enum:
            - PERSISTED
            - AT_ACCEPT
          example: PERSISTED
        expectedDepositDetails:
          description: >-
            Preview of the deposit details the trade will carry once this quote
            is accepted. Omitted when the preview could not be resolved (the
            quote itself is unaffected — accept normally and use the deposit
            instructions on the trade).
          allOf:
            - $ref: '#/components/schemas/FxQuoteExpectedDepositDetailsDto'
      required:
        - id
        - pair
        - amount
        - grossSource
        - displayedDestination
        - rate
        - expiresAt
    FxNotExecutableResponseDto:
      type: object
      properties:
        message:
          type: string
          description: Stable error code.
          enum:
            - fx_quote_capacity_exhausted
            - fx_quote_amount_too_small
            - fx_quote_amount_too_large
            - fx_quote_temporarily_unavailable
          example: fx_quote_amount_too_large
        hint:
          type: string
          description: Human-readable explanation.
          example: Amount is above the maximum for this corridor.
        limits:
          description: >-
            Per-corridor source-amount bounds. Present only for the
            `fx_quote_amount_too_small` / `fx_quote_amount_too_large` codes on
            `POST /v1/fx/quotes`, and only when available.
          allOf:
            - $ref: '#/components/schemas/FxNotExecutableLimitsDto'
        requested:
          type: string
          description: >-
            The originally requested source amount in minor units. Present only
            alongside `limits`.
          example: '100000000'
      required:
        - message
        - hint
    FxPairDto:
      type: object
      properties:
        sourceCurrency:
          type: string
          example: USDT
        sourceNetwork:
          type: string
          description: >-
            Network for crypto source (e.g. BASE, ETHEREUM). Required when
            source is a crypto asset; must be omitted when source is fiat.
          example: BASE
        sourceRail:
          type: string
          description: >-
            Rail for fiat source (SEPA, SEPA_INSTANT, FASTER_PAYMENTS). Required
            when source is fiat; must be omitted when source is crypto. For EUR
            onramp prefer `SEPA`; `SEPA_INSTANT` remains accepted. Slow EUR
            rails are not available today.
          example: SEPA
        destinationCurrency:
          type: string
          example: USDC
        destinationNetwork:
          type: string
          description: >-
            Network for crypto destination. Required when destination is a
            crypto asset; must be omitted when destination is fiat.
          example: BASE
        destinationRail:
          type: string
          description: >-
            Rail for fiat destination (SEPA, SWIFT, ACH). Required when
            destination is fiat; must be omitted when destination is crypto.
          example: SEPA
      required:
        - sourceCurrency
        - destinationCurrency
    FxAmountDto:
      type: object
      properties:
        value:
          type: string
          description: >-
            Amount in minor units of whichever side is locked. Positive integer
            string.
          example: '10000000'
        side:
          type: string
          enum:
            - SOURCE
            - DESTINATION
          description: >-
            Which amount the customer locked. SOURCE = customer's gross spend;
            DESTINATION = customer's receivable.
          example: SOURCE
      required:
        - value
        - side
    FxQuoteExpectedDepositDetailsDto:
      type: object
      properties:
        kind:
          type: string
          description: >-
            How the source side will be funded after accepting. CRYPTO_ADDRESS:
            the deposit address is known now (`address` + `network`).
            FIAT_INSTRUCTIONS_ON_ACCEPT: bank wire instructions are issued on
            the trade returned by accepting the quote.
          enum:
            - CRYPTO_ADDRESS
            - FIAT_INSTRUCTIONS_ON_ACCEPT
          example: CRYPTO_ADDRESS
        address:
          type: string
          description: >-
            Deposit address the trade will use. Present only when
            `kind=CRYPTO_ADDRESS`. NOT active until the trade returned by
            accepting this quote carries deposit instructions — see `note`.
          example: 0xCustomerInfiniteTxWallet...
        network:
          type: string
          description: Network of `address`. Present only when `kind=CRYPTO_ADDRESS`.
          example: BASE
        note:
          type: string
          description: Pre-accept warning to surface alongside the preview.
          example: >-
            Deposit instructions become active only when the trade created by
            accepting this quote includes them — immediately on accept, or after
            the fx_trade.deposit_instructions_ready event if the trade starts in
            PENDING_WALLET_APPROVAL. Funds sent before then cannot be matched to
            a trade.
      required:
        - kind
        - note
    FxNotExecutableLimitsDto:
      type: object
      properties:
        sourceCurrency:
          type: string
          example: USDC
        min:
          type: string
          description: Minimum source amount in minor units.
          example: '0'
        max:
          type: string
          description: Maximum source amount in minor units.
          example: '10000000'
      required:
        - sourceCurrency
        - min
        - max
  securitySchemes:
    bearer:
      scheme: bearer
      bearerFormat: API Key
      type: http
      description: API Key in Bearer format (e.g., Bearer sk_test_...)

````

## Related topics

- [Accept a firm FX quote and create a trade](/api-reference/fx/accept-a-firm-fx-quote-and-create-a-trade.md)
- [Get an indicative FX rate for a pair](/api-reference/fx/get-an-indicative-fx-rate-for-a-pair.md)
- [Agents](/concepts/agents.md)
- [Confirm an unlocked transfer intent](/api-reference/transfers/confirm-an-unlocked-transfer-intent.md)
- [Create a quote](/api-reference/quotes/create-a-quote.md)
