Hệ thống bên ngoài — máy tính tiền, phần mềm kế toán hoặc khách sạn — có thể lấy thực đơn, đọc đơn và hóa đơn của quán, và gửi cho chúng tôi đơn mà chính nó đã nhận. Có một API riêng cho việc này: nó hoạt động nhân danh quán và không cần tài khoản nhân viên.
Địa chỉ là địa chỉ ứng dụng Qreaty cộng với /api/external/v1. Trên bản chính thức đó là https://qreaty.com/api/external/v1; địa chỉ có sẵn được hiển thị trong mục «Truy cập qua API» (cách mở) — hãy sao chép từ đó. Mọi yêu cầu bên dưới đều tính từ địa chỉ này: GET /menu/items nghĩa là GET https://qreaty.com/api/external/v1/menu/items.
Phản hồi là JSON theo chuẩn JSON:API (data, attributes), nội dung yêu cầu là JSON. Token gửi trong header Authorization: Bearer <token>; nên luôn kèm Accept: application/json.
Ngôn ngữ. Tên và mô tả trả về bằng ngôn ngữ bạn yêu cầu: tham số ?locale=vi (mã ngôn ngữ: ru, en, vi…) hoặc header Accept-Language: vi. Có những ngôn ngữ nào, API tự cho biết: mỗi phản hồi của GET /menu/items và GET /menu/modifiers có meta.menus — với mỗi thực đơn là danh sách locales (đã dịch sang những ngôn ngữ nào) và source_locale — ngôn ngữ bản gốc, ngôn ngữ chủ quán đã nhập thực đơn. Nếu chưa có bản dịch cho ngôn ngữ được yêu cầu (hoặc không yêu cầu), trả về bản gốc.
{primary} Token thuộc về quán, không thuộc về một người: nhân viên đã tạo token nghỉ việc thì token vẫn hoạt động cho đến khi bạn thu hồi. Mỗi token chỉ thấy quán của nó.
API làm được gì:
| Việc | Yêu cầu | Quyền của token |
|---|---|---|
| Tất cả món | GET /menu/items |
menu:read |
| Nhóm tùy chọn và các tùy chọn | GET /menu/modifiers |
menu:read |
Bàn (id, number, name, zone) |
GET /tables |
orders:read |
| Đơn | GET /orders, GET /orders/{id} |
orders:read |
| Hóa đơn | GET /bills, GET /bills/{id} |
orders:read |
| Nhận một đơn | POST /orders |
orders:write |
Chủ quán hoặc người có quyền thay đổi cài đặt của quán tạo token.
{warning} Token giống như mật khẩu: ai có nó đều hành động nhân danh quán trong phạm vi quyền đã cấp. Đừng gửi nó trong chat hay lưu trong kho mã. Nếu token có thể đã bị lộ, hãy thu hồi ở cùng mục và tạo token mới — token đã thu hồi ngừng hoạt động ngay.
Một token cho một hệ thống được kết nối. Nhờ vậy biết ai gọi và khi nào, và thu hồi một hệ thống không làm hỏng các hệ thống khác.
Hệ thống bên ngoài gọi các mục bằng SKU — mã nằm trong danh mục của nó. Mỗi món và mỗi tùy chọn đều có SKU, không bao giờ để trống:
QR-D<số> (món) hoặc QR-M<số> (tùy chọn) — duy nhất và không đổi.. _ - /.Đơn ghi nhớ SKU cùng với tên: nếu ngày mai bạn đổi mã món, hóa đơn hôm qua vẫn giữ mã mà món đã được bán.
{primary} Nếu hai món trong một thực đơn trùng mã (có thể xảy ra với dữ liệu cũ liên kết thủ công), API sẽ báo:
GET /menu/itemsvà/menu/modifierscómeta.duplicate_skus. Cho đến khi sửa bản trùng, không thể đặt SKU đó — yêu cầu sẽ nhận lỗi.
GET /menu/items trả về các món của thực đơn đang hoạt động — thực đơn mà khách và quầy dùng để gọi món — 50 món mỗi trang (?per_page= tối đa 200, ?page=). Có thể yêu cầu thực đơn khác một cách rõ ràng: filter[menu]=<id>; id thực đơn và ngôn ngữ của chúng nằm trong meta.menus.
Khóa của món là SKU: nó cũng nằm ở id và được gửi lại trong đơn. Một món có: sku, name, description, price_type (fixed, from, range, variable — theo yêu cầu) cùng price_value / price_min / price_max / price_unit, currency, kind (food, drink, alcohol, other), section, available — có gọi được ngay bây giờ không (không bị ẩn, không hết hàng, danh mục đang bật), sold_out — món có nằm trong danh sách hết hàng không, và modifier_group_ids — các nhóm tùy chọn gắn với món.
Bộ lọc: filter[available]=1, filter[section], filter[sku], filter[menu], filter[updated_since]=2026-10-14T00:00:00Z — tiện cho việc đối chiếu định kỳ: chỉ lấy phần đã thay đổi.
GET /menu/modifiers — các nhóm tùy chọn của thực đơn đang hoạt động cùng các tùy chọn. Mỗi tùy chọn gọi bằng SKU riêng (options[].sku) và có name, price, is_default, max_qty cùng prices — bảng giá theo kích cỡ (driver_option_sku là tùy chọn kích cỡ, price là giá khi chọn nó). Nhóm có name, pricing_mode (replace — giá tùy chọn thay giá món, như kích cỡ; add — cộng thêm, như topping), required, selection_min / selection_max — được chọn bao nhiêu, item_skus — gắn với những món nào, và parent_option_sku — khi nhóm mở ra dưới một tùy chọn của nhóm khác. id của nhóm là tham chiếu của nó trong modifier_group_ids của món.
curl -s -g "https://qreaty.com/api/external/v1/menu/items?filter[available]=1&locale=vi" \
-H "Authorization: Bearer $TOKEN" -H "Accept-Language: vi"
{primary} Tất cả yêu cầu bên dưới đã được gom thành bộ sưu tập Postman làm sẵn: tải về. Nhập tệp, điền token vào biến
tokencủa bộ sưu tập — là gửi được; SKU và số bàn tự điền.
Địa chỉ có bộ lọc được ghép từ các phần: đường-dẫn?filter[tên]=giá-trị&filter[tên2]=giá-trị2. Dưới đây là các dòng làm sẵn, dùng nguyên văn. Với curl thêm -g để dấu ngoặc vuông không bị hiểu là mẫu; trong Postman gõ đúng như ở đây. Dấu + trong giờ viết là %2B (+07:00 → %2B07:00), nếu không nó sẽ thành khoảng trắng.
| Cần gì | Yêu cầu |
|---|---|
| Tất cả món bằng tiếng Việt, 200 món mỗi trang | GET /menu/items?locale=vi&per_page=200 |
| Chỉ các món hiện có thể gọi | GET /menu/items?filter[available]=1 |
| Món theo SKU | GET /menu/items?filter[sku]=PHO-1 |
Món của một thực đơn (id thực đơn nằm trong meta.menus) |
GET /menu/items?filter[menu]=12 |
| Thực đơn đã đổi gì kể từ một thời điểm | GET /menu/items?filter[updated_since]=2026-10-14T00:00:00Z |
| Nhóm tùy chọn của một thực đơn | GET /menu/modifiers?filter[menu]=12 |
GET /orders — các đơn (lượt gọi của hóa đơn), mới nhất ở trên. Mỗi đơn kèm các dòng, tùy chọn đã chọn, trạng thái, bàn, số và thời gian. Dòng gọi món bằng SKU (lines[].sku), còn tùy chọn lồng nhau bằng lines[].modifiers[].sku.
| Bộ lọc | Tác dụng |
|---|---|
filter[status] |
pending, confirmed, completed, rejected, cancelled; nhiều giá trị — cách nhau bằng dấu phẩy |
filter[source] |
guest (khách qua QR), staff (nhân viên), external (nhận qua API) |
filter[table] |
số bàn |
filter[bill] |
id hóa đơn |
filter[external_id] |
id đơn trong hệ thống của bạn |
filter[placed_from], filter[placed_to] |
khoảng thời gian nhận đơn (từ — gồm, đến — không gồm) |
filter[updated_since] |
mọi thứ thay đổi từ thời điểm đã cho |
GET /bills — hóa đơn của bàn: số tiền, thuế, hình thức thanh toán (tender), số phòng, thời điểm mở và đóng, và danh sách id đơn. Với ?embed=orders các đơn được trả đầy đủ. Bộ lọc: filter[status]=open|closed, filter[tender] (cash, transfer, card, ewallet, room_charge, voucher, none — chưa ghi thanh toán), filter[table], filter[number], filter[room_number], filter[opened_from|opened_to], filter[closed_from|closed_to], filter[updated_since]. Sắp xếp: ?sort=-closed_at.
Thời gian trong yêu cầu theo ISO 8601 (2026-10-14T09:00:00+07:00); phản hồi cũng vậy.
{primary} Để không bỏ sót thay đổi, hãy lưu thời điểm lần lấy thành công gần nhất và lần sau yêu cầu
filter[updated_since]lùi lại một chút — bản ghi lặp vẫn nhận ra qua id.
Cùng quy tắc (-g trong curl, %2B thay cho +). Giờ theo múi giờ Việt Nam (+07:00).
| Cần gì | Yêu cầu |
|---|---|
| Đơn đang chờ xác nhận | GET /orders?filter[status]=pending |
| Đã xác nhận và đã hoàn tất | GET /orders?filter[status]=confirmed,completed |
| Đơn của ngày 14 tháng 10 | GET /orders?filter[placed_from]=2026-10-14T00:00:00%2B07:00&filter[placed_to]=2026-10-15T00:00:00%2B07:00 |
| Chỉ đơn đến qua API | GET /orders?filter[source]=external |
| Đơn đã xác nhận của bàn 5 | GET /orders?filter[table]=6512&filter[status]=confirmed |
| Mọi thứ thay đổi kể từ lần đối chiếu gần nhất, cũ trước | GET /orders?filter[updated_since]=2026-10-14T09:00:00Z&sort=updated_at |
| Đơn của chúng tôi theo số trong hệ thống của bạn | GET /orders?filter[external_id]=POS-100234 |
| Hóa đơn đang mở | GET /bills?filter[status]=open |
| Hóa đơn đã đóng ngày 14 tháng 10, kèm đơn và các dòng | GET /bills?filter[status]=closed&filter[closed_from]=2026-10-14T00:00:00%2B07:00&filter[closed_to]=2026-10-15T00:00:00%2B07:00&embed=orders |
| Hóa đơn ghi vào phòng khách sạn | GET /bills?filter[status]=closed&filter[tender]=room_charge |
| Hóa đơn của một phòng | GET /bills?filter[room_number]=412 |
| Hóa đơn đã đóng chưa ghi thanh toán | GET /bills?filter[status]=closed&filter[tender]=none |
| Trang tiếp theo | thêm &page=2 vào bất kỳ yêu cầu nào |
POST /orders — hệ thống bên ngoài chuyển đơn mà nó đã nhận từ khách. Đơn vào quán như một đơn đã xác nhận bình thường: đi xuống bếp và in phiếu, trừ kho, vào hóa đơn của bàn và báo cáo. Giá do chúng tôi tính theo thực đơn — bạn không cần gửi giá.
{
"external_id": "POS-100234",
"table": 6512,
"room_number": "412",
"note": "Không ngò",
"items": [
{
"sku": "PHO-1",
"quantity": 2,
"note": "Ớt để riêng",
"modifiers": [
{ "sku": "SIZE-L" },
{ "sku": "EGG", "quantity": 1 }
]
}
]
}
| Trường | Ý nghĩa |
|---|---|
external_id |
Số đơn trong hệ thống của bạn. Bắt buộc: yêu cầu lặp được nhận ra qua nó |
table |
id của bàn đúng như GET /tables trả về (một số như 6512; số ghi trên bàn là trường number, chỉ dùng để đối chiếu bàn của bạn với bàn của chúng tôi) |
room_number |
Số phòng, để ghi đơn vào phòng khách sạn |
served |
true — đơn đã được phục vụ: ghi nhận là hoàn tất, không đi xuống bếp |
items[].sku, quantity |
Món và số lượng (1–99) |
items[].modifiers[] |
Tùy chọn đã chọn theo SKU; tùy chọn lồng nhau nằm trong modifiers của chúng |
Phản hồi 201 chứa đơn đã tạo — với id, số và giá của chúng tôi.
Gửi lại là an toàn. Nếu kết nối bị đứt và bạn gửi lại cùng external_id với cùng nội dung, bạn nhận 200 và đơn đã tạo — không có đơn thứ hai. Cùng external_id với nội dung khác là lỗi IDEMPOTENCY_KEY_REUSED: hoặc là lỗi, hoặc là đơn mới mang số cũ.
Đơn chỉ được nhận cho các món của thực đơn đang hoạt động mà hiện có thể gọi (không bị ẩn, không nằm trong danh sách hết hàng).
Bộ sưu tập Postman làm sẵn chứa mọi yêu cầu của trang này, với bộ lọc bật/tắt được và các bài kiểm tra. Tải về: qreaty-external-api.postman_collection.json.
https://qreaty.com/downloads/qreaty-external-api.postman_collection.json) rồi nhấn Enter. Bộ sưu tập «Qreaty — External API» sẽ xuất hiện.token (cách tạo). base_url đã trỏ tới https://qreaty.com/api/external/v1; đổi nó cho môi trường khác (không có dấu gạch chéo ở cuối). Nhấn Save.sku, option_sku và số bàn vào các biến làm việc của bộ sưu tập (chúng xuất hiện trong danh sách sau lần chạy đầu tiên).201 nghĩa là đơn đã được tạo; gửi lại với cùng external_id (tạo biến bộ sưu tập keep_external_id với giá trị bất kỳ) sẽ trả về 200 và đơn cũ.{primary} Xác thực là Bearer token cho cả bộ sưu tập, nên không cần đặt trong từng yêu cầu. Nếu phản hồi là
401, kiểm tra token dán không có khoảng trắng và chưa bị thu hồi;403nghĩa là token thiếu quyền cho yêu cầu đó.
| Mã | Khi nào | Cần làm gì |
|---|---|---|
401 |
không có token, token đã thu hồi, hết hạn, hoặc không phải token của quán | tạo token mới |
403 |
token thiếu quyền cho yêu cầu này | cấp quyền hoặc tạo token khác |
404 |
không có đơn hoặc hóa đơn với id này trong quán | kiểm tra id |
422 |
nội dung sai: SKU hoặc bàn không tồn tại, món hiện không có, chưa chọn tùy chọn bắt buộc | đọc errors — mỗi lỗi nêu đường dẫn, ví dụ items.0.sku |
422 + IDEMPOTENCY_KEY_REUSED |
external_id đã dùng với nội dung khác |
đổi số hoặc gửi lại nội dung gốc |
429 |
quá nhanh | thử lại sau Retry-After giây |
Giới hạn là 120 yêu cầu mỗi phút cho mỗi token. Với việc đối chiếu thực đơn định kỳ thì thừa sức: dùng filter[updated_since] và trang 200 mục.
Có thể yêu cầu bộ phận hỗ trợ cung cấp đặc tả máy đọc được (OpenAPI) cho lập trình viên của bên tích hợp.