> ## Documentation Index
> Fetch the complete documentation index at: https://developers.fhsc.com.vn/llms.txt
> Use this file to discover all available pages before exploring further.

# Huỷ lệnh

> > ⚠️ Endpoint đang ở giai đoạn **preview**.

Huỷ 1 lệnh đang chờ khớp. Yêu cầu **Tier 2 HMAC + X-FH-BODYHASH +
X-FH-2FA-TOKEN**.

**Pre-check bắt buộc**: gọi
`GET /trading/v1/accounts/{subAccountId}/order-book/{orderId}` trước
để xác nhận lệnh đang ở trạng thái huỷ được (`SENT`,
`WAITING_TO_SEND`, `SENDING`). Không huỷ được khi `order_status` là
`MATCHED`, `MATCHED_ALL`, `CANCELLED`, `COMPLETED`, `FAILED`.

Với lệnh **đã khớp một phần**, huỷ chỉ áp dụng cho phần unmatched —
phần đã khớp vẫn giữ trong `execute_quantity`.




## OpenAPI

````yaml /openapi.yaml delete /trading/oa/sub-accounts/{subAccountId}/orders/{orderId}
openapi: 3.1.0
info:
  title: Finhay Securities Open API
  version: 0.2.0-preview.2
  description: |
    Đặc tả chính thức của Finhay Securities Open API, dùng chung cho SDK
    codegen, Redoc docs, và (sau này) mock server / contract test.

    ## Authentication — 2 tier

    - **Tier 1 — chỉ cần API key**: các endpoint đọc dữ liệu thị trường
      (`GET /market/**`, `GET /trading/market/**`). Gửi kèm header
      `X-FH-APIKEY` là đủ.
    - **Tier 2 — HMAC signing**: các endpoint liên quan đến account /
      trading / user. Gửi kèm 4 header `X-FH-APIKEY` + `X-FH-TIMESTAMP` +
      `X-FH-NONCE` + `X-FH-SIGNATURE`; thêm `X-FH-BODYHASH` khi request có
      body. Chi tiết thuật toán xem extension `x-finhay-signing` ở root
      spec hoặc phần README.

    ## Bootstrap flow

    Gọi 2 endpoint tag **Khởi tạo** (`GET /users/v1/users/me` và
    `GET /users/v1/users/{userId}/sub-accounts`) **1 lần khi khởi tạo
    client** để lấy thông tin `user_id` và `subAccountId`. Mọi endpoint thuộc
    tag **Tổng tài sản / Tiểu khoản / Danh mục đầu tư / Sổ lệnh / Lãi-lỗ /
    Quyền cổ đông** đều cần 2 giá trị này để truyền vào path parameter.
  contact: {}
servers:
  - url: https://open-api.fhsc.com.vn
    description: Production
security:
  - FinhayApiKey: []
tags:
  - name: Khởi tạo
    description: >-
      Khởi tạo client — lấy `user_id` và `subAccountId`. Gọi 1 lần khi khởi tạo
      SDK rồi cache lại.
  - name: Dữ liệu giao dịch
    description: >-
      Giá stock realtime và lịch sử OHLCV (dạng columnar, phục vụ charting /
      time-series).
  - name: Phân tích cơ bản
    description: >-
      Chỉ số tài chính cơ bản của doanh nghiệp — chỉ số tổng quan, phân tích
      theo kỳ và báo cáo tài chính chuẩn (income statement / balance sheet /
      cash flow).
  - name: Tin tức-sự kiện
    description: >-
      Sự kiện doanh nghiệp (cổ tức, quyền mua, ĐHCĐ, …), tin tức stock, tin tức
      tài chính toàn cầu (forex / commodities / economic-indicators /
      stock-market / cryptocurrency) và báo cáo khuyến nghị từ analyst.
  - name: Kinh tế vĩ mô
    description: >-
      Chỉ số kinh tế vĩ mô (CPI, PMI, PCE, GDP, …) và lãi suất tiền gửi ngân
      hàng.
  - name: Hàng hoá
    description: >-
      Hàng hoá và tài sản thay thế — vàng, bạc (spot / chart / theo nhà cung
      cấp) và crypto trending.
  - name: Tổng hợp đa loại
    description: >-
      Endpoint composite tổng hợp cross-domain (vàng / bạc / crypto / FX / lãi
      suất / US index) trong 1 call. Nên dùng endpoint chuyên biệt nếu chỉ cần 1
      loại.
  - name: Quỹ mở
    description: >-
      Quỹ mở (open-ended funds) — danh sách quỹ, công ty quản lý, NAV history,
      holdings, ranking và benchmark cross-fund.
  - name: Tổng tài sản
    description: >-
      Tổng quan tài sản cấp user — cross-product (stock, fund, bond, hay0) kèm
      cash, debt, PnL.
  - name: Tiểu khoản
    description: Thông tin tiểu khoản — số dư, margin, dư nợ và ngân hàng liên kết.
  - name: Danh mục đầu tư
    description: Danh mục stock đang nắm giữ kèm giá realtime và PnL theo vị thế.
  - name: Sổ lệnh
    description: >-
      Quản lý lệnh — sổ lệnh trong ngày, danh sách đầy đủ hoặc chi tiết theo
      `orderId`.
  - name: Lãi-lỗ
    description: PnL và analytics cá nhân — lãi / lỗ trong ngày tổng hợp theo user.
  - name: Quyền cổ đông
    description: Quyền cổ đông (cổ tức, quyền mua, bỏ phiếu, …) của tiểu khoản.
  - name: Phiên giao dịch
    description: >-
      Hạ tầng trading — trạng thái phiên giao dịch và order type khả dụng của
      mỗi exchange.
  - name: Thực thi lệnh
    description: |
      ⚠️ Nhóm endpoint này đang ở giai đoạn **preview**.

      Đặt / sửa / huỷ lệnh trên sàn — write operation nhạy cảm, yêu cầu
      Tier 2 HMAC đầy đủ + `X-FH-BODYHASH` + `X-FH-2FA-TOKEN` (daily 2FA
      session).
paths:
  /trading/oa/sub-accounts/{subAccountId}/orders/{orderId}:
    delete:
      tags:
        - Thực thi lệnh
      summary: Huỷ lệnh
      description: |
        > ⚠️ Endpoint đang ở giai đoạn **preview**.

        Huỷ 1 lệnh đang chờ khớp. Yêu cầu **Tier 2 HMAC + X-FH-BODYHASH +
        X-FH-2FA-TOKEN**.

        **Pre-check bắt buộc**: gọi
        `GET /trading/v1/accounts/{subAccountId}/order-book/{orderId}` trước
        để xác nhận lệnh đang ở trạng thái huỷ được (`SENT`,
        `WAITING_TO_SEND`, `SENDING`). Không huỷ được khi `order_status` là
        `MATCHED`, `MATCHED_ALL`, `CANCELLED`, `COMPLETED`, `FAILED`.

        Với lệnh **đã khớp một phần**, huỷ chỉ áp dụng cho phần unmatched —
        phần đã khớp vẫn giữ trong `execute_quantity`.
      operationId: ordersCancel
      parameters:
        - $ref: '#/components/parameters/SubAccountId'
        - $ref: '#/components/parameters/OrderId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CancelOrderRequest'
            example:
              sub_account: 120C000008.1
      responses:
        '200':
          description: |
            Server đã xử lý request. **Phải đọc `result[].order_status`** để
            xác nhận lệnh đã được huỷ (`CANCELLED`) hoặc `result[].code` để
            biết lý do nếu huỷ thất bại.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CancelOrderResponse'
              example:
                error_code: '0'
                message: success
                result:
                  - order_id: ORD123456
                    account_id: 120C000008.1
                    transaction_date: '2026-05-28'
                    symbol: HPG
                    order_side: BUY
                    order_quantity: 100
                    limit_price: 25500
                    market_price: null
                    execute_quantity: 0
                    execute_price: 0
                    order_status: CANCELLED
                    fee_amount: 0
                    tax_amount: 0
                    execute_amount: 0
                    order_type: LO
                    code: null
                    rejected_reason: null
                    lot: EVEN
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
      security:
        - FinhayApiKey: []
          FinhayTimestamp: []
          FinhayNonce: []
          FinhaySignature: []
          FinhayBodyHash: []
          FinhayTwoFactor: []
      x-codeSamples:
        - lang: bash
          label: cURL
          source: >
            BODY='{"sub_account":"120C000008.1"}'

            BODY_HASH=$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk
            '{print $2}')


            curl -X DELETE \
              -H "X-FH-APIKEY: $FINHAY_API_KEY" \
              -H "X-FH-TIMESTAMP: $TIMESTAMP_MS" \
              -H "X-FH-NONCE: $NONCE_UUID" \
              -H "X-FH-SIGNATURE: $SIGNATURE_HEX" \
              -H "X-FH-BODYHASH: $BODY_HASH" \
              -H "X-FH-2FA-TOKEN: $FINHAY_2FA_TOKEN" \
              -H "Content-Type: application/json" \
              -d "$BODY" \
              "https://open-api.fhsc.com.vn/trading/oa/sub-accounts/$SUB_ACCOUNT_NORMAL/orders/ORD123456"
components:
  parameters:
    SubAccountId:
      name: subAccountId
      in: path
      required: true
      description: |
        subAccountId được lấy từ bootstrap flow
        (`GET /users/v1/users/{userId}/sub-accounts`), chọn NORMAL hoặc MARGIN
        tuỳ mục đích.
      schema:
        type: string
        example: '0001234567'
    OrderId:
      name: orderId
      in: path
      required: true
      description: |
        ID lệnh trên sàn — lấy từ field `order_id` trong response của
        `POST /trading/oa/sub-accounts/{subAccountId}/orders` (Place Order)
        hoặc từ `GET /trading/v1/accounts/{subAccountId}/order-book` (sổ lệnh
        trong ngày). Bắt buộc khi sửa hoặc huỷ lệnh.
      schema:
        type: string
        example: ORD123456
  schemas:
    CancelOrderRequest:
      type: object
      description: |
        Body của request huỷ lệnh
        (`DELETE /trading/oa/sub-accounts/{subAccountId}/orders/{orderId}`).

        > ⚠️ Đây là DELETE request có body — không chuẩn HTTP nhưng là contract
        > thật của upstream. Client phải tính `X-FH-BODYHASH` từ body này.

        Chỉ huỷ được khi trạng thái lệnh thuộc `SENT`, `WAITING_TO_SEND`,
        `SENDING`. Với lệnh đã khớp một phần, huỷ chỉ áp dụng cho phần
        unmatched.
      required:
        - sub_account
      properties:
        sub_account:
          type: string
          description: |
            Sub-account ID dạng extended (kèm hậu tố `.1` / `.6` …) — cùng giá
            trị dùng cho `sub_account` trong place-order.
          example: 120C000008.1
      example:
        sub_account: 120C000008.1
    CancelOrderResponse:
      allOf:
        - $ref: '#/components/schemas/EnvelopeBase'
        - type: object
          required:
            - result
          properties:
            result:
              type: array
              description: |
                Mảng kết quả — thông thường chứa **đúng 1** entry phản ánh trạng
                thái lệnh sau khi huỷ. `order_status` thường là `CANCELLED`
                (huỷ toàn bộ) hoặc giữ nguyên kèm phần `execute_quantity` cũ
                nếu lệnh đã khớp một phần (chỉ huỷ phần unmatched).
              items:
                $ref: '#/components/schemas/OrderExecutionResult'
    EnvelopeBase:
      type: object
      description: |
        Các field chung của envelope trong mọi response của Finhay API.

        - `error_code` là `"0"` (string) khi thành công, mã khác `"0"` khi lỗi.
        - `message` là thông điệp ngắn từ server.
      properties:
        error_code:
          type: string
          description: '`"0"` khi thành công, khác `"0"` khi lỗi.'
          example: '0'
        message:
          type: string
          description: Thông điệp trạng thái dễ đọc.
          example: success
    OrderExecutionResult:
      type: object
      description: >
        Kết quả thao tác đặt / sửa / huỷ lệnh — phản ánh trạng thái của 1 lệnh

        trên sàn sau khi server xử lý.


        > **Semantic cảnh báo**: HTTP 200 **không** đồng nghĩa với lệnh đã được

        > sàn chấp nhận. Nếu `code` non-null thì sàn từ chối lệnh
        (`order_status`

        > thường là `REJECTED` hoặc `FAILED`), `rejected_reason` chứa lý do dịch

        > sang ngôn ngữ end-user. Xem bảng `Order-level error codes` trong trang

        > Errors.
      required:
        - order_id
        - account_id
        - transaction_date
        - symbol
        - order_side
        - order_quantity
        - order_status
        - order_type
        - lot
      properties:
        order_id:
          type: string
          description: ID lệnh do sàn cấp.
          example: ORD123456
        account_id:
          type: string
          description: Sub-account ID dạng extended.
          example: 120C000008.1
        transaction_date:
          type: string
          description: Ngày giao dịch, định dạng `YYYY-MM-DD`.
          example: '2026-05-28'
        symbol:
          type: string
          example: HPG
        order_side:
          $ref: '#/components/schemas/OrderSide'
        order_quantity:
          type: integer
          format: int64
          description: Tổng số lượng đã đặt.
          example: 100
        limit_price:
          type:
            - integer
            - 'null'
          format: int64
          description: Giá limit (VND), `null` nếu là MARKET order.
          example: 25500
        market_price:
          description: Loại giá thị trường, `null` nếu là LIMIT order.
          oneOf:
            - $ref: '#/components/schemas/MarketPriceCode'
            - type: 'null'
        execute_quantity:
          type: integer
          format: int64
          description: Số lượng đã khớp tới hiện tại.
          example: 0
        execute_price:
          type: integer
          format: int64
          description: Giá khớp trung bình (VND), `0` nếu chưa khớp.
          example: 0
        order_status:
          $ref: '#/components/schemas/OrderStatus'
        fee_amount:
          type: number
          description: Phí giao dịch (VND).
          example: 0
        tax_amount:
          type: number
          description: Thuế (VND).
          example: 0
        execute_amount:
          type: integer
          format: int64
          description: Giá trị đã khớp = `execute_quantity * execute_price` (VND).
          example: 0
        order_type:
          $ref: '#/components/schemas/OrderType'
        code:
          type:
            - string
            - 'null'
          description: |
            Mã lỗi cấp lệnh do sàn / ORS trả về. `null` khi lệnh hợp lệ. Khi
            non-null, đi kèm `rejected_reason` mô tả lý do — xem trang Errors.
          example: null
        rejected_reason:
          type:
            - string
            - 'null'
          description: >-
            Lý do lệnh bị từ chối (đã dịch tiếng Việt), `null` khi `code =
            null`.
          example: null
        lot:
          $ref: '#/components/schemas/LotType'
    ErrorBody:
      type: object
      description: Body của response khi 4xx / 5xx.
      properties:
        error_code:
          type: string
          description: >-
            Mã lỗi khác `"0"` (ví dụ `AUTH_SIGNATURE_INVALID`,
            `RATE_LIMIT_EXCEEDED`, …).
          example: '400'
        message:
          type: string
          description: Thông điệp lỗi (tiếng Anh, từ server).
          example: Invalid parameter
      required:
        - error_code
        - message
    OrderSide:
      type: string
      description: |
        Phía của lệnh.

        | Giá trị | Ý nghĩa |
        |---------|---------|
        | `BUY`  | Lệnh mua |
        | `SELL` | Lệnh bán |
      enum:
        - BUY
        - SELL
      x-enum-varnames:
        - BUY
        - SELL
    MarketPriceCode:
      type: string
      description: >
        Mã loại lệnh thị trường — set vào field `market_price` khi `type` =

        `MARKET` ở `POST /trading/oa/sub-accounts/{subAccountId}/orders`.


        | Giá trị | Tên | Mô tả |

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

        | `MP`  | Market Price | Khớp tại giá tốt nhất hiện có (HOSE — ORS
        auto-convert sang `MTL`). |

        | `ATO` | At The Open | Khớp tại phiên mở cửa. |

        | `ATC` | At The Close | Khớp tại phiên đóng cửa. |

        | `MAK` | Make and Kill | Khớp một phần, phần còn lại huỷ (HNX — ORS
        auto-convert sang `FAK`). |

        | `MOK` | Make or Kill | Khớp toàn bộ hoặc huỷ (HNX — ORS auto-convert
        sang `FOK`). |

        | `MTL` | Match To Limit | Khớp theo giá thị trường rồi chuyển phần dư
        thành limit. |

        | `PLO` | Post Limit Order | Lệnh limit sau phiên ATC (HNX only). |

        | `FOK` | Fill or Kill | Khớp toàn bộ hoặc huỷ — dạng chuẩn hoá của
        `MOK`. |

        | `FAK` | Fill and Kill | Khớp một phần, huỷ phần còn lại — dạng chuẩn
        hoá của `MAK`. |


        Hỗ trợ order type theo sàn:

        - HOSE: `LO`, `MP`, `ATO`, `ATC`, `MTL`

        - HNX: `LO`, `MTL`, `MOK`, `MAK`, `PLO`, `ATC`

        - UPCOM / HCX: chỉ `LO`
      enum:
        - MP
        - ATO
        - ATC
        - MAK
        - MOK
        - MTL
        - PLO
        - FOK
        - FAK
      x-enum-varnames:
        - MP
        - ATO
        - ATC
        - MAK
        - MOK
        - MTL
        - PLO
        - FOK
        - FAK
    OrderStatus:
      type: string
      description: >
        Trạng thái lệnh trong vòng đời từ lúc đặt tới khi kết thúc.


        Nhóm chính:


        | Nhóm | Trạng thái |

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

        | Đang xử lý nội bộ | `WAITING_TO_ACTIVATE`, `WAITING_TO_SEND`,
        `SENDING`, `INTERNAL_SENDING`, `SENDING_TO_CORE`, `WAIT_FOR_ACCEPTING`,
        `ACCEPTING` |

        | Đã vào sàn / chờ khớp | `SENT`, `ACCEPTED`, `RECEIVED` |

        | Đang sửa / huỷ | `FIXING`, `FIXED`, `CANCELLING` |

        | Khớp | `MATCHED`, `MATCHED_ALL` |

        | Kết thúc thành công | `COMPLETED` |

        | Huỷ / từ chối / lỗi | `CANCELLED`, `INTERNAL_CANCELLED`,
        `CANCEL_BY_STOCK_EVENT`, `REJECTED`, `REJECTING`, `FAILED`, `EXPIRED`,
        `EXPIRED_ACTIVATION_TIME`, `EXPIRED_AUTHORIZATION` |


        Sau `place-order`, trạng thái khởi tạo phổ biến là `SENT` (đã đẩy lên

        sàn) hoặc `REJECTED` (sàn từ chối ngay). Sau `modify-order` /

        `cancel-order`, trạng thái phản ánh kết quả thao tác trên phần lệnh

        chưa khớp.
      enum:
        - WAITING_TO_ACTIVATE
        - WAITING_TO_SEND
        - SENDING
        - SENT
        - FIXING
        - FIXED
        - CANCELLED
        - CANCELLING
        - MATCHED
        - EXPIRED
        - MATCHED_ALL
        - REJECTED
        - COMPLETED
        - FAILED
        - EXPIRED_ACTIVATION_TIME
        - EXPIRED_AUTHORIZATION
        - RECEIVED
        - INTERNAL_SENDING
        - INTERNAL_CANCELLED
        - SENDING_TO_CORE
        - CANCEL_BY_STOCK_EVENT
        - WAIT_FOR_ACCEPTING
        - ACCEPTED
        - ACCEPTING
        - REJECTING
      x-enum-varnames:
        - WAITING_TO_ACTIVATE
        - WAITING_TO_SEND
        - SENDING
        - SENT
        - FIXING
        - FIXED
        - CANCELLED
        - CANCELLING
        - MATCHED
        - EXPIRED
        - MATCHED_ALL
        - REJECTED
        - COMPLETED
        - FAILED
        - EXPIRED_ACTIVATION_TIME
        - EXPIRED_AUTHORIZATION
        - RECEIVED
        - INTERNAL_SENDING
        - INTERNAL_CANCELLED
        - SENDING_TO_CORE
        - CANCEL_BY_STOCK_EVENT
        - WAIT_FOR_ACCEPTING
        - ACCEPTED
        - ACCEPTING
        - REJECTING
    OrderType:
      type: string
      description: |
        Loại order được đặt.

        | Giá trị | Ý nghĩa |
        |---------|---------|
        | `LO` | Giới hạn (Limit Order) |
        | `MP` | Khớp giá thị trường |
        | `ATO` | Phiên mở cửa |
        | `ATC` | Phiên đóng cửa |
        | `MAK` | Khớp và huỷ |
        | `MOK` | Khớp hoặc huỷ toàn bộ |
        | `MTL` | Khớp đến giới hạn rồi chuyển limit |
        | `PLO` | Post-limit (HNX, sau giờ khớp chính) |
        | `FOK` | Khớp toàn bộ hoặc huỷ |
        | `FAK` | Khớp phần nào được và huỷ phần còn lại |
      enum:
        - LO
        - MP
        - ATO
        - ATC
        - MAK
        - MOK
        - MTL
        - PLO
        - FOK
        - FAK
      x-enum-varnames:
        - LO
        - MP
        - ATO
        - ATC
        - MAK
        - MOK
        - MTL
        - PLO
        - FOK
        - FAK
    LotType:
      type: string
      description: |
        Phân loại lô của lệnh — chỉ xuất hiện ở response `OrderExecutionResult`.

        | Giá trị | Ý nghĩa |
        |---------|---------|
        | `EVEN` | Lô chẵn — quantity bội số của lot size (HOSE/HNX: 100). |
        | `ODD`  | Lô lẻ — 1..99 cổ phiếu; chỉ chấp nhận order type `LO`. |
      enum:
        - EVEN
        - ODD
      x-enum-varnames:
        - EVEN
        - ODD
  responses:
    BadRequest:
      description: Request không hợp lệ — thiếu hoặc sai tham số.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
          example:
            error_code: '400'
            message: Invalid parameter
    Unauthorized:
      description: Không xác thực — thiếu, sai hoặc không hợp lệ chữ ký / API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
          example:
            error_code: '401'
            message: Invalid signature
    Forbidden:
      description: |
        Không đủ quyền — IP bị chặn, scope bị từ chối, hoặc 2FA session
        (`X-FH-2FA-TOKEN`) chưa có / hết hạn / không hợp lệ / bị revoke. Khi
        `error_code` là 1 trong `OTP_SESSION_REQUIRED|EXPIRED|INVALID|REVOKED`,
        client cần chạy lại OTP flow để lấy token mới rồi retry request.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
          example:
            error_code: OTP_SESSION_EXPIRED
            message: 2FA session has expired
    NotFound:
      description: >-
        Tài nguyên không tồn tại — `error_code` mô tả cụ thể loại tài nguyên
        không tìm thấy.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
          example:
            error_code: '404'
            message: Not found
    RateLimited:
      description: >-
        Vượt giới hạn rate limit. Chờ đến thời điểm `X-RateLimit-Reset` rồi thử
        lại.
      headers:
        X-RateLimit-Reset:
          $ref: '#/components/headers/XRateLimitReset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
          example:
            error_code: '429'
            message: Too many requests
    InternalError:
      description: Lỗi server nội bộ.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
          example:
            error_code: '500'
            message: Internal server error
  headers:
    XRateLimitReset:
      description: |
        Unix timestamp (giây) — thời điểm window rate limit reset. Client nhận
        `429 Too Many Requests` nên chờ đến thời điểm này rồi retry.
      schema:
        type: integer
        format: int64
        example: 1713441600
  securitySchemes:
    FinhayApiKey:
      type: apiKey
      in: header
      name: X-FH-APIKEY
      description: >
        API key dài hạn của client. Cấu hình 1 lần lúc khởi tạo; có thể wire
        thẳng

        vào static setter của SDK tự-gen. Đi kèm với `FINHAY_API_SECRET` —
        secret

        này chỉ dùng ở phía client để tính `X-FH-SIGNATURE`, **không** bao giờ

        gửi qua mạng.
    FinhayTimestamp:
      type: apiKey
      in: header
      name: X-FH-TIMESTAMP
      description: >
        Unix time hiện tại tính bằng **milliseconds**, đưới dạng chuỗi số thập
        phân.


        Được tính per-request bởi signing middleware. **Không** set thủ công —
        dùng

        middleware mẫu trong README.
    FinhayNonce:
      type: apiKey
      in: header
      name: X-FH-NONCE
      description: |
        UUIDv4 duy nhất per-request (ví dụ `crypto.randomUUID()`). Server cache
        cặp `(apiKey, nonce)` trong 5 phút; nếu nonce được reuse với cùng apiKey
        trong window này, request sẽ bị từ chối với `AUTH_NONCE_REUSED` (401).

        Server chấp nhận chuỗi opaque bất kỳ về mặt kỹ thuật, nhưng nên dùng
        UUIDv4 để đảm bảo tính unique.

        Được tính per-request bởi signing middleware. **Không** set thủ công —
        xem middleware mẫu trong tài liệu Authentication.
    FinhaySignature:
      type: apiKey
      in: header
      name: X-FH-SIGNATURE
      description: >
        HMAC-SHA256 của canonical signing payload, encode hex (lowercase).


        Signing payload:

        ```

        {X-FH-TIMESTAMP}\n{METHOD}\n{REQUEST_PATH}[?{QUERY}]\n{BODYHASH}

        ```

        - `?{QUERY}` chỉ nối vào path khi request có query string.

        - `{BODYHASH}` là chuỗi rỗng khi body rỗng (vẫn không có newline sau
        đó).


        Được tính per-request bởi signing middleware. **Không** set thủ công —
        dùng

        middleware mẫu trong README.
    FinhayBodyHash:
      type: apiKey
      in: header
      name: X-FH-BODYHASH
      description: |
        SHA-256 của raw request body, encode hex (lowercase). **Bắt buộc khi
        request có body** (POST / PUT / PATCH). Có thể bỏ qua — hoặc gửi chuỗi
        rỗng — khi body rỗng.

        Là segment cuối của canonical signing payload
        (`{timestamp}\n{method}\n{path}[?{query}]\n{bodyHash}`). Server dùng giá
        trị client gửi lên để verify chữ ký; server **không** tự hash lại body,
        nên client phải hash đúng chuỗi bytes đã gửi đi.

        Được tính per-request bởi signing middleware. **Không** set thủ công —
        xem middleware mẫu trong tài liệu Authentication.
    FinhayTwoFactor:
      type: apiKey
      in: header
      name: X-FH-2FA-TOKEN
      description: |
        Daily 2FA session JWT do server cấp sau khi user xác thực qua OTP. Áp
        dụng cho các write operation nhạy cảm (đặt / sửa / huỷ lệnh) — phải đi
        cùng đủ 4 header HMAC + `X-FH-BODYHASH`.

        Token có tuổi thọ **1 ngày giao dịch** và được scope theo `apiKey`. Khi
        hết hạn hoặc bị revoke, server trả `HTTP 403` với 1 trong các
        `error_code`:

        - `OTP_SESSION_REQUIRED` — chưa có session, cần khởi tạo OTP flow.
        - `OTP_SESSION_EXPIRED` — session đã hết hạn.
        - `OTP_SESSION_INVALID` — token không hợp lệ / chữ ký sai.
        - `OTP_SESSION_REVOKED` — bị thu hồi (user logout, đổi key, …).

        Khi gặp 403 thuộc các mã trên, client phải chạy lại OTP flow để xin
        token mới rồi retry request.

````