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

# Create an order

> Creates a swap order, your intent, and returns **HTTP 201** with the full order object, including the per-order deposit address (`walletAddress`) on the deposit token's chain. From there, send your deposit to `walletAddress` before `timeout` and a solver fills the order against the escrowed deposit.

A tenant API key is enough to create orders.

Validation failures (a missing or malformed `receivingAddress`, invalid token ids, missing fields) return HTTP `500` with a descriptive message. Match on the `message` field to tell causes apart. The address validator names the settle token's chain (`blockchain.network` in the catalog), so the same mistake reads `Invalid BTC address` when settling to native Bitcoin and `Invalid SOL address` on Solana.

<Warning>Creation does not validate `intendedAmount`. An out-of-range intent is accepted, and one below the minimum returns `initialQuote: 0`. The `minimalAmount` and `maximalAmount` bounds in the response apply to the actual deposit: send an amount inside them, send only the exact deposit token, and fund `walletAddress` before `timeout` (about 30 minutes after creation). See [Order lifecycle](/api-reference/order-lifecycle).</Warning>


## OpenAPI

````yaml /openapi.json post /v1/orders/create
openapi: 3.1.0
info:
  title: Vane API
  version: 1.0.0
  summary: Cross-chain and same-chain swaps filled by an open network of solvers.
  description: >-
    Vane turns a swap into an intent: you declare what you want to receive, the
    API returns a per-order deposit address, and a solver fills the order
    against the escrowed deposit ([how solvers fill
    orders](/features/solver-auctions)).


    **Authentication.** Most endpoints accept a tenant API key sent as the
    `x-tenant-api-key` header (accountless integration). The key pre-filled in
    the API playground is a shared public key for evaluating the API. Production
    integrations use their own tenant key, requested from support
    (help@vane.xyz) and kept server-side. A JWT access token from SIWX
    wallet-signature auth also satisfies these endpoints and attributes orders
    to a user account, which adds order history (`GET /v1/orders`) and points.


    **Error behavior.** Errors use the envelope `{statusCode, message, error}`.
    Field order varies and some errors omit `error`. Most business validation
    failures (an unknown token id, a malformed address, an invalid amount, an
    unknown order UUID) return HTTP `500` with a descriptive message, while
    `400` appears only for malformed query parameters. Match on the message text
    for programmatic handling, not just the status codes.


    **The fields `exchange` and `tradePath`** describe how a quote is priced and
    routed across order-book legs. They say nothing about settlement, which
    solvers perform separately.
  contact:
    name: Vane support
    email: help@vane.xyz
    url: https://vane.xyz
  termsOfService: https://vane.xyz/terms-and-conditions
servers:
  - url: https://api.vane.xyz/api
    description: Production
security:
  - tenantApiKey: []
tags:
  - name: Tokens
    description: The token catalog, swap limits, and quotes.
  - name: Orders
    description: Create swap orders and track them to a terminal state.
  - name: Auth
    description: >-
      Optional SIWX wallet-signature authentication. Adds order history and
      points.
paths:
  /v1/orders/create:
    post:
      tags:
        - Orders
      summary: Create an order
      description: >-
        Creates a swap order, your intent, and returns **HTTP 201** with the
        full order object, including the per-order deposit address
        (`walletAddress`) on the deposit token's chain. From there, send your
        deposit to `walletAddress` before `timeout` and a solver fills the order
        against the escrowed deposit.


        A tenant API key is enough to create orders.


        Validation failures (a missing or malformed `receivingAddress`, invalid
        token ids, missing fields) return HTTP `500` with a descriptive message.
        Match on the `message` field to tell causes apart. The address validator
        names the settle token's chain (`blockchain.network` in the catalog), so
        the same mistake reads `Invalid BTC address` when settling to native
        Bitcoin and `Invalid SOL address` on Solana.
      operationId: createOrder
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateOrderRequest'
            example:
              depositTokenId: 158
              settleTokenId: 231
              receivingAddress: '0x1234567890abcdef1234567890abcdef12345678'
              intendedAmount: 0.005
              intendedIsDeposit: true
      responses:
        '201':
          description: >-
            Order created. Send the deposit to `walletAddress` before `timeout`,
            within `minimalAmount` and `maximalAmount`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
              example:
                id: 74
                uuid: 7f9c2e4a-1b3d-4c5e-8f6a-2d9b0c1e3f5a
                status: AWAITING_USER_DEPOSIT
                timeout: '2026-01-15T14:30:00.000Z'
                intendedAmount: 0.005
                intendedIsDeposit: true
                initialQuote: 316.23212
                depositTokenId: 158
                settleTokenId: 231
                receivingAddress: '0x1234567890abcdef1234567890abcdef12345678'
                depositAmount: null
                depositEstSettleAmount: null
                settleAmount: null
                minimalAmount: 0.00020766
                maximalAmount: 0.14162023
                exchange: CEX
                senderDepositTx: null
                exchangeWithdrawTx: null
                exchangeWithdrawTxLink: null
                tradePath:
                  - symbol: BTCUSDT
                    side: SELL
                    inputToken: BTC
                    outputToken: USDT
                userId: null
                createdAt: '2026-01-15T14:00:00.000Z'
                walletAddress: bc1p...
        '401':
          $ref: '#/components/responses/UnauthorizedTenant'
        '500':
          description: >-
            Validation failed and no order was created. The response is a `500`
            with a descriptive message; the `message` field is what
            distinguishes the causes. Address errors carry the settle chain's
            code; the examples below settle to Ethereum, hence `ETH`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                missingAddress:
                  summary: Missing receivingAddress
                  value:
                    message: 'Invalid ETH address: undefined'
                    error: Internal Server Error
                    statusCode: 500
                malformedAddress:
                  summary: Malformed receivingAddress
                  value:
                    message: 'Invalid ETH address: not-an-address'
                    error: Internal Server Error
                    statusCode: 500
                invalidTokenId:
                  summary: Invalid token id
                  value:
                    message: 'Invalid deposit token id provided: 999999'
                    error: Internal Server Error
                    statusCode: 500
components:
  schemas:
    CreateOrderRequest:
      type: object
      description: Order creation payload, which is your swap intent.
      properties:
        depositTokenId:
          type: integer
          description: >-
            Numeric id of the token you will deposit. Ids are chain-specific;
            look them up with `GET /v1/tokens`.
        settleTokenId:
          type: integer
          description: >-
            Numeric id of the token to receive, on the chain you want to receive
            it on.
        receivingAddress:
          type: string
          description: >-
            Address where the settle tokens will be delivered by the filling
            solver. Must be valid for the settle token's chain.
        intendedAmount:
          type: number
          description: >-
            Intended swap amount. It is not validated against the swap limits:
            an out-of-range intent is accepted, and a too-small one (`0`
            included) yields `initialQuote: 0`. The actual deposit must respect
            the order's `minimalAmount` and `maximalAmount`.
        intendedIsDeposit:
          type: boolean
          description: >-
            `true` if `intendedAmount` is the deposit amount, `false` if it is
            the settle amount you want to receive.
      required:
        - depositTokenId
        - settleTokenId
        - receivingAddress
        - intendedAmount
        - intendedIsDeposit
    Order:
      description: >-
        A swap order. Created by `POST /v1/orders/create`. A solver fills it
        against the deposit escrowed at `walletAddress`.
      allOf:
        - $ref: '#/components/schemas/OrderBase'
        - type: object
          properties:
            walletAddress:
              type: string
              description: >-
                The deposit address: a per-order escrow address on the deposit
                token's chain (a taproot `bc1p...` address for BTC). Send only
                the exact deposit token here, within the min/max bounds, before
                `timeout`.
          required:
            - walletAddress
    Error:
      type: object
      description: >-
        Canonical error envelope. Field order varies and `error` is sometimes
        omitted (the unknown-order `500` returns only `statusCode` and
        `message`); message casing varies too (`Internal Server Error` vs
        `Internal server error`). Most business validation failures return `500`
        with a descriptive message, so match on `message` for programmatic
        handling.
      properties:
        statusCode:
          type: integer
          description: HTTP status code.
        message:
          type: string
          description: >-
            Error description. The most reliable field for distinguishing
            causes.
        error:
          type: string
          description: >-
            HTTP status text, for example `Bad Request`, `Unauthorized`.
            Sometimes absent.
      required:
        - statusCode
        - message
    OrderBase:
      type: object
      description: >-
        Common order fields, shared by the create and get responses and by
        order-history items.
      properties:
        id:
          type: integer
          description: >-
            Internal numeric order id. SSE events do not carry it; their
            `orderId` is the `uuid`.
        uuid:
          type: string
          format: uuid
          description: >-
            Public order identifier and a bearer capability: anyone holding it
            can read the order. Store it server-side and keep it out of public
            URLs. For accountless orders it is your only handle. SSE events echo
            it as `orderId`.
        status:
          $ref: '#/components/schemas/OrderStatus'
        timeout:
          type: string
          format: date-time
          description: >-
            UTC time at which the order expires if no deposit is received (30
            minutes after `createdAt`). Orders cannot expire after a deposit is
            made.
        intendedAmount:
          type: number
          description: >-
            Amount declared at creation. Not validated against `minimalAmount`
            and `maximalAmount`; those bounds bind the actual deposit.
        intendedIsDeposit:
          type: boolean
          description: Whether `intendedAmount` was expressed in deposit-token units.
        initialQuote:
          type: number
          description: >-
            Estimated settle amount computed from `intendedAmount` at creation.
            Comes back as `0` when the intent is below the minimum.
        depositTokenId:
          type: integer
          description: Id of the deposit token.
        settleTokenId:
          type: integer
          description: Id of the settle token.
        receivingAddress:
          type: string
          description: Address where the settle tokens are delivered.
        depositAmount:
          type:
            - number
            - 'null'
          description: Actual amount deposited, once detected. `null` before any deposit.
        depositEstSettleAmount:
          type:
            - number
            - 'null'
          description: >-
            Estimated settle amount recomputed from the actual `depositAmount`.
            `null` before any deposit.
        settleAmount:
          type:
            - number
            - 'null'
          description: >-
            Amount delivered to `receivingAddress`. Updates while the order
            settles and is final once `status` is `COMPLETED`. `null` before
            settlement starts.
        minimalAmount:
          type: number
          description: >-
            Minimum deposit-token amount this order accepts. It binds the actual
            deposit; creation does not check `intendedAmount` against it.
        maximalAmount:
          type: number
          description: >-
            Maximum deposit-token amount this order accepts. The actual deposit
            must stay at or below it.
        exchange:
          type: string
          description: >-
            Pricing source label carried over from the quote (for example
            `CEX`). Settlement still happens through solver intent matching.
        senderDepositTx:
          type:
            - string
            - 'null'
          description: Transaction hash of your deposit, once detected. `null` before that.
        exchangeWithdrawTx:
          type:
            - string
            - 'null'
          description: >-
            Transaction hash of the transfer delivering settle tokens to
            `receivingAddress`. `null` until the fill.
        exchangeWithdrawTxLink:
          type:
            - string
            - 'null'
          description: Block-explorer link for `exchangeWithdrawTx`. `null` until the fill.
        tradePath:
          type: array
          description: >-
            Order-book legs behind this order's quote. They describe pricing,
            not how the order settles.
          items:
            $ref: '#/components/schemas/TradePathLeg'
        userId:
          type:
            - string
            - 'null'
          description: >-
            User id for orders created with a JWT access token, a UUID string
            matching the `id` from `GET /auth/me`. `null` for accountless
            (tenant-key) orders.
        createdAt:
          type: string
          format: date-time
          description: UTC creation time.
      required:
        - id
        - uuid
        - status
        - timeout
        - intendedAmount
        - intendedIsDeposit
        - initialQuote
        - depositTokenId
        - settleTokenId
        - receivingAddress
        - depositAmount
        - depositEstSettleAmount
        - settleAmount
        - minimalAmount
        - maximalAmount
        - exchange
        - senderDepositTx
        - exchangeWithdrawTx
        - exchangeWithdrawTxLink
        - tradePath
        - userId
        - createdAt
    OrderStatus:
      type: string
      description: >-
        Order lifecycle status.


        - `AWAITING_USER_DEPOSIT`: waiting for your deposit to the order's
        `walletAddress`.

        - `AWAITING_USER_DEPOSIT_CONFIRMATIONS`: deposit detected, waiting for
        on-chain confirmations (`blockchain.neededConfirmations`).

        - `PROCESSING`: transitional state between deposit confirmation and
        completion. Treat it as in flight.

        - `COMPLETED`: fill delivered and `settleAmount` is final. Terminal.

        - `ERROR`: the swap hit an error. Contact support with the order UUID.
        Terminal.

        - `TIMED_OUT`: no deposit arrived before `timeout`. Terminal.
      enum:
        - AWAITING_USER_DEPOSIT
        - AWAITING_USER_DEPOSIT_CONFIRMATIONS
        - PROCESSING
        - COMPLETED
        - ERROR
        - TIMED_OUT
    TradePathLeg:
      type: object
      description: >-
        One order-book leg used to price a quote. This is pricing and routing
        information only; solvers perform settlement through intent matching.
        Cross pairs may have multiple legs, and `inputToken`/`outputToken`
        casing may vary across legs in multi-leg responses (for example
        lowercase `sol`, `eth`), so match symbols without regard to case.
      properties:
        symbol:
          type: string
          description: Order-book pair symbol, for example `BTCUSDT`.
        side:
          type: string
          enum:
            - SELL
            - BUY
          description: Side of the order-book leg.
        inputToken:
          type: string
          description: Input token symbol for this leg.
        outputToken:
          type: string
          description: Output token symbol for this leg.
      required:
        - symbol
        - side
        - inputToken
        - outputToken
  responses:
    UnauthorizedTenant:
      description: >-
        Missing or invalid tenant API key. The message says "access token" but
        refers to the `x-tenant-api-key` header (a valid JWT access token also
        satisfies this endpoint).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            message: Valid access token required.
            error: Unauthorized
            statusCode: 401
  securitySchemes:
    tenantApiKey:
      type: apiKey
      in: header
      name: x-tenant-api-key
      x-default: c7eccc0aaed64932a85d35658fa55a4fb2d60cd3d2c529cfd643dc676ee82e82
      description: >-
        Vane's shared tenant key. Contact support for a dedicated key if you
        need custom parameters or separate order tracking.

````