> ## 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.

# Error codes

> Bảng tra cứu mã lỗi, HTTP status mapping và chiến lược xử lý.

API trả về lỗi dưới 2 dạng:

* **HTTP status** ở response header (4xx / 5xx).
* **`error_code`** ở response body — string `"0"` khi thành công, mã khác
  `"0"` khi lỗi.

Body response lỗi có shape:

```json theme={null}
{
  "error_code": "AUTH_SIGNATURE_INVALID",
  "message": "Invalid signature"
}
```

## Bảng HTTP status

| Status | Ý nghĩa               | Khi nào                                                                                  |
| ------ | --------------------- | ---------------------------------------------------------------------------------------- |
| `200`  | OK                    | Request thành công, `error_code: "0"`                                                    |
| `400`  | Bad Request           | Thiếu / sai param, body không hợp lệ                                                     |
| `401`  | Unauthorized          | API key sai, signature không hợp lệ, timestamp lệch, nonce reused                        |
| `403`  | Forbidden             | IP bị chặn, scope bị từ chối, hoặc 2FA session (`X-FH-2FA-TOKEN`) hết hạn / không hợp lệ |
| `429`  | Too Many Requests     | Vượt rate limit — xem [Rate limits](/rate-limits)                                        |
| `500`  | Internal Server Error | Lỗi server. Retry sau khi backoff                                                        |

## Mã lỗi xác thực (HTTP 401)

<AccordionGroup>
  <Accordion title="AUTH_API_KEY_INVALID" icon="key">
    API key không hợp lệ hoặc đã bị thu hồi. Liên hệ team Finhay để kiểm
    tra trạng thái key hoặc cấp key mới.
  </Accordion>

  <Accordion title="AUTH_SIGNATURE_INVALID" icon="signature">
    `X-FH-SIGNATURE` không match với payload do client tính. Nguyên nhân
    phổ biến:

    * Sai thuật toán: phải là `HMAC-SHA256` với output **hex lowercase**.
    * Sai thứ tự / format payload: đúng phải là
      `{TIMESTAMP}\n{METHOD}\n{PATH}[?{QUERY}]\n{BODYHASH}`.
    * `BODYHASH` thiếu hoặc tính sai khi request có body.
    * `QUERY` không canonical (sort key sai, encode sai).

    Xem chi tiết ở [Authentication — Signing payload](/authentication#signing-payload).
  </Accordion>

  <Accordion title="AUTH_TIMESTAMP_OUT_OF_RANGE" icon="clock">
    `X-FH-TIMESTAMP` lệch quá **±30 giây** so với giờ server. Đảm bảo client
    đồng bộ NTP. `X-FH-TIMESTAMP` là Unix timestamp tính bằng **mili-giây**,
    không phải giây.
  </Accordion>

  <Accordion title="AUTH_NONCE_REUSED" icon="repeat">
    `X-FH-NONCE` đã được sử dụng với cùng `apiKey` trong vòng 5 phút gần
    nhất. Mỗi request phải sinh nonce mới — khuyến nghị dùng UUIDv4.
  </Accordion>

  <Accordion title="AUTH_BODYHASH_MISMATCH" icon="hashtag">
    `X-FH-BODYHASH` không match với `SHA256(body)` server tính. Đảm bảo:

    * Body được serialize stable (cùng JSON string client ký và client gửi).
    * Hash là **hex lowercase**, không phải base64.
  </Accordion>
</AccordionGroup>

## Mã lỗi request (HTTP 400)

<AccordionGroup>
  <Accordion title="INVALID_PARAMETER" icon="circle-xmark">
    Param không hợp lệ — sai enum, sai range, sai format. `message` mô tả
    field cụ thể.
  </Accordion>

  <Accordion title="MISSING_REQUIRED_PARAMETER" icon="triangle-exclamation">
    Thiếu param bắt buộc. Ví dụ `/market/financial-data/macro` thiếu `type`
    hoặc `country`.
  </Accordion>

  <Accordion title="MUTUALLY_EXCLUSIVE_PARAMETER" icon="ban">
    Truyền cùng lúc nhiều param loại trừ lẫn nhau. Ví dụ
    `/market/stock-realtime` chỉ được truyền **đúng 1** trong `symbol` /
    `symbols` / `exchange`.
  </Accordion>
</AccordionGroup>

## Mã lỗi rate limit (HTTP 429)

<AccordionGroup>
  <Accordion title="RATE_LIMIT_EXCEEDED" icon="gauge-high">
    Vượt giới hạn request trong cửa sổ thời gian hiện tại. Response kèm
    header `X-RateLimit-Reset` cho biết thời điểm có thể retry.

    Xem chi tiết ở [Rate limits](/rate-limits).
  </Accordion>
</AccordionGroup>

## Mã lỗi 2FA session (HTTP 403)

Áp dụng cho các endpoint nhóm **Thực thi lệnh** (preview — `POST` /
`PUT` / `DELETE` dưới `/trading/oa/**`).

<AccordionGroup>
  <Accordion title="OTP_SESSION_REQUIRED" icon="lock">
    Chưa có 2FA session — client chưa gửi header `X-FH-2FA-TOKEN`. Khởi
    tạo OTP flow để xin token mới.
  </Accordion>

  <Accordion title="OTP_SESSION_EXPIRED" icon="clock">
    Token đã hết hạn (token có tuổi thọ 1 ngày giao dịch). Chạy lại OTP
    flow để xin token mới rồi retry.
  </Accordion>

  <Accordion title="OTP_SESSION_INVALID" icon="circle-xmark">
    Token không hợp lệ — chữ ký sai hoặc bị làm giả. Không retry, xác
    minh lại logic lưu trữ / truyền token ở client.
  </Accordion>

  <Accordion title="OTP_SESSION_REVOKED" icon="ban">
    Token đã bị thu hồi (user logout, đổi API key, hoặc admin force
    revoke). Chạy lại OTP flow để xin token mới.
  </Accordion>
</AccordionGroup>

## Order-level error codes (Thực thi lệnh — preview)

<Warning>
  **Semantic đặc biệt**: với 3 endpoint nhóm Thực thi lệnh, `HTTP 200`
  **không** đồng nghĩa với lệnh đã được sàn chấp nhận. Phải đọc
  `result[].code` trong body — nếu non-null thì sàn từ chối lệnh
  (`result[].order_status` thường là `REJECTED` / `FAILED`,
  `result[].rejected_reason` chứa lý do).
</Warning>

| `code`                                            | Ý nghĩa                                                                          |
| ------------------------------------------------- | -------------------------------------------------------------------------------- |
| `-400116`, `QMAX_EXCEED`                          | Vượt quá sức mua / sức bán.                                                      |
| `-900017`, `-10011`, `INVALID_PRICE_LOT`          | Giá / lot không hợp lệ — kiểm tra bước nhảy giá và lot size theo sàn.            |
| `-700106`, `-700104`, `-700105`                   | Điều chỉnh số lượng / giá đặt rồi thử lại.                                       |
| `-700114`                                         | Đối với lô lẻ, chỉ được đặt lệnh `LO`.                                           |
| `-300025`                                         | Ngoài giờ giao dịch — vui lòng đặt lại trong phiên sau.                          |
| `-100113`, `INVALID_ORDER_TYPE_FOR_THIS_SESSION`  | Loại lệnh không phù hợp với phiên hiện tại (ví dụ đặt `ATO` ngoài phiên mở cửa). |
| `-400099`                                         | Chứng khoán nằm ngoài danh mục được phép mua.                                    |
| `-700069`, `CAN_NOT_PLACE_ORDER_ON_HALTED_SYMBOL` | Mã chứng khoán đang bị hạn chế / tạm dừng giao dịch.                             |
| `MUST_PUBLISH_TRADE_INFO`                         | Yêu cầu công bố thông tin trước khi giao dịch (cổ đông lớn / nội bộ).            |
| `-701111`                                         | (Modify) Lệnh đã khớp một phần — chỉ sửa được phần chưa khớp.                    |
| `FAILED`                                          | Có lỗi xảy ra phía sàn / ORS, vui lòng thử lại.                                  |

## Chiến lược xử lý lỗi

<Steps>
  <Step title="Kiểm tra HTTP status trước">
    `2xx` → parse body. `4xx` / `5xx` → đọc `error_code` để phân loại.
  </Step>

  <Step title="Retry chỉ khi đúng case">
    * **Retry với backoff** cho `429` (tới `X-RateLimit-Reset`) và `5xx`
      (exponential backoff, max 3 lần).
    * **Không retry** cho `400` và `401` — fix root cause trước.
  </Step>

  <Step title="Ghi log đủ context">
    Khi có lỗi, ghi log đầy đủ: `error_code`, `message`, `traceId` (nếu
    có trong response thành công trước đó), HTTP status, request path.
    Khi báo team hỗ trợ, cung cấp các trường này.
  </Step>
</Steps>
