SFI External API — Hồ sơ chuyên gia
Hồ sơ giới thiệu của nhân sự SFI dành cho ứng dụng đối tác — không cần đăng nhập khách hàng, chỉ xác thực bằng X-Api-Key.
https://a.sfi.com.vn/ekyc/ex_apiChínhhttps://b.sfi.com.vn/ekyc/ex_apiDự phòngTổng quan
Toàn bộ endpoint trong tài liệu này nằm trong entry point /ekyc/ex_api, dùng chung quy ước
?cmd={tên_lệnh} và chung khung phản hồi JSON. Khác với nhóm API giao dịch
(open_position, account_status…), các API ở đây không cần JWT và không gắn với tài khoản khách hàng nào.
Phần Tổng quan → Mã lỗi chung dùng chung cho mọi nhóm API công khai của /ekyc/ex_api;
phần riêng của nhóm này (tham số, cấu trúc dữ liệu, lưu ý nghiệp vụ) nằm ở khối bên dưới.
Danh mục endpoint
| Nhóm | Endpoint | Mô tả | Xác thực |
|---|---|---|---|
| 2 · Hồ sơ chuyên gia | GET ?cmd=expert_profile_fields | Bảng nhãn khoá động, dùng chung cho mọi hồ sơ — gọi một lần rồi cache | X-Api-Key |
| 2 · Hồ sơ chuyên gia | GET ?cmd=expert_profiles | Danh sách chuyên gia (nhân sự SFI), có phân trang và sắp xếp | X-Api-Key |
| 2 · Hồ sơ chuyên gia | GET ?cmd=expert_profile&id=… | Chi tiết hồ sơ một chuyên gia theo mã nhân sự | X-Api-Key |
Danh mục này là nguồn tra cứu nhanh của nhóm Hồ sơ chuyên gia — mỗi endpoint có một mục mô tả chi tiết bên dưới.
Xác thực bằng API Key
Mọi request phải gửi kèm header:
X-Api-Key: {api_key_được_SFI_cấp}
Nếu thiếu hoặc sai key, server trả về HTTP 401 với body
{"success": false, "message": "Unauthorized."}.
Key được cấp riêng cho từng ứng dụng đối tác; vui lòng lưu ở phía server, không nhúng vào ứng dụng client.
X-Api-Key dùng chung cho tất cả nhóm API trong tài liệu này, và cũng chính là key dùng
cho guestcmd=login_request ở luồng OOB Auth.
Định dạng phản hồi
Toàn bộ API dùng chung khung phản hồi JSON của hệ thống SFI:
{
"success": true,
"message": "Thành công!",
"data": [ ... ],
"svr": "srv-01"
}
| Trường | Kiểu | Mô tả |
|---|---|---|
| success | boolean | Kết quả xử lý |
| message | string | Thông điệp (tiếng Việt) |
| data | array / object | Dữ liệu trả về. Rỗng ([]) khi lỗi; vắng mặt ở phản hồi lỗi xác thực JWT — xem Mã lỗi chung |
| svr | string | Định danh máy chủ xử lý (dùng khi báo lỗi) |
Mã lỗi chung
| HTTP | message | Nguyên nhân |
|---|---|---|
| 401 | Unauthorized. | Thiếu header X-Api-Key hoặc key không hợp lệ |
| 200 | [IAH] Phiên làm việc đã hết hạn. Vui lòng đăng nhập lại! | cmd không thuộc nhóm API công khai, hoặc gọi bằng phương thức khác GET — request rơi vào nhánh yêu cầu JWT. Phản hồi này không có khóa data. |
| 200 | (tuỳ nghiệp vụ) | Lỗi nghiệp vụ — xem success: false và message |
200 với
success: false. Client luôn phải kiểm tra trường success, không
chỉ dựa vào HTTP status. Mã lỗi riêng của nhóm này được liệt kê ở cuối khối bên dưới.
Hồ sơ chuyên gia
Hồ sơ giới thiệu của nhân sự SFI (môi giới, cộng tác viên, đại lý, nhân sự đối tác) — ảnh, chức danh, giới thiệu, triết lý đầu tư, dịch vụ cung cấp, thông tin nổi bật và hồ sơ kinh nghiệm. Nhân sự tự điền trên cổng AMG, bộ phận CSKH của SFI duyệt trước khi công khai.
1 · Bảng nhãn khoá động
?cmd=expert_profile_fields
Hai nhóm highlights / experience trong hồ sơ dùng
khoá động do SFI khai: khoá có thể được thêm, đổi nhãn hoặc ẩn bất cứ lúc nào. Bảng nhãn
này giống nhau cho mọi hồ sơ nên nằm ở endpoint riêng — gọi một lần, cache lại, rồi dùng
cho toàn bộ danh sách và chi tiết. Hai API hồ sơ ở dưới chỉ trả value, không lặp lại bảng nhãn.
Request
curl 'https://a.sfi.com.vn/ekyc/ex_api?cmd=expert_profile_fields' \
-H 'X-Api-Key: YOUR_API_KEY'
Response
{
"success": true,
"message": "Thành công!",
"data": {
"HIGHLIGHT": [
{ "key": "years_experience", "label": "Số năm kinh nghiệm", "icon": "briefcase", "inputType": "TEXT" },
{ "key": "clients_served", "label": "Số nhà đầu tư đồng hành", "icon": "users", "inputType": "TEXT" }
],
"EXPERIENCE": [
{ "key": "aum", "label": "Tổng tài sản đang quản lý", "icon": "", "inputType": "TEXT" },
{ "key": "awards", "label": "Vinh danh - Giải thưởng", "icon": "", "inputType": "MULTILINE" }
]
},
"svr": "srv-01"
}
| Trường | Kiểu | Mô tả |
|---|---|---|
| HIGHLIGHT | array | Nhóm Thông tin nổi bật — các ô số lớn |
| EXPERIENCE | array | Nhóm Hồ sơ kinh nghiệm |
| [].key | string | Khoá tra value trong highlights / experience của hồ sơ |
| [].label | string | Nhãn hiển thị |
| [].icon | string | Mã icon Lucide kebab-case. Chỉ nhóm HIGHLIGHT có, nhóm còn lại thường rỗng |
| [].inputType | string | MULTILINE → value là array<string>; TEXT / TEXTAREA / NUMBER → value là string |
key trong hồ sơ —
đừng hardcode danh sách khoá. Thứ tự mảng chính là thứ tự hiển thị SFI mong muốn, không cần
sắp lại. Danh sách chỉ gồm khoá đang bật; số lượng và thứ tự có thể đổi giữa hai lần gọi, nên nếu cache
thì đặt TTL (ví dụ 1 giờ) thay vì cache vĩnh viễn. Khoá SFI đang ẩn và khoá nhân sự chưa điền
không xuất hiện trong hồ sơ trả ra.
Thử ngay — ?cmd=expert_profile_fields
Không có tham số.
2 · Danh sách chuyên gia
?cmd=expert_profiles
Trả về danh sách chuyên gia theo trang, kèm toàn bộ nội dung hồ sơ của từng người — không cần gọi thêm API chi tiết để dựng danh sách hay trang giới thiệu.
Tham số truy vấn
| Tham số | Kiểu | Bắt buộc | Mặc định | Mô tả |
|---|---|---|---|---|
| q | string | Không | (rỗng) |
Tìm theo tên hoặc số điện thoại nhân sự (khớp một trong hai, chứa chuỗi). Tên: không phân biệt hoa thường và không phân biệt dấu — nguyen van khớp Nguyễn Văn.SĐT: chỉ dò khi q chỉ gồm chữ số (cho phép khoảng trắng, + . - ( )) và có ≥ 3 chữ số;
ký tự phân cách bị bỏ qua, đầu +84 được quy về 0.Tối đa 100 ký tự, dài hơn: lỗi success: false. Lọc trước khi sắp xếp/phân trang,
nên paging.total là tổng số kết quả tìm được.
|
| page | int | Không | 1 | Trang, bắt đầu từ 1. Giá trị < 1 được đưa về 1. |
| size | int | Không | 20 | Số bản ghi mỗi trang, tối đa 100. Giá trị lớn hơn bị giới hạn về 100. |
| sort | string | Không | volume |
volume — khối lượng giao dịch lớn nhấtclients — nhiều khách hàng nhấtGiá trị khác: lỗi success: false. Xem Sắp xếp theo số liệu tháng.
|
| order | string | Không | desc |
desc (cao → thấp) hoặc asc. Giá trị khác được coi là desc. |
data.paging có total và
totalPages nên đối tác biết trước tổng số bản ghi. Khi bằng điểm sắp xếp, thứ tự được chốt
theo tên rồi mã nhân sự — nhờ vậy phân trang không bị lặp hoặc mất bản ghi.
Request
# Trang 1, 20 chuyên gia, khối lượng giao dịch lớn nhất trước
curl 'https://a.sfi.com.vn/ekyc/ex_api?cmd=expert_profiles&page=1&size=20&sort=volume' \
-H 'X-Api-Key: YOUR_API_KEY'
# Nhiều khách hàng nhất
curl 'https://a.sfi.com.vn/ekyc/ex_api?cmd=expert_profiles&sort=clients' \
-H 'X-Api-Key: YOUR_API_KEY'
# Tìm theo tên (không dấu) hoặc số điện thoại — nhớ URL-encode q
curl 'https://a.sfi.com.vn/ekyc/ex_api?cmd=expert_profiles&q=nguyen%20van' \
-H 'X-Api-Key: YOUR_API_KEY'
curl 'https://a.sfi.com.vn/ekyc/ex_api?cmd=expert_profiles&q=0901234' \
-H 'X-Api-Key: YOUR_API_KEY'
Response
{
"success": true,
"message": "Thành công!",
"data": {
"items": [
{
"id": "MG0123",
"name": "Nguyễn Văn An",
"phone": "0901234567",
"branch": "Chi nhánh Hồ Chí Minh",
"avatar": "https://img.saigonfutures.com/uploads/ab12-portrait.jpg",
"age": 32,
"jobTitle": "Chuyên viên tư vấn đầu tư hàng hóa cấp cao",
"intro": "Xin chào Quý Nhà đầu tư,\n\nTôi là…",
"philosophy": "Kỷ luật - Quản trị rủi ro - Tăng trưởng bền vững",
"styles": [
{ "icon": "shield-check", "title": "Kỷ luật", "subtitle": "Đặt nguyên tắc lên hàng đầu" }
],
"services": [
"Xây dựng kế hoạch đầu tư phù hợp với mục tiêu và khẩu vị rủi ro của khách hàng."
],
"highlights": { "years_experience": "8+", "clients_served": "650+" },
"experience": { "aum": "Đến 100 tỷ", "awards": ["Top 1 - Bảng vàng 2025"] },
"stats": { "month": "08-2026", "volume": 1284, "clients": 37 },
"publishedAt": "2026-08-12 14:05:22"
}
],
"paging": { "page": 1, "size": 20, "total": 57, "totalPages": 3 },
"q": "",
"sort": "volume",
"order": "desc",
"statsMonth": "08-2026"
},
"svr": "srv-01"
}
highlights / experience
không nằm ở đây — lấy từ cmd=expert_profile_fields
(mục 2.1) và cache lại, vì bảng nhãn dùng chung cho mọi hồ sơ.
Thử ngay — ?cmd=expert_profiles
3 · Chi tiết một chuyên gia
?cmd=expert_profile&id={mã nhân sự}
Trả về hồ sơ của đúng một chuyên gia. Nội dung giống hoàn toàn một phần tử
trong items của API danh sách (mục 2.2) — API này chỉ tiện khi đối tác đã có mã nhân sự (ví dụ mã môi
giới phụ trách một khách hàng) và không muốn tải cả danh sách.
Tham số truy vấn
| Tham số | Kiểu | Bắt buộc | Mô tả |
|---|---|---|---|
| id | string | Có | Mã nhân sự, đúng giá trị id ở API danh sách. Phải là mã chính — mã phụ không có hồ sơ riêng. |
Request
curl 'https://a.sfi.com.vn/ekyc/ex_api?cmd=expert_profile&id=MG0123' \
-H 'X-Api-Key: YOUR_API_KEY'
Response
{
"success": true,
"message": "Thành công!",
"data": {
"expert": { "...": "cùng cấu trúc với một phần tử items ở mục 2.2" },
"statsMonth": "08-2026"
},
"svr": "srv-01"
}
Thử ngay — ?cmd=expert_profile
4 · Sắp xếp theo số liệu tháng
Hai tiêu chí sắp xếp đều là số liệu giao dịch của tháng hiện tại (tháng ghi ở
statsMonth, định dạng MM-YYYY), tính lại ở mỗi lần gọi:
sort | Ý nghĩa | Trường tương ứng |
|---|---|---|
| volume | Khối lượng giao dịch lớn nhất — tổng số lot của mọi giao dịch gắn mã nhân sự trong tháng | stats.volume |
| clients | Nhiều khách hàng nhất — số tài khoản giao dịch khác nhau gắn mã nhân sự trong tháng | stats.clients |
- Số liệu chỉ tính tháng hiện tại, không phải luỹ kế — đầu tháng gần như mọi chuyên gia sẽ về 0.
- Nhân sự chưa có giao dịch trong tháng vẫn xuất hiện trong danh sách với
volume = 0,clients = 0. API không loại họ ra. - Một nhân sự có thể có nhiều mã (mã phụ, mã cũ); SFI đã gộp hết về mã chính, và một khách hàng
giao dịch dưới hai mã của cùng nhân sự chỉ được tính một lần trong
clients. - Con số phản ánh hoạt động kinh doanh nội bộ của SFI. Nếu dùng để xếp hạng công khai, đối tác nên thống nhất trước với SFI về cách diễn giải.
5 · Trường dữ liệu chuyên gia
| Trường | Kiểu | Mô tả |
|---|---|---|
| id | string | Mã nhân sự (dùng cho API chi tiết) |
| name | string | Họ tên |
| phone | string | Số điện thoại liên hệ |
| branch | string | Chi nhánh |
| avatar | string (URL) | Ảnh đại diện, URL đầy đủ và không hết hạn. Rỗng nếu chưa có ảnh |
| age | int / null | Tuổi. SFI không trả ngày sinh; null khi nhân sự chưa điền |
| jobTitle | string | Chức danh nghề nghiệp |
| intro | string | Giới thiệu bản thân, nhiều dòng (\n), thuần văn bản — không phải HTML |
| philosophy | string | Triết lý đầu tư, một dòng ngắn |
| styles | array | Triết lý & phong cách, tối đa 4 mục: icon, title, subtitle |
| styles[].icon | string | Mã icon Lucide dạng kebab-case, ví dụ shield-check. Không phải emoji, không phải URL ảnh |
| services | array<string> | Dịch vụ cung cấp, tối đa 10 dòng |
| highlights | object | Thông tin nổi bật — khoá động, tra nhãn ở HIGHLIGHT của mục 2.1 |
| experience | object | Hồ sơ kinh nghiệm — khoá động, tra nhãn ở EXPERIENCE của mục 2.1 |
| stats.month | string MM-YYYY | Tháng của số liệu giao dịch |
| stats.volume | int | Tổng số lot trong tháng |
| stats.clients | int | Số tài khoản giao dịch khác nhau trong tháng |
| publishedAt | string Y-m-d H:i:s | Lần hồ sơ chính thức thay đổi gần nhất — dùng để cache |
string, riêng khoá có
inputType: "MULTILINE" (ví dụ Vinh danh - Giải thưởng) là
array<string>. Luôn kiểm kiểu theo inputType ở
mục 2.1 thay vì giả định.
Mã lỗi riêng của nhóm
| HTTP | message | Nguyên nhân |
|---|---|---|
| 404 | Không tìm thấy hồ sơ chuyên gia của mã nhân sự này. | Mã không tồn tại, là mã phụ, nhân sự đã ngừng hoạt động, hoặc hồ sơ chưa duyệt / đang bị ẩn |
| 200 | Thiếu tham số id (mã nhân sự). | Gọi cmd=expert_profile mà không truyền id |
| 200 | Tham số sort không hợp lệ, chỉ nhận: volume, clients | sort ngoài hai giá trị cho phép |
Khuyến nghị tích hợp
- Gọi API từ máy chủ của đối tác, không gọi trực tiếp từ trình duyệt / app để tránh lộ API Key.
- Luôn kiểm tra
successtrước khi đọcdata; ghi lạisvrkhi cần báo lỗi cho SFI. - Cache dữ liệu ít thay đổi (ví dụ
news_products) và đặt TTL tối thiểu 1–5 phút cho dữ liệu danh sách. - Đồng bộ tăng dần bằng cách lưu
idlớn nhất đã lấy và dừng khi gặp lạiidđó. - Tôn trọng giới hạn phân trang (
size≤ 100) thay vì kéo toàn bộ kho dữ liệu trong một lần. - Đặt timeout hợp lý (5–10s) và retry có backoff; nếu domain chính chậm > 5s, chuyển sang domain dự phòng.
Ví dụ code
Hàm gọi chung dưới đây dùng được cho mọi endpoint công khai của /ekyc/ex_api — chỉ thay
cmd và tham số.
JavaScript (server-side / Node.js)
const BASE = 'https://a.sfi.com.vn/ekyc/ex_api';
const HEADERS = { 'X-Api-Key': process.env.SFI_API_KEY };
async function call(params) {
const qs = new URLSearchParams(params);
const res = await fetch(`${BASE}?${qs}`, { headers: HEADERS });
const body = await res.json();
if (!body.success) throw new Error(body.message);
return body.data;
}
// Bảng nhãn khoá động — gọi một lần rồi cache
const fields = await call({ cmd: 'expert_profile_fields' });
// Danh sách + chi tiết hồ sơ
const experts = await call({ cmd: 'expert_profiles', page: 1, size: 20, sort: 'volume', order: 'desc' });
const profile = await call({ cmd: 'expert_profile', id: experts.items[0].id });
PHP
function sfiCall(array $params) {
$url = 'https://a.sfi.com.vn/ekyc/ex_api?' . http_build_query($params);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-Api-Key: ' . getenv('SFI_API_KEY')],
CURLOPT_TIMEOUT => 10,
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);
if (empty($body['success'])) {
throw new RuntimeException($body['message'] ?? 'SFI API error');
}
return $body['data'];
}
$experts = sfiCall(['cmd' => 'expert_profiles', 'page' => 1, 'size' => 20, 'sort' => 'volume']);