openapi: 3.1.0
info:
  title: Light Horse Trading API
  version: 1.0.0
  description: REST API for managing brokerage accounts, positions, and orders on the Light Horse Trading platform.
  contact:
    name: Light Horse Support
    url: https://www.lighthorse.io
    email: support@lighthorse.io
  license:
    name: Proprietary
tags:
  - name: Account
    description: Account balance and state.
  - name: Positions
    description: Open positions for an account.
  - name: Orders
    description: Order management — history, preview, placement, and cancellation.
  - name: Cash
    description: Deposit, withdraw operations
servers:
  - url: https://interface.lighthorse.io/open-api/lighthorse/v1
    description: Production with cryptographic signatures authentication
  - url: https://interface.lighthorse.io/api/lighthorse/v1
    description: Production with access tokens authentication
security:
  - SignatureAuth: []

components:
  securitySchemes:
    SignatureAuth:
      type: apiKey
      in: header
      name: x-trade-signature
      description: Please refer to authentication.md
      x-signature-algorithm: HMAC-SHA256
      x-required-headers: [x-trade-apikey, x-trade-algorithm, x-trade-nonce, x-trade-timestamp, x-trade-signature]
  schemas:
    ErrorResponse:
      type: object
      properties:
        s:
          type: string
          description: "Error code string, e.g. `invalid_grant`."
        errmsg:
          type: string
          description: Human-readable error message.
      example:
        s: invalid_grant
        errmsg: Invalid grant, the account may not exist or may not be opened yet.
    CustomField:
      type: object
      properties:
        id:
          type: string
          description: Field identifier.
        value:
          oneOf:
            - type: number
            - type: string
          description: Field value.
    OrderBody:
      type: object
      required:
        - instrument
        - side
        - type
        - quantityType
        - category
        - durationType
        - extendHours
      properties:
        instrument:
          type: string
          description: "Security symbol. Example: `AAPL`."
        side:
          type: string
          enum: [buy, sell]
          description: Order direction.
        type:
          type: string
          enum: [market, limit, stop, stopLimit]
          description: Order type.
        quantityType:
          type: string
          enum: [qty, amount]
          description: Whether the order size is specified by quantity or notional amount.
        category:
          type: string
          enum: [stock, etf, crypto, option, future, arbitrage, others]
          description: Asset class.
        durationType:
          type: string
          enum: [day, gtc]
          description: Order time-in-force.
        extendHours:
          type: string
          enum: [reg, all]
          description: Trading session.
        qty:
          type: string
          description: "Order quantity. Required when `quantityType` is `qty`."
        amount:
          type: string
          description: "Order notional amount. Required when `quantityType` is `amount`."
        limitPrice:
          type: string
          description: "Limit price. Required for `limit` and `stopLimit` order types."
        stopPrice:
          type: string
          description: "Stop trigger price. Required for `stop` and `stopLimit` order types."
        openClose:
          type: string
          enum: [open, close]
          description: Position direction.
        takeProfit:
          type: object
          description: Take-profit leg.
          properties:
            price:
              type: string
              description: Take-profit limit price.
            type:
              type: string
              description: "Order type. Only `limit` supported. Defaults to `limit`."
        stopLoss:
          type: object
          description: Stop-loss leg.
          properties:
            stopPrice:
              type: string
              description: Stop trigger price.
            price:
              type: string
              description: "Limit price for `stopLimit` type."
            type:
              type: string
              enum: [stop, stopLimit]
              description: "Order type. Defaults to `stop`."

paths:
  /accounts/{accountId}/state:
    get:
      operationId: getAccountBalance
      tags: [Account]
      summary: Get Account Balance
      description: Return the current balance and buying-power snapshot for the specified account.
      parameters:
        - name: accountId
          in: path
          required: true
          schema:
            type: string
          description: The account identifier.
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                type: object
                properties:
                  s:
                    type: string
                    description: "Status indicator. `ok` on success."
                  d:
                    type: object
                    description: Account state snapshot.
                    properties:
                      cash:
                        type: number
                        description: Cash balance. Negative when the account carries margin debt.
                      equity:
                        type: number
                        description: Total account equity (cash + market value of positions).
                      mkt:
                        type: number
                        description: Total market value of all open positions.
                      dayPL:
                        type: number
                        description: Intraday profit/loss in account currency.
                      dayPLP:
                        type: number
                        description: "Intraday profit/loss as a decimal fraction (e.g. `-0.1117` = -11.17%)."
                      unrealizedPL:
                        type: number
                        description: Total unrealized profit/loss across all open positions.
                      customFields:
                        type: array
                        description: "Additional computed fields. Known IDs: `dayBP`, `overnightBP`, `daytradeLeft`, `marginRequirement`, `dayTradeTimes`."
                        items:
                          $ref: '#/components/schemas/CustomField'
              example:
                s: ok
                d:
                  cash: -741504.84
                  equity: 1015356.46
                  mkt: 1756861.30
                  dayPL: -127711.66
                  dayPLP: -0.1117
                  unrealizedPL: 212276.61
                  customFields:
                    - id: dayBP
                      value: 1447119.17
                    - id: overnightBP
                      value: 835568.39
                    - id: daytradeLeft
                      value: Unlimited
                    - id: marginRequirement
                      value: 427607.33
                    - id: dayTradeTimes
                      value: 0
        '401':
          description: Unauthorized — missing or invalid authentication.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        default:
          description: Error response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /accounts/{accountId}/positions:
    get:
      operationId: getPositions
      tags: [Positions]
      summary: Get Positions
      description: Return all open positions for the specified account.
      parameters:
        - name: accountId
          in: path
          required: true
          schema:
            type: string
          description: The account identifier.
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                type: object
                properties:
                  s:
                    type: string
                    description: "Status indicator. `ok` on success."
                  d:
                    type: array
                    description: Array of open positions.
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          description: Unique position identifier.
                        instrument:
                          type: string
                          description: Ticker symbol.
                        name:
                          type: string
                          description: Security name.
                        securityType:
                          type: string
                          enum: [stock, etf, option, future, crypto]
                          description: Asset class.
                        side:
                          type: string
                          enum: [buy, sell]
                          description: "Position direction. `buy` — long; `sell` — short."
                        qty:
                          type: number
                          description: Position size in shares. Negative for short positions.
                        last:
                          type: number
                          description: Last traded price.
                        close:
                          type: number
                          description: Previous session close price.
                        avgPrice:
                          type: number
                          description: Average cost per share.
                        mkt:
                          type: number
                          description: Current market value of the position.
                        change:
                          type: number
                          description: Absolute price change from previous close.
                        changePct:
                          type: number
                          description: Percentage price change from previous close.
                        unrealizedPL:
                          type: number
                          description: Unrealized profit/loss in account currency.
                        unrealizedPLP:
                          type: number
                          description: Unrealized profit/loss as a decimal fraction.
                        dayPL:
                          type: number
                          description: Intraday profit/loss.
                        dayPLP:
                          type: number
                          description: Intraday profit/loss as a decimal fraction.
                        exchange:
                          type: string
                          description: Exchange identifier.
                        unit:
                          type: number
                          description: Contract unit size.
                        weight:
                          type: number
                          description: Portfolio weight of the position.
                        customFields:
                          type: array
                          description: "Additional computed fields. Known IDs: `breakEvenPrice`, `holdingDays`."
                          items:
                            $ref: '#/components/schemas/CustomField'
              example:
                s: ok
                d:
                  - id: U000016649-sell
                    instrument: AAPL
                    name: Apple
                    securityType: stock
                    side: sell
                    qty: -75.2
                    last: 261.7179
                    close: 255.78
                    avgPrice: 188.4730752401
                    mkt: -19681.19
                    change: 5.9379
                    changePct: 0.0232
                    unrealizedPL: -5508.0108
                    unrealizedPLP: -0.3886
                    dayPL: 0
                    dayPLP: 0
                    exchange: "185"
                    unit: 1
                    weight: 0
                    customFields:
                      - id: breakEvenPrice
                        value: 88.3581150266
                      - id: holdingDays
                        value: 595
        '401':
          description: Unauthorized — missing or invalid authentication.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        default:
          description: Error response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /accounts/{accountId}/ordersHistory:
    get:
      operationId: getOrders
      tags: [Orders]
      summary: Get Orders
      description: Return all orders for the specified account.
      parameters:
        - name: accountId
          in: path
          required: true
          schema:
            type: string
          description: The account identifier.
        - name: startTime
          in: query
          required: false
          schema:
            type: number
          description: "Start timestamp in milliseconds. Example: `1736772969000`."
        - name: endTime
          in: query
          required: false
          schema:
            type: number
          description: "End timestamp in milliseconds. Example: `1736772969000`."
        - name: pageIndex
          in: query
          required: false
          schema:
            type: integer
          description: "Page number (1-based). Defaults to `1`."
        - name: pageSize
          in: query
          required: false
          schema:
            type: integer
          description: "Records per page. Defaults to `100`."
        - name: instrument
          in: query
          required: false
          schema:
            type: string
          description: "Filter by ticker symbol. Example: `AAPL`."
        - name: side
          in: query
          required: false
          schema:
            type: string
          description: "Filter by order direction. Enum: `buy`; `sell`; `sellShort`; `buyToCover`. Multiple values joined with `|`, e.g. `buy|sell`."
        - name: status
          in: query
          required: false
          schema:
            type: string
          description: "Filter by order status. Enum: `pending`; `filled`; `rejected`; `cancelled`; `partialFilled`. Multiple values joined with `|`, e.g. `pending|filled`."
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                type: object
                properties:
                  s:
                    type: string
                    description: "Status indicator. `ok` on success."
                  d:
                    type: array
                    description: Array of orders.
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          description: Unique order identifier.
                        instrument:
                          type: string
                          description: Ticker symbol.
                        name:
                          type: string
                          description: Security name.
                        securityType:
                          type: string
                          enum: [stock, etf, option, future, crypto]
                          description: Asset class.
                        side:
                          type: string
                          enum: [buy, sell, sellShort, buyToCover]
                          description: Order direction.
                        type:
                          type: string
                          enum: [market, limit, stop, stopLimit]
                          description: Order type.
                        qty:
                          type: number
                          description: Requested quantity in shares.
                        amount:
                          type: number
                          description: "Requested notional value (used when quantityType is `amount`)."
                        quantityType:
                          type: string
                          enum: [qty, amount]
                          description: How quantity is expressed.
                        limitPrice:
                          type: number
                          description: "Limit price for `limit` and `stopLimit` orders."
                        stopPrice:
                          type: number
                          description: "Stop trigger price for `stop` and `stopLimit` orders."
                        durationType:
                          type: string
                          enum: [Day, GTC]
                          description: Time-in-force.
                        extendHours:
                          type: string
                          enum: [Regular, Pre, Post, PrePost]
                          description: Extended hours participation.
                        status:
                          type: string
                          enum: [Working, Filled, PartiallyFilled, Cancelled, Rejected, DoneForDay]
                          description: Current order status.
                        isActive:
                          type: boolean
                          description: "`true` if the order is still open and working."
                        filledQty:
                          type: number
                          description: Number of shares filled so far.
                        filledAmount:
                          type: number
                          description: Total notional value filled.
                        avgPrice:
                          type: number
                          description: Average execution price.
                        filledTime:
                          type: number
                          description: "Unix timestamp (ms) of the last fill. `0` if unfilled."
                        lastModified:
                          type: number
                          description: Unix timestamp (ms) of the last status change.
                        exchange:
                          type: string
                          description: Exchange identifier.
                        unit:
                          type: number
                          description: Contract unit size.
                        message:
                          type: object
                          description: Human-readable status message from the broker.
                          properties:
                            text:
                              type: string
                              description: Message text.
                            type:
                              type: string
                              enum: [information, warning, error]
                              description: Message severity.
              example:
                s: ok
                d:
                  - id: "0434111664758259712"
                    instrument: UPXI
                    name: Upexi
                    securityType: stock
                    side: sell
                    type: market
                    qty: 1.0
                    amount: 0.0
                    quantityType: qty
                    limitPrice: 0.0
                    stopPrice: 0.0
                    durationType: Day
                    extendHours: Regular
                    status: Rejected
                    isActive: false
                    filledQty: 0.0
                    filledAmount: 0.0
                    avgPrice: 0.0
                    filledTime: 0
                    lastModified: 1728569086321
                    exchange: "186"
                    unit: 1
                    message:
                      text: "Order is rejected: Corporate action in progress, trading restricted temporarily"
                      type: error
        '401':
          description: Unauthorized — missing or invalid authentication.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        default:
          description: Error response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /accounts/{accountId}/previewOrder:
    post:
      operationId: previewOrder
      tags: [Orders]
      summary: Preview Order
      description: "Preview an order before submission. Returns a `confirmId` and structured confirmation details. Use this to validate the order and show results to the user before calling Place Order."
      parameters:
        - name: accountId
          in: path
          required: true
          schema:
            type: string
          description: The account identifier.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OrderBody'
            example:
              instrument: BAC
              side: buy
              type: limit
              quantityType: qty
              qty: "100"
              limitPrice: "30.0"
              category: stock
              durationType: day
              extendHours: reg
      responses:
        '200':
          description: Preview generated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  s:
                    type: string
                    description: "Status indicator. `ok` on success."
                  errmsg:
                    type: string
                    description: Error message if the preview could not be generated.
                  d:
                    type: object
                    properties:
                      confirmId:
                        type: string
                        description: "Confirmation token to pass back as `confirmId` when calling Place Order."
                      sections:
                        type: array
                        description: Informational sections to display to the user before order submission.
                        items:
                          type: object
                          properties:
                            header:
                              type: string
                              description: Section heading.
                            rows:
                              type: array
                              items:
                                type: object
                                properties:
                                  label:
                                    type: string
                                  value:
                                    type: string
                            warnings:
                              type: array
                              items:
                                type: string
                              description: Warning messages for the section.
                            errors:
                              type: array
                              items:
                                type: string
                              description: Error messages for the section.
              example:
                s: ok
                d:
                  confirmId: "0000001"
                  sections:
                    - header: Estimated
                      rows:
                        - label: Estimated Cost
                          value: "$1,000.00"
                      warnings:
                        - A warning is some message that should be shown to the user, but not necessarily preventing from executing the order.
                      errors:
                        - The order can not be executed right now because of errors specified here.
        '401':
          description: Unauthorized — missing or invalid authentication.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        default:
          description: Error response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /accounts/{accountId}/orders:
    post:
      operationId: placeOrder
      tags: [Orders]
      summary: Place Order
      description: "Place a new order for the specified account. Call Preview Order first to pre-validate and obtain a `confirmId`, then pass it here."
      parameters:
        - name: accountId
          in: path
          required: true
          schema:
            type: string
          description: The account identifier.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
                - $ref: '#/components/schemas/OrderBody'
                - type: object
                  properties:
                    confirmId:
                      type: string
                      description: "The `confirmId` returned from a prior preview request."
            example:
              instrument: BAC
              side: buy
              type: limit
              quantityType: qty
              qty: "100"
              limitPrice: "30.0"
              category: stock
              durationType: day
              extendHours: reg
              confirmId: "0000001"
      responses:
        '200':
          description: Order accepted.
          content:
            application/json:
              schema:
                type: object
                properties:
                  s:
                    type: string
                    description: "Status indicator. `ok` on success."
                  d:
                    type: object
                    properties:
                      orderId:
                        type: string
                        description: The identifier of the newly created order.
              example:
                s: ok
                d:
                  orderId: "112358"
        '401':
          description: Unauthorized — missing or invalid authentication.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        default:
          description: Error response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /accounts/{accountId}/orders/{orderId}:
    delete:
      operationId: cancelOrder
      tags: [Orders]
      summary: Cancel Order
      description: Cancel an open order for the specified account.
      parameters:
        - name: accountId
          in: path
          required: true
          schema:
            type: string
          description: The account identifier.
        - name: orderId
          in: path
          required: true
          schema:
            type: string
          description: The order identifier to cancel.
      responses:
        '200':
          description: Order cancelled successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  s:
                    type: string
                    description: "Status indicator. `ok` on success."
              example:
                s: ok
        '401':
          description: Unauthorized — missing or invalid authentication.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        default:
          description: Error response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
