curl \
-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" \
"https://open-api.fhsc.com.vn/trading/pnl-today/$USER_ID"import requests
url = "https://open-api.fhsc.com.vn/trading/pnl-today/{userId}"
headers = {
"X-FH-APIKEY": "<api-key>",
"X-FH-TIMESTAMP": "<api-key>",
"X-FH-NONCE": "<api-key>",
"X-FH-SIGNATURE": "<api-key>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {
'X-FH-APIKEY': '<api-key>',
'X-FH-TIMESTAMP': '<api-key>',
'X-FH-NONCE': '<api-key>',
'X-FH-SIGNATURE': '<api-key>'
}
};
fetch('https://open-api.fhsc.com.vn/trading/pnl-today/{userId}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://open-api.fhsc.com.vn/trading/pnl-today/{userId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-FH-APIKEY: <api-key>",
"X-FH-NONCE: <api-key>",
"X-FH-SIGNATURE: <api-key>",
"X-FH-TIMESTAMP: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://open-api.fhsc.com.vn/trading/pnl-today/{userId}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-FH-APIKEY", "<api-key>")
req.Header.Add("X-FH-TIMESTAMP", "<api-key>")
req.Header.Add("X-FH-NONCE", "<api-key>")
req.Header.Add("X-FH-SIGNATURE", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://open-api.fhsc.com.vn/trading/pnl-today/{userId}")
.header("X-FH-APIKEY", "<api-key>")
.header("X-FH-TIMESTAMP", "<api-key>")
.header("X-FH-NONCE", "<api-key>")
.header("X-FH-SIGNATURE", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://open-api.fhsc.com.vn/trading/pnl-today/{userId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-FH-APIKEY"] = '<api-key>'
request["X-FH-TIMESTAMP"] = '<api-key>'
request["X-FH-NONCE"] = '<api-key>'
request["X-FH-SIGNATURE"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"error_code": "0",
"message": "success",
"data": {
"sub_account_id": "ALL",
"pnl_amount": 1500000,
"pnl_rate": 2.5
}
}{
"error_code": "400",
"message": "Invalid parameter"
}{
"error_code": "401",
"message": "Invalid signature"
}{
"error_code": "429",
"message": "Too many requests"
}{
"error_code": "500",
"message": "Internal server error"
}Lãi-lỗ hôm nay
Lãi / lỗ trong ngày của user, tổng hợp qua mọi tiểu khoản.
curl \
-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" \
"https://open-api.fhsc.com.vn/trading/pnl-today/$USER_ID"import requests
url = "https://open-api.fhsc.com.vn/trading/pnl-today/{userId}"
headers = {
"X-FH-APIKEY": "<api-key>",
"X-FH-TIMESTAMP": "<api-key>",
"X-FH-NONCE": "<api-key>",
"X-FH-SIGNATURE": "<api-key>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {
'X-FH-APIKEY': '<api-key>',
'X-FH-TIMESTAMP': '<api-key>',
'X-FH-NONCE': '<api-key>',
'X-FH-SIGNATURE': '<api-key>'
}
};
fetch('https://open-api.fhsc.com.vn/trading/pnl-today/{userId}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://open-api.fhsc.com.vn/trading/pnl-today/{userId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-FH-APIKEY: <api-key>",
"X-FH-NONCE: <api-key>",
"X-FH-SIGNATURE: <api-key>",
"X-FH-TIMESTAMP: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://open-api.fhsc.com.vn/trading/pnl-today/{userId}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-FH-APIKEY", "<api-key>")
req.Header.Add("X-FH-TIMESTAMP", "<api-key>")
req.Header.Add("X-FH-NONCE", "<api-key>")
req.Header.Add("X-FH-SIGNATURE", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://open-api.fhsc.com.vn/trading/pnl-today/{userId}")
.header("X-FH-APIKEY", "<api-key>")
.header("X-FH-TIMESTAMP", "<api-key>")
.header("X-FH-NONCE", "<api-key>")
.header("X-FH-SIGNATURE", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://open-api.fhsc.com.vn/trading/pnl-today/{userId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-FH-APIKEY"] = '<api-key>'
request["X-FH-TIMESTAMP"] = '<api-key>'
request["X-FH-NONCE"] = '<api-key>'
request["X-FH-SIGNATURE"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"error_code": "0",
"message": "success",
"data": {
"sub_account_id": "ALL",
"pnl_amount": 1500000,
"pnl_rate": 2.5
}
}{
"error_code": "400",
"message": "Invalid parameter"
}{
"error_code": "401",
"message": "Invalid signature"
}{
"error_code": "429",
"message": "Too many requests"
}{
"error_code": "500",
"message": "Internal server error"
}Authorizations
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.
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.
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.
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.
Path Parameters
User ID. Được lấy từ bootstrap flow (GET /users/v1/users/me).
123456
Response
Trả về data chứa pnl_amount (lãi / lỗ tuyệt đối) và pnl_rate (% so với portfolio) tổng hợp qua mọi tiểu khoản.
Các field chung của envelope trong mọi response của Finhay API.
error_codelà"0"(string) khi thành công, mã khác"0"khi lỗi.messagelà thông điệp ngắn từ server.