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

# Build a swap

> The instructions of the swap for `userPublicKey`, ready to assemble and sign, plus their
budget (`transactionConfig`) and what the transaction costs the wallet (`costs`). With
`serialize: true` the response also carries the whole unsigned v1 transaction
(`swapTransaction`) and `lastValidBlockHeight`.

**Which route is built**, in this order:
1. `quoteResponse`: the route of that quote, as quoted. No re-quote and no age check: build
   right after quoting, or the transaction may revert on `minReturn`.
2. `routeTicket`: the signed route of a quote (only when your router sets `ROUTER_TICKET_SECRET`).
3. Otherwise `inputMint` + `outputMint` + `amount` (and the quote parameters): quoted now and built.

**Assembling the transaction yourself:** `setupInstructions`, then every entry of
`swapInstructions` (two for a split), then `cleanupInstruction` if present, then
`otherInstructions`, with `transactionConfig` in the v1 header (`POST /tx/v1` does the
serialization). `computeBudgetInstructions` and `addressLookupTableAddresses` are always
empty: a v1 message carries its budget in the header and takes no lookup tables.

**Differences from Jupiter:** `quoteResponse` is optional; `feeAccount` is the fee
**wallet** (the router derives its token account); `destinationTokenAccount` is the
receiving **wallet**, not a token account; the transaction is v1 with no lookup tables;
extra fields `swapInstructions`, `quoteId`, `buildId`, `shape`, `minReturn`, `maxAmountIn`,
`computeUnits`, `loadedAccountsDataSize`, `txVersion`, `transactionConfig`, `routePlan`,
`costs`; no `tokenLedgerInstruction`, `prioritizationType`, `simulationError` or
`dynamicSlippageReport`; `useSharedAccounts`, `dynamicComputeUnitLimit`,
`skipUserAccountsRpcCalls`, `dynamicSlippage`, `trackingAccount` and `blockhashSlotsToExpiry`
are ignored.


Guides: [Quote and swap](/router/quote-and-swap), [Transactions](/router/transactions), [Platform fee](/router/fees). Errors: [build declines](/router/errors#build-declines).


## OpenAPI

````yaml router.openapi.yaml POST /swap-instructions
openapi: 3.1.0
info:
  title: Raze Swap Router API
  version: 1.0.0
  description: >
    Quotes and **unsigned** transactions for swaps on Solana, routed over ~20
    venues through a

    deploy of the `swap` program. The router **never signs and never sends**:
    you get a

    quote, then the instructions (or a serialized, unsigned transaction), and
    you sign and

    broadcast from your backend.


    **Public router.** `https://router.raze.bot` is Raze's router: it takes no
    key and builds for

    Raze's deploy of the `swap` program,
    `DADMMjfNnY6z8H9h9RfHZ9tfarBySsj4Yb65qLyKJDAD`.


    **One router, one `swap` deploy.** A router builds for the program address
    in its

    `ROUTER_SWAP_PROGRAM_ID` (the `programId` of every `swapInstruction` is that
    address) and

    reads that deploy's on-chain config: a venue the config has no live row for
    is never served,

    and while the config is paused every build answers `503`.


    **No authentication.** A router you run yourself has no keys, no accounts
    and no rate limit. It

    listens on loopback by default (`ROUTER_LISTEN=127.0.0.1:4700`); keep it
    behind your firewall or

    your own gateway.


    **Conventions:**

    - Amounts are integers in the token's base units (lamports, atoms). In
    quotes and builds the
      u64 amounts are decimal **strings** (`inAmount`, `outAmount`, `otherAmountThreshold`,
      `platformFee.amount`, every `costs.*`). `minReturn`, `maxAmountIn`, `computeUnits` and
      `contextSlot` are JSON numbers.
    - Mints and wallets are base58 addresses; wrapped SOL is
    `So11111111111111111111111111111111111111112`.

    - Venue labels (`label`, `dexes`, `excludeDexes`) are the `dex` names of
    `GET /venues`; input
      labels match case- and punctuation-insensitively, aliases included.
    - Request bodies are read as JSON whatever the `Content-Type`; at most 256
    KiB (larger is `413`).

    - Unknown fields and query parameters are ignored, not rejected.


    **Transactions are v1** (SIMD-0385, prefix `0x81`, up to 4,096 bytes and 64
    account keys, no

    address lookup tables). The compute-unit limit, loaded-accounts limit and
    priority fee travel in

    the message header (`transactionConfig`), not as ComputeBudget instructions.
    Signing a v1

    transaction needs an SDK that supports it. `txVersion: 0` and
    `asLegacyTransaction: true` are

    refused.


    **Errors** are `{"error", "reason", "quoteId"}`: `error` is a closed code,
    `reason` a label or a

    sentence, `quoteId` present once the request was parsed. The status says
    whose move it is:

    `400` fix the request, `404` no route exists, `409` re-quote or retry later,
    `413` too large,

    `422` a named decline that waiting will not change, `500` a router bug,
    `503` not ready: retry

    with backoff. Two bodies differ: `not_ready` carries `reasons` (a list)
    instead of `reason`, and

    a `low_liquidity` decline adds `liquidity`.


    The quote and swap fields mirror Jupiter's Swap API (Metis), so most clients
    change only the

    host; differences are listed on each operation.
servers:
  - url: https://router.raze.bot
    description: Raze's public router
  - url: http://127.0.0.1:4700
    description: Your own router (default ROUTER_LISTEN)
security: []
tags:
  - name: ops
    description: Liveness and readiness
  - name: venues
    description: The venues this router knows, and the price oracle's verdict on each
  - name: swap
    description: Quote, then build the instructions or the unsigned transaction
  - name: transactions
    description: Serialize your own instructions as an unsigned v1 transaction
paths:
  /swap-instructions:
    post:
      tags:
        - swap
      summary: Build the swap instructions
      description: >
        The instructions of the swap for `userPublicKey`, ready to assemble and
        sign, plus their

        budget (`transactionConfig`) and what the transaction costs the wallet
        (`costs`). With

        `serialize: true` the response also carries the whole unsigned v1
        transaction

        (`swapTransaction`) and `lastValidBlockHeight`.


        **Which route is built**, in this order:

        1. `quoteResponse`: the route of that quote, as quoted. No re-quote and
        no age check: build
           right after quoting, or the transaction may revert on `minReturn`.
        2. `routeTicket`: the signed route of a quote (only when your router
        sets `ROUTER_TICKET_SECRET`).

        3. Otherwise `inputMint` + `outputMint` + `amount` (and the quote
        parameters): quoted now and built.


        **Assembling the transaction yourself:** `setupInstructions`, then every
        entry of

        `swapInstructions` (two for a split), then `cleanupInstruction` if
        present, then

        `otherInstructions`, with `transactionConfig` in the v1 header (`POST
        /tx/v1` does the

        serialization). `computeBudgetInstructions` and
        `addressLookupTableAddresses` are always

        empty: a v1 message carries its budget in the header and takes no lookup
        tables.


        **Differences from Jupiter:** `quoteResponse` is optional; `feeAccount`
        is the fee

        **wallet** (the router derives its token account);
        `destinationTokenAccount` is the

        receiving **wallet**, not a token account; the transaction is v1 with no
        lookup tables;

        extra fields `swapInstructions`, `quoteId`, `buildId`, `shape`,
        `minReturn`, `maxAmountIn`,

        `computeUnits`, `loadedAccountsDataSize`, `txVersion`,
        `transactionConfig`, `routePlan`,

        `costs`; no `tokenLedgerInstruction`, `prioritizationType`,
        `simulationError` or

        `dynamicSlippageReport`; `useSharedAccounts`, `dynamicComputeUnitLimit`,

        `skipUserAccountsRpcCalls`, `dynamicSlippage`, `trackingAccount` and
        `blockhashSlotsToExpiry`

        are ignored.
      operationId: getSwapInstructions
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SwapRequest'
            examples:
              fromQuote:
                summary: Build the route of a quote
                value:
                  userPublicKey: 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM
                  quoteResponse:
                    inputMint: So11111111111111111111111111111111111111112
                    inAmount: '100000000'
                    outputMint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
                    outAmount: '11769095'
                    otherAmountThreshold: '11710249'
                    swapMode: ExactIn
                    slippageBps: 50
                    priceImpactPct: '0'
                    routePlan:
                      - swapInfo:
                          ammKey: HTvjzsfX3yU6BUodCjZ5vZkUrAxMDTrBs3CJaq43ashR
                          label: Meteora DLMM
                          inputMint: So11111111111111111111111111111111111111112
                          outputMint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
                          inAmount: '100000000'
                          outAmount: '11769095'
                          walkSteps: 1
                        percent: 100
                        bps: 10000
                    contextSlot: 452409471
                    timeTaken: 0.000367825
                    quoteId: 23e14e01000044c6
              pair:
                summary: Quote now and build (no quoteResponse)
                value:
                  userPublicKey: 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM
                  inputMint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
                  outputMint: So11111111111111111111111111111111111111112
                  amount: '5000000'
                  slippageBps: 100
                  prioritizationFeeLamports:
                    priorityLevelWithMaxLamports:
                      maxLamports: 10000
                      priorityLevel: high
      responses:
        '200':
          description: The instructions (and, with `serialize`, the unsigned transaction)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SwapResponse'
              examples:
                built:
                  $ref: '#/components/examples/SwapBuilt'
        '400':
          $ref: '#/components/responses/SwapBadRequest'
        '404':
          $ref: '#/components/responses/NoRoute'
        '409':
          $ref: '#/components/responses/SwapConflict'
        '413':
          $ref: '#/components/responses/TooLarge'
        '422':
          $ref: '#/components/responses/SwapDeclined'
        '500':
          $ref: '#/components/responses/Internal'
        '503':
          $ref: '#/components/responses/SwapNotReady'
components:
  schemas:
    SwapRequest:
      type: object
      required:
        - userPublicKey
      properties:
        userPublicKey:
          type: string
          description: >-
            The wallet that signs and pays: fee payer, source of the input,
            owner of every intermediate account. Alias `wallet`
        quoteResponse:
          $ref: '#/components/schemas/QuoteResponse'
          description: >-
            A quote to build as it is (no re-quote). Takes precedence over
            `routeTicket` and the pair fields
        routeTicket:
          type: string
          description: The `routeTicket` of a quote, instead of `quoteResponse`
        inputMint:
          type: string
          description: >-
            Pair mode (no quote): the mint you spend. With a quote or ticket, if
            present, must match it
        outputMint:
          type: string
          description: >-
            Pair mode: the mint you receive. With a quote or ticket, if present,
            must match it
        amount:
          type:
            - string
            - integer
          description: >-
            Pair mode: u64 amount, as in `/quote`. With a ticket, if present,
            must match it
        swapMode:
          type: string
          enum:
            - ExactIn
            - ExactOut
            - exactIn
            - exactOut
          default: ExactIn
          description: Pair mode only
        slippageBps:
          type: integer
          description: >-
            Overrides the slippage of the quote or ticket; pair-mode default 50.
            Above 10000 is taken as 10000. Must be a JSON number
        maxHops:
          type: integer
          description: Pair mode only
        onlyDirectRoutes:
          type: boolean
          description: Pair mode only
        dexes:
          oneOf:
            - type: string
            - type: array
              items:
                type: string
          description: Pair mode only. Alias `includeDex`
        excludeDexes:
          oneOf:
            - type: string
            - type: array
              items:
                type: string
          description: Pair mode only. Alias `excludeDex`
        allowSplit:
          type: boolean
          default: false
          description: Pair mode only; a split quote is built as a split anyway
        forJitoBundle:
          type: boolean
          default: false
          description: Pair mode only
        reserveKeys:
          type: integer
          default: 0
          description: Pair mode only
        wrapAndUnwrapSol:
          type: boolean
          default: true
          description: >-
            `true`: SOL input is wrapped from the wallet's lamports and its wSOL
            account closed after the swap; SOL output is unwrapped back to the
            wallet (not when `destinationTokenAccount` is another wallet).
            `false`: the route spends from and pays into the wallet's wSOL
            account. Alias `unwrapSol`
        feeAccount:
          type: string
          description: >-
            The integrator fee **wallet** (not a token account): a token-side
            fee goes to its associated token account, created if missing; a
            SOL-side fee is paid to the wallet itself. Must differ from
            `userPublicKey`. Required when the quote priced a platform fee.
            Alias `feeWallet`
        feeBps:
          type: integer
          description: >-
            The fee in basis points. Pinned quote: must equal
            `platformFee.feeBps` when the quote priced one. On a quote that
            priced no fee it is added at build time and lowers the floor, so up
            to `feeBps` less than the quoted `outAmount` can arrive. Pair mode:
            priced like `platformFeeBps`, only with `feeAccount`
        feeOnInput:
          type: boolean
          description: As in `/quote`; must match a priced quote
        prioritizationFeeLamports:
          $ref: '#/components/schemas/PrioritizationFee'
        computeUnitPriceMicroLamports:
          type: integer
          description: Priority price per compute unit (micro-lamports)
        transactionsFeeLamports:
          type: integer
          description: >-
            Older name of a total priority fee in lamports; wins over every
            other priority field
        tipWallet:
          type: string
          description: >-
            With `tipLamports`: a System transfer of the tip to this wallet, in
            `otherInstructions`. Wins over `jitoTipLamports`
        tipLamports:
          type: integer
        destinationTokenAccount:
          type: string
          description: >-
            The **wallet** that receives the output; the route delivers to its
            associated token account, created if missing. A token account here
            is `400 bad_recipient`. Default `userPublicKey`. Alias `recipient`
        txVersion:
          type: integer
          const: 1
          default: 1
          description: '`0` is refused'
        asLegacyTransaction:
          type: boolean
          const: false
        serialize:
          type: boolean
          default: false
          description: >-
            Also return the unsigned transaction (`swapTransaction`) and
            `lastValidBlockHeight`
    SwapResponse:
      type: object
      properties:
        computeBudgetInstructions:
          type: array
          items:
            $ref: '#/components/schemas/Instruction'
          description: Always empty in v1 (the budget is `transactionConfig`)
        setupInstructions:
          type: array
          items:
            $ref: '#/components/schemas/Instruction'
          description: >-
            Before the swap: create the token accounts (idempotent), wrap SOL,
            initialize venue accounts
        swapInstruction:
          $ref: '#/components/schemas/Instruction'
          description: The first `swap` instruction (program = your deploy)
        swapInstructions:
          type: array
          items:
            $ref: '#/components/schemas/Instruction'
          description: >-
            Every `swap` instruction in order: one, or two for a split. Sign all
            of them
        cleanupInstruction:
          $ref: '#/components/schemas/Instruction'
          description: >-
            The first account close after the swap (usually the wSOL unwrap).
            Absent when nothing is closed
        otherInstructions:
          type: array
          items:
            $ref: '#/components/schemas/Instruction'
          description: 'Everything after: further closes, the tip'
        addressLookupTableAddresses:
          type: array
          items:
            type: string
          maxItems: 0
          description: Always empty
        quoteId:
          type: string
        buildId:
          type: string
          description: 32 hex digits identifying this build
        shape:
          type: string
          enum:
            - token_exact_in
            - native_exact_in
            - exact_out
            - token_exact_in_split
          description: >-
            `exact_out`: one hop with a pinned output and an input cap. A
            multi-hop ExactOut is `token_exact_in` with `minReturn` = the
            requested output
        inAmount:
          type: string
        outAmount:
          type: string
        otherAmountThreshold:
          type: string
        swapMode:
          type: string
          enum:
            - ExactIn
            - ExactOut
        minReturn:
          type: integer
          description: >-
            The floor the program enforces on the output. ExactOut: the
            requested output
        maxAmountIn:
          type: integer
          description: >-
            What the route deposits. ExactOut: the slippage cap
            (`otherAmountThreshold`)
        computeUnits:
          type: integer
          description: The compute-unit limit declared
        loadedAccountsDataSize:
          type: integer
          description: The loaded-accounts byte limit declared
        txVersion:
          type: string
          const: v1
        transactionConfig:
          $ref: '#/components/schemas/TransactionConfig'
        swapTransaction:
          type: string
          description: >-
            With `serialize: true`: the unsigned v1 transaction, base64. Sign it
            with `userPublicKey`
        lastValidBlockHeight:
          type: integer
          description: 'With `serialize: true`: last block height of its blockhash'
        routePlan:
          type: array
          items:
            $ref: '#/components/schemas/RoutePlanStep'
        costs:
          $ref: '#/components/schemas/Costs'
    QuoteResponse:
      type: object
      required:
        - inputMint
        - inAmount
        - outputMint
        - outAmount
        - otherAmountThreshold
        - swapMode
        - slippageBps
        - priceImpactPct
        - routePlan
      properties:
        inputMint:
          type: string
        inAmount:
          type: string
          description: >-
            What leaves the wallet, platform fee included. ExactIn: the `amount`
            asked
        outputMint:
          type: string
        outAmount:
          type: string
          description: >-
            What arrives, net of venue and platform fees. ExactOut: the `amount`
            asked
        otherAmountThreshold:
          type: string
          description: >-
            ExactIn: the least that arrives, `outAmount × (10000 − slippageBps)
            / 10000`. ExactOut: the most that is spent, `inAmount × (10000 +
            slippageBps) / 10000`
        swapMode:
          type: string
          enum:
            - ExactIn
            - ExactOut
        slippageBps:
          type: integer
        priceImpactPct:
          type: string
          description: >-
            Price impact as a decimal fraction (`0.01` is 1%). `0` when it is
            not known
        routePlan:
          type: array
          items:
            $ref: '#/components/schemas/RoutePlanStep'
          description: >-
            The hops in order. A split is two routes one after the other: a
            route ends at the first step whose `outputMint` is the quote's
        contextSlot:
          type: integer
          description: Slot of the pool state the quote was priced on
        timeTaken:
          type: number
          description: Seconds spent inside the router
        platformFee:
          $ref: '#/components/schemas/PlatformFee'
        quoteId:
          type: string
          description: 16 hex digits; the build of this quote carries the same `quoteId`
        routeTicket:
          type: string
          description: >-
            The route signed with HMAC-SHA256
            (`base64url(JSON).base64url(MAC)`), valid for `ROUTER_TICKET_TTL_S`
            (default 60 s). Only when your router sets `ROUTER_TICKET_SECRET`
          example: eyJ2IjoyLCJxdW90ZUlkIjoiMjNlMTRlMDEwMDAwNDRjNiIsImlucHV0TWlu…
    PrioritizationFee:
      description: >
        The priority fee, Jupiter style. A number is the **total** in lamports.
        `"auto"` takes the

        75th percentile of recent prioritization fees, within 10,000 and
        1,000,000 micro-lamports

        per compute unit. `priorityLevelWithMaxLamports` is `auto` capped at
        `maxLamports`

        (`priorityLevel` is ignored). `jitoTipLamports` adds a tip transfer to a
        Jito tip account

        instead of a priority fee. Absent means no priority fee. The fee is
        charged on the declared

        compute-unit limit, not on the units used.
      oneOf:
        - type: integer
          description: Total priority fee in lamports
        - type: string
          description: '`auto`, or a total in lamports as a string'
        - type: object
          required:
            - priorityLevelWithMaxLamports
          properties:
            priorityLevelWithMaxLamports:
              type: object
              properties:
                maxLamports:
                  type: integer
                priorityLevel:
                  type: string
                  description: Ignored
        - type: object
          required:
            - jitoTipLamports
          properties:
            jitoTipLamports:
              type: integer
        - type: object
          required:
            - jitoTipLamportsWithPayer
          properties:
            jitoTipLamportsWithPayer:
              type: object
              properties:
                lamports:
                  type: integer
    Instruction:
      type: object
      required:
        - programId
        - accounts
        - data
      properties:
        programId:
          type: string
        accounts:
          type: array
          items:
            $ref: '#/components/schemas/AccountMeta'
        data:
          type: string
          description: Instruction data, standard base64
    TransactionConfig:
      type: object
      description: >-
        The v1 message header. An absent field is absent from the header; at
        runtime an absent limit counts as zero, so carry every field into the
        transaction you assemble
      properties:
        priorityFeeLamports:
          type: integer
          description: Total priority fee in lamports. Absent when there is none
        computeUnitLimit:
          type: integer
        loadedAccountsDataSizeLimit:
          type: integer
        heapSize:
          type: integer
    RoutePlanStep:
      type: object
      required:
        - swapInfo
      properties:
        swapInfo:
          $ref: '#/components/schemas/SwapInfo'
        percent:
          type: integer
          minimum: 1
          maximum: 100
          description: >-
            On the first step of a route, that route's share of the input,
            rounded; 100 elsewhere
        bps:
          type: integer
          minimum: 1
          maximum: 10000
          description: The exact share in basis points
    Costs:
      type: object
      description: >-
        What the transaction takes from the wallet besides the swap input, in
        lamports as strings
      properties:
        baseFeeLamports:
          type: string
          description: 5,000 per required signature
        priorityFeeLamports:
          type: string
          description: The total priority fee the message declares
        priorityFeeSource:
          type: string
          enum:
            - client
            - chain
            - floor
            - ceiling
            - none
          description: >-
            Where the price per compute unit came from: your request, the chain
            (`auto`), its floor or ceiling, or no priority fee
        priorityFeeMicroLamportsPerCu:
          type: string
        tipLamports:
          type: string
        rentLamports:
          type: string
          description: >-
            Rent the transaction deposits into the accounts it creates, counted
            as if the wallet had none of them: an upper bound the wallet must
            hold
        rentRefundedLamports:
          type: string
          description: >-
            Rent the same transaction gives back when it closes accounts it
            created
        rentExact:
          type: boolean
          description: >-
            `false`: a Token-2022 account's size is not known exactly and
            `rentLamports` is a minimum
        totalLamports:
          type: string
          description: base + priority + tip + rent − rent refunded
    Error:
      type: object
      required:
        - error
        - reason
      properties:
        error:
          type: string
          description: >-
            Closed error code: `bad_request`, `declined`, `not_found`,
            `internal`, `quote_mismatch`, `invalid_route_ticket`,
            `route_ticket_mismatch`, `route_expired`, `bad_recipient`,
            `venue_red`, `rpc`, or on `/tx/v1` `bad_address`, `no_instructions`,
            `bad_data`, `missing_budget`, `invalid_message`, `wire_limit`
        reason:
          type: string
          description: >-
            With `declined`, a stable label (`no_route`, `cold_unresolved`,
            `platform_fee`, …); otherwise a sentence for humans
        quoteId:
          type: string
          description: >-
            16 hex digits, also in the router's logs. Absent when the request
            could not be parsed, and on `/tx/v1`
    LowLiquidityError:
      type: object
      required:
        - error
        - reason
        - liquidity
      properties:
        error:
          type: string
          const: declined
        reason:
          type: string
          const: low_liquidity
        liquidity:
          type: object
          description: The deepest direct pool of the pair, all too shallow to price
          properties:
            venue:
              type: string
              description: '`dex` label of the pool'
            hubMint:
              type: string
              description: The pool's SOL, USDC or USDT side
            hubAmount:
              type: string
              description: Its balance in base units of `hubMint` (u64 as string)
        quoteId:
          type: string
    NotReadyError:
      type: object
      required:
        - error
        - reasons
      properties:
        error:
          type: string
          const: not_ready
        reasons:
          type: array
          items:
            type: string
          description: Every reason the router cannot serve this request now
        quoteId:
          type: string
    PlatformFee:
      type: object
      description: Present when `platformFeeBps` > 0
      properties:
        amount:
          type: string
          description: The fee, in base units of `feeMint`
        feeBps:
          type: integer
        feeMint:
          type: string
          description: >-
            Router extension: the mint the fee is taken in (`inputMint` or
            `outputMint`)
    AccountMeta:
      type: object
      required:
        - pubkey
      properties:
        pubkey:
          type: string
        isSigner:
          type: boolean
          default: false
        isWritable:
          type: boolean
          default: false
    SwapInfo:
      type: object
      required:
        - ammKey
        - label
        - inputMint
        - outputMint
        - inAmount
        - outAmount
      properties:
        ammKey:
          type: string
          description: Pool address
        label:
          type: string
          description: Venue `dex` label
        inputMint:
          type: string
        outputMint:
          type: string
        inAmount:
          type: string
          description: Input of this hop (after the platform fee when it is on the input)
        outAmount:
          type: string
          description: Output of this hop
        walkSteps:
          type: integer
          description: >-
            Router extension: ticks or bins this hop walked. Keep it when you
            send the quote back: without it the build declares the maximum
            compute budget for the hop (and pays priority fee on it)
  examples:
    SwapBuilt:
      summary: '0.1 SOL to USDC, serialize: true, prioritizationFeeLamports: auto'
      value:
        computeBudgetInstructions: []
        setupInstructions:
          - programId: ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL
            accounts:
              - pubkey: 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM
                isSigner: true
                isWritable: true
              - pubkey: 8LjUgMjzZuHj8VdyxzkmLLQVmW4C3gd56md1nLd76TNW
                isSigner: false
                isWritable: true
              - pubkey: 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM
                isSigner: false
                isWritable: false
              - pubkey: So11111111111111111111111111111111111111112
                isSigner: false
                isWritable: false
              - pubkey: '11111111111111111111111111111111'
                isSigner: false
                isWritable: false
              - pubkey: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
                isSigner: false
                isWritable: false
            data: AQ==
          - programId: ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL
            accounts:
              - pubkey: 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM
                isSigner: true
                isWritable: true
              - pubkey: FGETo8T8wMcN2wCjav8VK6eh3dLk63evNDPxzLSJra8B
                isSigner: false
                isWritable: true
              - pubkey: 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM
                isSigner: false
                isWritable: false
              - pubkey: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
                isSigner: false
                isWritable: false
              - pubkey: '11111111111111111111111111111111'
                isSigner: false
                isWritable: false
              - pubkey: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
                isSigner: false
                isWritable: false
            data: AQ==
          - programId: '11111111111111111111111111111111'
            accounts:
              - pubkey: 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM
                isSigner: true
                isWritable: true
              - pubkey: 8LjUgMjzZuHj8VdyxzkmLLQVmW4C3gd56md1nLd76TNW
                isSigner: false
                isWritable: true
            data: AgAAAADh9QUAAAAA
          - programId: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
            accounts:
              - pubkey: 8LjUgMjzZuHj8VdyxzkmLLQVmW4C3gd56md1nLd76TNW
                isSigner: false
                isWritable: true
            data: EQ==
        swapInstruction:
          programId: DADMMjfNnY6z8H9h9RfHZ9tfarBySsj4Yb65qLyKJDAD
          accounts:
            - pubkey: 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM
              isSigner: true
              isWritable: true
            - pubkey: 6FnGsVD12kgwbjhdcqwVZZ2s53FXiTmj6hmt9nms4bww
              isSigner: false
              isWritable: false
            - pubkey: LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo
              isSigner: false
              isWritable: false
            - pubkey: HTvjzsfX3yU6BUodCjZ5vZkUrAxMDTrBs3CJaq43ashR
              isSigner: false
              isWritable: true
            - pubkey: 9HcJeBEsq5px2bYZbdo7vzQWVsPK3SHTkchy42hBn7HC
              isSigner: false
              isWritable: true
            - pubkey: H7j5NPopj3tQvDg4N8CxwtYciTn3e8AEV6wSVrxpyDUc
              isSigner: false
              isWritable: true
            - pubkey: HbYjRzx7teCxqW3unpXBEcNHhfVZvW2vW9MQ99TkizWt
              isSigner: false
              isWritable: true
            - pubkey: 8LjUgMjzZuHj8VdyxzkmLLQVmW4C3gd56md1nLd76TNW
              isSigner: false
              isWritable: true
            - pubkey: FGETo8T8wMcN2wCjav8VK6eh3dLk63evNDPxzLSJra8B
              isSigner: false
              isWritable: true
            - pubkey: So11111111111111111111111111111111111111112
              isSigner: false
              isWritable: false
            - pubkey: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
              isSigner: false
              isWritable: false
            - pubkey: EgEYXef2FCoEYLHJJW74dMbom1atLXo6KwPuA6mSATYA
              isSigner: false
              isWritable: true
            - pubkey: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
              isSigner: false
              isWritable: false
            - pubkey: MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr
              isSigner: false
              isWritable: false
            - pubkey: D1ZN9Wj1fRSUQfCjhvnu1hqDMT7hzjzBBpi12nVniYD6
              isSigner: false
              isWritable: false
            - pubkey: AHWjpDEN41mddq8DgUKmX2iQwK3Srg6MCgi1iMjV55To
              isSigner: false
              isWritable: true
            - pubkey: 6AfKQDv42gJRLEBj4zhHR1uTZd4Mj5g75xaozWqs3CGP
              isSigner: false
              isWritable: true
            - pubkey: 9SW7tJc6qCDLHWFRWKf3pb1rNW3NgcGuqQ9HfhMJnbd5
              isSigner: false
              isWritable: true
            - pubkey: 3FRoVcNFxmznbZTQP5muKU4VvFJbiACmE8H9nbc31tyP
              isSigner: false
              isWritable: true
            - pubkey: 95ZfXjhrsjLtbYggDyyXjviVnzFnc3qyyab5ZQvCUiTH
              isSigner: false
              isWritable: true
            - pubkey: 7mtH8doACVxtgnpuHf28rT6YC6KxgGaHwkk1Abr7KdJF
              isSigner: false
              isWritable: true
            - pubkey: BTbdjpRazxzETE5NHiRyhPSs31bcuS66UVdEqhpS8pgn
              isSigner: false
              isWritable: true
            - pubkey: 3T2k3Jj1Gy5wnzL262XERtkZVuuk3eUnHXVz1SBeydqG
              isSigner: false
              isWritable: true
            - pubkey: 7r1eVXSdLReZaW2nQHT18o4fhrvKexkb9YvUB1tuKtG9
              isSigner: false
              isWritable: true
            - pubkey: GvcoDmDQxxefuNc2Jp6EgY9kmWQFRfLXWxbBeKMY2cAH
              isSigner: false
              isWritable: true
            - pubkey: DxK58yoaYhMChMRYTDu7pLkSenkabRjmjFvrH7WBx2n8
              isSigner: false
              isWritable: true
            - pubkey: EdVxQZg2LWQpJ5sYkP9W9yHdE82Sh72MXzLCkZq7Vep9
              isSigner: false
              isWritable: true
            - pubkey: GDnVaY9DZNnrirV7QXia6X5aPzdqhQ8seSvGDeVXcDE3
              isSigner: false
              isWritable: true
            - pubkey: 97kDUqyxUEh4iCqWxREYUtU9scA4TKMuHBm1TD6D9fRv
              isSigner: false
              isWritable: true
            - pubkey: 84z7SCPSzAtvpsYNq6DFCZtaGgaNvUXzgj1RjJk2xPXy
              isSigner: false
              isWritable: true
            - pubkey: pHnkoj6wRWqeXDM9K5CNioiGie73H6BFxKF4H9mrEqG
              isSigner: false
              isWritable: true
          data: >-
            AQEDAQAAMgD/////AOH1BQAAAAAHNgAfCvr/////Cf8IFimvsgAAAAAACv4AEAAAAAAAAAAACAcIIQIAHAAHlbMAgPD6BgKDhIWGh4gJCosCwAwMDQ4Cj5CRkpOUlZaXmJmam5ydngAIAADh9QUAAAAAARAAKa+yAAAAAABBSz9M61tbiADh9QUAAAAAKa+yAAAAAAAAAAAA
        swapInstructions:
          - programId: DADMMjfNnY6z8H9h9RfHZ9tfarBySsj4Yb65qLyKJDAD
            accounts:
              - pubkey: 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM
                isSigner: true
                isWritable: true
              - pubkey: 6FnGsVD12kgwbjhdcqwVZZ2s53FXiTmj6hmt9nms4bww
                isSigner: false
                isWritable: false
              - pubkey: LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo
                isSigner: false
                isWritable: false
              - pubkey: HTvjzsfX3yU6BUodCjZ5vZkUrAxMDTrBs3CJaq43ashR
                isSigner: false
                isWritable: true
              - pubkey: 9HcJeBEsq5px2bYZbdo7vzQWVsPK3SHTkchy42hBn7HC
                isSigner: false
                isWritable: true
              - pubkey: H7j5NPopj3tQvDg4N8CxwtYciTn3e8AEV6wSVrxpyDUc
                isSigner: false
                isWritable: true
              - pubkey: HbYjRzx7teCxqW3unpXBEcNHhfVZvW2vW9MQ99TkizWt
                isSigner: false
                isWritable: true
              - pubkey: 8LjUgMjzZuHj8VdyxzkmLLQVmW4C3gd56md1nLd76TNW
                isSigner: false
                isWritable: true
              - pubkey: FGETo8T8wMcN2wCjav8VK6eh3dLk63evNDPxzLSJra8B
                isSigner: false
                isWritable: true
              - pubkey: So11111111111111111111111111111111111111112
                isSigner: false
                isWritable: false
              - pubkey: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
                isSigner: false
                isWritable: false
              - pubkey: EgEYXef2FCoEYLHJJW74dMbom1atLXo6KwPuA6mSATYA
                isSigner: false
                isWritable: true
              - pubkey: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
                isSigner: false
                isWritable: false
              - pubkey: MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr
                isSigner: false
                isWritable: false
              - pubkey: D1ZN9Wj1fRSUQfCjhvnu1hqDMT7hzjzBBpi12nVniYD6
                isSigner: false
                isWritable: false
              - pubkey: AHWjpDEN41mddq8DgUKmX2iQwK3Srg6MCgi1iMjV55To
                isSigner: false
                isWritable: true
              - pubkey: 6AfKQDv42gJRLEBj4zhHR1uTZd4Mj5g75xaozWqs3CGP
                isSigner: false
                isWritable: true
              - pubkey: 9SW7tJc6qCDLHWFRWKf3pb1rNW3NgcGuqQ9HfhMJnbd5
                isSigner: false
                isWritable: true
              - pubkey: 3FRoVcNFxmznbZTQP5muKU4VvFJbiACmE8H9nbc31tyP
                isSigner: false
                isWritable: true
              - pubkey: 95ZfXjhrsjLtbYggDyyXjviVnzFnc3qyyab5ZQvCUiTH
                isSigner: false
                isWritable: true
              - pubkey: 7mtH8doACVxtgnpuHf28rT6YC6KxgGaHwkk1Abr7KdJF
                isSigner: false
                isWritable: true
              - pubkey: BTbdjpRazxzETE5NHiRyhPSs31bcuS66UVdEqhpS8pgn
                isSigner: false
                isWritable: true
              - pubkey: 3T2k3Jj1Gy5wnzL262XERtkZVuuk3eUnHXVz1SBeydqG
                isSigner: false
                isWritable: true
              - pubkey: 7r1eVXSdLReZaW2nQHT18o4fhrvKexkb9YvUB1tuKtG9
                isSigner: false
                isWritable: true
              - pubkey: GvcoDmDQxxefuNc2Jp6EgY9kmWQFRfLXWxbBeKMY2cAH
                isSigner: false
                isWritable: true
              - pubkey: DxK58yoaYhMChMRYTDu7pLkSenkabRjmjFvrH7WBx2n8
                isSigner: false
                isWritable: true
              - pubkey: EdVxQZg2LWQpJ5sYkP9W9yHdE82Sh72MXzLCkZq7Vep9
                isSigner: false
                isWritable: true
              - pubkey: GDnVaY9DZNnrirV7QXia6X5aPzdqhQ8seSvGDeVXcDE3
                isSigner: false
                isWritable: true
              - pubkey: 97kDUqyxUEh4iCqWxREYUtU9scA4TKMuHBm1TD6D9fRv
                isSigner: false
                isWritable: true
              - pubkey: 84z7SCPSzAtvpsYNq6DFCZtaGgaNvUXzgj1RjJk2xPXy
                isSigner: false
                isWritable: true
              - pubkey: pHnkoj6wRWqeXDM9K5CNioiGie73H6BFxKF4H9mrEqG
                isSigner: false
                isWritable: true
            data: >-
              AQEDAQAAMgD/////AOH1BQAAAAAHNgAfCvr/////Cf8IFimvsgAAAAAACv4AEAAAAAAAAAAACAcIIQIAHAAHlbMAgPD6BgKDhIWGh4gJCosCwAwMDQ4Cj5CRkpOUlZaXmJmam5ydngAIAADh9QUAAAAAARAAKa+yAAAAAABBSz9M61tbiADh9QUAAAAAKa+yAAAAAAAAAAAA
        cleanupInstruction:
          programId: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
          accounts:
            - pubkey: 8LjUgMjzZuHj8VdyxzkmLLQVmW4C3gd56md1nLd76TNW
              isSigner: false
              isWritable: true
            - pubkey: 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM
              isSigner: false
              isWritable: true
            - pubkey: 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM
              isSigner: true
              isWritable: false
          data: CQ==
        otherInstructions: []
        addressLookupTableAddresses: []
        quoteId: 23e14e01000044c6
        buildId: e2492701bd5ca34f3f2ae4c6d7e8ea5e
        shape: token_exact_in
        inAmount: '100000000'
        outAmount: '11769095'
        otherAmountThreshold: '11710249'
        swapMode: ExactIn
        minReturn: 11710249
        maxAmountIn: 100000000
        computeUnits: 250000
        loadedAccountsDataSize: 2848871
        txVersion: v1
        transactionConfig:
          priorityFeeLamports: 6864
          computeUnitLimit: 250000
          loadedAccountsDataSizeLimit: 2848871
        swapTransaction: gQEACg8AAABzC5BGsDaM61xZPkeGm/RoYH/gF9m9YhrkMz2ZM9aR9wYifowI…
        lastValidBlockHeight: 430448451
        routePlan:
          - swapInfo:
              ammKey: HTvjzsfX3yU6BUodCjZ5vZkUrAxMDTrBs3CJaq43ashR
              label: Meteora DLMM
              inputMint: So11111111111111111111111111111111111111112
              outputMint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
              inAmount: '100000000'
              outAmount: '11769095'
              walkSteps: 1
            percent: 100
            bps: 10000
        costs:
          baseFeeLamports: '5000'
          priorityFeeLamports: '6864'
          priorityFeeSource: chain
          priorityFeeMicroLamportsPerCu: '27456'
          tipLamports: '0'
          rentLamports: '2976880'
          rentRefundedLamports: '1488440'
          rentExact: true
          totalLamports: '1500304'
  responses:
    SwapBadRequest:
      description: >
        Fix the request; retrying will not help. `error` is one of:

        `bad_request` (a field is missing, malformed, or contradicts another:
        see `reason`),

        `quote_mismatch` (`inputMint`/`outputMint` differ from the
        `quoteResponse`, or the quote priced a

        platform fee and `feeAccount` is missing or `feeBps`/`feeOnInput`
        differ),

        `invalid_route_ticket` (bad signature or shape, or tickets disabled on
        this router),

        `route_ticket_mismatch` (mints or amount differ from the ticket),

        `bad_recipient` (`destinationTokenAccount` is a token account; send the
        wallet),

        `declined` with `reason` `platform_fee` (the fee cannot be built:
        `feeAccount` is the user,

        a SOL-side fee would open a missing fee wallet below rent, an on-chain
        fee pin, or tampered

        amounts) or `zero_amount`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            noUser:
              summary: userPublicKey missing
              value:
                error: bad_request
                reason: userPublicKey is required
                quoteId: 23e14e010000450e
            v0:
              summary: txVersion 0
              value:
                error: bad_request
                reason: 'txVersion 0 is not served: this router emits v1'
                quoteId: 23e14e010000450f
            mismatch:
              summary: inputMint differs from the quote
              value:
                error: quote_mismatch
                reason: quoteResponse.inputMint differs from the request
                quoteId: 23e14e0100004512
            feeAccount:
              summary: The quote priced a fee and feeAccount is missing
              value:
                error: quote_mismatch
                reason: 'feeAccount is required: the quote priced a platform fee'
                quoteId: 23e14e01000044cd
            ticketsOff:
              summary: routeTicket on a router without ROUTER_TICKET_SECRET
              value:
                error: invalid_route_ticket
                reason: tickets are disabled on this host
                quoteId: 23e14e0100004510
            recipient:
              summary: A token account as destination
              value:
                error: bad_recipient
                reason: >-
                  destinationTokenAccount is the WALLET that receives the output
                  (the route delivers to its associated token account), not a
                  token account
                quoteId: 23e14e010000453d
            feeToSelf:
              summary: feeAccount equal to userPublicKey
              value:
                error: declined
                reason: platform_fee
                quoteId: 23e14e01000044f8
            malformed:
              summary: Not JSON
              value:
                error: bad_request
                reason: EOF while parsing an object at line 1 column 1
    NoRoute:
      description: >
        `declined` with `no_route` (no route exists under these filters and hop
        limit) or `no_cycle`

        (input equals output and no cycle returns more than it costs). Widen the
        filters or the

        amount; retrying the same request will not change it unless the market
        does.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: declined
            reason: no_route
            quoteId: 23e14e01000045c5
    SwapConflict:
      description: >
        Re-quote, then build again. `error` is `route_expired` (the
        `routeTicket` is past its TTL),

        `venue_red` (the pinned route crosses a venue the price oracle now holds
        out), or `declined`

        with `pool_missing`, `satellite`, `layout`, `token_program` or
        `shared_account` (the pool

        state the route needs is not available or changed; a retry or a fresh
        quote can fix it).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            expired:
              summary: Ticket expired (shape from the code)
              value:
                error: route_expired
                reason: Expired
                quoteId: 23e14e0100000002
            satellite:
              summary: A pool account is missing (shape from the code)
              value:
                error: declined
                reason: satellite
                quoteId: 23e14e0100000003
    TooLarge:
      description: The request body is over 256 KiB (plain-text body)
      content:
        text/plain:
          schema:
            type: string
    SwapDeclined:
      description: >
        A named decline that waiting will not change. `error` is `declined`;
        `reason` is a quote

        decline (as in `GET /quote`, for a build without `quoteResponse`) or a
        build decline:

        `unbuildable` (the venue has no builder), `exact_out_shape` (this
        exact-out shape is not

        built, e.g. an output-side fee), `wire_limit` (over 64 keys, 64
        instructions or 4,096 bytes),

        `wire`, `program_hop_limit` (more than 4 hops in a route),
        `compute_budget` (over 1.4M

        compute units), `transfer_guard`, `dark_trader` (the venue charges this
        wallet a listed-trader

        fee: exclude it), or the sentence `<venue> has no live row in the swap
        on-chain config` (your

        deploy's config does not allow that venue).
      content:
        application/json:
          schema:
            anyOf:
              - $ref: '#/components/schemas/Error'
              - $ref: '#/components/schemas/LowLiquidityError'
          examples:
            notAllowed:
              summary: Venue not in your deploy's config (shape from the code)
              value:
                error: declined
                reason: PumpSwap has no live row in the swap on-chain config
                quoteId: 23e14e0100000004
            wireLimit:
              summary: Too many accounts (shape from the code)
              value:
                error: declined
                reason: wire_limit
                quoteId: 23e14e0100000005
    Internal:
      description: >-
        A router bug: `error` is `internal` (`quote task failed`, `build task
        failed`, …). Report it with the `quoteId`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            build:
              summary: The build task panicked (shape from the code)
              value:
                error: internal
                reason: build task failed
                quoteId: 23e14e0100000009
    SwapNotReady:
      description: >
        Retry with backoff. `error` is `not_ready` with `reasons` (the router is
        not ready, the

        blockhash for `serialize` is unavailable, your deploy's config cannot be
        read, or the

        program is paused: `swap is paused on chain`), `declined` with
        `router_config` or with a

        sentence when the chain read for the route failed, or `rpc` when the
        owner of

        `destinationTokenAccount` could not be read.
      content:
        application/json:
          schema:
            anyOf:
              - $ref: '#/components/schemas/NotReadyError'
              - $ref: '#/components/schemas/Error'
          examples:
            paused:
              summary: Your deploy is paused (shape from the code)
              value:
                error: not_ready
                reasons:
                  - swap is paused on chain
                quoteId: 23e14e0100000006
            blockhash:
              summary: serialize without a fresh blockhash (shape from the code)
              value:
                error: not_ready
                reasons:
                  - blockhash unavailable
                quoteId: 23e14e0100000007
            fetch:
              summary: The chain read failed (shape from the code)
              value:
                error: declined
                reason: 'satellite account missing: dad-rpc fetch failed'
                quoteId: 23e14e0100000008

````

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