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

# Create split

> Creates a group of swaps that share one `multiId`. Post the orders straight here — there is no quote step and no `quoteId`.

- routes are chosen for you, per order
- [Get split quotes](/api-reference/split/get-split-quotes) is optional, for showing rates first
- each swap starts at status NEW and is prepared in the background
- poll [Get batch status](/api-reference/split/get-batch-status) for deposit addresses
- `fixed: true` uses a fixed rate and needs a `refundAddress`. To pay the receiver an exact amount, also set `amountType: "receive"`. Read the final `inAmount` and `outAmount` from batch status, once the order has a `depositAddress`.

See the [Split flow](/developer-hub/swap-flows/split) for the full sequence.



## OpenAPI

````yaml https://api-partner.houdiniswap.com/v2/openapi.json post /exchanges/multi
openapi: 3.0.0
info:
  title: Houdini Partner API
  version: 2.1.2
  description: >-
    Quote and execute private, standard, and DEX swaps — one at a time or
    batched.
  license:
    name: ISC
  contact: {}
servers:
  - url: https://api-partner.houdiniswap.com/v2
security: []
tags:
  - name: Private and Standard Swaps
    description: >-
      CEX swaps in two modes, sharing the same endpoints — pick one with the
      `types` parameter.


      - `types=standard` — direct single-leg swap. Fastest, no privacy hop.

      - `types=private` — two legs through a privacy bridge, so deposit and
      payout are not linkable on-chain. Adds `anonymous`, `useXmr`,
      `rotatePayoutWallets` and the `inLeg*` / `outLeg*` filters.


      Flow: [Get tokens](/api-reference/private-and-standard-swaps/get-tokens)
      with `hasCex=true` → [Get
      quotes](/api-reference/private-and-standard-swaps/get-quotes) → [Create
      exchange](/api-reference/private-and-standard-swaps/create-exchange) →
      [track the
      order](/api-reference/private-and-standard-swaps/get-order-details).
      `markup` works in both modes.
  - name: Private Send
    description: >-
      Send a token to another wallet privately — same token in and out, with no
      on-chain link between the two addresses.


      - find eligible tokens with [Get
      tokens](/api-reference/private-send/get-tokens) and `hasSelfPrivate=true`

      - quote with Get private send quote, then create with Create private send
      order

      - you can also stay on the main endpoints with a private same-token
      `quoteId`


      See the [Private send](/docs/v2/private-send) guide.
  - name: Split
    description: >-
      Create and track a group of swaps sharing one `multiId`.


      - post the orders straight to Create split — there is no quote step and no
      `quoteId`

      - Get split quotes is optional, for showing rates first

      - each order gets its own deposit address; poll [Get batch
      status](/api-reference/split/get-batch-status) for every leg

      - CEX standard and private only — no DEX in a batch


      To fund the whole group in one transaction, see Bundler SOL or Bundler
      EVM. See the [Split flow](/developer-hub/swap-flows/split) for the full
      sequence.
  - name: Bundler SOL
    description: >-
      Fund a whole Split group with one Solana batch transfer.


      - one call — Get batch transaction returns the transaction to sign and
      broadcast

      - every order must send the same token

      - deposits per batch depend on `txVersion`: up to 20 SOL or 10 token
      deposits with `legacy` or `v0`, up to 60 SOL or 10 token deposits with
      `v1`

      - find batchable tokens with [Get tokens](/api-reference/split/get-tokens)
      and `hasBundler=true`

      - nothing to submit back afterwards — retry and recovery are EVM-only


      See the [Split flow](/developer-hub/swap-flows/split) for the full
      sequence.
  - name: Bundler EVM
    description: >-
      Fund a whole Split group with one ERC-4337 UserOperation, submitted
      through the bundler.


      - Ethereum, Base and BNB Smart Chain only; other EVM chains are rejected

      - up to 50 orders per group, funded in one transaction; every order must
      send the same source token

      - find batchable tokens with [Get tokens](/api-reference/split/get-tokens)
      and `hasBundler=true`

      - build the UserOp, then submit the signed result

      - if a bundle fails: retry within 30 minutes, or recover stuck assets


      See the [Split flow](/developer-hub/swap-flows/split) for the full
      sequence.
  - name: On-chain DEX or Bridge
    description: >-
      On-chain swaps signed and funded from the user's own wallet.


      Flow: [Get tokens](/api-reference/on-chain-dex-or-bridge/get-tokens) with
      `hasDex=true` → [Get
      quotes](/api-reference/on-chain-dex-or-bridge/get-quotes) with `types=dex`
      → [Get token approval
      data](/api-reference/on-chain-dex-or-bridge/get-token-approval-data) →
      send it and poll [Check token
      allowance](/api-reference/on-chain-dex-or-bridge/check-token-allowance) →
      [Get next chain
      signature](/api-reference/on-chain-dex-or-bridge/get-next-chain-signature)
      → [Create exchange](/api-reference/on-chain-dex-or-bridge/create-exchange)
      → [Confirm DEX
      transaction](/api-reference/on-chain-dex-or-bridge/confirm-dex-transaction)
      → [track the
      order](/api-reference/on-chain-dex-or-bridge/get-order-details).


      - `slippage` applies to DEX only

      - `markup` is not supported
  - name: Reference Data
    description: >-
      Optional lookups: supported chains, liquidity providers, and per-pair
      min/max swap amounts. Responses are cached and change rarely — safe to
      fetch once and reuse. Token ids come from `/tokens`, listed in each swap
      section above.
  - name: Partner Account
    description: >-
      Your orders, profile, earned commissions, withdrawals, volume analytics,
      and the rate-limit budget attached to your API key. Every endpoint is
      scoped to the partner that owns the key making the request.
  - name: System
    description: >-
      Service health. [Get system
      health](/api-reference/system/get-system-health) is unauthenticated and
      exempt from x402 payment — use it for uptime monitoring.
paths:
  /exchanges/multi:
    post:
      tags:
        - Split
      summary: Create split
      description: >-
        Creates a group of swaps that share one `multiId`. Post the orders
        straight here — there is no quote step and no `quoteId`.


        - routes are chosen for you, per order

        - [Get split quotes](/api-reference/split/get-split-quotes) is optional,
        for showing rates first

        - each swap starts at status NEW and is prepared in the background

        - poll [Get batch status](/api-reference/split/get-batch-status) for
        deposit addresses

        - `fixed: true` uses a fixed rate and needs a `refundAddress`. To pay
        the receiver an exact amount, also set `amountType: "receive"`. Read the
        final `inAmount` and `outAmount` from batch status, once the order has a
        `depositAddress`.


        See the [Split flow](/developer-hub/swap-flows/split) for the full
        sequence.
      operationId: CreateMultiExchange
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MultiExchangeRequest'
      responses:
        '200':
          description: Split created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MultiExchangeCreateResult'
              examples:
                Example 1:
                  value:
                    multiId: 8ppABEC1HZGrSr1PGbUnCN
                    orders:
                      - order:
                          created: '2026-09-24T09:45:09.594Z'
                          houdiniId: nkuYKXXrfzabgG4u3nZhpq
                          receiverAddress: '0x9f1f9a5c0f1d9a5c0f1d9a5c0f1d9a5c0f1d9a5c'
                          status: -1
                          anonymous: false
                          expires: '2026-09-24T10:15:09.594Z'
                          fixed: false
                          inFixed: false
                          inAmount: 0.3
                          inSymbol: SOL
                          outSymbol: ETH
                          multiId: 8ppABEC1HZGrSr1PGbUnCN
                          isDex: false
                          id: 6ab4f12584e2f105f5a2fbbf
                          hashUrl: ''
                          statusLabel: NEW
                          displayStatus: WAITING_FOR_DEPOSIT
        '401':
          description: >-
            Credentials missing, malformed, or rejected — all return
            `INVALID_API_CREDENTIALS`. Sending only `partner-id` returns
            `PARTNER_ID_NOT_SUPPORTED`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '402':
          description: >-
            Payment required — x402 protocol. The body is empty; what to pay is
            in the `payment-required` header. Not returned when you send an
            `Authorization` header.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/X402PaymentRequired'
          headers:
            payment-required:
              schema:
                type: string
              required: true
        '403':
          description: Access Denied
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Token not found or disabled
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: >-
            Every order failed and the first failure was a deposit address still
            held by another order (`STATIC_DEPOSIT_IN_USE`). Retry after the
            number of seconds in the `Retry-After` header.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
          headers:
            Retry-After:
              schema:
                type: string
              required: true
        '422':
          description: Validation Failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationError'
        '429':
          description: Rate limit exceeded — back off and retry
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '502':
          description: >-
            Every order failed and the first failure was a provider rejection
            (`SWAP_PROVIDER_REJECTED_QUOTE`,
            `ANON_SWAP_PROVIDER_REJECTED_QUOTE`, `PROVIDER_EXCHANGE_FAILED`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: >-
            Every order failed and the first failure was that no provider could
            take the order right now (`PRICE_QUOTES_NOT_RETRIEVED`), or private
            swaps are disabled (`ANONYMOUS_DISABLED`). Retry shortly.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - apiKey: []
components:
  schemas:
    MultiExchangeRequest:
      properties:
        orders:
          items:
            $ref: '#/components/schemas/MultiOrderItem'
          type: array
          minItems: 1
          maxItems: 50
        filters:
          $ref: '#/components/schemas/QuoteFilters'
          description: Provider filters applied to every order in the batch
        intermediateRefundAddress:
          type: string
          description: >-
            Default `intermediateRefundAddress` for every order that doesn't
            send its own; see that field. Use it to collect all failed hops'
            USDC in one wallet.


            - It must fit every order: a batch mixing Solana and other
            destinations needs per-order addresses.

            - One shared address links those orders' recipients for anyone who
            knows it.
          maxLength: 200
      required:
        - orders
      type: object
      additionalProperties: false
    MultiExchangeCreateResult:
      description: >-
        Response for POST /exchanges/multi — per-item envelope, some may be
        errors
      properties:
        multiId:
          type: string
        orders:
          items:
            $ref: '#/components/schemas/MultiOrderResult'
          type: array
      required:
        - multiId
        - orders
      type: object
      additionalProperties: false
    ErrorResponse:
      properties:
        message:
          type: string
        code:
          type: string
          description: >-
            Machine-readable reason for the failure. Branch on this, not on
            `message` — messages are free to change.


            The value depends on the HTTP status. The common ones:


            - `400` — `BAD_REQUEST`

            - `401` — `INVALID_API_CREDENTIALS`, `PARTNER_ID_NOT_SUPPORTED`

            - `403` — `ACCESS_DENIED`, `FIXED_RATE_NOT_ALLOWED`

            - `404` — `NOT_FOUND`, `TOKEN_NOT_FOUND`, `TOKEN_DISABLED`

            - `409` — `ALREADY_SUBMITTED`, `STATIC_DEPOSIT_IN_USE`

            - `422` — `VALIDATION_ERROR`, `AMOUNT_TOO_LOW`, `INVALID_SWAP`,
            `FIXED_RATE_QUOTE_EXPIRED`, and most other request problems

            - `429` — `RATE_LIMIT_EXCEEDED`

            - `5xx` — `INTERNAL_SERVER_ERROR`, `PROVIDER_EXCHANGE_FAILED`,
            `SERVICE_UNAVAILABLE`


            New codes are added over time, so treat this as an open set: match
            the ones you handle and fall back to the HTTP status for the rest.
        requestId:
          type: string
          description: >-
            Unique id for this request. Quote it when contacting support — it is
            how we find the failure in our logs.
      required:
        - message
        - code
      type: object
      additionalProperties: false
    X402PaymentRequired:
      description: >-
        Body of a `402 Payment required`. Empty — `{}` — for API clients; a
        request that looks like a browser gets an HTML paywall page instead.


        This is the x402 payment protocol, not the normal error format, so there
        is no `code` or `message` to branch on. What to pay is always in the
        `payment-required` response header, in both cases: base64-encoded JSON
        whose `accepts[]` entries each carry the `network`, the `asset` to pay
        in, the `amount`, and the `payTo` address, alongside `maxTimeoutSeconds`
        and the x402 `scheme`.


        Sending `Authorization` skips the payment flow, so a 402 only reaches
        callers paying per request. An `apiKey` query param also skips it but is
        not a credential — those requests fail with `401
        INVALID_API_CREDENTIALS`.
      properties: {}
      type: object
      additionalProperties: false
    ValidationError:
      properties:
        message:
          type: string
        code:
          type: string
          description: >-
            Machine-readable reason for the failure. Branch on this, not on
            `message` — messages are free to change.


            The value depends on the HTTP status. The common ones:


            - `400` — `BAD_REQUEST`

            - `401` — `INVALID_API_CREDENTIALS`, `PARTNER_ID_NOT_SUPPORTED`

            - `403` — `ACCESS_DENIED`, `FIXED_RATE_NOT_ALLOWED`

            - `404` — `NOT_FOUND`, `TOKEN_NOT_FOUND`, `TOKEN_DISABLED`

            - `409` — `ALREADY_SUBMITTED`, `STATIC_DEPOSIT_IN_USE`

            - `422` — `VALIDATION_ERROR`, `AMOUNT_TOO_LOW`, `INVALID_SWAP`,
            `FIXED_RATE_QUOTE_EXPIRED`, and most other request problems

            - `429` — `RATE_LIMIT_EXCEEDED`

            - `5xx` — `INTERNAL_SERVER_ERROR`, `PROVIDER_EXCHANGE_FAILED`,
            `SERVICE_UNAVAILABLE`


            New codes are added over time, so treat this as an open set: match
            the ones you handle and fall back to the HTTP status for the rest.
        requestId:
          type: string
          description: >-
            Unique id for this request. Quote it when contacting support — it is
            how we find the failure in our logs.
        fields:
          $ref: '#/components/schemas/FieldErrors'
          description: >-
            The inputs that failed, keyed by field name — or by path for a
            nested field, e.g. `filters.rotatePayoutWallets`. Each entry has a
            `message` and, when you sent one, the `value`.


            Not every `422` names its input, so `fields` can be `{}`: branch on
            `code`, and use `fields` to highlight the input when one is named.
      required:
        - message
        - code
        - fields
      type: object
      additionalProperties: false
    MultiOrderItem:
      description: >-
        A single order within a Split batch. Quotes are resolved internally — no
        quoteId required.
      properties:
        from:
          type: string
          description: >-
            Token you are swapping from — an `id` from [Get
            tokens](/api-reference/private-and-standard-swaps/get-tokens), e.g.
            `6689b73ec90e45f3b3e51566`.
          example: 6689b73ec90e45f3b3e51566
          minLength: 24
          maxLength: 24
        to:
          type: string
          description: >-
            Token you are swapping to — an `id` from [Get
            tokens](/api-reference/private-and-standard-swaps/get-tokens), e.g.
            `6689b73ec90e45f3b3e51558`.
          example: 6689b73ec90e45f3b3e51558
          minLength: 24
          maxLength: 24
        amount:
          type: number
          format: double
          description: >-
            Amount you send. With `amountType: "receive"`, the amount the
            receiver gets instead.
        amountType:
          type: string
          enum:
            - send
            - receive
          description: >-
            What `amount` means. Use `receive` to pay an exact amount.


            - `send` (default): `amount` is what you deposit

            - `receive`: `amount` is what the receiver gets. The deposit is the
            order's `inAmount`: read it from [Get batch
            status](/api-reference/split/get-batch-status) once the order has a
            `depositAddress`. The create response only shows an estimate.

            - `receive` needs `fixed: true`, or the batch is rejected with
            `EXACT_OUT_REQUIRES_FIXED_RATE`
        addressTo:
          type: string
          description: Destination wallet address
          minLength: 1
          maxLength: 200
        anonymous:
          type: boolean
          description: Use anonymous (private) routing
        destinationTag:
          type: string
          description: >-
            Memo/tag for `addressTo`, e.g. XRP destination tag, Stellar memo,
            TON comment. Send it when the destination token's chain has
            `memoNeeded: true` — see [Get
            chains](/api-reference/reference-data/get-chains).
          maxLength: 64
        useXmr:
          type: boolean
          description: >-
            Use Monero (XMR) as the bridge token on a private swap. Unset picks
            from a rotating set of other tokens.
        walletInfo:
          type: string
          description: >-
            Name of the wallet the user is swapping from, e.g. `MetaMask`,
            `Phantom`, `Trust Wallet`. Optional.
          maxLength: 256
        filters:
          $ref: '#/components/schemas/QuoteFilters'
          description: >-
            Deprecated provider filters alias. Use top-level
            MultiExchangeRequest.filters instead.
        fixed:
          type: boolean
          description: >-
            Use a fixed rate for this order. You do not send a `quoteId`.


            - the rate is quoted when you create the order, and the exchange
            locks it when the order gets its `depositAddress`. If it expired
            before then, the order fails with `FIXED_RATE_QUOTE_EXPIRED`

            - with 2 or more orders, read the final `inAmount` and `outAmount`
            from [Get batch status](/api-reference/split/get-batch-status) once
            the order has a `depositAddress`. If its first route fails, a
            standard order can move to another fixed route with a slightly worse
            rate (by default at most 5%)

            - `refundAddress` is required

            - your account must have fixed-rate access, or you get
            `FIXED_RATE_NOT_ALLOWED`

            - fixed orders expire sooner than floating ones, so send the deposit
            as soon as the `depositAddress` is ready
        refundAddress:
          type: string
          description: >-
            Where funds are returned if the swap cannot complete.


            - **use a wallet the user controls, not an exchange deposit
            address**

            - must be on the source chain — the refund comes back as the token
            you deposited

            - required when `fixed` is true

            - optional otherwise
          maxLength: 200
        refundExtraId:
          type: string
          description: >-
            Memo/tag for `refundAddress`, e.g. XRP destination tag, Stellar
            memo, TON comment. Send it when the source token's chain has
            `memoNeeded: true` — see [Get
            chains](/api-reference/reference-data/get-chains).
          maxLength: 64
        intermediateRefundAddress:
          type: string
          description: >-
            Where USDC is returned if this order's on-chain hop fails. Private
            orders to a token with no direct private route swap privately to
            USDC, then hop on-chain to the token; `refundAddress` still covers
            the deposit.


            - Optional. Falls back to the batch-level
            `intermediateRefundAddress`, then to `addressTo`. Send it to get
            refunds in a wallet other than the recipient.

            - No quote needed: a Solana address for Solana destinations, an EVM
            address for any other. Use a wallet you control on the refund chain;
            a contract wallet may not exist there.

            - Send one when `addressTo` is an EVM contract wallet, on a chain
            outside EVM and Solana, or an exchange deposit address. Without one,
            the first two cases don't take the hop, and neither does an order
            whose hop can't be priced at the time: the order is created without
            it and, since it has no direct route, will almost always fail on its
            own. An amount outside the hop's limits is reported in that order's
            own envelope. The rest of the batch is unaffected.

            - Used only by private, floating-rate orders that need the hop;
            ignored otherwise. The hop needs `privateOnchainLegEnabled` on your
            account.

            - The whole batch is rejected with `ONCHAIN_LEG_BUNDLE_REJECTED`
            (the message names the failing order, for example `orders[1]`) and
            no order is created if the address is invalid on the refund chain or
            sanctioned, or if the order needs the hop but can't take it (for
            example the hop has no route, `privateOnchainLegEnabled` is off, or
            the amount is outside the hop's limits). Only if the batch can't be
            checked at all, for example during a temporary pricing outage, is it
            rejected with `503 PRICE_QUOTES_NOT_RETRIEVED`, which can be
            retried. Checks that run as each order is created, such as the
            per-receiver open-order cap, can still fail one order after earlier
            orders in the batch were created; that order alone carries the
            error.

            - When more than one order in a batch takes the hop with a refund
            address you sent (here or at the batch level), their total is also
            capped. Above the cap the whole batch is rejected with
            `ONCHAIN_LEG_BUNDLE_OVER_LIMIT`, and no order is created. Orders
            that rely on the `addressTo` default don't fail the batch at the
            cap: if counting them would go over it, they are created without the
            hop instead, and will almost always fail on their own.
          maxLength: 200
        markup:
          type: number
          format: double
          description: >-
            Markup for this request, as a percentage — `0.5` means 0.5%.


            - range 0–4; overrides your account default for this trade

            - send `0` for no markup, or omit the field to use your account
            default

            - providers that cannot apply it are excluded from the results
          example: 0.5
          minimum: 0
          maximum: 4
      required:
        - from
        - to
        - amount
        - addressTo
      type: object
      additionalProperties: false
    QuoteFilters:
      properties:
        onlySwaps:
          items:
            type: string
          type: array
          description: >-
            Only quote these providers. Omit to use all of them. Values are
            `shortName` from [Get swap
            providers](/api-reference/reference-data/get-swap-providers).
        rotatePayoutWallets:
          type: boolean
          description: >-
            Rotate the payout path so your orders reuse the same routes less,
            for better privacy.


            - applies to orders, standard and private

            - in a Split, it also spreads the orders of one batch across
            different routes

            - ignored by quotes
        rotateFallback:
          type: boolean
          description: >-
            When strict rotation runs out of rotated routes, use a valid
            non-rotated route instead of failing. Default false. Needs
            `rotatePayoutWallets` — on its own it does nothing.
        deviationThreshold:
          type: number
          format: double
          description: >-
            How much worse a rotated route may be, as a percentage, before it is
            rejected. Default 5. Only used when `rotatePayoutWallets` is true.


            For `amountType: "receive"` orders the payout is the same on every
            route, so this limits how much bigger the deposit may be instead.
          minimum: 0
          maximum: 100
        rotationLookback:
          type: integer
          format: int32
          description: >-
            How many of your recent orders to look at when picking a different
            payout path. Default 10. Only used when `rotatePayoutWallets` is
            true.
          minimum: 1
          maximum: 100
        inLeg:
          $ref: '#/components/schemas/LegFilter'
          description: >-
            Provider filter for the in-leg of a private (2-hop) route. Omit it
            and `onlySwaps` applies to both legs. Ignored by standard and DEX,
            which are single-hop.
        outLeg:
          $ref: '#/components/schemas/LegFilter'
          description: >-
            Provider filter for the out-leg of a private (2-hop) route. Omit it
            and `onlySwaps` applies to both legs. Ignored by standard and DEX,
            which are single-hop.
      type: object
      additionalProperties: false
    MultiOrderResult:
      description: >-
        One entry per requested swap: either the created order, or the error
        that stopped it
      properties:
        order:
          $ref: '#/components/schemas/OrderV2PublicResponse'
        error:
          $ref: '#/components/schemas/MultiOrderError'
      type: object
      additionalProperties: false
    FieldErrors:
      properties: {}
      type: object
      additionalProperties:
        properties:
          value: {}
          message:
            type: string
        required:
          - message
        type: object
    LegFilter:
      properties:
        include:
          items:
            type: string
          type: array
          description: >-
            Only use these providers for this leg. Values are `shortName` from
            [Get swap
            providers](/api-reference/reference-data/get-swap-providers).
        exclude:
          items:
            type: string
          type: array
          description: >-
            Never use these providers for this leg. Values are `shortName` from
            [Get swap
            providers](/api-reference/reference-data/get-swap-providers).
      type: object
      additionalProperties: false
    OrderV2PublicResponse:
      properties:
        houdiniId:
          type: string
          description: Public order id. Use it with Get order details.
        depositTag:
          type: string
          description: >-
            Memo/tag that must be sent with the deposit, on chains that use one
            (XRP, TON, Stellar, …).


            Show it to your user next to `depositAddress` — a deposit sent
            without it may not be credited.
        expires:
          type: string
          format: date-time
          description: >-
            Deposit deadline — send the funds by this time or the order expires.
            Not a rate lock.
        displayStatus:
          $ref: '#/components/schemas/DisplayStatus'
          description: >-
            Human-readable state for your UI, derived from `status` and the leg
            statuses. Prefer this over `status`.
        status:
          $ref: '#/components/schemas/OrderStatus'
          description: >-
            Numeric order state. For anything user-facing prefer
            `displayStatus`.


            - `-2` initializing

            - `-1` created

            - `0` waiting for your deposit

            - `1` confirming your deposit

            - `2` exchanging

            - `3` anonymizing — private swaps only

            - `4` finished

            - `5` expired

            - `6` failed

            - `7` refunded

            - `8` deleted
        eta:
          type: number
          format: double
          description: ETA time, depending on swap
        inAmount:
          type: number
          format: double
          description: Amount to deposit, in the input token.
        inSymbol:
          type: string
          description: Symbol of the input token, e.g. `BTC`.
        outAmount:
          type: number
          format: double
          description: Amount you receive, in the output token.
        outSymbol:
          type: string
          description: Symbol of the output token, e.g. `ETH`.
        inAmountUsd:
          type: number
          format: double
          description: USD value of the input amount at order creation time.
        outAmountUsd:
          type: number
          format: double
          description: '`outAmount` valued in USD.'
        inToken:
          $ref: '#/components/schemas/Token'
          description: Token you sent.
        outToken:
          $ref: '#/components/schemas/Token'
          description: Token you received.
        receiverAddress:
          type: string
          description: Wallet the payout is sent to.
        refundAddress:
          type: string
          description: Refund address recorded for this order.
        intermediateRefundAddress:
          type: string
          description: >-
            The `intermediateRefundAddress` sent at [Create
            exchange](/api-reference/private-and-standard-swaps/create-exchange):
            where the intermediate hop's funds are returned if that hop cannot
            complete. Separate from `refundAddress`, which covers the deposit
            leg.


            Present only on orders whose route settles through an on-chain hop —
            those quoted with `requiresIntermediateRefundAddress: true`.
        anonymous:
          type: boolean
          description: True when this order took the private two-leg route.
        isDex:
          type: boolean
          description: True when the order executed on a DEX route.
        fixed:
          type: boolean
          description: True when the order settled at a locked rate.
        express:
          type: boolean
          description: >-
            True when this swap ran on a route expected to settle faster than
            usual. Absent when it did not.
        nonRefundable:
          type: boolean
          description: True when the deposit can no longer be refunded.
        actionRequired:
          type: boolean
          description: >-
            True when the order failed but your deposit had already arrived —
            contact support to recover the funds.
        rerouted:
          type: boolean
          description: >-
            True when the route that executed is not the one that was quoted,
            because the quoted route failed and a fallback was used. The amounts
            may differ from the quote — compare `inAmount` against
            `quotedInAmount` and `outAmount` against `quotedOutAmount`.
        quotedInAmount:
          type: number
          format: double
          description: >-
            The deposit amount originally quoted, present only when the order
            was rerouted. `inAmount` is what the fallback route actually asks
            for; on an exact-out order this is the side that moves.
        quotedOutAmount:
          type: number
          format: double
          description: >-
            The payout originally quoted, present only when the order was
            rerouted. `outAmount` is what the fallback route will actually pay;
            on an exact-in order this is the side that moves.
        refundHash:
          type: string
          description: >-
            Hash of the transaction that returned your funds. Absent unless the
            order refunded.
        refundChain:
          type: string
          description: >-
            Chain the refund was returned on, e.g. "bsc". Refunds are returned
            on the input chain.
        refundAmount:
          type: number
          format: double
          description: >-
            Amount returned to you, after the provider's refund fee. Absent when
            the exchange did not report one.
        inStatus:
          $ref: '#/components/schemas/Status'
          description: >-
            Progress of the incoming leg — your deposit reaching the provider.
            For reference and debugging; drive your UI from `displayStatus`
            instead.


            - `0` created

            - `1` waiting for the deposit

            - `2` deposit seen, waiting for confirmations

            - `3` exchanging

            - `4` sending funds on

            - `5` finished

            - `6` failed

            - `7` refunded

            - `8` on hold for a compliance check

            - `9` expired — no deposit arrived in time

            - `10` finished through a fallback payout
        created:
          type: string
          format: date-time
        modified:
          type: string
          format: date-time
        inCreated:
          type: string
          format: date-time
          description: When the incoming leg was created.
        notified:
          type: boolean
        id:
          type: string
        metadata:
          description: Extra data from the provider. The shape depends on the route.
        receiverTag:
          type: string
          nullable: true
          description: Memo/tag required when receiving funds for assets that use one
        swapName:
          type: string
          description: >-
            Name of the exchange handling the deposit leg. Omitted on private
            orders, which withhold the provider, and on Split orders that have
            not yet been assigned one.
        multiId:
          type: string
          description: Split group ID. Present only on orders created as part of a batch.
        outStatus:
          $ref: '#/components/schemas/Status'
          description: >-
            Status of the payout leg. Present only on private orders — public
            orders settle in a single leg and never carry one. For reference and
            debugging; drive your UI from `displayStatus` instead.


            - `0` created

            - `1` waiting for the deposit

            - `2` deposit seen, waiting for confirmations

            - `3` exchanging

            - `4` sending funds on

            - `5` finished

            - `6` failed

            - `7` refunded

            - `8` on hold for a compliance check

            - `9` expired — no deposit arrived in time

            - `10` finished through a fallback payout
        transactionHash:
          type: string
          nullable: true
          description: >-
            Hash of the transaction that delivered the result of the order. Use
            this field to show or link the payout — it works the same on
            standard and private orders.


            - Finished order: the payout to `receiverAddress`.

            - Refunded order: the transaction that returned your funds.

            - Otherwise: empty until the payout is sent.
        hashUrl:
          type: string
          description: >-
            Block explorer link for `transactionHash`. Empty until
            `transactionHash` is set, or when the chain has no explorer.
        inHash:
          type: string
          nullable: true
          description: Hash of your deposit transaction. Empty until the deposit is seen.
        inTransactionInHash:
          type: string
          nullable: true
          description: |-
            Deprecated. Use `inHash`.

            Hash of your deposit transaction. Empty until the deposit is seen.
          deprecated: true
        outTransactionOutHash:
          type: string
          nullable: true
          description: >-
            Deprecated. Use `transactionHash`.


            Payout hash of the second leg of a private order. Empty on standard
            orders, and on private orders until that leg has paid out.
          deprecated: true
        orderFinishedReceived:
          type: string
          format: date-time
          description: >-
            When the order reached a final state. Stamped only when an order
            finishes — orders that expire, fail or refund never receive one.
        depositAddress:
          type: string
          description: >-
            The deposit address where the user must send funds. Omitted on Split
            orders whose per-order setup did not complete.
      required:
        - houdiniId
        - expires
        - displayStatus
        - status
        - eta
        - inAmount
        - inSymbol
        - outAmount
        - outSymbol
        - inAmountUsd
        - outAmountUsd
        - inToken
        - outToken
        - receiverAddress
        - anonymous
        - isDex
        - actionRequired
        - inStatus
        - created
        - inCreated
        - notified
        - id
      type: object
      additionalProperties: false
    MultiOrderError:
      properties:
        message:
          type: string
        code:
          anyOf:
            - type: string
            - type: number
              format: double
      required:
        - message
      type: object
      additionalProperties: false
    DisplayStatus:
      description: >-
        Human-readable order state, derived from `status` and the per-leg
        statuses. Use this to drive your UI.


        - `WAITING_FOR_DEPOSIT` — waiting for your deposit to arrive

        - `DEPOSIT_DETECTED` — deposit seen, waiting for confirmations

        - `EXCHANGE_IN_PROGRESS` — the swap is running

        - `SENDING_TO_INTERMEDIARY` — private only: first leg on its way to the
        bridge token

        - `REACHED_INTERMEDIARY` — private only: first leg done

        - `INITIATING_SECOND_EXCHANGE` — private only: second leg starting

        - `SECOND_EXCHANGE_IN_PROGRESS` — private only: second leg running

        - `SENDING_TO_RECEIVER` — payout on its way to `receiverAddress`

        - `SWAP_COMPLETED` — finished

        - `EXPIRED` — no deposit arrived before `expires`

        - `FAILED` — the swap could not complete; check `actionRequired`

        - `REFUNDED` — funds returned to `refundAddress`

        - `DELETED` — order removed
      enum:
        - WAITING_FOR_DEPOSIT
        - DEPOSIT_DETECTED
        - EXCHANGE_IN_PROGRESS
        - SENDING_TO_INTERMEDIARY
        - REACHED_INTERMEDIARY
        - INITIATING_SECOND_EXCHANGE
        - SECOND_EXCHANGE_IN_PROGRESS
        - SENDING_TO_RECEIVER
        - SWAP_COMPLETED
        - EXPIRED
        - FAILED
        - REFUNDED
        - DELETED
      type: string
    OrderStatus:
      description: |-
        - **-2** Order is being initialized (label: INITIALIZING)
        - **-1** Order initialized (label: NEW)
        - **0** Waiting for deposit confirmation (label: WAITING)
        - **1** Deposit is being confirmed (label: CONFIRMING)
        - **2** Exchange is in progress (label: EXCHANGING)
        - **3** Order is going through anonymization (label: ANONYMIZING)
        - **4** Order completed successfully (label: FINISHED)
        - **5** Order has expired (label: EXPIRED)
        - **6** Order failed (label: FAILED)
        - **7** Order was refunded (label: REFUNDED)
        - **8** Order was deleted (label: DELETED)
      enum:
        - -2
        - -1
        - 0
        - 1
        - 2
        - 3
        - 4
        - 5
        - 6
        - 7
        - 8
      type: number
    Token:
      properties:
        icon:
          type: string
          description: Token icon URL.
        id:
          type: string
          description: The token id. Pass this as `from` / `to` when quoting.
        address:
          type: string
          nullable: true
          description: Contract address. Null for a chain's native coin — see `mainnet`.
        chain:
          type: string
          description: >-
            Chain short name, e.g. `ethereum`. Matches `shortName` on
            `chainData`.
        decimals:
          type: integer
          format: int32
          description: >-
            On-chain decimals. Amounts in this API are decimals in the token's
            own units, so you only need this for on-chain work.
        symbol:
          type: string
        name:
          type: string
        created:
          type: string
          format: date-time
        modified:
          type: string
          format: date-time
        chainData:
          $ref: '#/components/schemas/Chain'
          description: The chain this token lives on.
        description:
          type: string
          nullable: true
          description: Token description from CoinGecko.
        mainnet:
          type: boolean
          description: >-
            True for the chain's native coin (e.g. ETH on Ethereum), false for
            an issued token (e.g. USDT). Not related to mainnet vs testnet.
        enabled:
          type: boolean
          description: False when the token is temporarily not swappable.
        unverified:
          type: boolean
          description: >-
            True when we have not reviewed this token yet — check `securityScan`
            before using it.
        hasDex:
          type: boolean
          description: True when the token can be swapped on DEX routes.
        hasCex:
          type: boolean
          description: True when the token can be swapped on private and standard routes.
        hasBundler:
          type: boolean
          description: >-
            True when the bundler can fund this token — paying for a whole Split
            group with one transaction instead of a deposit per order. Available
            on Solana, and on supported EVM chains.
        hasSelfPrivate:
          type: boolean
          description: >-
            True when the token supports self-to-self private swaps — send it
            and receive the same token at another address, with no on-chain
            link.
        cexTokenId:
          type: string
          description: The token's identifier on centralized exchanges.
          default: ''
        rank:
          type: number
          format: double
          nullable: true
          description: CoinGecko market-cap rank. Null when unranked.
        cgId:
          type: string
          nullable: true
          description: CoinGecko id for this token.
        marketCapChange24h:
          type: number
          format: double
          description: 24h market cap change percentage from CoinGecko.
        circulatingSupply:
          type: number
          format: double
          description: Token circulating supply from CoinGecko.
        price:
          type: number
          format: double
          nullable: true
          description: Current price in USD, from CoinGecko.
        marketCap:
          type: number
          format: double
          nullable: true
          description: Market cap in USD, from CoinGecko.
        volume:
          type: number
          format: double
          nullable: true
          description: 24h trading volume in USD, from CoinGecko.
        fdv:
          type: number
          format: double
          nullable: true
          description: Fully diluted valuation in USD, from CoinGecko.
        change:
          type: number
          format: double
          nullable: true
          description: 24h price change, as a percentage.
        priority:
          type: number
          format: double
          nullable: true
          description: Display order — lower sorts first. Unrelated to `rank`.
        warningMessage:
          type: string
          description: Warning to show the user before swapping this token.
        securityScan:
          $ref: '#/components/schemas/TokenSecurityScan'
          description: >-
            Latest security verdict for this token. Absent until the token has
            been used in a swap at least once.
      required:
        - icon
        - id
        - chain
        - decimals
        - symbol
        - name
        - created
        - chainData
        - enabled
      type: object
      additionalProperties: false
    Status:
      description: |-
        - **0** New swap
        - **1** Waiting for confirmation
        - **2** Being confirmed
        - **3** Exchange in progress
        - **4** Sending to destination
        - **5** Swap completed
        - **6** Swap failed
        - **7** Swap refunded
        - **8** Verifying swap
        - **9** Swap expired
        - **10** Fallback mode
      enum:
        - 0
        - 1
        - 2
        - 3
        - 4
        - 5
        - 6
        - 7
        - 8
        - 9
        - 10
      type: number
    Chain:
      properties:
        icon:
          type: string
          description: Chain icon URL.
        addressValidation:
          type: string
          description: >-
            Regex a wallet address on this chain must match. Use it to validate
            `addressTo` before creating an exchange.
        tokenAddressValidation:
          type: string
          description: Regex a token contract address on this chain must match.
        id:
          type: string
        created:
          type: string
          format: date-time
        modified:
          type: string
          format: date-time
        name:
          type: string
          description: Readable chain name, e.g. `Bitcoin`.
        shortName:
          type: string
          description: >-
            The chain's identifier. Pass this wherever an endpoint takes a
            chain, e.g. `ethereum`.
        memoNeeded:
          type: boolean
          nullable: true
          description: >-
            True when an address on this chain needs a memo or destination tag,
            e.g. XRP or TON. Send it as `destinationTag` for the payout address,
            or `refundExtraId` for the refund address.
        hashUrl:
          type: string
          description: >-
            Explorer link for a transaction hash, when it differs from
            `explorerUrl`.
        explorerUrl:
          type: string
          description: >-
            Template for a transaction link — substitute `{txHash}`, e.g.
            `https://blockchair.com/bitcoin/transaction/{txHash}`.
        addressUrl:
          type: string
          description: >-
            Template for an address link — substitute `{address}`, e.g.
            `https://blockchair.com/bitcoin/address/{address}`.
        priority:
          type: number
          format: double
          description: |-
            Display order, lower sorts first.
            * `0` is the highest priority and `99999` the lowest.
        kind:
          type: string
          description: >-
            Chain family, e.g. `evm`, `sol`, `bitcoin`, `xmr`, `ltc`. Determines
            the address format and which on-chain steps a DEX swap needs.
        chainId:
          type: number
          format: double
          nullable: true
          description: EVM chain id, e.g. `1` for Ethereum. Null on non-EVM chains.
        enabled:
          type: boolean
          description: False when the chain is temporarily not routing swaps.
        shortNameV1:
          type: string
          description: The chain's name in the v1 API. Use `shortName` instead.
      required:
        - icon
        - addressValidation
        - tokenAddressValidation
        - id
        - created
        - name
        - shortName
        - explorerUrl
        - addressUrl
        - priority
        - kind
        - enabled
        - shortNameV1
      type: object
      additionalProperties: false
    TokenSecurityScan:
      properties:
        provider:
          type: string
          description: Screening provider that produced this verdict.
        resultType:
          $ref: '#/components/schemas/TokenScanResult'
        providerResultType:
          type: string
          description: >-
            The provider's own `result_type` string, kept unmapped so a verdict
            we don't model yet is still visible to support instead of being
            erased.
        maliciousScore:
          type: number
          format: double
          description: >-
            Provider `malicious_score`, 0..1. Arrives as a string; stored as a
            number.
        features:
          items:
            $ref: '#/components/schemas/TokenScanFeature'
          type: array
          default: []
        unscannedReason:
          $ref: '#/components/schemas/TokenScanUnscannedReason'
        unscannedDetail:
          type: string
          description: >-
            Free-text detail behind `unscannedReason` (provider message,
            status…).
        scannedAt:
          type: string
          format: date-time
        expiresAt:
          type: string
          format: date-time
          description: When this verdict goes stale and the token should be re-scanned.
      required:
        - scannedAt
        - expiresAt
      type: object
      additionalProperties: false
    TokenScanResult:
      description: >-
        Security verdict for a token. Branch on this rather than on `features`.


        - `Benign` — no issues found

        - `Warning` — show a warning before swapping

        - `Malicious` — do not swap

        - `Unscanned` — could not be screened. Screening is fail-open, so this
        never blocks a swap on its own.
      enum:
        - Benign
        - Warning
        - Malicious
        - Unscanned
      type: string
    TokenScanFeature:
      description: >-
        One finding from the security scan, for display only. The list of
        possible findings changes over time, so branch on `resultType` instead.
      properties:
        featureId:
          type: string
        type:
          type: string
          description: >-
            Provider severity for this feature: Malicious | Warning | Benign |
            Info.
        description:
          type: string
      type: object
      additionalProperties: false
    TokenScanUnscannedReason:
      description: >-
        Why a token ended up `UNSCANNED`. Diagnostic only — never a branching
        input.
      enum:
        - NOT_CONFIGURED
        - UNSUPPORTED_CHAIN
        - NATIVE_TOKEN
        - RATE_LIMITED
        - TIMEOUT
        - PROVIDER_ERROR
        - NO_RESULT
        - SCAN_PENDING
        - NOT_A_TOKEN
        - UNKNOWN_RESULT_TYPE
      type: string
  securitySchemes:
    apiKey:
      type: apiKey
      name: Authorization
      in: header
      description: >-
        Send `Authorization: <ApiKey>:<ApiSecret>` — joined by a colon, raw. No
        `Bearer` prefix, no base64.


        [Get your
        credentials](https://docs.houdini.com/developer-hub/getting-started/authentication)

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.