openapi: 3.1.0
info:
  title: True Markets Gateway API
  description: >-
    Gateway API for the True Markets trading platform - order orchestration,
    quotes, and balance management
  version: 1.0.0
servers:
  - url: https://api.truemarkets.co/v1/conductor
    description: Production
tags:
  - name: Quotes
    description: >-
      Request real-time market quotes for trading pairs without creating an
      order.
  - name: Orders
    description: Create, execute, cancel, and monitor orders across CeFi and DeFi.
  - name: Balances
    description: Query account balances for the authenticated user.
paths:
  /quotes:
    post:
      operationId: computeQuote
      summary: Compute market quote
      description: Returns a quote for a market order without creating an order
      tags:
        - Quotes
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QuoteRequest'
      responses:
        '200':
          description: Quote computed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/QuoteResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
  /orders:
    post:
      operationId: createOrder
      summary: Create new order
      description: >-
        Creates a new order. For DeFi orders, returns unsigned payloads for
        client signing.
      tags:
        - Orders
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateOrderRequest'
      responses:
        '201':
          description: Order created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateOrderResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
    get:
      operationId: listOrders
      summary: List user orders
      description: >-
        Returns a paginated list of completed and failed orders with execution
        data for the authenticated user
      tags:
        - Orders
      security:
        - bearerAuth: []
      parameters:
        - name: limit
          in: query
          description: Maximum number of orders to return
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 50
        - name: cursor
          in: query
          description: RFC3339 timestamp cursor for pagination
          required: false
          schema:
            type: string
            format: date-time
        - name: status
          in: query
          description: Comma-separated list of order statuses to filter by
          required: false
          schema:
            type: string
            example: pending,canceled
      responses:
        '200':
          description: Orders retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetOrdersResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalError'
  /orders/{id}/execute:
    post:
      operationId: executeOrder
      summary: Execute pending order
      description: >-
        Executes a pending order using client-provided signatures for the
        unsigned payloads
      tags:
        - Orders
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          description: Order ID
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ExecuteOrderRequest'
      responses:
        '200':
          description: Order execution initiated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExecuteOrderResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
  /orders/{id}:
    delete:
      operationId: cancelOrder
      tags:
        - Orders
      summary: Cancel a pending limit order
      description: >
        Submits a cancellation request for a pending limit order on CeFi.


        Cancellation is asynchronous — the order moves to `cancel_pending`
        immediately,

        then the order syncer reconciles the final state:

        - `cancelled` if the CeFi exchange confirms the cancellation

        - `complete` if the order filled before the cancel landed (race
        condition)


        Only CeFi limit orders in `pending` or `active` status are cancellable.

        DeFi orders and market orders return 400.
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          description: Order ID
          required: true
          schema:
            type: string
      responses:
        '202':
          description: Cancellation request accepted
          content:
            application/json:
              schema:
                type: object
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'
  /orders/{id}/status:
    get:
      operationId: getOrderStatus
      summary: Get order status
      description: Returns the current status of an order
      tags:
        - Orders
      security:
        - bearerAuth: []
      parameters:
        - name: id
          in: path
          description: Order ID
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Order status retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetOrderStatusResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'
  /balances/unified:
    get:
      operationId: listBalances
      summary: List balances
      description: Returns unified balances across CeFi and DeFi for the authenticated user
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Balances retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListBalancesResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          description: Service unavailable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /balances:
    get:
      operationId: getBalances
      summary: Get user balances
      description: Returns balances for the authenticated user
      tags:
        - Balances
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Balances retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BalancesResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  responses:
    BadRequest:
      description: Bad request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Unauthorized:
      description: Unauthorized
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Forbidden:
      description: Forbidden
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotFound:
      description: Not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Conflict:
      description: Conflict
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ServiceUnavailable:
      description: Service unavailable
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  schemas:
    OrderSide:
      type: string
      enum:
        - buy
        - sell
      example: buy
      description: |
        The side of the order.
        * **buy** — Purchase the base asset using the quote asset.
        * **sell** — Sell the base asset in exchange for the quote asset.
    OrderType:
      type: string
      enum:
        - market
        - limit
      example: market
      description: >
        The type of order to place.

        * **market** — Execute immediately at the best available price. Buy
        orders require `qty_unit: quote`. Price must not be specified.

        * **limit** — Place an order at a specific price. Requires `price` and
        `qty_unit: base`. Only supported on CeFi; `chain` must not be specified.
    OrderStatus:
      type: string
      enum:
        - initialized
        - pending
        - cancel_pending
        - complete
        - canceled
        - active
        - failed
      example: complete
      description: >
        The current status of the order.

        * **initialized** — Order has been created but not yet submitted. For
        DeFi orders, the client must sign the returned payloads and call the
        execute endpoint. For CeFi buy orders with insufficient balance, a
        funding bridge is prepared first.

        * **pending** — Order has been submitted but is not yet confirmed by the
        CeFi exchange or on-chain.

        * **active** — Order was accepted by the CeFi exchange and is open for
        trading. Applies to limit orders that are working in the order book.

        * **cancel_pending** — A cancellation request has been sent to the CeFi
        exchange and is awaiting confirmation.

        * **complete** — Order has been fully executed. For CeFi orders this
        means the CeFi exchange reported a fill; for DeFi orders the on-chain
        swap was confirmed.

        * **canceled** — Order was successfully canceled via a cancel request or
        by exchange/market conditions.

        * **failed** — Order was rejected by the CeFi exchange or DeFi execution
        failed (e.g. on-chain transaction reverted, balance check failed).
    SigningMethod:
      type: string
      enum:
        - web_authn
        - api_key
      example: api_key
      description: >
        The authentication method used to sign transaction payloads.

        * **web_authn** — Signed using a passkey (WebAuthn/FIDO2 credential) via
        the browser.

        * **api_key** — Signed using an API key. Suitable for
        programmatic/headless access.
    Chain:
      type: string
      enum:
        - solana
        - base
      example: solana
      description: |
        The blockchain network for DeFi orders. Omit for CeFi orders.
        * **solana** — Execute the swap on the Solana blockchain.
        * **base** — Execute the swap on the Base (Ethereum L2) blockchain.
    QuoteRequest:
      type: object
      description: Request to compute a market quote
      required:
        - base_asset
        - quote_asset
        - qty
        - qty_unit
        - side
      properties:
        base_asset:
          type: string
          description: Base asset identifier (e.g. `BTC`, `ETH`, `SOL`)
          example: BTC
        quote_asset:
          type: string
          description: Quote asset identifier (e.g. `USD`, `USDC`)
          example: USD
        qty:
          type: string
          description: Quantity as a positive decimal string
          example: '0.5'
        qty_unit:
          type: string
          enum:
            - base
            - quote
          description: >
            Unit of the quantity.

            * **base** — Quantity is denominated in the base asset (e.g. 0.5
            BTC).

            * **quote** — Quantity is denominated in the quote asset (e.g. 1000
            USD).
          example: quote
        side:
          $ref: '#/components/schemas/OrderSide'
    QuoteResponse:
      type: object
      description: >-
        Quote computation result with the expected output quantity and execution
        price
      properties:
        qty:
          type: string
          description: >-
            Expected output quantity as a decimal string. For a buy order this
            is the amount of base asset received; for a sell order it is the
            amount of quote asset received.
          example: '0.01485'
        price:
          type: string
          description: Effective execution price per unit of base asset as a decimal string
          example: '67340.25'
    CreateOrderRequest:
      type: object
      description: |
        Request to create a new order.

        **Limit orders** (`type: limit`):
        - `price` is required and must be a positive decimal string
        - `qty_unit` must be `base`
        - `chain` is not supported (CeFi only)

        **Market orders** (`type: market`):
        - `price` is not accepted
        - Buy orders require `qty_unit: quote`
        - Sell orders accept `qty_unit: base` or `qty_unit: quote`
        - `chain` is optional (omit for CeFi, include for DeFi)
      required:
        - base_asset
        - quote_asset
        - qty
        - qty_unit
        - type
        - side
      properties:
        base_asset:
          type: string
          description: Base asset identifier (e.g. `BTC`, `ETH`, `SOL`)
          example: BTC
        quote_asset:
          type: string
          description: Quote asset identifier (e.g. `USD`, `USDC`)
          example: USD
        qty:
          type: string
          description: Quantity as a positive decimal string
          example: '100'
        price:
          type: string
          description: >
            Limit price per unit of base asset as a decimal string. Required for
            limit orders; must not be sent for market orders.
          example: '67500.00'
        qty_unit:
          type: string
          enum:
            - base
            - quote
          description: >
            Unit of the quantity.

            * **base** — Quantity is denominated in the base asset. Required for
            limit orders. Supported for market sell orders.

            * **quote** — Quantity is denominated in the quote asset. Required
            for market buy orders. For DeFi sell orders, `base` must be used
            instead.
          example: quote
        type:
          $ref: '#/components/schemas/OrderType'
        side:
          $ref: '#/components/schemas/OrderSide'
        chain:
          allOf:
            - $ref: '#/components/schemas/Chain'
          description: >
            Blockchain network for DeFi orders. Omit for CeFi orders. Not
            supported for limit orders.
    UnsignedPayload:
      type: object
      description: >
        An unsigned transaction payload that the client must sign before
        executing the order. Sign each payload using your API key or WebAuthn
        credential, then submit the resulting stamps to the execute endpoint in
        the same order.
      required:
        - digest
        - payload
      properties:
        digest:
          type: string
          description: SHA-256 hash of the payload, used as the signing input
        payload:
          type: string
          description: Base64-encoded transaction payload to be signed
    QuoteDetails:
      type: object
      description: >-
        Detailed quote information returned with DeFi order creation, showing
        expected swap output and fees
      properties:
        base_asset:
          type: string
          description: Base asset identifier (e.g. `SOL`, `ETH`)
        quote_asset:
          type: string
          description: Quote asset identifier (e.g. `USDC`)
        qty:
          type: string
          description: Input quantity as a decimal string — the amount being swapped from
        qty_out:
          type: string
          description: >-
            Expected output quantity as a decimal string — the amount the user
            will receive after fees
        fee:
          type: string
          description: Platform fee amount as a decimal string
        fee_asset:
          type: string
          description: Asset in which the fee is denominated (e.g. `USDC`)
        issues:
          type: array
          items:
            type: string
          description: >-
            Warnings about the quote (e.g. high price impact, low liquidity).
            Empty when there are no issues.
    CreateOrderResponse:
      type: object
      description: >
        Response from creating an order. For DeFi orders (and CeFi buy orders
        requiring a funding bridge), the response includes unsigned payloads
        that must be signed by the client and submitted via the execute
        endpoint. For CeFi sell orders and sufficiently funded CeFi buy orders,
        the order is submitted immediately and no payloads are returned.
      properties:
        order_id:
          type: string
          description: Unique order identifier
        status:
          $ref: '#/components/schemas/OrderStatus'
        payloads:
          type: array
          items:
            $ref: '#/components/schemas/UnsignedPayload'
          description: >
            Unsigned transaction payloads that the client must sign and return
            via the execute endpoint. Present for DeFi orders and CeFi buy
            orders that require a funding bridge. Empty or absent when the order
            is submitted immediately (e.g. CeFi sell orders).
        quote:
          $ref: '#/components/schemas/QuoteDetails'
          description: >-
            Quote details for DeFi orders including expected output quantity and
            fees
        web_authn_payload:
          type: string
          description: WebAuthn payload (deprecated, use payloads instead)
          deprecated: true
    ExecuteOrderRequest:
      type: object
      description: >
        Request to execute an order that is in `initialized` status. The client
        must sign each payload returned by the create endpoint and submit the
        signatures in the same order.
      required:
        - signatures
        - auth_type
      properties:
        signatures:
          type: array
          items:
            type: string
          minItems: 1
          description: >
            Signed stamps for the unsigned payloads, in the same order as the
            payloads returned by the create endpoint. Each signature corresponds
            to one payload.
        auth_type:
          $ref: '#/components/schemas/SigningMethod'
    ExecuteOrderResponse:
      type: object
      description: >
        Response from executing an order. For DeFi orders, a successful
        execution transitions the order directly to `complete`. For CeFi orders,
        the order moves to `pending` while it is processed by the CeFi exchange.
      properties:
        status:
          $ref: '#/components/schemas/OrderStatus'
    GetOrderStatusResponse:
      type: object
      description: Order status response
      properties:
        status:
          $ref: '#/components/schemas/OrderStatus'
    OrderDetail:
      type: object
      description: >
        Order with execution data. Returned by the list orders endpoint for
        completed, canceled, and failed orders. Includes fill information from
        the CeFi exchange for CeFi orders.
      properties:
        order_id:
          type: string
          description: Unique order identifier
        base_asset:
          type: string
          description: Base asset identifier (e.g. `BTC`, `ETH`, `SOL`)
        quote_asset:
          type: string
          description: Quote asset identifier (e.g. `USD`, `USDC`)
        type:
          $ref: '#/components/schemas/OrderType'
        side:
          $ref: '#/components/schemas/OrderSide'
        price:
          type: string
          description: >
            For limit orders, the limit price submitted. For market orders, the
            reference price at order creation.
        qty:
          type: string
          description: >-
            Original order quantity in the denomination specified by `qty_unit`
            at creation
        executed_qty:
          type: string
          description: Quantity of the base asset that has been filled so far
        leaves_qty:
          type: string
          description: >-
            Remaining base asset quantity yet to be filled. Zero when the order
            is complete.
        executed_vwap:
          type: string
          description: Volume-weighted average price across all fills for this order
        status:
          $ref: '#/components/schemas/OrderStatus'
        created_at:
          type: string
          format: date-time
          description: Timestamp when the order was created (RFC 3339)
    Pagination:
      type: object
      description: Cursor-based pagination metadata
      properties:
        next_cursor:
          oneOf:
            - type: string
              format: date-time
            - type: 'null'
          description: RFC3339 timestamp cursor for next page, null if no more data
        limit:
          type: integer
          description: Number of items per page
    GetOrdersResponse:
      type: object
      description: Paginated list of orders with execution data
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/OrderDetail'
          description: List of orders
        pagination:
          $ref: '#/components/schemas/Pagination'
    Balance:
      type: object
      description: Balance for a single asset
      properties:
        asset_name:
          type: string
          description: Human-readable asset name
        asset_id:
          type: string
          description: Asset identifier
        balance:
          type: string
          description: Balance amount as decimal string
    BalancesResponse:
      type: object
      description: User balances response
      properties:
        balances:
          type: array
          items:
            $ref: '#/components/schemas/Balance'
          description: List of asset balances
    ListBalancesResponse:
      type: object
      description: Unified balances across CeFi and DeFi venues
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/BalanceItem'
          description: List of asset balances
    BalanceItem:
      type: object
      description: A single asset balance on a specific venue
      properties:
        symbol:
          type: string
          description: Asset ticker symbol (e.g. BTC, USDC)
        name:
          type: string
          description: Human-readable asset name
        chain:
          type: string
          nullable: true
          description: >-
            Blockchain network ("solana", "base"), or null for exchange-held
            assets
        address:
          type: string
          nullable: true
          description: Token contract/mint address, or null for exchange-held assets
        decimals:
          type: integer
          description: Display precision (e.g. 8 for BTC, 6 for USDC)
        total:
          type: string
          description: Gross balance including held amounts (decimal string)
        available:
          type: string
          description: Usable balance after holds (decimal string)
        held:
          type: string
          description: Amount locked in orders or transfers (decimal string)
        stable:
          type: boolean
          description: Whether this is a stablecoin
        tradeable:
          type: boolean
          description: Whether this asset is active for trading
    ErrorResponse:
      type: object
      description: Error response
      properties:
        message:
          type: string
          description: Error message
