Chuyển tới nội dung chính

Shukah vs Locate

Tổng quan​

Không có tài liệu API Shukah nào ở bất cứ đâu. Trang này là nơi duy nhất phía Shukah được ghi lại: mobile app gửi gì tới từng route Shukah, nhận lại gì, và route Locate thay thế nó khác ra sao. Mọi link "So sánh với Shukah" trên một trang endpoint đều trỏ tới một mục ở đây.

Cách dùng:

  • Bắt đầu với hai bảng bên dưới. Bấm vào một route Shukah để nhảy tới mục của nó.
  • Đọc Các khác biệt chung một lần. Base URL, token, body lỗi, id, ngày tháng và header thay đổi giống nhau trên mọi route, nên các mục bên dưới không lặp lại chúng.
  • Một mục có URL dev đầy đủ, request mà app gửi, một lệnh curl (bỏ qua cho các route xóa tài khoản hoặc thu tiền), response Shukah đã capture, các lỗi đã thấy, và, với một route đã thay thế, một link tới trang Locate và một bảng theo từng field.
  • Các capture Shukah được lấy trên dev vào 2026-10-01 với client test dev 356259. Vào 2026-10-02 một parity audit đã gửi cùng một input tới Shukah và tới Locate cho mọi route có thể gọi an toàn, với các header của app 2.31.5; một mục nói rõ khi một giá trị đến từ lần chạy đó. Các field cá nhân trong mọi sample đều được thay bằng giá trị minh họa. Một giá trị mà không nguồn nào cho thấy được đánh dấu "Chưa được tài liệu hóa". Khi kỳ vọng của chính app là nguồn Shukah duy nhất, mục đó sẽ nói rõ.
  • $SHUKAH_BASE_URL là https://dev-api.shukah.com và $SHUKAH_TOKEN là một token opaque của Shukah. Các trang Locate dùng $AUTH_BASE_URL, $ORDER_BASE_URL và $TOKEN.
  • Hai mục Shukah, update profile và update setting, là cùng một route Shukah. Chúng là hai dòng vì Locate tách chúng thành hai route.

Auth​

API ShukahAPI LocateServiceTrạng thái
GET /maeda/api/reset-otpGET /api/v1/clients/reset-otpauth-service✅ Đã thay thế
GET /maeda/api/verify-otpGET /api/v1/clients/verify-otpauth-service✅ Đã thay thế
GET /maeda/api/verify-tokenGET /api/v1/clients/verify-tokenauth-service✅ Đã thay thế
GET /maeda/clientGET /api/v1/clientsauth-service✅ Đã thay thế
GET /maeda/address-bookGET /api/v1/clients/address-bookauth-service✅ Đã thay thế
GET /maeda/address-book/:idGET /api/v1/clients/address-book/:idauth-service✅ Đã thay thế
POST /maeda/address-bookPOST /api/v1/clients/address-bookauth-service✅ Đã thay thế
PUT /maeda/address-book/:idPUT /api/v1/clients/address-book/:idauth-service✅ Đã thay thế
DELETE /maeda/address-book/:idDELETE /api/v1/clients/address-book/:idauth-service✅ Đã thay thế
PUT /maeda/client/:client_idPUT /api/v1/clients/:client_idauth-service✅ Đã thay thế
PUT /maeda/client/:client_idPUT /api/v1/clients/settingauth-service✅ Đã thay thế
POST /maeda/client/add-device-idPOST /api/v1/clients/add-device-idauth-service✅ Đã thay thế
GET /maeda/client/status——❌ Chưa thay thế
GET /maeda/client/delete——❌ Chưa thay thế

Điểm​

API ShukahAPI LocateServiceTrạng thái
GET /maeda/client/pointsGET /api/v2/client/pointsorder-v2 → point-service✅ Đã thay thế
GET /maeda/point-rateGET /api/v2/client/system_configs/point_ratesorder-v2✅ Đã thay thế 🚩 enableMerchantService
GET /maeda/giftcard-code/usePOST /api/v2/client/gift-card-codeorder-v2✅ Đã thay thế 🚩 enableMerchantService
GET /maeda/client/point-historyGET /api/v2/client/point-historyorder-v2 → point-service✅ Đã thay thế
GET /maeda/point-offerGET /api/v2/client/point-offersorder-v2 → point-service✅ Đã thay thế
GET /maeda/point-occasionGET /api/v2/client/point-occasionsorder-v2 → point-service✅ Đã thay thế
POST /maeda/point-orderPOST /api/v2/client/point-ordersorder-v2 → point-service✅ Đã thay thế 🚩 POINT_ORDER_POINT_ENABLED
POST /maeda/point-order/get-descriptionPOST /api/v2/client/point-orders/descriptionorder-v2 → point-service✅ Đã thay thế
POST /maeda/order/checkout-payment-standalonePOST /api/v2/client/point-orders/:correlation_id/pay/cardorder-v2 → point-service✅ Đã thay thế 🚩 POINT_ORDER_CARD_ENABLED
POST /maeda/order/checkout-payment-flowPOST /api/v2/client/point-orders/:correlation_id/pay/sessionorder-v2 → point-service✅ Đã thay thế 🚩 POINT_ORDER_CARD_ENABLED
GET /maeda/points-faqGET /api/v2/client/points-faqorder-v2 → point-service✅ Đã thay thế
GET /maeda/point-order——❌ Chưa thay thế
POST /maeda/order/checkout-payment——❌ Chưa thay thế
POST /maeda/order/checkout-payment-stcpay——❌ Chưa thay thế
POST /maeda/order/payfort-token——❌ Chưa thay thế
POST /maeda/order/payfort-stc-pay-checkout——❌ Chưa thay thế

Khi tài liệu và code mâu thuẫn​

Các nhận định của các phiên bản trước của trang này mà các capture 2026-10-02 hoặc code mâu thuẫn. Mỗi mục giờ nói rõ điều đã tìm thấy.

  • 2026-10-02: Token nói một JWT Locate chạy trên các route điểm của order-v2. Trên dev giờ nó nhận 401; chỉ token Shukah chạy ở đó.
  • 2026-10-02: Id và ba mục thanh toán nói app gửi point_order_id dưới dạng integer. App 2.31.5 gửi một chuỗi ("1252", "1253").
  • 2026-10-02: Định dạng số và mục balance ghi số dư Shukah là "128712.41", bằng khoảng một phần tư của Locate. Giờ nó là "514853.64", cao hơn Locate 447.96 điểm.
  • 2026-10-02: reset-otp, update profile, update setting, add-device-id và danh sách quà đã gửi chưa có capture Shukah. Giờ chúng đã có.
  • 2026-10-02: verify-otp ghi body mã sai với type kiểu Yii. Body Shukah hiện nay có type của Symfony.
  • 2026-10-02: mục verify-otp không có capture Shukah của lời gọi thành công. Giờ đã có: 200 {access_token, data}, cùng hồ sơ 13 key với giá trị bằng nhau như Locate, và các session trước vẫn hợp lệ.
  • 2026-10-02: danh sách địa chỉ ghi 13 và 28 địa chỉ, không có mặc định trên Shukah và tất cả đều mặc định trên Locate, và thứ tự Shukah chưa rõ. Giờ là 15 và 30, Shukah 0 ở cả 15, Locate true ở 28 trong 30, và Shukah sắp theo position.
  • 2026-10-02: danh sách địa chỉ không cho thấy khác biệt image_urls. Locate đã mất URL ảnh của 4 địa chỉ Shukah có ảnh.
  • 2026-10-02: mục address get không cho thấy khác biệt is_default hay image_urls. Cùng một địa chỉ là 0 trên Shukah và 1 trên Locate, và có URL ảnh trên Shukah còn [] trên Locate.
  • 2026-10-02: mục point history nói các số tiền earn mới nhất của Shukah (0.5, 0.5, 2.5) ở một thang đo khác với của Locate. Các dòng mới nhất của Shukah giờ là 2, 2, 2, 2, 10: không còn chênh thang đo. Dòng mới nhất của Shukah là 2026-10-01 17:00:01, không phải 10:40:44, và 8 trong 9 dòng earn của Locate trong 10 dòng đầu có description rỗng, không phải bốn trong năm.
  • 2026-10-02: các mục point-order create và danh sách quà đã gửi kỳ vọng occasion_id. Shukah gửi point_occasion_id.
  • 2026-10-02: mục point-order create không có capture Shukah và không biết create có trả lời với dòng order hay không. Giờ nó có một capture: 201 với cùng mười hai key như các dòng order.
  • 2026-10-02: mục PayFort token không nêu lời gọi Locate nào. order-v2 có một relay tới cùng route Shukah.
  • 2026-10-02: GET /maeda/client/status từng được liệt kê là được khai báo nhưng không bao giờ được gọi. Traffic production cho thấy 768 lời gọi trong 3 ngày, nên giờ nó có một mục.

Các khác biệt chung​

Base URL​

ShukahLocate
API Auth (login, profile, address book)Dev https://dev-api.shukah.com/maeda/, production https://api.shukah.com/maeda/ (BASE_URL của app).Auth service, được gọi trực tiếp. Dev https://dev.authentication.locate.sa, prefix /api/v1. Host production: Chưa được tài liệu hóa.
API điểmCùng base URL của Shukah.order-v2. Dev https://dev.v2.api.order.locate.sa, prefix /api/v2/client. Production https://v2.api.order.locate.sa/api/v2 (BASE_URL_V2 production của app). order-v2 chuyển phần lớn route điểm sang point service, mà không được expose cho app.

Điều gì thay đổi với app:

  • Hai prefix là mới, một cái biến mất. Mọi route Shukah nằm dưới /maeda. Host auth của Locate không phục vụ nó: GET /maeda/api/verify-token trên host auth trả 404 (capture trên dev, 2026-10-01). Các route auth chuyển sang /api/v1/clients/…, các route điểm sang /api/v2/client/….
  • Segment api/ không ổn định trên Shukah. Các route login có nó (/maeda/api/reset-otp); address book thì không (/maeda/address-book). Một lời gọi /maeda/api/address-book trên Shukah dev trả 404 (capture 2026-10-01).
  • Path điểm thành số nhiều. point-offer thành point-offers, point-occasion thành point-occasions và point-order thành point-orders.
  • App không có base URL của auth service. Không file môi trường nào của app nêu host auth. Nó có một base URL order-v2 (BASE_URL_V2), mà nó đã dùng cho một vài lời gọi ở chế độ Merchant.
  • Dựng URL. App nối base URL, / và endpoint, rồi một query sắp theo key. Dấu gạch chéo ở đầu endpoint không có khác biệt.

Token​

Shukah cấp một token opaque. Locate cấp một JWT (HS256, payload {client_id, phone}) mà không bao giờ hết hạn. Cả hai đều đi trong Authorization: Bearer <token>.

Hiện nay không có token đơn nào chạy được trên cả hai service. Route Locate nào nhận token nào (dev, được capture vào 2026-10-02 với cả hai token trên mọi route có thể gọi an toàn):

Route LocateToken
Auth: reset-otp, verify-otp, exchange-token, add-device-idKhông cần.
Auth: verify-token, client lookup, năm route address-book, update profile, update settingChỉ JWT Locate. Token Shukah nhận 401 {"status":401,"message":"Unauthorization"} (đã capture).
Auth: user detail (GET /api/v1/users)Cần header x-auth-from (422 nếu thiếu). Với x-auth-from: SHUKAH và auth_source của dev là shukah, token được Shukah dev kiểm tra: một token Shukah qua được và một JWT Locate bị từ chối. Với auth_source đặt là locate, mọi JWT Locate nhận 401 (một defect).
Các route điểm của order-v2 (balance, history, FAQ, offers, occasions, point orders)Chỉ token Shukah. Một JWT Locate nhận 401 {"success":false,"error":{"code":"UNAUTHORIZED","message":"Invalid or expired token"}} trên các route balance, history, FAQ, offers và occasions (đã capture). Các route point-order dùng cùng cách kiểm tra. Vào 2026-10-01 một JWT Locate vẫn nhận 200 trên route balance.
Tỷ lệ tích điểm của order-v2Không cần: public. 200 khi không có token, với một token Shukah và với một JWT Locate (đã capture).
Gift-card code của order-v2Cùng cách kiểm tra như các route điểm, nên chỉ token Shukah (đọc code; chưa gọi với token, vì nó cộng điểm).

Vì sao (từ code trên origin/develop): guard client của auth service chạy jwt.verify, nên một token Shukah opaque không qua được. Point service và order-v2 hỏi auth service người gọi là ai với x-auth-from: SHUKAH: guard của order-v2 hard-code nó, và point service gửi nó theo mặc định (setting AUTH_VERIFY_APPLICATION của nó). Setting auth_source của dev là shukah (đọc từ client settings công khai vào 2026-10-02), nên auth service chuyển token sang Shukah dev, nơi từ chối JWT Locate (suy luận từ 401: verify-token của Shukah dev không được gọi với chính JWT). Vào 2026-10-01 Shukah vẫn chấp nhận nó. Đặt auth_source là locate sẽ không giúp được một mình: ở nhánh đó mọi JWT Locate nhận 401, vì một defect được mô tả trên User detail. Vậy hiện nay app cần cả hai token: JWT cho auth service, token Shukah cho order-v2.

Bản thân Shukah trả lời bốn route không cần token: point-offer, point-occasion, point-rate và points-faq. Locate cần token cho offers, occasions và FAQ.

Exchange-token chuyển đổi một token theo cả hai hướng (target_platform là locate hoặc shukah). App không bao giờ gọi nó. Vì vậy một user đang đăng nhập bằng token Shukah mà gọi verify-token của Locate sẽ nhận 401, và app xóa token đã lưu khi gặp 401 đó (chỉ verify-token và delete-account làm vậy), khiến user bị đăng xuất. Các route ở lại Shukah (xóa tài khoản, danh sách quà đã gửi, các thanh toán PayFort và Frames) vẫn cần một token mà Shukah chấp nhận: Locate đẩy mỗi JWT nó cấp sang Shukah theo kiểu best-effort (sau một server setting), hoặc app có thể exchange lấy token Shukah với target_platform: "shukah". Vào 2026-10-02 Shukah dev không còn chấp nhận JWT Locate (xem ở trên), nên không thể dựa vào push đó ở đó.

Body lỗi​

Năm shape lỗi gặp nhau trong lần migrate này. Một body thật của mỗi loại:

Gửi bởiBody thậtCapture ở đâu
Shukah (Laravel, probe hôm nay){"name":"Unauthorized","message":"Your request was made with invalid credentials.","code":0,"status":401,"type":"Illuminate\\Auth\\AuthenticationException"}GET /maeda/api/verify-token không có token, dev, 2026-10-01. Cùng các key name, code, status và type mang một 404 ({"name":"Not Found","message":"Object not found: 162119",…,"type":"Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException"}, address get sau khi delete, 2026-10-01).
Shukah (Yii, capture cũ hơn){"name":"Bad Request","message":"Last Name cannot be blank.","code":0,"status":400,"type":"yii\\web\\BadRequestHttpException"}Từ một lời gọi tới reset-otp của Shukah, trong capture tháng 7 năm 2026 lưu ở draft doc của auth service (api-auth-draft.md, 2026-07-07). Shukah có còn gửi nó hay không: Chưa được tài liệu hóa. 400 của reset-otp và client-lookup của chính auth service cũng dùng shape Yii này.
Auth service{"status":401,"message":"Unauthorization"}GET /api/v1/clients/verify-token, không token, dev, 2026-10-01. 500 là {"status":500,"message":"Internal server error"} trên production. Trên dev nó mang text lỗi gốc và một field stack.
Point service (qua order-v2){"success":false,"error":{"code":"UNAUTHORIZED","message":"Missing or invalid authorization header"}}GET /api/v2/client/points, không token, dev, 2026-10-01. Một key details được thêm cho lỗi validation. order-v2 dựng body 502 và 504 cùng shape.
Chính order-v2 (Nest){"message":"Unauthorized","statusCode":401}POST /api/v2/client/gift-card-code, không token, dev, 2026-10-01.

Cách app hiển thị chúng: một status từ 400 trở lên thành một lỗi có message là body.message, hoặc toàn bộ body dạng chuỗi JSON khi không có message ở cấp cao nhất. Vì vậy:

  • Body của Shukah, auth-service và Nest hiển thị message của chúng. Các key name, type, code và statusCode không bao giờ được đọc.
  • Envelope của point-service không có message ở cấp cao nhất, nên app sẽ hiển thị chuỗi JSON thô {"success":false,"error":{…}} cho user trừ khi nó tự đọc error.message.
  • Một body không phải JSON (một trang HTML 404) thành {message: <text>}.
  • App mặc định mở một global error cho 403, 500, 502, 503, 504 và 505. Các flag point-order trả 403, nên đó là một lỗi nghiêm trọng trừ khi danh sách status được đổi.
  • Tín hiệu đăng ký vẫn chạy nếu text giữ nguyên: app mở màn hình đăng ký khi reset-otp trả 400 và message chứa Last Name.

Id​

ThứShukahLocate
Clientclient_id integer (356259).Cùng integer đó cho client đã migrate. Client đăng ký trong Locate nhận id từ 1,000,000,001.
Địa chỉid integer (162115).Chuỗi hex 24 ký tự (6abbeed8a492ed4862500b74). Một giá trị chỉ gồm chữ số trong path vẫn được thử trước như id Shukah cũ.
Point offer, point occasionid integer, 1 đến 5 và 1 đến 7.Chuỗi hex 24 ký tự. Một integer Shukah gửi tới Locate là 400.
Point orderpoint_order_id, một số trong danh sách order của Shukah. Các body payment của app 2.31.5 gửi nó dưới dạng chuỗi, "1252" (capture trên dev, 2026-10-02).UUID correlation_id, trong path của các route get và pay. Một point_order_id trong body bị bỏ qua. order_no (từ 100000) là số dễ đọc.
Dòng point-historyid integer trên các dòng expense, shukah_id trên các dòng earn.id hex 24 ký tự trên các dòng expense. shukah_id là null cho các dòng Locate tự ghi.

App khai báo mọi id có kiểu number. Lời gọi delete-address của nó biến id thành số bằng toán tử unary plus, nên một id 24-hex thành NaN. Id của offer và occasion đến Locate dưới dạng text và chạy được.

Phân trang​

Lời gọiShukahLocate
Point historyKhông có: toàn bộ lịch sử trong một mảng (8,134 dòng cho client 356259 vào 2026-10-01, 2.3 s; 8,136 vào 2026-10-02).Query page và limit. Mặc định 20, tối đa 100. Không có total và không có marker next-page. App không gửi cái nào.
Danh sách quà đã gửi (GET point-order)Query page và per-page. Tổng trong các response header x-pagination-total-count và x-pagination-page-count.Không có route.
Danh sách địa chỉ, offers, occasions, FAQ, ratesKhông có.Không có.

Ngày tháng và múi giờ​

Cả hai phía đều dùng giờ đồng hồ Riyadh (Asia/Riyadh, UTC+3, không có giờ mùa hè) cho các dòng ledger, và không có dấu múi giờ.

Giá trịShukahLocate
date_created của point-historyYYYY-MM-DD HH:mm:ss, giờ Riyadh.Cùng định dạng và múi giờ.
pointsExpirationDateYYYY-MM-DD.YYYY-MM-DD, một ngày theo Riyadh.
birth_dateYYYY-MM-DD.YYYY-MM-DD: ngày UTC của giá trị đã ghi.
date_created của kết quả gift-cardChưa được tài liệu hóa.yyyy-mm-dd hh:mm:ss, giờ Ả Rập (UTC+3).
created_at, updated_at của địa chỉKhông trả về.ISO 8601 theo UTC (2026-09-29T17:01:10.000Z), chỉ trên câu trả lời list và create.

Định dạng số​

Giá trịShukahLocate
Số dư điểm pointsChuỗi với hai chữ số thập phân: "514853.64" (2026-10-02).Chuỗi với tối đa bốn chữ số thập phân, bỏ số 0 ở cuối: "514405.6788". "0" khi không có tài khoản. App chuyển bằng Number(points) || 0.
total_points của historyMột số trên các dòng earn, một chuỗi với hai chữ số thập phân trên các dòng expense ("684.00", do team point service đo vào 2026-07-17).Một số trên các dòng earn và một chuỗi với chính xác hai chữ số thập phân trên các dòng expense ("360.00").
amount của offer, money_amount của orderamount là chuỗi với hai chữ số thập phân: "40.00".amount giống nhau; money_amount của order là chuỗi với hai chữ số thập phân.
point_amount, purchased_point_amount của offerInteger.Số. purchased_point_amount có thể là null khi offer không có giá bằng điểm.
lat, lng của địa chỉSố JSON trên mọi route.Số trên list và create, chuỗi trên get và update.
is_default của địa chỉ0 hoặc 1 trong type của app. 0 trên mọi địa chỉ và mọi route trong các capture 2026-10-02.Boolean trên list và create, 0 hoặc 1 trên get và update (được xác nhận bởi code và các capture 2026-10-02).
sex, receive_offers, push_enabledInteger (sex 0, 1, 2 hoặc 9).Integer. sex 9 được lưu là không rõ và đọc lại là 0.

Request header​

Request. App gửi những thứ này trên mọi lời gọi Shukah (và trên các lời gọi order-v2):

Header hoặc queryGiá trịLocate
AuthorizationBearer <stored token> khi đã đăng nhập.Cần trên các route có guard. Xem Token.
Accept, Content-Typeapplication/json.Content-Type: application/json cần cho các route POST của order-v2 mà đọc body.
x-from-applicationLOCATE_CLIENT_V2.Auth service bỏ qua. order-v2 không chuyển nó sang point service.
from-application, x-from-versionChế độ app và phiên bản app.Giống vậy: bỏ qua hoặc không chuyển tiếp.
language (query)en-GB, hoặc ar-SA cho bất kỳ ngôn ngữ nào khác.Auth service bỏ qua, trừ reset-otp, nơi lưu phần trước dấu -. Các route điểm bỏ qua nó, và nhãn occasion chỉ là tiếng Ả Rập khi language chính xác là ar.
key (query)maeda, chỉ gửi trên reset-otp và phone lookup.Bị bỏ qua.
x-auth-fromSHUKAH, chỉ được gửi bởi helper shukahApi của app, không phải client chính.Point service tự đặt giá trị của nó khi gọi auth service. App không cần gửi nó.

Các capture 2026-10-01 chỉ gửi Accept, cộng x-from-application và Content-Type trên các lời gọi ghi, kèm token, và nhận 200. Các capture 2026-10-02 gửi các header của app 2.31.5 (x-from-application, from-application, x-from-version: 2.31.5, x-user-id, Accept) và ?language=en-GB ở cả hai phía. x-device-id không được app gửi.

Response: các header app-version. App đọc new_version, old_version, has_new_version và is_required_update từ response của bất kỳ lời gọi nào có URL chứa api/verify-token hoặc client/points, và hiển thị popup cập nhật từ chúng. Shukah có gửi chúng hay không: Chưa được tài liệu hóa (các capture chỉ lưu request header). Không Locate service nào gửi chúng. URL verify-token của Locate (/api/v1/clients/verify-token) không chứa api/verify-token, nên app sẽ không tìm ở đó. URL điểm của Locate có chứa client/points, nhưng không có gì set các header. Nếu Shukah hiện nay gửi chúng, popup cập nhật sẽ lặng lẽ ngừng sau khi chuyển. Xem Verify token.

Response: các header phân trang. Danh sách quà đã gửi đọc x-pagination-total-count và x-pagination-page-count. Xem Phân trang.

API Auth​

GET /maeda/api/reset-otp​

Thay thế bằng Locate: GET /api/v1/clients/reset-otp

URL dev đầy đủ: https://dev-api.shukah.com/maeda/api/reset-otp

Một route làm cả đăng nhập và đăng ký. Không có Authorization: user đang đăng xuất.

Request (từ app). Đăng nhập gửi contact_phone (chỉ chữ số, bỏ +), key=maeda và language. Đăng ký thêm first_name, last_name, email_address và, tùy chọn, sex (0, 1, 2 hoặc 9), birth_date (yyyy-mm-dd) và receive_offers (gửi là 1 chỉ khi user đồng ý, không bao giờ là 0).

# Sends a real SMS to the phone. Use a test-mode number.
curl -s -G "$SHUKAH_BASE_URL/maeda/api/reset-otp" --data-urlencode "contact_phone=$PHONE" --data-urlencode "key=maeda" --data-urlencode "language=en-GB"

Response Shukah đã capture. 200, 895 ms, cho một phone đã biết (capture trên dev, 2026-10-02; nó đã gửi một SMS). Locate trả lời cùng body. Type app parse là {status: any}. Draft doc của auth service (api-auth-draft.md, 2026-07-07), từ một lời gọi tới dev Shukah, cho thấy cùng {"status": true} cho một lần đăng ký.

{
"status": true
}

Lỗi đã thấy.

  • Thiếu phone, 400, bằng tiếng Ả Rập và với type của Laravel (capture trên dev, 2026-10-01, với key=maeda và không có language): {"name":"Bad Request","message":"حقل contact phone مطلوب.","code":0,"status":400,"type":"Illuminate\\Validation\\ValidationException"}
  • Phone không tồn tại và không có field đăng ký, 400, trong capture tháng 7 năm 2026 lưu ở draft doc của auth service (api-auth-draft.md, 2026-07-07): {"name":"Bad Request","message":"Last Name cannot be blank.","code":0,"status":400,"type":"yii\\web\\BadRequestHttpException"}. Tín hiệu để app mở đăng ký. Hôm nay Shukah có còn gửi text này hay không: Chưa được tài liệu hóa.
FieldShukahLocateGhi chú
contact_phone (query)Chỉ chữ số, + bị app bỏ.Bỏ khoảng trắng, khớp có hoặc không có + ở đầu. Không kiểm tra định dạng.Trống cho 400 ở cả hai.
key (query)maeda.Bị bỏ qua.App có thể tiếp tục gửi nó.
first_name, last_name, email_address (query)Các field đăng ký.Cần khi không client active nào có phone. Kiểm tra theo thứ tự last name, first name, email.Một lời gọi trần cho phone không tồn tại nhận Last Name cannot be blank. trên Locate. Text hiện tại của Shukah: Chưa được tài liệu hóa.
sex (query)0, 1, 2 hoặc 9.1 nam, 2 nữ. Mọi giá trị khác được lưu là không rõ.
birth_date (query)yyyy-mm-dd.Được đọc như một ngày, lưu dạng YYYY-MM-DD. Giá trị xấu được lặng lẽ lưu rỗng.
receive_offers (query)Chỉ gửi 1.Không được đọc. Client mới bắt đầu với giá trị tắt.
language (query)en-GB hoặc ar-SA.Lưu phần trước dấu -, chữ thường. Thiếu thì thành ar.Không đổi ngôn ngữ SMS (tiếng Ả Rập).
status (response)true.true. Cũng true khi một mã còn chờ và không có SMS mới được gửi.Đừng đọc true là "đã gửi SMS".
Lỗi thiếu phoneMessage tiếng Ả Rập, type Laravel.{"name":"Bad Request","message":"Phone number cannot be blank.","code":0,"status":400,"type":"yii\\web\\BadRequestHttpException"} (capture trên dev, 2026-10-01).Các key giống nhau, text và type khác nhau.

GET /maeda/api/verify-otp​

Thay thế bằng Locate: GET /api/v1/clients/verify-otp

URL dev đầy đủ: https://dev-api.shukah.com/maeda/api/verify-otp

Request (từ app). Query contact_phone, code (4 chữ số), fcm_token (bỏ qua khi app không lấy được), platform (Android, iOS hoặc Huawei) và language. Không có key. Không có Authorization.

# Uses up the code and returns a new token. Use a test-mode number.
curl -s -G "$SHUKAH_BASE_URL/maeda/api/verify-otp" --data-urlencode "contact_phone=$PHONE" --data-urlencode "code=$CODE" --data-urlencode "platform=iOS"

Response Shukah đã capture. 200 trên dev, 2026-10-02 (mã đúng 2022, platform=iOS, không có token). Giá trị access_token đã bị che, nên loại token không được ghi lại ở đây. Profile data là cùng 13 field với giá trị bằng nhau như trên Locate.

{
"access_token": "<redacted>",
"data": {
"client_id": 356259,
"odoo_id": "1342170",
"contact_phone": "+966500000000",
"status": "active",
"email_address": "user@example.com",
"first_name": "Test",
"last_name": "User",
"sex": 1,
"birth_date": "1990-01-01",
"receive_offers": 0,
"push_enabled": 0,
"is_food_truck_user": 1,
"is_cod_disabled": 0
}
}

Hai token phát hành trước đó vẫn dùng được sau lời gọi này (Shukah GET /maeda/client/points 200): một lần đăng nhập mới không kết thúc các session trước đó. Shukah xử lý fcm_token và platform thế nào vẫn chưa thấy trong response.

Lỗi đã thấy. Mã sai, 400 (capture trên dev, 2026-10-02): {"name":"Bad Request","message":"Sorry, but your verification code is incorrect","code":0,"status":400,"type":"Symfony\\Component\\HttpKernel\\Exception\\HttpException"}. Capture tháng 7 năm 2026 lưu ở draft doc của auth service (api-auth-draft.md, 2026-07-07) có cùng message với type kiểu Yii yii\\web\\BadRequestHttpException.

FieldShukahLocateGhi chú
contact_phone (query)Chữ số.Bỏ khoảng trắng, khớp có hoặc không có +.
code (query)4 chữ số.So sánh dạng text, nên số 0 ở đầu có ý nghĩa.
fcm_token (query)Gửi khi app có. Shukah làm gì với nó: Chưa được tài liệu hóa.Bị bỏ.Nếu Shukah có dùng nó, nó sẽ mất. App cũng lưu FCM token của nó riêng, sang order-v2 (client/fcm/save-token).
platform (query)Android, iOS hoặc Huawei. Shukah làm gì với nó: Chưa được tài liệu hóa.Bị bỏ.
language (query)Có gửi.Bị bỏ qua.
access_token (response)Một token opaque của Shukah.Một JWT Locate, không bao giờ hết hạn.Mọi lời gọi /api/v1/clients/* sau đó đều cần JWT.
data (response)Cùng hồ sơ 13 field như Locate, giá trị bằng nhau (capture trên dev, 2026-10-02).Hồ sơ 13 field, như ở verify-token.Không có: shape và giá trị khớp nhau trong cặp gọi 2026-10-02.
Lỗi mã saiBody Laravel ở trên (type của Symfony).{"status":400,"message":"Sorry, but your verification code is incorrect"} (capture trên dev, 2026-10-01 và 2026-10-02).name, code và type không còn. Một message duy nhất bao phủ mã sai, hết hạn, đã dùng và phone không tồn tại.

GET /maeda/api/verify-token​

Thay thế bằng Locate: GET /api/v1/clients/verify-token

URL dev đầy đủ: https://dev-api.shukah.com/maeda/api/verify-token

Request. Authorization: Bearer <stored token>, language. App cũng đặt Accept, Content-Type và x-from-application: LOCATE_CLIENT_V2 tường minh trên lời gọi này. Nó chạy mỗi lần app khởi động và lại khi Home mở.

curl -s "$SHUKAH_BASE_URL/maeda/api/verify-token" -H "Authorization: Bearer $SHUKAH_TOKEN"

Response Shukah đã capture. 200, 731 ms.

{
"client_id": 356259,
"odoo_id": "1342170",
"contact_phone": "+966500000000",
"status": "active",
"email_address": "user@example.com",
"first_name": "Test",
"last_name": "User",
"sex": 1,
"birth_date": "1990-01-01",
"receive_offers": 0,
"push_enabled": 0,
"is_food_truck_user": 1,
"is_cod_disabled": 0
}

Capture trên dev, 2026-10-01 (client 356259); các field cá nhân đã được thay thế. Vào 2026-10-02 body Shukah và body Locate (với một JWT Locate) lại bằng nhau, từng key một. Type hồ sơ của app bỏ qua odoo_id, is_food_truck_user và is_cod_disabled.

Lỗi đã thấy. Không có token, 401 (capture trên dev, 2026-10-01): body Laravel được hiển thị ở Body lỗi. Với mọi 401 app xóa token đã lưu.

FieldShukahLocateGhi chú
client_id, odoo_id, contact_phone, status, email_address, first_name, last_name, sex, birth_date, receive_offers, push_enabled, is_food_truck_user, is_cod_disabled (response)13 key ở trên.Cùng 13 key, kiểu và giá trị cho client 356259 (capture trên dev, 2026-10-01).Body là drop-in.
Authorization (header)Một token opaque của Shukah.Chỉ JWT Locate.Token Shukah nhận 401. Xem Token.
language, x-from-application và các header khácCó gửi.Được chấp nhận và bỏ qua.
Body 401Body Laravel ở trên.{"status":401,"message":"Unauthorization"} (capture trên dev, 2026-10-01).Mọi chỗ so khớp theo text, name hay type đều phải đổi.
Các response header app-versionShukah có gửi chúng hay không: Chưa được tài liệu hóa.Không gửi. URL Locate không chứa api/verify-token.Xem Request header.

GET /maeda/client​

Thay thế bằng Locate: GET /api/v1/clients

URL dev đầy đủ: https://dev-api.shukah.com/maeda/client?contact_phone=<digits>&key=maeda&language=en-GB

Dùng để tìm người nhận quà theo phone. Request. Bearer token. Query contact_phone (chữ số, app bỏ +), key=maeda, language.

curl -s -G "$SHUKAH_BASE_URL/maeda/client" -H "Authorization: Bearer $SHUKAH_TOKEN" --data-urlencode "contact_phone=$PHONE" --data-urlencode "key=maeda"

Response Shukah đã capture. 200, 867 ms. Một mảng với một object.

[
{
"client_id": 356259,
"contact_phone": "+966500000000",
"first_name": "Test",
"last_name": "User"
}
]

Capture trên dev, 2026-10-01 (client 356259); các field cá nhân đã được thay thế. Capture đã thay last_name, nên Shukah có che nó hay không không thấy được: Chưa được tài liệu hóa.

Lỗi đã thấy. Không có token, 401, body Laravel (capture trên dev, 2026-10-01). App chỉ lấy dòng đầu tiên và coi mảng rỗng là "User not found".

FieldShukahLocateGhi chú
client_id (response)Integer.Integer.
contact_phone (response)Phone.Phone như đã lưu, không bị che.
first_name (response)Tên.Đã trim; trống thành null. Không bị che.
last_name (response)Chưa được tài liệu hóa (không thấy được việc che trong capture).Bị che: giữ ký tự đầu và cuối, phần giữa thành * (User thành U**r); một hoặc hai ký tự giữ nguyên.App copy nó từ dòng đầu tiên. Hãy kiểm tra flow tặng quà.
Phone không tồn tạiChưa được tài liệu hóa.200 với [], cũng cho client không active.App đã coi [] là "User not found".
Authorization (header)Một token Shukah.Chỉ JWT Locate.Xem Token.
key, language (query)Có gửi.Bị bỏ qua.
Body 401Body Laravel.{"status":401,"message":"Unauthorization"}.

GET /maeda/address-book​

Thay thế bằng Locate: GET /api/v1/clients/address-book

URL dev đầy đủ: https://dev-api.shukah.com/maeda/address-book (không có segment api/).

Request. Bearer token. Không có tham số nào ngoài language.

curl -s "$SHUKAH_BASE_URL/maeda/address-book" -H "Authorization: Bearer $SHUKAH_TOKEN"

Response Shukah đã capture. 200, 770 ms. Một mảng phẳng gồm 13 địa chỉ cho client 356259; địa chỉ đầu tiên:

{
"id": 162115,
"location_name": "Saihat",
"is_default": 0,
"formatted_address": "King Fahd Rd, Al Olaya, Riyadh 12211",
"area_name": "A12345",
"street": "King Fahd Rd",
"city": "Saihat",
"area": "Eastern Province",
"state": "Al-Qatif",
"zipcode": "32461",
"country": "Saudi Arabia",
"country_code": "SA",
"lat": 24.7136,
"lng": 46.6753,
"image_urls": ["https://example.com/address-photo.jpg"],
"position": 0
}

Capture trên dev, 2026-10-01 (client 356259); các field cá nhân và tọa độ đã được thay thế. Không địa chỉ nào trong 10 địa chỉ đầu là mặc định. Vào 2026-10-02 list có 15 địa chỉ, tất cả is_default là 0, sắp theo position từ 0 đến 14 trong khi các id không theo thứ tự (162115, 161996, 162101, …).

Lỗi đã thấy. Không có cho route này. Path /maeda/api/address-book trả 404 {"name":"Not Found","message":"The route maeda/api/address-book could not be found.",…} (capture 2026-10-01): app không gọi nó.

FieldShukahLocateGhi chú
idInteger (162115).Chuỗi 24 ký tự.App khai báo kiểu của nó là number.
is_default0 hoặc 1.Boolean.Một phép thử truthiness chạy được với cả hai. Một phép so sánh strict với 1 thì không.
location_name, formatted_address, area_name, street, city, area, state, zipcode, country, country_codeChuỗi.Chuỗi, null khi thiếu (list shape).
lat, lngSố JSON.Số JSON trên list.
image_urlsMột mảng hoặc null. Bốn trong 15 địa chỉ có URL ảnh (2026-10-02).Luôn là mảng. [] trên các bản copy Locate của bốn địa chỉ đó (2026-10-02).Ảnh bị mất khi copy sang Locate. Nguyên nhân: Chưa được tài liệu hóa.
positionInteger.Không trả về.App không đọc nó.
source, created_at, updated_atKhông trả về.source (mt_client_inline, mt_address_book hoặc locate) và hai ngày ISO UTC.App không đọc chúng.
Thứ tựTheo position, từ 0 đến 14 (capture trên dev, 2026-10-02).created_at mới nhất trước.Danh sách có thể hiển thị theo thứ tự khác.
Số lượng cho client 35625915 địa chỉ (2026-10-02; 13 vào 2026-10-01).30 địa chỉ, cùng client, cùng ngày (28 vào 2026-10-01).Các lần xóa làm trên Shukah không bao giờ tới Locate, và một địa chỉ xuất hiện ba lần.
Địa chỉ mặc địnhis_default là 0 ở cả 15 (2026-10-02).true ở 28 trong 30 (2026-10-02).App lấy mặc định đầu tiên nó thấy.
AuthorizationMột token Shukah.Chỉ JWT Locate.

GET /maeda/address-book/:id​

Thay thế bằng Locate: GET /api/v1/clients/address-book/:id

URL dev đầy đủ: https://dev-api.shukah.com/maeda/address-book/<id>

Request. Bearer token. Path id, một integer từ list.

curl -s "$SHUKAH_BASE_URL/maeda/address-book/$ADDRESS_ID" -H "Authorization: Bearer $SHUKAH_TOKEN"

Response Shukah đã capture. 200, 286 ms: cùng 16 key như mục list ở trên, phẳng.

{
"id": 162115,
"location_name": "Saihat",
"is_default": 0,
"formatted_address": "King Fahd Rd, Al Olaya, Riyadh 12211",
"area_name": "A12345",
"street": "King Fahd Rd",
"city": "Saihat",
"area": "Eastern Province",
"state": "Al-Qatif",
"zipcode": "32461",
"country": "Saudi Arabia",
"country_code": "SA",
"lat": 24.7136,
"lng": 46.6753,
"image_urls": ["https://example.com/address-photo.jpg"],
"position": 0
}

Capture trên dev, 2026-10-01 (client 356259); text địa chỉ và tọa độ đã được thay thế.

Lỗi đã thấy. Sau một lần delete, 404 (capture trên dev, 2026-10-01): {"name":"Not Found","message":"Object not found: 162119","code":0,"status":404,"type":"Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException"}. Địa chỉ của client khác (id 1), 403 (capture trên dev, 2026-10-02): {"name":"Forbidden","message":"You can only view address that belong to you.","code":0,"status":403,"type":"Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException"}.

FieldShukahLocateGhi chú
idInteger.Chuỗi 24 ký tự. Id số của Shukah vẫn chạy trong path với các địa chỉ đến từ Shukah.App so sánh id chọn lần cuối đã lưu dưới dạng chuỗi, nên một integer Shukah đã lưu không còn khớp.
is_default0 hoặc 1.0 hoặc 1.Cùng type, nhưng không phải lúc nào cũng cùng giá trị: địa chỉ 162115 là 0 trên Shukah và 1 trên Locate (2026-10-02).
lat, lngSố JSON.Chuỗi ("24.7136").App chuyển bằng Number().
Các field textChuỗi.Chuỗi, "" khi thiếu, không bao giờ là null.
image_urlsMột mảng hoặc null.Luôn là mảng.Địa chỉ 162115 có một URL ảnh trên Shukah và [] trên Locate (2026-10-02).
positionInteger.Không trả về.
Địa chỉ của người khác403 với body Laravel ở trên.404 Address not found, như với một id không tồn tại (đọc code; một id của người khác chưa được thử live trên Locate).Status và text app hiển thị sẽ đổi.
Body 404Body Laravel ở trên.{"status":404,"message":"Address not found"} (capture trên dev, 2026-10-01). Trên dev nó cũng mang một field stack với stack trace của server.Text app hiển thị sẽ đổi.

POST /maeda/address-book​

Thay thế bằng Locate: POST /api/v1/clients/address-book

URL dev đầy đủ: https://dev-api.shukah.com/maeda/address-book

Request (từ app). JSON với lat và lng dạng chuỗi, is_default (0 hoặc 1), area_name, location_name và image_urls (một mảng hoặc null). Trước lời gọi app xóa mọi địa chỉ hiện có cùng location_name, nên một lần lưu là một delete rồi mới đến create này.

# Creates an address on dev. Delete it afterwards.
curl -s -X POST "$SHUKAH_BASE_URL/maeda/address-book" -H "Authorization: Bearer $SHUKAH_TOKEN" -H "Content-Type: application/json" -d '{"lat":"24.7136","lng":"46.6753","is_default":0,"area_name":"Olaya","location_name":"Docs test","image_urls":[]}'

Response Shukah đã capture. 200, 678 ms. Địa chỉ mới, phẳng. Shukah đã điền street, city, area, state, zipcode, country và formatted address từ tọa độ.

{
"id": 162119,
"location_name": "Docs capture (Shukah)",
"is_default": 0,
"formatted_address": "King Fahd Rd, Al Olaya, Riyadh 12211",
"area_name": "Olaya",
"street": "King Fahd Rd",
"city": "Riyadh",
"area": "Riyadh Province",
"state": "Riyadh Principality",
"zipcode": "12251",
"country": "Saudi Arabia",
"country_code": "SA",
"lat": 24.7136,
"lng": 46.6753,
"image_urls": [],
"position": 13
}

Capture trên dev, 2026-10-01 (client 356259, request body như ở curl nhưng với tên Docs capture (Shukah)); đã xóa sau đó.

Lỗi đã thấy. Chưa capture lỗi nào.

FieldShukahLocateGhi chú
lat, lng (body)Chuỗi từ app.Số hoặc numeric string; mọi thứ khác được lưu là null.
is_default (body)0 hoặc 1.1, "1" hoặc true nghĩa là mặc định; mọi thứ khác thì không.Trên Locate một mặc định cũng xóa flag trên các địa chỉ khác.
area_name, location_name (body)Có gửi.Lưu đã trim.
image_urls (body)Mảng hoặc null.Mảng; chuỗi được trim, chuỗi trống bị bỏ.
street, city, area, state, zipcode, country, country_code, formatted_addressShukah điền từ tọa độ (đã capture lại vào 2026-10-02). Bằng cách nào: Chưa được tài liệu hóa.Chỉ lưu nếu được gửi, nếu không là null: cả tám giá trị đều trả về null cho body của app (capture trên dev, 2026-10-02).Một địa chỉ tạo bằng body hiện tại của app không có street hay city trên Locate.
Shape responseChính địa chỉ, phẳng, với id integer và position.{"status":200,"address":{…}} với id 24 ký tự, source: "locate" và các ngày ISO.App đọc id, lat, lng ở cấp cao nhất, nên với wrapper chúng bị thiếu. Hãy đọc address.
Được lưu ở đâuShukah.Locate, rồi một bản copy best-effort sang Shukah.Trên dev bản copy không tới được Shukah vào 2026-10-01 hay vào 2026-10-02: bản copy được post tới /maeda/api/address-book, mà Shukah dev trả lời bằng 404.

PUT /maeda/address-book/:id​

Thay thế bằng Locate: PUT /api/v1/clients/address-book/:id

URL dev đầy đủ: https://dev-api.shukah.com/maeda/address-book/<id>

Request (từ app). Path id. JSON với bất kỳ key nào trong street, city, location_name, state, zipcode, country_code, country, area, formatted_address, is_default (0 hoặc 1) và image_urls. Màn hình Edit address của app gửi location_name, area, is_default và image_urls. Không có lat, lng hay area_name khi update.

# Edits an address on dev. Use one you created.
curl -s -X PUT "$SHUKAH_BASE_URL/maeda/address-book/$ADDRESS_ID" -H "Authorization: Bearer $SHUKAH_TOKEN" -H "Content-Type: application/json" -d '{"location_name":"Docs test (edited)"}'

Response Shukah đã capture. 200, 245 ms. Địa chỉ đầy đủ, phẳng, với field đã đổi.

{
"id": 162119,
"location_name": "Docs capture (Shukah, edited)",
"is_default": 0,
"formatted_address": "King Fahd Rd, Al Olaya, Riyadh 12211",
"area_name": "Olaya",
"street": "King Fahd Rd",
"city": "Riyadh",
"area": "Riyadh Province",
"state": "Riyadh Principality",
"zipcode": "12251",
"country": "Saudi Arabia",
"country_code": "SA",
"lat": 24.7136,
"lng": 46.6753,
"image_urls": [],
"position": 13
}

Capture trên dev, 2026-10-01 (client 356259, body {"location_name":"Docs capture (Shukah, edited)"}); đã xóa sau đó.

Lỗi đã thấy. Chưa capture lỗi nào. Một id không tồn tại trả 404 Laravel được hiển thị ở get.

FieldShukahLocateGhi chú
id (path)Integer.Một id 24 ký tự, hoặc chữ số cho một id Shukah.
Các key của bodyCác key ở trên; update một phần.Cùng các key, một phần. Một key gửi là null, "" hoặc khoảng trắng sẽ xóa field (image_urls thành []).
is_default0 hoặc 1.Chỉ khi key có trong body. Đặt nó sẽ di chuyển mặc định. Quy tắc mặc định của Shukah: Chưa được tài liệu hóa.
ResponseĐịa chỉ phẳng, id integer, lat và lng dạng số, position.Địa chỉ phẳng, id 24 ký tự, lat và lng dạng chuỗi, không có position.Các key app đọc đều có đủ.
Copy sang ShukahKhông áp dụng.Một bản copy best-effort. Khi không có Shukah id nó tạo một địa chỉ mới ở đó, có thể gây trùng lặp.Trên dev việc sửa một địa chỉ do Locate tạo không tới được Shukah vào 2026-10-02. Một lần sửa làm trên Shukah cũng không tới được Locate.

DELETE /maeda/address-book/:id​

Thay thế bằng Locate: DELETE /api/v1/clients/address-book/:id

URL dev đầy đủ: https://dev-api.shukah.com/maeda/address-book/<id>

Request. Path id, không có body. App trước tiên biến id thành số bằng toán tử unary plus.

# Deletes an address on dev, permanently. Use one you created.
curl -s -X DELETE "$SHUKAH_BASE_URL/maeda/address-book/$ADDRESS_ID" -H "Authorization: Bearer $SHUKAH_TOKEN"

Response Shukah đã capture. 204 với body rỗng, 286 ms (capture trên dev, 2026-10-01). App không đọc body.

Lỗi đã thấy. Lần đọc thứ hai của id đã xóa trả 404 Laravel Object not found: 162119 (capture trên dev, 2026-10-01).

FieldShukahLocateGhi chú
id (path)Integer.Một id 24 ký tự, hoặc chữ số cho một id Shukah.Unary plus của app biến một id 24-hex thành NaN, nên lời gọi thành .../address-book/NaN và nhận 404.
Thành công204, body rỗng.200 {"status":200}.Không có: app không đọc body.
Body 404Body Laravel.{"status":404,"message":"Address not found"}. Lần delete thứ hai cũng nhận nó.
Copy sang ShukahKhông áp dụng.Delete không bao giờ được copy sang Shukah.Một địa chỉ được sửa qua Locate rồi xóa có thể vẫn còn trên Shukah.

PUT /maeda/client/:client_id​

Thay thế bằng Locate: PUT /api/v1/clients/:client_id

URL dev đầy đủ: https://dev-api.shukah.com/maeda/client/<client_id>

Một route Shukah này phục vụ hai entry registry. Việc sửa hồ sơ và công tắc push-notification đều gọi PUT /maeda/client/<client_id>. Chúng chỉ được phân biệt bằng body: sửa hồ sơ mang các key hồ sơ, công tắc push mang {client_id, push_enabled}. Locate tách chúng: entry này ánh xạ tới PUT /api/v1/clients/:client_id, và update setting ánh xạ tới PUT /api/v1/clients/setting. App không có lời gọi setting Shukah riêng.

Request (từ app). Path client_id (số, lặp lại trong body). JSON client_id cộng bất kỳ key nào trong contact_phone, email_address, first_name, last_name, sex (0, 1, 2 hoặc 9), birth_date (YYYY-MM-DD, hoặc null) và receive_offers (0 hoặc 1).

# Writes the profile on dev. Send the client's current value back.
curl -s -X PUT "$SHUKAH_BASE_URL/maeda/client/$CLIENT_ID" -H "Authorization: Bearer $SHUKAH_TOKEN" -H "Content-Type: application/json" -d "{\"client_id\":$CLIENT_ID,\"receive_offers\":$CURRENT_RECEIVE_OFFERS}"

Response Shukah đã capture. 200, 239 ms (capture trên dev, 2026-10-02, với body {"client_id":356259,"receive_offers":0}, giá trị hiện tại được ghi lại): hồ sơ 13 field, với cùng key, type và giá trị như sample verify-token. Locate trả lời cùng body. App parse nó thành UserServer.

Lỗi đã thấy. Một birth_date sai ("not-a-date"), 422 (capture trên dev, 2026-10-02): [{"field":"birth_date","message":"The birth date field must match the format Y-m-d."}]. Đó là một mảng lỗi theo field, không phải object lỗi Laravel. Locate trả lời 400 {"status":400,"message":"birth_date is invalid","stack":"…"} cho cùng body. Các quy tắc validation khác của Shukah: Chưa được tài liệu hóa.

FieldShukahLocateGhi chú
client_id (path và body)Id số, ở cả hai. Shukah có kiểm tra nó với token hay không: Chưa được tài liệu hóa.Phải bằng client của token trong path, và trong body nếu có gửi, nếu không 400 client_id does not match the authenticated client.
contact_phoneCó chấp nhận phone bị đổi hay không: Chưa được tài liệu hóa.Phải bằng đúng phone đã lưu, kể cả + ở đầu, nếu không 400 contact_phone cannot be changed. Không bao giờ được ghi.Đừng định dạng lại phone.
first_name, last_nameChuỗi.null hoặc tối đa 100 ký tự sau khi trim, nếu không 400.
email_addressChuỗi.Mọi chuỗi hoặc null, không kiểm tra định dạng.
birth_dateYYYY-MM-DD hoặc null.Bất cứ thứ gì new Date() đọc được, lưu dưới dạng ngày UTC. null xóa nó. "" hoặc giá trị xấu là 400 birth_date is invalid.
sex0, 1, 2 hoặc 9.1 nam, 2 nữ. Mọi giá trị khác được lưu là không rõ và đọc lại là 0.Một 9 của Shukah đọc là không rõ sau khi chuyển.
receive_offers0 hoặc 1.1, "1" hoặc true nghĩa là bật, mọi thứ khác là tắt.
push_enabledĐược chấp nhận trên route này: công tắc push dùng nó.Bị bỏ qua. Lời gọi trả 200 với hồ sơ không đổi.Chuyển công tắc sang update setting, nếu không nó lặng lẽ không làm gì.
ResponseHồ sơ 13 field (capture trên dev, 2026-10-02).Cùng hồ sơ 13 field (capture trên dev, 2026-10-01 và 2026-10-02).
Lỗi422 với một mảng {field, message} (đã capture cho birth_date, 2026-10-02).400 {"status":400,"message":"…"}, chỉ kiểm tra lỗi đầu tiên. Trên dev body cũng có field stack.App hiển thị message, nên nó mất tên field, và status đổi từ 422 sang 400.
AuthorizationMột token Shukah.Chỉ JWT Locate.
Copy sang ShukahKhông áp dụng.Không được copy.Mọi thứ vẫn đọc hồ sơ từ Shukah sẽ giữ giá trị cũ.

PUT /maeda/client/:client_id​

Thay thế bằng Locate: PUT /api/v1/clients/setting

URL dev đầy đủ: https://dev-api.shukah.com/maeda/client/<client_id>

Cùng route Shukah với update profile. Nó là công tắc push khi body chỉ là {client_id, push_enabled}.

Request (từ app). JSON {"client_id": <id>, "push_enabled": 0 or 1}.

# Writes the push setting on dev. Send the current value back.
curl -s -X PUT "$SHUKAH_BASE_URL/maeda/client/$CLIENT_ID" -H "Authorization: Bearer $SHUKAH_TOKEN" -H "Content-Type: application/json" -d "{\"client_id\":$CLIENT_ID,\"push_enabled\":$CURRENT_PUSH_ENABLED}"

Response Shukah đã capture. 200, 252 ms (capture trên dev, 2026-10-02, với body {"client_id":356259,"push_enabled":0}, giá trị hiện tại được ghi lại): hồ sơ 13 field với push_enabled là 0, như ở sample verify-token. Route setting của Locate trả lời cùng body. App đọc push_enabled từ đó. Vì giá trị được ghi là giá trị hiện tại, capture không chứng minh rằng Shukah áp dụng push_enabled trên route này.

Lỗi đã thấy. Chưa capture lỗi nào: Chưa được tài liệu hóa.

FieldShukahLocateGhi chú
RoutePUT /maeda/client/<client_id>, route hồ sơ.PUT /api/v1/clients/setting, không có id trong path.Trỏ công tắc push sang route mới.
client_id (body)Có gửi. Shukah có kiểm tra nó hay không: Chưa được tài liệu hóa.Bắt buộc. Phải bằng client của token, nếu không 400 client_id does not match the authenticated client.App đã gửi nó.
push_enabled (body)0 hoặc 1.Bắt buộc. 1, "1" hoặc true bật nó, mọi thứ khác tắt. Key bị thiếu là 400 push_enabled is required.
Các key khácCác key hồ sơ được chấp nhận trên cùng route.Không được chấp nhận: chỉ client_id và push_enabled.
ResponseHồ sơ 13 field (capture trên dev, 2026-10-02).Hồ sơ 13 field với push_enabled mới (capture trên dev, 2026-10-01 và 2026-10-02).
AuthorizationMột token Shukah.Chỉ JWT Locate.
Copy sang ShukahKhông áp dụng.Không được copy. Shukah giữ giá trị cũ.

POST /maeda/client/add-device-id​

Thay thế bằng Locate: POST /api/v1/clients/add-device-id

URL dev đầy đủ: https://dev-api.shukah.com/maeda/client/add-device-id

Request (từ app). JSON {"device_id": "<device unique id>"}. App gửi nó một lần cho mỗi bản cài, chỉ khi đã đăng nhập, và ghi lại rằng nó đã được gửi sau một 200.

curl -s -X POST "$SHUKAH_BASE_URL/maeda/client/add-device-id" -H "Authorization: Bearer $SHUKAH_TOKEN" -H "Content-Type: application/json" -d '{"device_id":"00000000-0000-4000-8000-000000000000"}'

Response Shukah đã capture. 200, 236 ms (capture trên dev, 2026-10-02, với device id giả của lệnh curl ở trên). App bỏ qua câu trả lời.

{
"id": 1074,
"client_id": 356259,
"device_id": "00000000-0000-4000-8000-000000000000"
}

Shukah đã lưu một dòng thiết bị mới (1074) cho người gọi. Không API nào xóa nó, nên dòng giả vẫn còn trên dev.

Lỗi đã thấy. Chưa capture lỗi nào.

FieldShukahLocateGhi chú
device_id (body)Device id. Shukah lưu một dòng thiết bị mới cho người gọi ở mỗi lời gọi (2026-10-02).Được echo lại. Không validate, không lưu.
id (response)Id của dòng thiết bị mới (1074).Luôn là 920, cho mọi caller.Một giá trị giả cố định.
client_id (response)Id của người gọi (356259).Luôn là 356315, không phải id của người gọi.Một giá trị giả cố định.
device_id (response)Được echo.Được echo; một id mẫu cố định khi body không có.
AuthorizationApp gửi token của nó. Shukah có yêu cầu nó hay không: Chưa được tài liệu hóa.Không cần, không kiểm tra.
Tác dụngMột dòng thiết bị được lưu cho người gọi (2026-10-02).Không có: không có gì được lưu.App đánh dấu thiết bị là đã gửi và không bao giờ thử lại, dù không có gì được lưu.

GET /maeda/client/status​

Chưa có thay thế từ Locate — bất cứ thứ gì gọi route này vẫn gọi Shukah.

URL dev đầy đủ: https://dev-api.shukah.com/maeda/client/status

Shape của request. Chưa được tài liệu hóa. Snapshot app ngày 2026-02-26 khai báo endpoint này, nhưng không có code nào trong đó gọi endpoint, nên request mà nó sẽ gửi không rõ.

curl -s "$SHUKAH_BASE_URL/maeda/client/status" -H "Authorization: Bearer $SHUKAH_TOKEN"

Response Shukah đã capture. 404, 320 ms (capture trên dev, 2026-10-02): Shukah dev không có route như vậy.

{
"name": "Not Found",
"message": "The route maeda/client/status could not be found.",
"code": 0,
"status": 404,
"type": "Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException"
}

Lỗi đã thấy. 404 ở trên.

Những gì đã biết:

  • Bảng traffic production ngày 2026-10-02 cho thấy 768 lời gọi tới route này trong 3 ngày, nên có thứ gì đó gọi nó trên production. Client nào gửi chúng: Chưa được tài liệu hóa. App 2.31.5 mới hơn snapshot, nên hãy hỏi team mobile màn hình nào gọi nó.
  • Shukah dev trả 404: route bị thiếu trong bản port Laravel trên dev. Production có còn phục vụ nó hay không: Chưa được tài liệu hóa. Nếu app 2.31.5 gọi nó, lời gọi đó hiện fail trên dev.
  • Không tìm thấy route Locate nào cho nó. Không code nào đã đọc cho audit (snapshot app, auth service, order-v2 và ba backend Locate khác) gọi nó; route status riêng của order-v2 là một kiểm tra disaster-recovery và không liên quan. Route làm gì: Chưa được tài liệu hóa.

GET /maeda/client/delete​

Chưa có thay thế từ Locate — app vẫn gọi Shukah.

URL dev đầy đủ: https://dev-api.shukah.com/maeda/client/delete

Cảnh báo: route này xóa tài khoản, và nó là một GET. Nó chưa bao giờ được gọi khi viết trang này, với bất kỳ token nào. Cố ý không có lệnh chạy được ở đây. Đừng chạy nó với một tài khoản thật, và đừng để một link preview, một crawler hay một health check gọi nó.

Shape của request. GET, không có query nào ngoài language, không có body. Authorization: Bearer <stored token> là input duy nhất. Lý do mà user chọn trên màn hình xóa không được gửi.

Response Shukah đã capture. Không có: chưa bao giờ được gọi. App không kỳ vọng body. Khi thành công app đăng xuất user ở local. Một 401 khiến app xóa token đã lưu.

Lỗi đã thấy. Không có.

Những gì đã biết:

  • Không route nào trong auth service, point service hay order-v2 xóa một tài khoản. App vẫn gọi route Shukah này, route cần một token mà Shukah chấp nhận (xem Token).
  • Shukah làm gì với bản ghi (soft delete, đổi status) và điều đó đến Locate như thế nào: Chưa được tài liệu hóa. Không code Locate nào set một client là đã xóa.

API điểm​

GET /maeda/client/points​

Thay thế bằng Locate: GET /api/v2/client/points

URL dev đầy đủ: https://dev-api.shukah.com/maeda/client/points

Request. Bearer token, language. Không có tham số nào khác. Một caller thứ hai của app (package food-court) thêm x-auth-from: SHUKAH.

curl -s "$SHUKAH_BASE_URL/maeda/client/points" -H "Authorization: Bearer $SHUKAH_TOKEN"

Response Shukah đã capture. 200, 251 ms.

{
"id": "356259",
"user_id": "356259",
"points": "514853.64",
"pointsExpirationDate": "2026-11-30"
}

Capture trên dev, 2026-10-02 (client 356259). Vào 2026-10-01 cùng lời gọi trả "128712.41", nên dữ liệu Shukah dev đã thay đổi trong khoảng đó.

Lỗi đã thấy. Không có token, 401, body Laravel (capture trên dev, 2026-10-01).

FieldShukahLocateGhi chú
idClient id dạng text.Client id dạng text.
user_idGiống id.Giống id.
pointsChuỗi với hai chữ số thập phân: "514853.64" (2026-10-02).Chuỗi với tối đa bốn chữ số thập phân: "514405.6788" (cùng client, cùng ngày, với một token Shukah).App dùng Number(points) || 0. Locate thấp hơn 447.96 điểm, khoảng 0.09%. Dòng ledger mới nhất của Locate cũ hơn của Shukah hai ngày, khớp với khoảng chênh (suy luận).
pointsExpirationDate"2026-11-30"."2026-11-28".Sớm hơn hai ngày; null trừ khi quy tắc hết hạn áp dụng.
AuthorizationMột token Shukah.Chỉ token Shukah trên dev hiện nay: một JWT Locate nhận 401 Invalid or expired token (capture trên dev, 2026-10-02). Vào 2026-10-01 cả hai đều chạy.App phải giữ một token Shukah cho route này. Xem Token.
Body lỗiBody Laravel.Envelope của point-service.
Các header app-versionShukah có gửi chúng trên URL này hay không: Chưa được tài liệu hóa.Không gửi. URL Locate cũng chứa client/points, nên app sẽ tìm.Xem Request header.

GET /maeda/point-rate​

Thay thế bằng Locate: GET /api/v2/client/system_configs/point_rates

URL dev đầy đủ: https://dev-api.shukah.com/maeda/point-rate

Public trên Shukah: 200 khi không có token. App chỉ gọi route Locate thay thế ở chế độ Merchant (enableMerchantService: true trong client settings).

Request. Không có tham số nào ngoài language.

curl -s "$SHUKAH_BASE_URL/maeda/point-rate"

Response Shukah đã capture. 200, 235 ms.

[
{"amount_from": 0, "amount_to": 139, "point_earn": 2},
{"amount_from": 140, "amount_to": 153, "point_earn": 12},
{"amount_from": 154, "amount_to": 250, "point_earn": 16},
{"amount_from": 251, "amount_to": 450, "point_earn": 20},
{"amount_from": 451, "amount_to": null, "point_earn": 30}
]

Capture trên dev, 2026-10-01.

Lỗi đã thấy. Không có.

FieldShukahLocateGhi chú
amount_fromInteger, bắt đầu từ 0.Bắt đầu từ 70.App thêm một dòng bên dưới dòng đầu, nên một tổng dưới 70 hiển thị 0 điểm trên Locate.
amount_toInteger, null ở dòng cuối. Các khoảng không chồng lên nhau (139, rồi 140).Integer, null ở dòng cuối. Các khoảng dùng chung giá trị cuối (140 kết thúc một dòng và bắt đầu dòng kế tiếp).Một tổng chính xác 140 hoặc 251 có thể khớp hai dòng.
point_earn2, 12, 16, 20, 30.2, 4, 10, 16.Các bậc khác nhau trên dev.
Số dòngNăm.Bốn: 70-140, 140-251, 251-451, 451 trở lên (capture trên dev, 2026-10-01).Bảng nào là đúng: Chưa được tài liệu hóa.
Câu trả lời rỗngChưa được tài liệu hóa.[] khi tùy chọn chưa được đặt.App đọc dòng đầu mà không kiểm tra.
AuthorizationKhông cần.Không cần.
Quy tắc creditKhông áp dụng.order-v2 vẫn tính số điểm một order tích được từ bảng của Shukah.Thẻ có thể khác với số điểm thực sự được credit.

GET /maeda/giftcard-code/use​

Thay thế bằng Locate: POST /api/v2/client/gift-card-code

URL dev đầy đủ: https://dev-api.shukah.com/maeda/giftcard-code/use?code=<code>

Request. Bearer token. Query code. App chỉ gọi route Locate thay thế ở chế độ Merchant (enableMerchantService: true).

Cảnh báo: một GET mà cộng điểm khi code hợp lệ. Nó chưa bao giờ được gọi khi viết trang này.

# Credits points if the code is valid. Use a code you may spend.
curl -s -G "$SHUKAH_BASE_URL/maeda/giftcard-code/use" -H "Authorization: Bearer $SHUKAH_TOKEN" --data-urlencode "code=$GIFT_CODE"

Response Shukah đã capture. Không có: nó cộng điểm. App kỳ vọng sáu key: total_points, date_created, description, message, points_type, trans_type. Giá trị thật của Shukah: Chưa được tài liệu hóa.

Lỗi đã thấy. Chưa capture lỗi nào.

FieldShukahLocateGhi chú
Method và codeGET với ?code=.POST với {"code":"<code>"} trong body.Đổi method, URL và nơi đặt code.
total_points, date_created, description, message, points_type, trans_type (response)Sáu key mà app parse. Giá trị thật: Chưa được tài liệu hóa.Cùng sáu key. date_created là yyyy-mm-dd hh:mm:ss theo giờ Ả Rập.App parse cùng các key ở cả hai chế độ.
Kho codeCác code của chính Shukah.Các code trong merchant database của order-v2. Các code do Shukah phát hành có ở đó không: Chưa được tài liệu hóa.Một code chạy được trên Shukah có thể bị từ chối.
AuthorizationMột token Shukah.Cùng cách kiểm tra token như các route điểm (qua /api/v1/users); chưa capture với token.
Khoản credit đáp xuống đâuKhông áp dụng.Shukah hoặc point service, theo một server flag (mặc định tắt: Shukah trước). Giá trị trên dev: Chưa được tài liệu hóa.Với flag tắt, số dư Locate chỉ thay đổi sau khi sync.
Body lỗiChưa được tài liệu hóa.Nest: {"message":"Unauthorized","statusCode":401} cho token bị thiếu.

GET /maeda/client/point-history​

Thay thế bằng Locate: GET /api/v2/client/point-history

URL dev đầy đủ: https://dev-api.shukah.com/maeda/client/point-history

Request. Bearer token. Không có page hay limit.

curl -s "$SHUKAH_BASE_URL/maeda/client/point-history" -H "Authorization: Bearer $SHUKAH_TOKEN"

Response Shukah đã capture. 200, 2,254 ms: một mảng JSON gồm 8,134 dòng (8,136 vào 2026-10-02). Dòng earn đầu tiên:

{
"shukah_id": 1351762,
"total_points": 0.5,
"date_created": "2026-10-01 10:40:44",
"description": "Points gained by buy item Order ID L07678739",
"message": "",
"points_type": "earn",
"trans_type": "adjustment"
}

Capture trên dev, 2026-10-01 (client 356259), dòng đầu tiên trong 8,134 dòng (capture giữ 10 dòng đầu, tất cả đều là dòng earn). Các dòng expense không có trong các dòng đã lưu; 14 key của chúng (id, client_id, merchant_id, order_id, total_points dạng chuỗi như "684.00", status, date_created, ip_address, total_points_amt, trans_type, points_type, remarks, external_id, description) lấy từ báo cáo parity của point service, locate-point-service: docs/reports/2026-07-17-client-api-parity.md (đo vào 2026-07-17).

Lỗi đã thấy. Không có token, 401, body Laravel (capture trên dev, 2026-10-01).

FieldShukahLocateGhi chú
Phân trangKhông có: toàn bộ lịch sử.page và limit, mặc định 20, tối đa 100.App không gửi cái nào, nên nó sẽ hiển thị 20 dòng mới nhất.
shukah_id (earn)Integer.Integer, hoặc null cho các dòng Locate đã ghi.
total_points (earn)Một số.Một số.Không có chênh thang đo vào 2026-10-02: 2, 2, 2, 2, 10 trên các dòng mới nhất của Shukah (0.5, 0.5, 2.5 vào 2026-10-01).
date_createdYYYY-MM-DD HH:mm:ss, Riyadh.Giống vậy.Dòng mới nhất 2026-10-01 17:00:01 trên Shukah, 2026-09-29 12:45:07 trên Locate (2026-10-02): Locate bị trễ.
descriptionText, ví dụ Points gained by buy item Order ID L07678739."" trên 8 trong 9 dòng earn trong 10 dòng đầu, manual credit trên một dòng (2026-10-02).App sẽ hiển thị một dòng trống.
message""."".
points_typeearn hoặc expenses.Giống vậy.
trans_typeadjustment trên các dòng earn đã capture.adjustment trên earn, order trên dòng expense đã capture.
id của expenseMột integer.Một chuỗi 24 ký tự.Type lịch sử của app không có id.
total_points của expenseMột chuỗi với hai chữ số thập phân.Một chuỗi với chính xác hai chữ số thập phân ("360.00").
Expense client_id, merchant_id, order_id, status, ip_address, total_points_amt, remarks, external_idCó trên các dòng expense của Shukah (báo cáo parity tháng 7 năm 2026); chưa capture giá trị.Có: status luôn là "active", ip_address luôn là "", external_id luôn là null.
Dòng hết hạnMột dòng earn âm.Một dòng expense với số tiền dương cho các lần hết hạn từ 2026-09-16; các dòng cũ hơn là dòng earn âm.
Body lỗiBody Laravel.Envelope của point-service.

GET /maeda/point-offer​

Thay thế bằng Locate: GET /api/v2/client/point-offers

URL dev đầy đủ: https://dev-api.shukah.com/maeda/point-offer

Public trên Shukah: 200 khi không có token.

Request. Không có tham số nào cho list. App cũng gọi nó với ?id=<id> rồi tự chọn offer ra khỏi danh sách trả về.

curl -s "$SHUKAH_BASE_URL/maeda/point-offer"

Response Shukah đã capture. 200, 235 ms: năm offer.

[
{"id": 1, "point_amount": 100, "purchased_point_amount": 110, "amount": "40.00"},
{"id": 2, "point_amount": 200, "purchased_point_amount": 240, "amount": "60.00"},
{"id": 3, "point_amount": 300, "purchased_point_amount": 360, "amount": "90.00"},
{"id": 4, "point_amount": 400, "purchased_point_amount": 480, "amount": "120.00"},
{"id": 5, "point_amount": 500, "purchased_point_amount": 600, "amount": "150.00"}
]

Capture trên dev, 2026-10-01.

Lỗi đã thấy. Không có.

FieldShukahLocateGhi chú
idInteger, 1 đến 5.Chuỗi 24 ký tự, ví dụ 6a46104f3dd7b3dd6a261d90.Đừng bao giờ trộn hai loại: Locate từ chối integer của Shukah.
point_amountInteger.Giá trị bằng nhau vào 2026-10-01.
purchased_point_amountInteger.Giá trị bằng nhau, nhưng có thể là null khi offer không có giá bằng điểm.App khai báo kiểu của nó là number.
amountChuỗi với hai chữ số thập phân.Giá trị bằng nhau vào 2026-10-01.
?id= (query)Trả về toàn bộ danh sách.Được chấp nhận và bỏ qua: lại toàn bộ danh sách.Cách tự chọn phía client của app chạy được với các id mới.
AuthorizationKhông cần.Bắt buộc: 401 khi không có token (capture trên dev, 2026-10-01).Một màn hình hiển thị offer trước khi đăng nhập sẽ lỗi.
Thứ tựChưa được tài liệu hóa.Theo sequence do admin đặt, rồi Shukah id.
Body lỗiChưa được tài liệu hóa (public).Envelope của point-service.

GET /maeda/point-occasion​

Thay thế bằng Locate: GET /api/v2/client/point-occasions

URL dev đầy đủ: https://dev-api.shukah.com/maeda/point-occasion

Public trên Shukah: 200 khi không có token.

Request. Không có tham số nào cho list; app cũng gọi nó với ?id=<id> và tự lọc danh sách.

curl -s "$SHUKAH_BASE_URL/maeda/point-occasion"

Response Shukah đã capture. 200, 249 ms: bảy occasion.

[
{"id": 1, "occasion": "Birthday", "occasion_en": "Birthday", "is_custom": 0},
{"id": 2, "occasion": "Born", "occasion_en": "Born", "is_custom": 0},
{"id": 3, "occasion": "Gift", "occasion_en": "Gift", "is_custom": 0},
{"id": 4, "occasion": "Wedding", "occasion_en": "Wedding", "is_custom": 0},
{"id": 5, "occasion": "Graduation", "occasion_en": "Graduation", "is_custom": 0},
{"id": 6, "occasion": "Thank", "occasion_en": "Thank", "is_custom": 1},
{"id": 7, "occasion": "Other", "occasion_en": "Other", "is_custom": 1}
]

Capture trên dev, 2026-10-01.

Lỗi đã thấy. Không có.

FieldShukahLocateGhi chú
idInteger, 1 đến 7.Chuỗi 24 ký tự.Đừng bao giờ trộn hai loại.
occasionText tiếng Anh.Tiếng Anh, hoặc tiếng Ả Rập khi language chính xác là ar.App gửi ar-SA, nên không bao giờ nhận được nhãn tiếng Ả Rập.
occasion_enText tiếng Anh.Giá trị bằng nhau vào 2026-10-01.Type của app đọc occasionEn, nên tên tiếng Anh của nó hiện là undefined ở cả hai phía.
is_custom0 hoặc 1.Giá trị bằng nhau vào 2026-10-01.
?id= (query)Trả về toàn bộ danh sách.Bị bỏ qua: lại toàn bộ danh sách.
AuthorizationKhông cần.Bắt buộc: 401 khi không có token.
Body lỗiChưa được tài liệu hóa (public).Envelope của point-service.

POST /maeda/point-order​

Thay thế bằng Locate: POST /api/v2/client/point-orders

URL dev đầy đủ: https://dev-api.shukah.com/maeda/point-order

Request (từ app). JSON point_offer_id (string), to_client_id (string), payment_type (point, hoặc với thanh toán online là giá trị payment từ common settings: payfort, hyperpay hoặc checkout), và tùy chọn point_occasion_id và occasion (text tự do). Không có idempotency key: một POST được thử lại tạo order thứ hai.

Cảnh báo: tạo một order. payment_type point làm điểm di chuyển ngay (người gửi trả một markup: 110 cho 100). Chỉ thử checkout, vốn ở lại trạng thái chưa thanh toán. Mỗi loại được gọi một lần trên dev ngày 2026-10-02, được người dùng chấp thuận (order 1256 và 1257).

# Creates an unpaid order on dev.
curl -s -X POST "$SHUKAH_BASE_URL/maeda/point-order" -H "Authorization: Bearer $SHUKAH_TOKEN" -H "Content-Type: application/json" -d "{\"point_offer_id\":\"$OFFER_ID\",\"to_client_id\":\"$TO_CLIENT_ID\",\"payment_type\":\"checkout\"}"

Response Shukah đã capture. 201, 320 ms: một order checkout tới chính id của client.

{
"point_order_id": 1256,
"payment_point_order_id": "p-1256",
"client_id": 356259,
"to_client_id": 356259,
"point_amount": 100,
"purchased_point_amount": 110,
"amount": "40.00",
"status": "initial_order",
"payment_type": "checkout",
"point_occasion_id": null,
"occasion": "",
"description": ""
}

Capture trên dev, 2026-10-02 (client 356259). Order point (1257, tới một client dev khác) có cùng mười hai key, với status là successful. Nó làm số dư Shukah giảm 110 và để nguyên số dư Locate.

Create trả lời với cùng các key như các dòng order của danh sách quà đã gửi. App cũng kỳ vọng chúng, trừ việc nó khai báo occasion_id: Shukah gửi point_occasion_id (một số hoặc null), nên occasionId của app luôn là undefined.

Lỗi đã thấy. Chưa capture lỗi nào.

FieldShukahLocateGhi chú
point_offer_id (body)Integer dạng text.Chuỗi 24 ký tự từ danh sách Locate.Một integer Shukah là 400.
to_client_id (body)Chuỗi của id.Một số nguyên dương; một numeric string được chấp nhận.
payment_type (body)point, payfort, hyperpay hoặc checkout.Chỉ point hoặc checkout.payfort và hyperpay là 400. Nếu settings ghi payfort hoặc hyperpay, create lỗi.
point_occasion_id (body)Integer dạng text.Chuỗi 24 ký tự, hoặc không có.
occasion (body)Text tự do.Đã trim, 1 đến 255 ký tự.
HTTP status201.200 (capture trên dev, 2026-10-02).Không có khi app chấp nhận mọi 2xx.
point_order_id (response)Integer.Không trả về. Order id là UUID correlation_id.Các route pay và get nhận nó trong path.
client_id, to_client_id, amount, occasion, point_occasion_id, description, payment_point_order_id (response)App có đọc, và kỳ vọng occasion_id trong khi các dòng order của Shukah có point_occasion_id.Không trả về.Object order phải được dựng lại từ các key mới.
correlation_id, order_no, payment_status, money_amount, order_type (response)Không trả về.Mới: UUID, số từ 100000, trạng thái gateway hoặc null, chuỗi hai chữ số thập phân, gift hoặc transfer.
status, point_amount, purchased_point_amount, payment_type (response)Các từ status của app: initial_order, payment_failed, successful, paid.Cùng các từ đó (một order Locate chỉ đạt tới ba từ đầu).
FlagKhông có.point cần POINT_ORDER_POINT_ENABLED; tắt trả 403. Bật trên dev (probe 2026-10-01); production chưa xác nhận.
Tự tặngĐược phép.Được phép với checkout, 400 với point.
Số dư sau một order pointChỉ số dư Shukah giảm (110 cho order 1257).Chỉ số dư Locate giảm (110 cho order 100012).Các ledger không được đồng bộ khi tiêu điểm (dev, 2026-10-02, trong vài giây của lần chạy; việc nó có tới sau đó hay không thì chưa được kiểm tra). Hãy đọc số dư và lịch sử ở chính bên tạo order.
Body lỗiChưa được tài liệu hóa.Envelope của point-service.

POST /maeda/point-order/get-description​

Thay thế bằng Locate: POST /api/v2/client/point-orders/description

URL dev đầy đủ: https://dev-api.shukah.com/maeda/point-order/get-description

Request (từ app). JSON point_offer_id (string), tùy chọn point_occasion_id (string) và occasion (text tự do). App gọi nó hai lần cho mỗi order. Nó không ghi gì.

curl -s -X POST "$SHUKAH_BASE_URL/maeda/point-order/get-description" -H "Authorization: Bearer $SHUKAH_TOKEN" -H "Content-Type: application/json" -d '{"occasion":"","point_offer_id":"1","point_occasion_id":"1"}'

Response Shukah đã capture. 200, 857 ms. Một description rỗng.

{
"description": ""
}

Capture trên dev, 2026-10-01 (client 356259), với body trong curl ở trên, và lại vào 2026-10-02 với cùng câu trả lời. Mọi body đã thử vào 2026-10-01 đều trả cùng kết quả: id dạng text, id dạng số, và với text tự do. Tài liệu của point service nói Shukah đã trả câu đầy đủ vào 2026-09-21 (locate-point-service: docs/integrations/2026-07-16-client-facing-point-apis.md, thay đổi lần cuối 2026-09-22). Vì sao giờ nó rỗng: Chưa được tài liệu hóa.

Lỗi đã thấy. Chưa capture lỗi nào.

FieldShukahLocateGhi chú
point_offer_id (body)Integer dạng text.Chuỗi 24 ký tự.Một integer Shukah là 400.
point_occasion_id (body)Integer dạng text.Chuỗi 24 ký tự, hoặc không có.
occasion (body)Text tự do.Text tự do; khi nó không rỗng nó thắng occasion id.
description (response)"" trên dev hôm nay. Câu đầy đủ theo tài liệu ngày 2026-09-21.You have received a gift Birthday of 100 points from Test User (*****0000) (capture trên dev, 2026-10-01).Với Shukah ô lời nhắn hiện nay sẽ rỗng.
Câu vănCùng cách diễn đạt; một khoảng trắng đôi khi không có occasion.Cùng cách diễn đạt và cùng khoảng trắng đôi.Đừng trim nó.
AuthorizationMột token Shukah.Một token Shukah (200 trên dev, 2026-10-02). Một JWT Locate chưa được thử ở đây; cùng bước kiểm tra đó cho nó 401 trên các route point khác.Xem Token.
Body lỗiChưa được tài liệu hóa.Envelope của point-service.

POST /maeda/order/checkout-payment-standalone​

Thay thế bằng Locate: POST /api/v2/client/point-orders/:correlation_id/pay/card

URL dev đầy đủ: https://dev-api.shukah.com/maeda/order/checkout-payment-standalone

Cùng route Shukah này cũng thanh toán order nhà hàng. Mục này nói về việc dùng nó cho point order.

Cảnh báo: tính tiền một thẻ đã lưu tại payment gateway. Không có lệnh chạy được ở đây, và nó chưa bao giờ được gọi khi viết trang này.

Shape của request. JSON {"id": "<saved card id>", "cvv": "<cvv>", "point_order_id": "<order id>"}. id là card.tokenName của app. point_order_id là một chuỗi: các body payment của app 2.31.5 được capture trên dev vào 2026-10-02 gửi nó là "1252" và "1253".

Response Shukah đã capture. Không có: nó tạo một khoản thanh toán. App kỳ vọng id, status, reference, 3ds (downgraded, enrolled) và _links (self, actions, redirect.href).

Lỗi đã thấy. Shukah dev trả lời các route thanh toán point-order bằng 422 (được báo cáo vào 2026-10-02, từ app 2.31.5 trên dev): {"name":"Unprocessable Content","message":"Checkout payment is not configured properly.","code":0,"status":422,"type":"Symfony\\Component\\HttpKernel\\Exception\\HttpException"}. Shukah dev hiện không nhận được một khoản thanh toán point. Lỗi thanh toán đến từ payment service dưới dạng 4xx riêng của nó.

FieldShukahLocateGhi chú
id (body)Id thẻ đã lưu.Giống vậy.
cvv (body)Mã bảo mật.Một string hoặc số, 1 đến 8 ký tự. Được forward, không lưu.
point_order_id (body)Một chuỗi như "1252", trong body (app 2.31.5, 2026-10-02).Được chấp nhận và bỏ qua. Order là UUID correlation_id trong path.App chỉ giữ pointOrderId; nó phải giữ id mới từ create.
payment_type (body)Không gửi trên route này.Được chấp nhận và bỏ qua.
ResponseApp kỳ vọng 3ds.downgraded và _links.redirect.Body của payment service không đổi; sample của nó có 3ds.is_redirect. Một khoản thanh toán bị từ chối có thể không có _links.redirect.Hãy kiểm tra bước bắt đầu 3-D Secure với một response thật.
FlagKhông có.POINT_ORDER_CARD_ENABLED; tắt trả 403 trước mọi lần đọc. Bật trên dev (probe 2026-10-01); production chưa xác nhận.
Body lỗiCủa chính payment service.Được chuyển tiếp không đổi cho lỗi thanh toán; nếu không là envelope của point-service.

POST /maeda/order/checkout-payment-flow​

Thay thế bằng Locate: POST /api/v2/client/point-orders/:correlation_id/pay/session

URL dev đầy đủ: https://dev-api.shukah.com/maeda/order/checkout-payment-flow

Cũng được dùng cho order nhà hàng. Mục này nói về point order.

Cảnh báo: mở một payment session tại payment gateway. Không có lệnh chạy được ở đây. Các tài liệu chưa bao giờ gọi nó; app 2.31.5 đã gọi nó trên dev vào 2026-10-02, và Shukah dev trả 422 (chưa được cấu hình).

Shape của request. JSON {"point_order_id": "<order id>", "payment_type": "<wallet>", "rememberMe": true or false}. App 2.31.5 đã gửi {"point_order_id":"1253","payment_type":"applePay","rememberMe":false} (capture trên dev, 2026-10-02). point_order_id là một chuỗi. Snapshot app cũng cho phép stcpay và card làm payment_type, nhưng app 2.31.5 gửi STC Pay tới route riêng của nó, checkout-payment-stcpay.

Response Shukah đã capture. Không có. App kỳ vọng id, payment_session_secret, payment_session_token và _links.self.href.

Lỗi đã thấy. Lời gọi của app 2.31.5 ở trên, 422 (capture trên dev, 2026-10-02): {"name":"Unprocessable Content","message":"Checkout payment is not configured properly.","code":0,"status":422,"type":"Symfony\\Component\\HttpKernel\\Exception\\HttpException"}.

FieldShukahLocateGhi chú
point_order_id (body)Một chuỗi như "1253" (app 2.31.5, 2026-10-02).Được chấp nhận và bỏ qua. Order là UUID correlation_id trong path.
payment_type (body)applePay trong capture 2.31.5. Snapshot cũng cho phép stcpay và card.Được chấp nhận và bỏ qua. Checkout session cung cấp các wallet.Wallet không còn được chọn ở server.
rememberMe (body)Boolean.true, false, "true" hoặc "false"; mặc định false. Mọi giá trị khác là 400.
ResponseApp kỳ vọng id, payment_session_secret, payment_session_token, _links.self.Session của payment service, không đổi, với cùng các key.
FlagKhông có.POINT_ORDER_CARD_ENABLED, như ở trên.
Body lỗiChưa được tài liệu hóa.Envelope của point-service.

GET /maeda/points-faq​

Thay thế bằng Locate: GET /api/v2/client/points-faq

URL dev đầy đủ: https://dev-api.shukah.com/maeda/points-faq

Public trên Shukah: 200 khi không có token.

Request. Không có tham số.

curl -s "$SHUKAH_BASE_URL/maeda/points-faq"

Response Shukah đã capture. 200, 233 ms: năm mục. Mục đầu tiên (text tiếng Ả Rập được rút ngắn ở đây):

{
"title_ar": "…",
"text_ar": "…",
"title_en": "How many points are worth in the Locate App?",
"text_en": "each point equal to 0.25 SR\r\nthat means, each 4 points equal to one SR"
}

Capture trên dev, 2026-10-01. Mảng năm mục bằng của Locate, kể cả thứ tự key.

Lỗi đã thấy. Không có.

FieldShukahLocateGhi chú
title_ar, text_ar, title_en, text_enChuỗi.Bằng nhau vào 2026-10-01.Drop-in.
AuthorizationKhông cần.Bắt buộc: 401 khi không có token (capture trên dev, 2026-10-01).Một màn hình hiển thị FAQ trước khi đăng nhập sẽ lỗi.
Body lỗiChưa được tài liệu hóa (public).Envelope của point-service.
Content-Typeapplication/jsonapplication/json; charset=utf-8

GET /maeda/point-order​

Chưa có thay thế từ Locate — app vẫn gọi Shukah.

URL dev đầy đủ: https://dev-api.shukah.com/maeda/point-order?page=<n>&per-page=<n>

Đây là tab "Sent gifts": danh sách duy nhất các món quà mà một user đã gửi.

Request. Bearer token. Query page và per-page.

curl -s -G "$SHUKAH_BASE_URL/maeda/point-order" -H "Authorization: Bearer $SHUKAH_TOKEN" --data-urlencode "page=1" --data-urlencode "per-page=20"

Response Shukah đã capture. 200, 251 ms, một mảng trần gồm 20 order cho page=1&per-page=20 (capture trên dev, 2026-10-02). Cái đầu tiên:

{
"point_order_id": 1255,
"payment_point_order_id": "p-1255",
"client_id": 356259,
"to_client_id": 356259,
"point_amount": 200,
"purchased_point_amount": 240,
"amount": "60.00",
"status": "initial_order",
"payment_type": "checkout",
"point_occasion_id": 3,
"occasion": "Gift",
"description": ""
}

App kỳ vọng một mảng order với point_order_id, client_id, to_client_id, point_amount, purchased_point_amount, amount, status, payment_type, occasion, occasion_id, description và payment_point_order_id. Shukah gửi point_occasion_id, không phải occasion_id, nên occasion id của app là undefined. App cũng đọc các response header x-pagination-total-count và x-pagination-page-count; capture không lưu response header.

Lỗi đã thấy. Không có.

Những gì đã biết:

  • Không route Locate nào liệt kê các point order của một client. Point service và order-v2 chỉ có create, get theo correlation_id, description và hai route pay. Không kế hoạch nào nêu một route list.
  • Gift checkout mở tab này sau khi thanh toán, nên một order tạo qua Locate không hiển thị ở đó.
  • Locate có một route get-theo-correlation_id, nhưng nó mới và không phải là thay thế cho list này. App cũng có GET /maeda/point-order/<id> trong code, nhưng không màn hình nào gọi nó.

POST /maeda/order/checkout-payment​

Chưa có thay thế từ Locate — app vẫn gọi Shukah.

URL dev đầy đủ: https://dev-api.shukah.com/maeda/order/checkout-payment

Cảnh báo: tạo một khoản thanh toán tại payment gateway. Không có lệnh chạy được ở đây.

Shape của request. JSON {"payment_token": "<Checkout.com Frames token>", "point_order_id": <order id>}. App dùng nó cho quà tặng điểm khi nó lấy một card token từ Checkout.com Frames.

Response Shukah đã capture. Không có. App kỳ vọng cùng các key như route standalone (id, status, reference, 3ds, _links).

Lỗi đã thấy. Không có.

Những gì đã biết: Locate cung cấp hai cách để thanh toán một point order, một thẻ đã lưu và một session. Một Frames token không có đối tác. App nên dùng lời gọi Locate nào thay thế: Chưa được tài liệu hóa.

POST /maeda/order/checkout-payment-stcpay​

Chưa có thay thế từ Locate — app vẫn gọi Shukah.

URL dev đầy đủ: https://dev-api.shukah.com/maeda/order/checkout-payment-stcpay

Cảnh báo: bắt đầu một khoản thanh toán STC Pay. Không có lệnh chạy được ở đây.

Shape của request. JSON {"point_order_id": "<order id>", "environment": "sandbox" or "production"}. App 2.31.5 đã gửi {"point_order_id":"1252","environment":"sandbox"} (capture trên dev, 2026-10-02): point_order_id là một chuỗi.

Response Shukah đã capture. Không có. App kỳ vọng một chuỗi (phần bắt đầu STC Pay).

Lỗi đã thấy. Lời gọi của app 2.31.5 ở trên, 422 (capture trên dev, 2026-10-02): {"name":"Unprocessable Content","message":"Checkout payment is not configured properly.","code":0,"status":422,"type":"Symfony\\Component\\HttpKernel\\Exception\\HttpException"}.

Những gì đã biết: Locate coi STC Pay là một wallet bên trong route pay-session và không dùng một endpoint STC Pay riêng cho point order.

POST /maeda/order/payfort-token​

Chưa có thay thế từ Locate — app vẫn gọi Shukah.

URL dev đầy đủ: https://dev-api.shukah.com/maeda/order/payfort-token

Cảnh báo: bắt đầu một khoản thanh toán PayFort. Không có lệnh chạy được ở đây.

Shape của request. JSON với point_order_id, device_id, digital_wallet, type: "GiftOrder" và tùy chọn promo_code. Dùng cho đường thẻ PayFort và đường Apple Pay của một món quà điểm.

Response Shukah đã capture. Không có. App kỳ vọng một response payment-token; các key của nó: Chưa được tài liệu hóa.

Lỗi đã thấy. Không có.

Những gì đã biết: PayFort nằm ngoài phạm vi của point order Locate ("deferred by design"). Khi giá trị payment của common settings không phải checkout, app gửi các khoản thanh toán thẻ, Apple Pay và STC Pay của quà điểm tới PayFort, và những khoản đó không thể dùng Locate. order-v2 có một route POST /api/v2/client/payments/sdk-token mà, với type: "GiftOrder", chỉ chuyển tiếp lời gọi tới route Shukah này cùng các header của người gọi. Nó không phải là bản thay thế: nó vẫn cần Shukah và một token mà Shukah chấp nhận.

POST /maeda/order/payfort-stc-pay-checkout​

Chưa có thay thế từ Locate — app vẫn gọi Shukah.

URL dev đầy đủ: https://dev-api.shukah.com/maeda/order/payfort-stc-pay-checkout

Cảnh báo: bắt đầu một khoản thanh toán PayFort STC Pay. Không có lệnh chạy được ở đây.

Shape của request. JSON với type GiftOrder. Các key khác: Chưa được tài liệu hóa.

Response Shukah đã capture. Không có. App kỳ vọng một URL thanh toán STC Pay; các key của nó: Chưa được tài liệu hóa.

Lỗi đã thấy. Không có.

Những gì đã biết: PayFort nằm ngoài phạm vi của point order Locate ("deferred by design"), nên đường STC Pay này vẫn gọi Shukah.