Xác thực API
XCaphe API sử dụng JWT Bearer token theo chuẩn RFC 7519. Token được cấp sau khi đăng nhập thành công và phải kèm vào header Authorization của mọi request yêu cầu xác thực.
Base URL:
Authentication Flow

Đăng nhập nhân viên chi nhánh
Dùng cho staff/manager của từng chi nhánh (app.xcaphe.vn).
POST /auth/login
Content-Type: application/jsonRequest body:
{
"phone": "0912345678",
"pin": "1234",
"orgSlug": "the-brew"
}| Field | Kiểu | Bắt buộc | Mô tả |
|---|---|---|---|
phone | string | ✓ | Số điện thoại nhân viên |
pin | string | ✓ | PIN 4–6 chữ số |
orgSlug | string | ✓ | Slug tổ chức (xem Cài đặt → Tổ chức) |
Response 200 OK:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"staff": {
"id": "uuid",
"name": "Nguyễn Văn A",
"role": "manager",
"branchId": "uuid-or-null"
}
}Lỗi thường gặp:
| HTTP | Mô tả |
|---|---|
401 | Số điện thoại hoặc PIN không đúng |
404 | Không tìm thấy tổ chức với slug này |
400 | Thiếu trường bắt buộc |
Đăng nhập nhân viên chuỗi
Dùng cho tài khoản quản lý chuỗi (chain_owner, chain_ops, chain_finance, ...).
POST /chain/auth/login
Content-Type: application/jsonRequest body (giống /auth/login):
{
"phone": "0987654321",
"pin": "5678",
"orgSlug": "the-brew"
}Response 200 OK:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"staff": {
"id": "uuid",
"fullName": "Trần Thị B",
"phone": "0987654321",
"role": "chain_finance",
"orgId": "uuid",
"orgName": "The Brew",
"orgSlug": "the-brew"
}
}Endpoint /chain/auth/login chỉ chấp nhận các role cấp chuỗi: chain_owner, chain_ops, chain_finance, chain_purchase, chain_warehouse, chain_hr, chain_marketing. Nhân viên chi nhánh thông thường phải dùng /auth/login.
Sử dụng token
Thêm token vào header Authorization của mọi request:
GET /orders
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Token chứa các claims:
{
"sub": "staff-uuid",
"org_id": "org-uuid",
"branch_id": "branch-uuid-or-null",
"role": "manager",
"iss": "xcaphe-api",
"aud": "xcaphe-dashboard",
"iat": 1740000000,
"exp": 1740028800
}Thời hạn token & đăng nhập lại
Token staff có hiệu lực 8 giờ kể từ lúc đăng nhập. Khi hết hạn, API trả về 401 Unauthorized.
HTTP/1.1 401 Unauthorized
{
"message": "Token không hợp lệ hoặc đã hết hạn."
}Xử lý phía client:
- Khi nhận
401, redirect người dùng về trang đăng nhập - Sau khi đăng nhập lại, lưu token mới và thực hiện lại request gốc
Chính sách 8 giờ áp dụng để bảo vệ trong trường hợp thiết bị bị mất hoặc PIN bị lộ. Nhân viên cần đăng nhập lại mỗi ca làm việc — phù hợp với quy trình check-in ca sáng/tối.
Không lưu token trong localStorage nếu bạn xây dựng ứng dụng nhúng public. Dùng httpOnly cookie hoặc secure storage của thiết bị.
Lấy thông tin người dùng hiện tại
GET /auth/me
Authorization: Bearer <token>Response 200 OK:
{
"id": "uuid",
"name": "Nguyễn Văn A",
"role": "manager",
"orgId": "uuid",
"branchId": "uuid"
}Headers bổ sung
| Header | Mô tả |
|---|---|
X-Org-ID | ID tổ chức (tùy chọn, override từ JWT claim org_id) |
X-Branch-ID | ID chi nhánh (tùy chọn, override từ JWT claim branch_id) |
X-Session-ID | Session ID của khách hàng (dùng cho customer-facing API) |
Rate limiting
API có rate limit theo từng nhóm endpoint:
| Nhóm | Giới hạn |
|---|---|
/auth/login, /chain/auth/login | 10 lần/phút per IP |
Đọc dữ liệu (GET) | 300 lần/phút per token |
Ghi dữ liệu (POST, PATCH) | 100 lần/phút per token |
Khi vượt giới hạn:
HTTP 429 Too Many Requests
Retry-After: 30
{
"message": "Quá nhiều yêu cầu. Vui lòng thử lại sau."
}Mã lỗi xác thực
| Mã HTTP | Message | Nguyên nhân |
|---|---|---|
400 | Thiếu thông tin đăng nhập | Thiếu phone, pin hoặc orgSlug |
401 | Số điện thoại hoặc PIN không đúng | Sai thông tin đăng nhập |
401 | Phiên đăng nhập không hợp lệ | Tài khoản bị vô hiệu hoá |
401 | Token không hợp lệ hoặc đã hết hạn | Token hết hạn sau 8 giờ |
403 | Bạn không có quyền thực hiện hành động này | Role không đủ quyền |
404 | Không tìm thấy tổ chức | orgSlug không tồn tại |