Skip to main content
POST
/
trading
/
oa
/
sub-accounts
/
{subAccountId}
/
orders
cURL
BODY='{"sub_account":"120C000008.1","side":"BUY","symbol":"HPG","quantity":100,"type":"LIMIT","limit_price":25500,"market_price":null,"stock_type":"STOCK"}'
BODY_HASH=$(printf '%s' "$BODY" | openssl dgst -sha256 -hex | awk '{print $2}')

curl -X POST \
  -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"
{
  "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": "SENT",
      "fee_amount": 0,
      "tax_amount": 0,
      "execute_amount": 0,
      "order_type": "LO",
      "code": null,
      "rejected_reason": null,
      "lot": "EVEN"
    }
  ]
}

Authorizations

X-FH-APIKEY
string
header
required

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.

X-FH-TIMESTAMP
string
header
required

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.

X-FH-NONCE
string
header
required

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.

X-FH-SIGNATURE
string
header
required

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.

X-FH-BODYHASH
string
header
required

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.

X-FH-2FA-TOKEN
string
header
required

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.

Path Parameters

subAccountId
string
required

subAccountId được lấy từ bootstrap flow (GET /users/v1/users/{userId}/sub-accounts), chọn NORMAL hoặc MARGIN tuỳ mục đích.

Example:

"0001234567"

Body

application/json

Body của request đặt lệnh mới (POST /trading/oa/sub-accounts/{subAccountId}/orders).

Quy tắc field giá theo type:

  • type = LIMIT → set limit_price (VND); market_price để null.
  • type = MARKET → set market_price (enum MarketPriceCode); limit_price để null.
sub_account
string
required

Sub-account ID dạng extended (kèm hậu tố .1 / .6 …), khác với subAccountId ở path param. Lấy từ field sub_account_ext của response GET /users/v1/users/{userId}/sub-accounts.

Example:

"120C000008.1"

side
enum<string>
required

Phía của lệnh.

Giá trịÝ nghĩa
BUYLệnh mua
SELLLệnh bán
Available options:
BUY,
SELL
symbol
string
required

Mã chứng khoán cần đặt lệnh.

Example:

"HPG"

quantity
integer<int64>
required

Số lượng cổ phiếu. Lô chẵn HOSE/HNX là bội số 100. Đặt 1..99 là lô lẻ và chỉ chấp nhận type = LIMIT.

Required range: x >= 1
Example:

100

type
enum<string>
required

Kiểu định giá khi đặt lệnh — quyết định field giá nào phải set trong request body.

Giá trịÝ nghĩaField giá phải set
LIMITLệnh giới hạn — khớp tại đúng giá limit_price hoặc tốt hơn.limit_price (VND); market_price = null.
MARKETLệnh thị trường — khớp theo logic của order type chỉ định.market_price (enum MarketPriceCode); limit_price = null.
Available options:
LIMIT,
MARKET
limit_price
integer<int64> | null

Giá đặt khi type = LIMIT, đơn vị VND (không nhân 1000). Để null khi type = MARKET.

Example:

25500

market_price
enum<string> | null

Mã loại lệnh thị trường khi type = MARKET. Để null khi type = LIMIT.

Available options:
MP,
ATO,
ATC,
MAK,
MOK,
MTL,
PLO,
FOK,
FAK
stock_type
enum<string>
default:STOCK

Phân loại công cụ tài chính. Mặc định STOCK nếu bỏ trống.

Available options:
STOCK,
BOND,
FUND_CERTIFICATE,
WARRANT,
ETF

Response

Server đã xử lý request. Phải đọc result[].code để biết sàn chấp nhận hay từ chối lệnh.

Các field chung của envelope trong mọi response của Finhay API.

  • error_code"0" (string) khi thành công, mã khác "0" khi lỗi.
  • message là thông điệp ngắn từ server.
result
object[]
required

Mảng kết quả — thông thường chứa đúng 1 entry phản ánh lệnh vừa đặt. Server vẫn trả về dưới dạng array để đồng nhất với modify / cancel.

error_code
string

"0" khi thành công, khác "0" khi lỗi.

Example:

"0"

message
string

Thông điệp trạng thái dễ đọc.

Example:

"success"