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

# Get token approval data

> Returns what the wallet must approve before a DEX swap. Call this first — both arrays come back empty when the allowance already covers the swap.

- `approvals` — transactions to send. After sending them, poll [Check token allowance](/api-reference/on-chain-dex-or-bridge/check-token-allowance) until it returns true.
- `signatures` — EIP-712 permits to sign instead, when the token and provider both support EIP-2612



## OpenAPI

````yaml https://api-partner.houdiniswap.com/v2/openapi.json post /dex/approve
openapi: 3.0.0
info:
  title: Houdini Swap 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: Multi-Exchange
    description: >-
      Create and track a group of swaps sharing one `multiId`.


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

      - Get multi quotes is optional, for showing rates first

      - each order gets its own deposit address; poll [Get batch
      status](/api-reference/multi-exchange/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 [multi-swap
      flow](https://docs.houdiniswap.com/developer-hub/swap-flows/multi-swap)
      for the full sequence.
  - name: Bundler SOL
    description: >-
      Fund a whole multi-exchange group with one Solana batch transfer.


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

      - up to 10 deposits per batch; every order must send the same token

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

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


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


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

      - up to 20 legs per batch; every order must send the same source token

      - find batchable tokens with [Get
      tokens](/api-reference/multi-exchange/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 [multi-swap
      flow](https://docs.houdiniswap.com/developer-hub/swap-flows/multi-swap)
      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:
  /dex/approve:
    post:
      tags:
        - On-chain DEX or Bridge
      summary: Get token approval data
      description: >-
        Returns what the wallet must approve before a DEX swap. Call this first
        — both arrays come back empty when the allowance already covers the
        swap.


        - `approvals` — transactions to send. After sending them, poll [Check
        token
        allowance](/api-reference/on-chain-dex-or-bridge/check-token-allowance)
        until it returns true.

        - `signatures` — EIP-712 permits to sign instead, when the token and
        provider both support EIP-2612
      operationId: Approve
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ApproveRequest'
      responses:
        '200':
          description: What the wallet must approve; both arrays empty if nothing is needed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApprovalResponse'
              examples:
                Example 1:
                  value:
                    approvals:
                      - from: '0xb7dE6b6eEBF7401aFea5a49D6405C9048fEf2d40'
                        to: '0xdac17f958d2ee523a2206206994597c13d831ec7'
                        data: >-
                          0x095ea7b30000000000000000000000001111111254eeb25477b68fb85ed929f73a960582000000000000000000000000000000000000000000000000000000003b9aca00
                        fromChain:
                          id: 6689b73ec90e45f3b3e5150a
                          name: Ethereum
                          shortName: ethereum
                          shortNameV1: ETH
                          kind: evm
                          chainId: 1
                          enabled: true
                          icon: https://api.houdiniswap.com/assets/networks/ETH.png
                          created: '2024-07-06T10:21:18.000Z'
                          explorerUrl: https://etherscan.io/tx/{txHash}
                          addressUrl: https://etherscan.io/address/{address}
                          addressValidation: ^0x[a-fA-F0-9]{40}$
                          tokenAddressValidation: ^0x[a-fA-F0-9]{40}$
                    signatures: []
        '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'
        '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'
      security:
        - apiKey: []
components:
  schemas:
    ApproveRequest:
      properties:
        quoteId:
          type: string
          description: Quote ID from a prior quote response.
          example: 69a02882f48d56c923119d95
        addressFrom:
          type: string
          description: Address from which the amount will be deducted (EVM or Tron)
          example: '0xb7dE6b6eEBF7401aFea5a49D6405C9048fEf2d40'
          pattern: ^(0x[0-9a-fA-F]{40}|T[1-9A-HJ-NP-Za-km-z]{33})$
        addressTo:
          type: string
          description: >-
            Destination address on the output chain. Only required by routes
            whose approval step signs the destination, currently HyperCore
            withdrawals. Format follows the output chain, so it is not
            restricted to EVM.
          example: 8jZnXYnZB1MJQG6zBXyouzcycsaPTrZtPXPHDNifjYaC
        usePermit:
          type: boolean
          description: >-
            Whether to use permit instead of approve. Defaults to true for swaps
            that support it.
          example: false
      required:
        - quoteId
        - addressFrom
      type: object
      additionalProperties: false
    ApprovalResponse:
      properties:
        approvals:
          items:
            $ref: '#/components/schemas/ApproveTransaction'
          type: array
          description: >-
            Transactions the wallet must send before the swap. Empty when the
            allowance already covers it.
        signatures:
          items:
            $ref: '#/components/schemas/ApprovalTypedData'
          type: array
          description: >-
            Messages to sign instead of sending an approval transaction, when
            the token and provider both support it. Pass the signed results to
            `signatures` on [Create
            exchange](/api-reference/private-and-standard-swaps/create-exchange).
      required:
        - approvals
        - signatures
      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'
      required:
        - message
        - code
        - fields
      type: object
      additionalProperties: false
    ApproveTransaction:
      properties:
        data:
          type: string
          description: >-
            Calldata to send. Encodes the approval for the amount this swap
            needs.
        to:
          type: string
          description: >-
            Send the transaction to this address — the contract of the token
            being approved.
        from:
          type: string
          description: >-
            Wallet that must send the transaction — the `addressFrom` you
            supplied.
        fromChain:
          $ref: '#/components/schemas/Chain'
          description: Chain the transaction runs on.
      required:
        - data
        - to
        - from
        - fromChain
      type: object
      additionalProperties: false
    ApprovalTypedData:
      properties:
        data:
          $ref: '#/components/schemas/EIP712TypedData'
          description: The EIP-712 payload for the wallet to sign.
        type:
          $ref: '#/components/schemas/SignatureType'
          description: >-
            `single` — sign it and you are done. `chained` — sign it, then call
            [Get next chain
            signature](/api-reference/on-chain-dex-or-bridge/get-next-chain-signature)
            for the next one.
        totalSteps:
          type: number
          format: double
          description: >-
            How many signatures this chain needs in total. `1` for a single
            signature.
        step:
          type: number
          format: double
          description: Which signature this is, counting from 1.
        isComplete:
          type: boolean
          description: >-
            True on the last signature of the chain — stop asking for more once
            you see it.
        key:
          type: string
          description: >-
            Identifies this signature. Pass it as `key` to [Get next chain
            signature](/api-reference/on-chain-dex-or-bridge/get-next-chain-signature)
            to fetch the next step.
        swapRequiredMetadata:
          $ref: '#/components/schemas/Record_string.any_'
          description: >-
            Provider data attached to this signature. Send it back unchanged
            with the signed result — the swap fails without it.
      required:
        - data
        - type
        - totalSteps
        - step
        - isComplete
        - key
      type: object
      additionalProperties: false
    FieldErrors:
      properties: {}
      type: object
      additionalProperties:
        properties:
          value: {}
          message:
            type: string
        required:
          - message
        type: object
    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.
        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
        - kind
        - enabled
        - shortNameV1
      type: object
      additionalProperties: false
    EIP712TypedData:
      properties:
        domain:
          $ref: '#/components/schemas/TypedDataDomain'
        types:
          $ref: '#/components/schemas/Record_string.TypedDataField-Array_'
        primaryType:
          type: string
        message:
          $ref: '#/components/schemas/Record_string.any_'
      required:
        - domain
        - types
        - primaryType
        - message
      type: object
      additionalProperties: false
    SignatureType:
      enum:
        - single
        - chained
      type: string
    Record_string.any_:
      properties: {}
      additionalProperties: {}
      type: object
      description: Construct a type with a set of properties K of type T
    TypedDataDomain:
      properties:
        name:
          type: string
        version:
          type: string
        chainId:
          type: number
          format: double
        verifyingContract:
          type: string
        salt:
          type: string
      type: object
      additionalProperties: false
    Record_string.TypedDataField-Array_:
      properties: {}
      additionalProperties:
        items:
          $ref: '#/components/schemas/TypedDataField'
        type: array
      type: object
      description: Construct a type with a set of properties K of type T
    TypedDataField:
      properties:
        name:
          type: string
        type:
          type: string
      required:
        - name
        - type
      type: object
      additionalProperties: false
  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.houdiniswap.com/developer-hub/getting-started/authentication)

````

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