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

# Place a limit order

> Builds an unsigned tx that places a resting order on the owner's limit-order maker book (auto-funds collateral). The order exists only once the owner signs and that tx lands on-chain.

The write is an `UpdateBookLimit`: every level change is guarded by the resting size the backend read, so if a fill lands between the build and the send the tx fails (`LevelSizeMismatch`) instead of overwriting the fill — refetch and retry. Preflight simulation catches this before the tx is returned whenever possible.

**Spread guard (post-only):** unless `crossSpread` is true, a buy priced at/above the best registered ask (or a sell at/below the best registered bid, across the market's registered maker books excluding the owner's own) is rejected with `CROSSES_SPREAD`; the program enforces the same rule on-chain (`PostOnlyWouldCross`). If `swapIfReject` is also set, a market order for the same base size is built instead (a `SwapFromArcherAccount` when `archerAccount` is given) and the response has `orderKind='market'`.



## OpenAPI

````yaml /openapi.json post /v1/order/limit
openapi: 3.0.3
info:
  description: >-
    REST API for the Archer Exchange — a high-performance Solana-based order
    book exchange.


    All monetary values (prices, sizes, fees) are returned as decimal strings
    for precision.


    ### Rate Limiting

    All endpoints are rate-limited via a token-bucket algorithm. When the limit
    is exceeded, the API returns `429 Too Many Requests`.


    ### Error Format

    All errors follow a consistent JSON format:

    ```json

    {
      "error": "ERROR_CODE",
      "message": "Human-readable description"
    }

    ```


    ### Handling errors

    Every error falls into one of five actions. REST errors come back as
    `{"error": CODE, "message"}`. A transaction that fails on-chain reports
    `{"InstructionError": [index, {"Custom": code}]}`; codes are the `errors`
    list of the program IDL (`archer-sdk/idl/archer_v1.json`). When a build
    endpoint's preflight catches an on-chain error first, it returns `400
    INVALID_PARAMS` with the reason in `message`.


    | Action | REST | On-chain (code) |

    |---|---|---|

    | **Retry as is**, with backoff | `RATE_LIMITED` (429),
    `SERVICE_UNAVAILABLE` (503), `INTERNAL_ERROR` (500); relay `OVERLOADED`,
    `PREFLIGHT_UNAVAILABLE`. Keep backing off on 429: 50 of them within a minute
    from one IP returns `BANNED` (403) for 10 minutes | none |

    | **Refetch, rebuild, retry**: the book or registry changed under you | |
    `LevelSizeMismatch` (527), `StaleSequenceNumber` (509),
    `SequenceNumberTooFarAhead` (522), `RegistryBooksMismatch` (525),
    `IncompleteMakerBooks` (513), `NoMatchingLiquidity` (507); relay status
    `expired` (re-sign with a fresh blockhash) |

    | **Reprice** | `CROSSES_SPREAD`, `SLIPPAGE_EXCEEDED` | `PostOnlyWouldCross`
    (524), `CrossingOrderLevels` (505), `InvalidPrice` (503),
    `SlippageToleranceExceeded` (703) |

    | **Resize** | `INSUFFICIENT_LIQUIDITY` (the body's `availableSize` is what
    fits) | `MakerBookSideFull` (528: cancel a level first),
    `InvalidSizeAtLevel` (506), `InsufficientBalance` (402) and SPL Token `1`
    (fund the account or shrink), `ZeroSwapAmount` (702) |

    | **Stop**: fix the request or the setup; retrying cannot help |
    `INVALID_PARAMS`, `MISSING_API_KEY` / `INVALID_API_KEY` (401), `FORBIDDEN`,
    `NOT_FOUND`, `MARKET_NOT_FOUND`, `METHOD_NOT_ALLOWED`; `MARKET_PAUSED` /
    `MARKET_FROZEN` until the market resumes |
    `UnauthorizedArcherAccountDelegate` (1001), `BuilderFeeExceedsAccountCap`
    (1003), `UnauthorizedMaker` (502), `MakerNotRegistered` (512),
    `PostOnlyRequiresLimitOrderBook` (526), `MarketNotActive` (107),
    `MarketFrozen` (114); any 200–399 code (wrong account wiring, a bug to
    report) |
  title: Archer Exchange API
  version: 1.0.0
servers:
  - description: Production
    url: https://api.archer.exchange
  - description: Staging
    url: https://api-staging.archer.exchange
  - description: Local
    url: http://localhost:8080
security:
  - apiKey: []
tags:
  - description: Discover and inspect available trading markets
    name: Markets
  - description: Token metadata for every mint Archer lists
    name: Tokens
  - description: Get price quotes before placing an order
    name: Quote
  - description: Build unsigned Solana transactions for swaps
    name: Orders
  - description: Build unsigned Solana transactions for limit orders
    name: Limit Orders
  - description: >-
      ArcherAccount — a wallet's delegated trading identity. Collateral sits in
      token accounts owned by the account PDA; an authorized delegate can trade
      and quote as the account but never withdraw.
    name: Account
  - description: Read a maker book — balances and resting levels — by PDA or by owner
    name: Maker Books
  - description: Deposit / withdraw / close — fund movement for a maker book
    name: Maker Funds
  - description: Public protocol-wide aggregate statistics
    name: Stats
  - description: >-
      Submit signed Solana transactions and let Archer land them. Hosted at
      `https://send.archer.exchange`, separate from the REST API, using the same
      API key.
    name: Transaction Relay
paths:
  /v1/order/limit:
    post:
      tags:
        - Limit Orders
      summary: Place a limit order
      description: >-
        Builds an unsigned tx that places a resting order on the owner's
        limit-order maker book (auto-funds collateral). The order exists only
        once the owner signs and that tx lands on-chain.


        The write is an `UpdateBookLimit`: every level change is guarded by the
        resting size the backend read, so if a fill lands between the build and
        the send the tx fails (`LevelSizeMismatch`) instead of overwriting the
        fill — refetch and retry. Preflight simulation catches this before the
        tx is returned whenever possible.


        **Spread guard (post-only):** unless `crossSpread` is true, a buy priced
        at/above the best registered ask (or a sell at/below the best registered
        bid, across the market's registered maker books excluding the owner's
        own) is rejected with `CROSSES_SPREAD`; the program enforces the same
        rule on-chain (`PostOnlyWouldCross`). If `swapIfReject` is also set, a
        market order for the same base size is built instead (a
        `SwapFromArcherAccount` when `archerAccount` is given) and the response
        has `orderKind='market'`.
      operationId: placeLimitOrder
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PlaceLimitOrderRequest'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlaceLimitOrderResponse'
          description: >-
            Unsigned transaction built (limit order, or a market order when
            swapIfReject fired).
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
          description: >-
            Invalid parameters (bad price/size, crossed/full book, 16-level cap,
            etc.), or the price crosses the spread with crossSpread=false and
            swapIfReject=false (error CROSSES_SPREAD).
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
          description: Missing or invalid API key.
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
          description: Maker book or order not found.
components:
  schemas:
    PlaceLimitOrderRequest:
      properties:
        accountOwner:
          description: >-
            The wallet that owns the ArcherAccount this request acts through.
            With `platform` it derives the account PDA server-side — you never
            handle a PDA. Omit for a plain wallet-owned book. Replaces the
            earlier `archerAccount` field, which is no longer read.
          nullable: true
          type: string
        crossSpread:
          default: false
          description: >-
            When false (default), a price that crosses the spread — a buy
            at/above the best registered ask, or a sell at/below the best
            registered bid — is rejected (or auto-swapped, see swapIfReject),
            and the tx is sent post-only so the program rejects it too if the
            books move before it lands. Set true to explicitly rest a
            spread-crossing limit order (the program's post-only check is
            skipped).
          type: boolean
        market:
          description: Market address (PDA). Get one from GET /v1/markets.
          example: u8tnfCb1JSSghuNFquQ2beStYgAN1kmd1f1Lhxbaec4
          type: string
        maxSlippageBps:
          default: 50
          description: >-
            Slippage tolerance (bps) for the swapIfReject market fallback.
            Ignored unless a swap fires. Defaults to 50 bps (0.5%).
          format: int32
          nullable: true
          type: integer
        platform:
          default: self
          description: >-
            Platform namespace for `accountOwner`. Ignored unless `accountOwner`
            is set.
          enum:
            - self
            - treadfi
          nullable: true
          type: string
        price:
          description: Limit price, quote per base (human units).
          example: '150.00'
          type: string
        side:
          enum:
            - buy
            - sell
          example: buy
          type: string
        signer:
          description: >-
            The wallet that signs: the book's maker, or with `accountOwner` the
            account's owner or delegate. Existing clients may keep sending it as
            `owner`; send one name only.
          example: u8tnfCb1JSSghuNFquQ2beStYgAN1kmd1f1Lhxbaec4
          type: string
        size:
          description: Order size in base tokens (human units).
          example: '1.5'
          type: string
        swapIfReject:
          default: false
          description: >-
            When true and the order would be rejected for crossing the spread
            (crossSpread false), build a market order for the same base size
            instead of erroring (from the ArcherAccount when archerAccount is
            given). The response then has orderKind='market'.
          type: boolean
        withInstructions:
          default: false
          description: >-
            Also return the unsigned instructions under `instructions`, for
            composing your own transaction instead of signing ours. Omitted or
            `false` leaves the response exactly as it was.
          nullable: true
          type: boolean
      required:
        - market
        - signer
        - side
        - price
        - size
      type: object
    PlaceLimitOrderResponse:
      allOf:
        - oneOf:
            - $ref: '#/components/schemas/LimitOrderActionResponse'
            - $ref: '#/components/schemas/BuildOrderResponse'
      description: >-
        Result of placing a limit order. When orderKind='limit', all
        LimitOrderActionResponse fields are present at the top level. When the
        price crossed the spread and swapIfReject was set, orderKind='market'
        and all BuildOrderResponse fields are present at the top level instead.
      properties:
        instructions:
          allOf:
            - $ref: '#/components/schemas/TransactionInstructions'
          description: >-
            Unsigned instructions, present only when the request set
            `withInstructions`.
          nullable: true
        orderKind:
          description: >-
            Which kind of order was built. 'market' only when a spread-crossing
            price triggered the swapIfReject fallback.
          enum:
            - limit
            - market
          type: string
      required:
        - orderKind
        - transaction
      type: object
    ErrorResponse:
      properties:
        error:
          description: Machine-readable error code.
          enum:
            - INVALID_PARAMS
            - MARKET_NOT_FOUND
            - MARKET_PAUSED
            - INSUFFICIENT_LIQUIDITY
            - SLIPPAGE_EXCEEDED
            - NOT_FOUND
            - FORBIDDEN
            - RATE_LIMITED
            - INTERNAL_ERROR
            - SERVICE_UNAVAILABLE
            - MARKET_FROZEN
            - CROSSES_SPREAD
            - MISSING_API_KEY
            - INVALID_API_KEY
            - BANNED
            - METHOD_NOT_ALLOWED
          type: string
        message:
          description: Human-readable error description.
          type: string
      required:
        - error
        - message
      type: object
    LimitOrderActionResponse:
      description: >-
        Unsigned tx for the owner to sign, plus affected order ids, action
        targeting, and auto-funded collateral.
      properties:
        addressLookupTables:
          items:
            type: string
          type: array
        anchorMidTicks:
          description: >-
            The book's mid anchor in ticks. Always 0 for limit-order books: a
            level's offset is its absolute price tick.
          format: int64
          type: integer
        depositBaseLots:
          format: int64
          type: integer
        depositQuoteLots:
          format: int64
          type: integer
        expiresAt:
          format: int64
          type: integer
        includesDeposit:
          type: boolean
        instructions:
          allOf:
            - $ref: '#/components/schemas/TransactionInstructions'
          description: >-
            Unsigned instructions, present only when the request set
            `withInstructions`.
          nullable: true
        nextSequenceNumber:
          description: The maker-book sequence number this tx writes.
          format: int64
          type: integer
        orderIds:
          items:
            type: string
          type: array
        price:
          description: >-
            Human price (quote per base) the order rests/rested at. Absent for
            cancel-all.
          nullable: true
          type: string
        requiredBaseLots:
          description: >-
            Total base lots the resulting book state requires as collateral (the
            program's update_book solvency check).
          format: int64
          type: integer
        requiredQuoteLots:
          description: Total quote lots required, including the positive-maker-fee buffer.
          format: int64
          type: integer
        side:
          description: Side this action targets. Absent for cancel-all.
          enum:
            - buy
            - sell
          nullable: true
          type: string
        size:
          description: >-
            Human base-token size the action targets — placed size (place), new
            size (modify), or canceled size (cancel-one). Absent for cancel-all.
          nullable: true
          type: string
        transaction:
          description: >-
            Base64 unsigned VersionedTransaction in its wire encoding: a v0
            message when the write fits 1232 bytes, otherwise a v1 (SIMD-0385)
            message, which a full maker registry needs. A v1 transaction must be
            sent base64-encoded and signed by a wallet that supports version 1.
          type: string
      required:
        - transaction
        - orderIds
        - requiredBaseLots
        - requiredQuoteLots
        - nextSequenceNumber
        - anchorMidTicks
        - includesDeposit
        - depositBaseLots
        - depositQuoteLots
        - expiresAt
        - addressLookupTables
      type: object
    BuildOrderResponse:
      description: >-
        A swap quote and, when a taker was named, the unsigned transaction built
        from it. `quoteResponse` comes from the same engine run as the
        transaction.
      properties:
        addressLookupTables:
          description: >-
            Address lookup tables the transaction references. None are
            configured; always empty today.
          items:
            type: string
          type: array
        instructions:
          allOf:
            - $ref: '#/components/schemas/TransactionInstructions'
          description: >-
            Unsigned instructions, present only when the request set
            `withInstructions`.
          nullable: true
        quoteResponse:
          $ref: '#/components/schemas/QuoteResponse'
        swapMode:
          description: >-
            The effective mode, including the default applied when `swapMode`
            was omitted.
          enum:
            - MaxAmountIn
            - MinAmountOut
          type: string
        transaction:
          description: >-
            Base64-encoded unsigned Solana transaction for the taker to sign and
            submit. `null` when the request carried no `signer`.
          nullable: true
          type: string
      required:
        - transaction
        - swapMode
        - quoteResponse
        - addressLookupTables
      type: object
    TransactionInstructions:
      description: >-
        The instruction form of a built transaction, for callers that assemble
        and sign their own — their own fee strategy, their own lookup tables, or
        bundling Archer's instructions with their own.


        Returned only when the request sets `withInstructions`. The accompanying
        `transaction` is still built and still valid; these are the same
        instructions it contains, so signing one or composing the other are
        equivalent (the backend asserts this: rebuilding these instructions
        compiles to a byte-identical message). They also reflect the same
        maker-book selection the quote was computed from, so a caller that
        re-composes them gets the quoted price.
      properties:
        addressLookupTables:
          description: >-
            Lookup tables the instructions assume. None are configured; always
            empty today.
          items:
            type: string
          type: array
        computeBudgetInstructions:
          description: >-
            Compute-unit limit and price, kept separate so you can drop them and
            substitute your own fee strategy without touching the rest.
          items:
            $ref: '#/components/schemas/SerializedInstruction'
          type: array
        instructions:
          description: >-
            Archer's instructions, in the order they must execute. Any ATA
            creation and WSOL wrap/unwrap are included.
          items:
            $ref: '#/components/schemas/SerializedInstruction'
          type: array
        signer:
          description: The account that must sign and pay the fee.
          type: string
      required:
        - computeBudgetInstructions
        - instructions
        - signer
        - addressLookupTables
      type: object
    QuoteResponse:
      description: >-
        A swap quote. Amounts are what actually leaves and enters the taker's
        wallet — protocol and builder fees and any Token-2022 transfer fees
        included — computed by the same engine, over the same maker books in the
        same order, that `POST /v1/orders/build` executes.
      properties:
        inAmount:
          description: >-
            Input debited from the taker (decimal string in the input token).
            For `MaxAmountIn` this is at most the requested size; fees are
            carved out of it.
          example: '150.600000'
          type: string
        inputMint:
          description: Mint the taker pays with.
          example: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
          type: string
        outAmount:
          description: >-
            Output credited to the taker (decimal string in the output token).
            For `MinAmountOut` this is at least the requested size.
          example: '1.000000000'
          type: string
        outputMint:
          description: Mint the taker receives.
          example: So11111111111111111111111111111111111111112
          type: string
        priceImpactPct:
          description: >-
            Distance of the average fill price from the best price on the
            consumed side, in percent, before fees. `0` when the fill sits
            entirely at the top of book; positive means worse.
          example: '0.0332'
          type: string
        slippageBps:
          description: The requested tolerance, echoed.
          example: 50
          type: integer
        swapMode:
          description: >-
            The effective mode, including the default applied when `swapMode`
            was omitted.
          enum:
            - MaxAmountIn
            - MinAmountOut
          type: string
        totalFee:
          $ref: '#/components/schemas/QuoteFees'
      required:
        - inputMint
        - outputMint
        - inAmount
        - outAmount
        - swapMode
        - slippageBps
        - priceImpactPct
        - totalFee
      type: object
    SerializedInstruction:
      description: One instruction.
      properties:
        accounts:
          items:
            $ref: '#/components/schemas/InstructionAccount'
          type: array
        data:
          description: Base64-encoded instruction data.
          type: string
        programId:
          type: string
      required:
        - programId
        - accounts
        - data
      type: object
    QuoteFees:
      description: >-
        What the taker pays on top of the matched notional, in quote tokens
        (decimal strings).
      properties:
        builderFee:
          description: The builder fee the swap carries; `0` when it carries none.
          example: '0.000000'
          type: string
        protocolFee:
          description: The market's taker fee. Negative on a market that rebates takers.
          example: '0.060000'
          type: string
      required:
        - protocolFee
        - builderFee
      type: object
    InstructionAccount:
      description: >-
        One account an instruction touches, in the shape `@solana/web3.js` and
        `@solana/kit` already accept.
      properties:
        isSigner:
          type: boolean
        isWritable:
          type: boolean
        pubkey:
          type: string
      required:
        - pubkey
        - isSigner
        - isWritable
      type: object
  securitySchemes:
    apiKey:
      in: header
      name: X-API-Key
      type: apiKey

````

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