🌐 Ngôn ngữ: 🇻🇳 Tiếng Việt (hiện tại) · 🇬🇧 English · 🇯🇵 日本語
Quy ước chung của REST API v2
Giới thiệu
Trang này gom các quy tắc dùng chung cho mọi endpoint v2: hình dạng phản hồi, phân trang, lọc và sắp xếp, chọn trường (fields) và
lấy kèm (include), lưu tạm với 304, bảng mã lỗi, mã yêu cầu X-Request-Id, chính sách ngừng hỗ trợ và cách sinh code client từ
openapi.json. Nắm các quy tắc này một lần, bạn đọc được mọi trang Tham chiếu mà không phải học lại từng endpoint.
Định dạng phản hồi, tham số danh sách & mã lỗi
Mục này giúp ứng dụng đọc đúng kết quả, lọc/sắp xếp danh sách và xử lý lỗi theo một cách duy nhất cho mọi endpoint.
Phản hồi thành công
- Mọi phản hồi đều là JSON, kể cả khi ứng dụng không gửi header
Accept: application/json.
ℹ️ Có từ: gp247/core 3.6.0 — trước bản này, gọi endpoint cần đăng nhập mà thiếu token và không gửi
Accept: application/json(mặc định của curl, Postman, nhiều SDK) nhận HTTP500thay cho401 unauthenticated.
| Trường hợp | Dạng phản hồi |
|---|---|
| Một bản ghi | {"data": {...}} |
| Danh sách | {"data": [...], "meta": {...}, "links": {...}} — meta có current_page, per_page, total, last_page; links có first, last, prev, next |
| Tên, mô tả sản phẩm/danh mục/trang | name, description… theo ngôn ngữ chọn bằng lang |
| Giá | price và price_final (giá khách trả trên cửa hàng, đã tính khuyến mãi) |
Tham số cho mọi endpoint danh sách
| Tham số | Ý nghĩa | Ví dụ |
|---|---|---|
filter[<tên>] |
Lọc theo trường được phép của từng loại dữ liệu (xem bảng dưới) | filter[brand_id]=5 |
sort |
Sắp xếp tăng dần; thêm - phía trước để giảm dần |
sort=-price |
q |
Tìm kiếm (tên, SKU, email… tùy loại dữ liệu) | q=ao-thun |
lang |
Ngôn ngữ của tên/mô tả; mã không hợp lệ → ngôn ngữ mặc định của site | lang=vi |
page[number], page[size] |
Trang và số bản ghi mỗi trang (mặc định 20, tối đa 100) | page[size]=50 |
Tên lọc hoặc trường sắp xếp không có trong danh sách → HTTP 422 (validation_failed), phản hồi nêu các
tên được phép.
| Dữ liệu | filter[...] |
sort |
|---|---|---|
| Sản phẩm | category_id, brand_id, kind, product_type, price_min, price_max (+ admin: status, approve, supplier_id) |
price, created_at, sort, sku |
| Danh mục | parent, top (admin: parent, status) |
sort, created_at |
| Thương hiệu, nhà cung cấp | (admin: status) |
sort, name |
| Khách hàng (admin) | status, group |
created_at, email |
| Đơn hàng (admin) | status, payment_status, shipping_status, customer_id |
created_at, total |
| Đơn hàng của khách | status |
created_at, total |
| Banner | type |
sort, created_at |
| Trang nội dung | — | created_at |
Chọn trường (fields) và lấy kèm (include)
ℹ️ Có từ: gp247/core 3.8.0, gp247/shop 3.7.0, gp247/front 3.5.0
Màn hình của ứng dụng thường chỉ cần vài trường. Gửi fields[<loại>] để nhận đúng các trường đó — phản hồi nhẹ hơn và máy chủ
không phải đọc dữ liệu nặng bạn không dùng (ví dụ biến thể sản phẩm). Gửi include để lấy kèm dữ liệu liên quan trong cùng một
lần gọi, thay vì gọi thêm cho từng bản ghi.
| Tham số | Ý nghĩa | Ví dụ |
|---|---|---|
fields[<loại>] |
Chỉ trả các trường liệt kê (luôn kèm id). <loại>: product, category, brand, supplier, customer, order, banner, page, hoặc loại của dữ liệu lấy kèm |
fields[product]=name,image,price_final |
include |
Lấy kèm dữ liệu liên quan — một cấp, tối đa 3 mỗi lần gọi (GP247_API_MAX_INCLUDE) |
include=brand,categories |
| Dữ liệu | include được phép |
Loại để chọn trường của dữ liệu kèm |
|---|---|---|
| Sản phẩm (cửa hàng) | images, brand (chỉ thương hiệu đang bật), categories (chỉ danh mục đang hiển thị) |
brand, category |
| Sản phẩm (quản trị) | images, brand, categories |
brand, category |
| Đơn hàng (quản trị) | transactions (sổ thanh toán), histories (lịch sử xử lý, văn bản thuần không HTML) |
transaction, history |
| Dữ liệu khác | — | — |
curl "https://your-domain.com/api/v2/front/product/list?fields[product]=name,image,price_final,brand&include=brand&fields[brand]=name"
- Không gửi
fields/include→ phản hồi y hệt như trước. - Loại, tên trường hay
includekhông có trong danh sách,includelồng (brand.products) hoặc quá số cho phép →422(validation_failed), phản hồi nêu các tên hợp lệ. - Chọn trường không mở thêm trường bị ẩn: API công khai vẫn không trả giá vốn hay số tồn kho.
- Dùng được cả trong chế độ đồng bộ
updated_since(mục dưới).
Lưu tạm và 304 Not Modified
ℹ️ Có từ: gp247/core 3.8.0, gp247/shop 3.7.0, gp247/front 3.5.0
Mỗi phản hồi GET thành công có header ETag — "dấu vân tay" của nội dung. Ứng dụng lưu nó cùng dữ liệu; lần sau gửi
If-None-Match: <ETag>. Dữ liệu không đổi thì API trả 304 không có nội dung, ứng dụng dùng bản đã lưu.
sequenceDiagram
participant App as Ứng dụng
participant API
App->>API: GET product/detail/12
API-->>App: 200 + ETag: W/"a1b2…"
Note over App: lưu dữ liệu + ETag
App->>API: GET product/detail/12<br/>If-None-Match: W/"a1b2…"
alt không đổi
API-->>App: 304 (không có nội dung)
else đã đổi (giá, tồn, khuyến mãi…)
API-->>App: 200 + ETag mới
end
ETagtính từ đúng nội dung trả về, nên mọi thay đổi ứng dụng nhìn thấy — kể cả khuyến mãi vừa bắt đầu — đều choETagmới. API không dùngLast-Modified.304tiết kiệm đường truyền cho khách; máy chủ vẫn đọc dữ liệu để so.- Sản phẩm, danh mục, thương hiệu, banner, trang nội dung gọi không token có
Cache-Control: public, max-age=<N>kèmVary: Authorization, nên trình duyệt hoặc CDN được giữ bản sao.Nmặc định0(luôn hỏi lại máy chủ, nhận304khi không đổi); chủ site tăng bằngGP247_API_PUBLIC_MAX_AGE(giây) — đổi lại, giá mới có thể hiện chậm tối đaNgiây. - Gọi có token, giỏ hàng, đặt đơn, tài khoản khách và API quản trị không bao giờ được lưu công khai.
Mã lỗi
ℹ️ Có từ: gp247/core 3.2.3 — mọi lỗi có cùng một dạng và mã HTTP đúng nghĩa:
{ "error": 1, "msg": "Not found", "code": "not_found" }
| HTTP | code |
Khi nào |
|---|---|---|
401 |
unauthenticated |
Thiếu/sai token, token hết hạn, tài khoản bị tắt/khoá, sai mật khẩu khi login |
401 |
api_connection_invalid |
API Connection đang bật mà thiếu/sai cặp apiconnection/apikey |
403 |
forbidden |
Đã đăng nhập nhưng không có quyền (Phân quyền và phạm vi dữ liệu của API Core) hoặc token sai loại |
404 |
not_found |
Bản ghi không tồn tại hoặc bạn không được xem; đường dẫn API không tồn tại |
404 |
api_disabled |
Nhóm API này đang tắt trên màn quản lý API của site (Bật/tắt API) — từ gp247/core 3.3.1 |
401 |
refresh_token_invalid |
Refresh token sai, hết hạn hoặc phiên đã bị đăng xuất (Refresh token — giữ đăng nhập mà token ngắn hạn) — từ gp247/core 3.6.0 |
401 |
refresh_token_reused |
Refresh token đã dùng rồi bị gửi lại: phiên bị đăng xuất để an toàn — đăng nhập lại (Refresh token — giữ đăng nhập mà token ngắn hạn) |
409 |
refresh_in_progress |
Refresh token vừa được dùng vài giây trước — dùng cặp token mới đã nhận (Refresh token — giữ đăng nhập mà token ngắn hạn) |
409 |
event_log_disabled |
Nhật ký sự kiện đang tắt trên màn quản lý API (Bật/tắt API, 6) — từ gp247/core 3.7.0 |
410 |
cursor_expired |
Con trỏ after cũ hơn phần nhật ký sự kiện đã dọn — đồng bộ lại bằng updated_since, rồi đọc sự kiện từ đầu (Định dạng phản hồi, tham số danh sách & mã lỗi) |
400 |
idempotency_key_required |
Header Idempotency-Key sai dạng (cần 8–255 ký tự in được), hoặc thiếu ở endpoint bắt buộc khoá (đặt đơn — Đặt đơn; ghi tồn kho — Luồng làm việc API Core (Admin)) |
409 |
idempotency_key_reused |
Idempotency-Key đã dùng cho một yêu cầu khác — dùng khoá mới (Luồng làm việc API Core (Admin), 10.2) |
409 |
idempotency_in_progress |
Yêu cầu cùng Idempotency-Key vẫn đang được xử lý — chờ rồi gửi lại (Luồng làm việc API Core (Admin)) — từ gp247/core 3.7.0 |
503 |
idempotency_unavailable |
Site chưa chạy php artisan gp247:update nên chưa nhận lệnh ghi quản trị có Idempotency-Key (Luồng làm việc API Core (Admin)) — từ gp247/core 3.7.0 |
401 |
challenge_required |
Tài khoản cần thêm bước xác thực (mã OTP…) do plugin cung cấp; thân có khoá challenge (Xác thực hai lớp (MFA) qua plugin) |
401 |
challenge_invalid |
Vé xác thực sai/hết hạn hoặc mã xác thực sai (Xác thực hai lớp (MFA) qua plugin) |
422 |
validation_failed |
Dữ liệu gửi lên không hợp lệ — xem thêm khoá errors theo từng trường |
422 |
stock_would_be_negative |
Lệnh xuất kho làm tồn kho xuống dưới 0 — không thay đổi gì (Luồng làm việc API Core (Admin)) — từ gp247/shop 3.6.0 |
422 |
stock_managed_by_components |
Sản phẩm dạng build (combo) lấy tồn kho từ các thành phần, không ghi tồn kho trực tiếp được (Luồng làm việc API Core (Admin)) — từ gp247/shop 3.6.0 |
429 |
too_many_attempts |
Gọi quá nhiều lần — chờ theo header Retry-After |
405 |
method_not_allowed |
Sai phương thức HTTP cho đường dẫn (ví dụ GET thay cho POST) |
| khác | http_error |
Lỗi HTTP khác — đọc msg |
500 |
server_error |
Lỗi máy chủ — nội dung chi tiết chỉ hiện khi site bật chế độ debug |
Giỏ hàng và đặt đơn có thêm mã lỗi riêng (Giỏ hàng & đặt đơn qua API); lệnh ghi đơn hàng bị từ chối trả 409 kèm mã lý do; mỗi dòng của stock/batch có mã kết quả riêng (Luồng làm việc API Core (Admin)). Hãy kiểm tra mã HTTP trước rồi mới đọc code để xử lý từng
trường hợp; msg là thông điệp để hiển thị hoặc ghi log.
Mã yêu cầu X-Request-Id
ℹ️ Có từ: gp247/core 3.4.0
Mọi phản hồi của API GP247 — kể cả phản hồi lỗi — có header X-Request-Id. Khi báo lỗi cho quản trị viên site,
hãy gửi kèm mã này: họ dùng nó để tìm đúng dòng trong nhật ký hệ thống.
- Ứng dụng có thể tự gửi
X-Request-Id(chỉ gồm chữ, số,.,_,-; dài 8–128 ký tự): site dùng lại đúng mã đó, tiện nối nhật ký của ứng dụng với nhật ký của site. - Thiếu hoặc sai định dạng → site tự sinh mã mới (UUID).
- Đường dẫn không khớp endpoint nào (404 trước khi vào API) có thể không có header này.
Chính sách ngừng hỗ trợ & sinh client từ OpenAPI
Ngừng hỗ trợ một phần API
ℹ️ Có từ: gp247/core 3.8.0
GP247 không gỡ endpoint hay tham số đang được dùng mà không báo trước:
- Báo trước ít nhất 12 tháng và ít nhất 2 bản minor trước khi gỡ hẳn.
- Trong thời gian đó, mọi phản hồi của phần sắp ngừng (kể cả lỗi) có các header sau:
| Header | Ý nghĩa | Ví dụ |
|---|---|---|
Deprecation |
Thời điểm bắt đầu ngừng hỗ trợ (RFC 9745, dạng @<unix time>) |
Deprecation: @1793491200 |
Sunset |
Ngày ngừng hẳn (RFC 8594) | Sunset: Fri, 31 Dec 2027 00:00:00 GMT |
Link |
Hướng dẫn chuyển đổi | Link: <https://gp247.net/vi/docs/api/about-api-gp247.html#…>; rel="deprecation" |
- Mọi thay đổi theo phiên bản ghi ở mục Lịch sử thay đổi cuối trang.
- API v1 đã ngưng phát triển nhưng chưa có ngày ngừng hẳn;
GET logoutcủa v1 vẫn trảDeprecation: truenhư trước.
Ứng dụng nên ghi log mỗi khi gặp header Deprecation để kịp chuyển sang cách mới.
Sinh client TypeScript từ openapi.json
GP247 không phát hành SDK riêng — openapi.json đủ để tự sinh kiểu dữ liệu và client cho ứng dụng của bạn.
Tải file về rồi chạy, ví dụ với openapi-typescript:
npx openapi-typescript ./openapi.json -o gp247-api.d.ts
Ngôn ngữ khác (Kotlin, Swift, Dart…) dùng OpenAPI Generator với cùng file. Mỗi khi nâng cấp
gp247/core, gp247/shop, gp247/front, hãy tải lại openapi.json và sinh lại client.
Hỏi & Đáp (Q&A)
Câu 1: Ứng dụng nên xử lý lỗi dựa vào gì?
→ Dựa vào khoá code trong thân lỗi (ví dụ not_found, validation_failed), không dựa vào câu chữ trong msg. Ý nghĩa từng mã
ở Xử lý sự cố.
Câu 2: Danh sách có giới hạn số dòng mỗi trang không?
→ Có: mặc định 20, tối đa 100 dòng mỗi trang (page[size]). Đọc tiếp bằng địa chỉ trong links.next.
📅 Cập nhật lần cuối: 2026-11-03 · ✍️ Tác giả (Author): GP247