{"openapi":"3.0.3","info":{"title":"ServeU API","version":"1.0.0","description":"Connect your POS, accounting, kitchen screen or automation tool to your ServeU business. Every request needs `Authorization: Bearer <your API key>` from Settings → Developers. Money is in halalas (100 = 1.00 SAR); times are ISO 8601 UTC. Every answer carries `X-Request-Id`; errors are `{ \"error\": { \"code\", \"message\", \"details\"?, \"request_id\" } }` — branch on `code`."},"servers":[{"url":"https://serveu-psi.vercel.app/api/v1"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Business","description":"The business and branches the key belongs to."},{"name":"Orders","description":"QR-menu orders: list, sync, sales summary, and moving an order along."},{"name":"Loyalty","description":"Cards, stamps and points."},{"name":"Menu","description":"Categories and items, including sync by your own codes."},{"name":"Webhooks","description":"Endpoints that receive events."}],"paths":{"/branches":{"get":{"operationId":"listBranches","summary":"Branches","description":"A branch-bound key sees only its own branch.","tags":["Business"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"business:read","x-serveu-errors":["unauthorized","api_disabled","rate_limited","server_error"],"parameters":[],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Branch"}}},"required":["data"],"additionalProperties":false},"example":{"data":[{"id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","name":{"ar":"العليا","en":"Olaya"},"order_types":{"dine_in":true,"pickup":true,"car":true},"open_now":true,"paused":false}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`api_disabled` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["api_disabled"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/business":{"get":{"operationId":"getBusiness","summary":"The business this key belongs to","description":"Use it to check a key: it answers the business and the key's own name, scopes and branch.","tags":["Business"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"business:read","x-serveu-errors":["unauthorized","api_disabled","rate_limited","server_error"],"parameters":[],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Business"},"example":{"id":"3f1c2a9e-5b7d-4c11-9a2e-7d4b8c6e1f20","slug":"nakhla-coffee","name":{"ar":"نخلة كوفي","en":"Nakhla Coffee"},"currency":"SAR","timezone":"Asia/Riyadh","prices_include_vat":true,"vat_rate":15,"paid_gate":"none","program":{"type":"stamps"},"key":{"id":"a9c1e3f5-b7d9-4e1f-8a3c-5e7a9c1e3f5b","name":"Olaya POS","scopes":["loyalty:write"],"branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f"}}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`api_disabled` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["api_disabled"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/cards":{"post":{"operationId":"createCard","summary":"Join a customer","description":"Creates an unverified card for this phone at your business, or answers the existing one (`existing: true`).","tags":["Loyalty"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"loyalty:write","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","business_suspended","invalid_request","conflict","idempotency_conflict","idempotency_in_progress","rate_limited","server_error"],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"1–100 visible ASCII characters, unique per operation (e.g. your receipt number). A retry with the same key and body gets the first answer (header `Idempotent-Replayed: true`); the same key with another body is `409 idempotency_conflict`. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"phone":{"type":"string","minLength":4,"maxLength":40,"description":"E.164 (+9665…) or a Saudi local format (05…)."},"name":{"type":"string","minLength":1,"maxLength":60},"branch_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["phone"]},"example":{"phone":"0500000000","name":"Noura"}}}},"responses":{"201":{"description":"Created","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"type":"object","properties":{"existing":{"type":"boolean"},"card":{"$ref":"#/components/schemas/Card"}},"required":["existing","card"],"additionalProperties":false},"example":{"existing":false,"card":{"id":"5b7d9f1a-3c5e-4f7a-9b1c-3d5e7f9a1b3c","card_number":"•••• 4821 7730","verified":false,"joined_via":"api","joined_at":"2026-11-08T09:41:12.482Z","balance":0,"visits":0,"program":{"type":"stamps","stamps_per_reward":7,"max_stamps_per_visit":5,"points_per_sar":null,"min_bill":null,"max_points_per_visit":null,"reward_name":{"ar":"قهوة مجانية","en":"Free coffee"}},"progress":{"type":"stamps","stamps_to_next":7,"rewards_available":0,"points_to_next":null,"next_reward_id":null,"affordable_reward_ids":[]},"rewards":[]}}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"409":{"description":"`conflict`, `idempotency_conflict`, `idempotency_in_progress`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["conflict","idempotency_conflict","idempotency_in_progress"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/cards/lookup":{"post":{"operationId":"lookupCard","summary":"Find a card by phone or scanned card","description":"Send exactly one of `phone` or `card_token` (the 24 digits from the card's QR, or the card page URL). The phone is never returned without customers:contact.","tags":["Loyalty"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"loyalty:read","x-serveu-errors":["unauthorized","insufficient_scope","api_disabled","invalid_request","not_found","rate_limited","server_error"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"phone":{"type":"string","minLength":4,"maxLength":40,"description":"E.164 (+9665…) or a Saudi local format (05…)."},"card_token":{"type":"string","minLength":1,"maxLength":300}}},"example":{"phone":"0500000000"}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Card"},"example":{"id":"5b7d9f1a-3c5e-4f7a-9b1c-3d5e7f9a1b3c","card_number":"•••• 4821 7730","verified":true,"joined_via":"poster","joined_at":"2026-11-08T09:41:12.482Z","balance":5,"visits":12,"program":{"type":"stamps","stamps_per_reward":7,"max_stamps_per_visit":5,"points_per_sar":null,"min_bill":null,"max_points_per_visit":null,"reward_name":{"ar":"قهوة مجانية","en":"Free coffee"}},"progress":{"type":"stamps","stamps_to_next":2,"rewards_available":0,"points_to_next":null,"next_reward_id":null,"affordable_reward_ids":[]},"rewards":[]}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`insufficient_scope`, `api_disabled` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["insufficient_scope","api_disabled"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/cards/{id}":{"get":{"operationId":"getCard","summary":"Get a card","tags":["Loyalty"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"loyalty:read","x-serveu-errors":["unauthorized","insufficient_scope","api_disabled","invalid_request","not_found","rate_limited","server_error"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Card"},"example":{"id":"5b7d9f1a-3c5e-4f7a-9b1c-3d5e7f9a1b3c","card_number":"•••• 4821 7730","verified":true,"joined_via":"poster","joined_at":"2026-11-08T09:41:12.482Z","balance":5,"visits":12,"program":{"type":"stamps","stamps_per_reward":7,"max_stamps_per_visit":5,"points_per_sar":null,"min_bill":null,"max_points_per_visit":null,"reward_name":{"ar":"قهوة مجانية","en":"Free coffee"}},"progress":{"type":"stamps","stamps_to_next":2,"rewards_available":0,"points_to_next":null,"next_reward_id":null,"affordable_reward_ids":[]},"rewards":[]}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`insufficient_scope`, `api_disabled` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["insufficient_scope","api_disabled"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/cards/{id}/earn":{"post":{"operationId":"earn","summary":"Add stamps or points for a sale","description":"Stamps programs: send `stamps`. Points programs: send `bill_amount` (halalas) and ServeU converts it with the program's rate, minimum and cap. Only for sales rung up on your POS: a ServeU menu order earns by itself when it's served (on the iPad or with the `serve` action), so don't call this for it too.","tags":["Loyalty"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"loyalty:write","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","business_suspended","invalid_request","not_found","idempotency_key_required","idempotency_conflict","idempotency_in_progress","rate_limited","server_error","no_program","below_min_bill","card_cap_reached"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"1–100 visible ASCII characters, unique per operation (e.g. your receipt number). A retry with the same key and body gets the first answer (header `Idempotent-Replayed: true`); the same key with another body is `409 idempotency_conflict`. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"stamps":{"type":"integer","minimum":1,"maximum":20},"bill_amount":{"type":"integer","minimum":0,"maximum":100000000,"description":"Amount in halalas (100 = 1.00 SAR)."},"branch_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"reference":{"description":"Your receipt number; shown in the card's history.","type":"string","minLength":1,"maxLength":100}}},"example":{"stamps":2,"reference":"R-10422"}}}},"responses":{"201":{"description":"Created","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"type":"object","properties":{"replayed":{"type":"boolean"},"capped":{"type":"boolean","description":"True when the per-visit cap reduced the points."},"event":{"$ref":"#/components/schemas/LoyaltyEvent"},"card":{"$ref":"#/components/schemas/Card"}},"required":["replayed","capped","event","card"],"additionalProperties":false},"example":{"replayed":false,"capped":false,"event":{"id":"c9e1a3b5-d7f9-4b1c-8d3e-5f7a9b1c3d5e","card_id":"5b7d9f1a-3c5e-4f7a-9b1c-3d5e7f9a1b3c","kind":"earn","source":"api","program_type":"stamps","amount":2,"bill_amount":null,"reward":null,"branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","order_id":null,"api_key":{"id":"a9c1e3f5-b7d9-4e1f-8a3c-5e7a9c1e3f5b","name":"Olaya POS"},"reference":"R-10422","reason":null,"voided":false,"voided_at":null,"created_at":"2026-11-08T09:41:12.482Z"},"card":{"id":"5b7d9f1a-3c5e-4f7a-9b1c-3d5e7f9a1b3c","card_number":"•••• 4821 7730","verified":true,"joined_via":"poster","joined_at":"2026-11-08T09:41:12.482Z","balance":5,"visits":12,"program":{"type":"stamps","stamps_per_reward":7,"max_stamps_per_visit":5,"points_per_sar":null,"min_bill":null,"max_points_per_visit":null,"reward_name":{"ar":"قهوة مجانية","en":"Free coffee"}},"progress":{"type":"stamps","stamps_to_next":2,"rewards_available":0,"points_to_next":null,"next_reward_id":null,"affordable_reward_ids":[]},"rewards":[]}}}}},"400":{"description":"`invalid_request`, `idempotency_key_required`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","idempotency_key_required"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"409":{"description":"`idempotency_conflict`, `idempotency_in_progress`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["idempotency_conflict","idempotency_in_progress"]}}}}}]}}}},"422":{"description":"`no_program`, `below_min_bill`, `card_cap_reached`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["no_program","below_min_bill","card_cap_reached"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/cards/{id}/events":{"get":{"operationId":"listCardEvents","summary":"A card's history","description":"Newest first, voided events included (`voided: true`).","tags":["Loyalty"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"loyalty:read","x-serveu-errors":["unauthorized","insufficient_scope","api_disabled","invalid_request","not_found","rate_limited","server_error"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` from the previous page.","schema":{"type":"string","maxLength":300,"pattern":"^[A-Za-z0-9_-]+$"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/LoyaltyEvent"}},"next_cursor":{"nullable":true,"description":"Pass as `cursor` for the next page; null on the last page.","type":"string"}},"required":["data","next_cursor"],"additionalProperties":false},"example":{"data":[{"id":"c9e1a3b5-d7f9-4b1c-8d3e-5f7a9b1c3d5e","card_id":"5b7d9f1a-3c5e-4f7a-9b1c-3d5e7f9a1b3c","kind":"earn","source":"api","program_type":"stamps","amount":2,"bill_amount":null,"reward":null,"branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","order_id":null,"api_key":{"id":"a9c1e3f5-b7d9-4e1f-8a3c-5e7a9c1e3f5b","name":"Olaya POS"},"reference":"R-10422","reason":null,"voided":false,"voided_at":null,"created_at":"2026-11-08T09:41:12.482Z"}],"next_cursor":null}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`insufficient_scope`, `api_disabled` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["insufficient_scope","api_disabled"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/cards/{id}/redeem":{"post":{"operationId":"redeem","summary":"Redeem a reward","description":"Stamps programs redeem one full card: nothing is required, but the body must still be JSON, so send `{}` or a `reference`. Points programs need `reward_id` from the card's `rewards`.","tags":["Loyalty"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"loyalty:write","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","business_suspended","invalid_request","not_found","idempotency_key_required","idempotency_conflict","idempotency_in_progress","rate_limited","server_error","no_program","reward_unavailable","not_enough_balance"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"1–100 visible ASCII characters, unique per operation (e.g. your receipt number). A retry with the same key and body gets the first answer (header `Idempotent-Replayed: true`); the same key with another body is `409 idempotency_conflict`. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reward_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"branch_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"reference":{"description":"Your receipt number; shown in the card's history.","type":"string","minLength":1,"maxLength":100}}},"example":{"reference":"R-10423"}}}},"responses":{"201":{"description":"Created","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"type":"object","properties":{"replayed":{"type":"boolean"},"event":{"$ref":"#/components/schemas/LoyaltyEvent"},"card":{"$ref":"#/components/schemas/Card"}},"required":["replayed","event","card"],"additionalProperties":false},"example":{"replayed":false,"event":{"id":"e1f3a5b7-c9d1-4e3f-8a5b-7c9d1e3f5a7b","card_id":"5b7d9f1a-3c5e-4f7a-9b1c-3d5e7f9a1b3c","kind":"redeem","source":"api","program_type":"stamps","amount":-7,"bill_amount":null,"reward":null,"branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","order_id":null,"api_key":{"id":"a9c1e3f5-b7d9-4e1f-8a3c-5e7a9c1e3f5b","name":"Olaya POS"},"reference":"R-10423","reason":null,"voided":false,"voided_at":null,"created_at":"2026-11-08T09:41:12.482Z"},"card":{"id":"5b7d9f1a-3c5e-4f7a-9b1c-3d5e7f9a1b3c","card_number":"•••• 4821 7730","verified":true,"joined_via":"poster","joined_at":"2026-11-08T09:41:12.482Z","balance":2,"visits":12,"program":{"type":"stamps","stamps_per_reward":7,"max_stamps_per_visit":5,"points_per_sar":null,"min_bill":null,"max_points_per_visit":null,"reward_name":{"ar":"قهوة مجانية","en":"Free coffee"}},"progress":{"type":"stamps","stamps_to_next":5,"rewards_available":0,"points_to_next":null,"next_reward_id":null,"affordable_reward_ids":[]},"rewards":[]}}}}},"400":{"description":"`invalid_request`, `idempotency_key_required`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","idempotency_key_required"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"409":{"description":"`idempotency_conflict`, `idempotency_in_progress`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["idempotency_conflict","idempotency_in_progress"]}}}}}]}}}},"422":{"description":"`no_program`, `reward_unavailable`, `not_enough_balance`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["no_program","reward_unavailable","not_enough_balance"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/loyalty-events/{id}/void":{"post":{"operationId":"voidLoyaltyEvent","summary":"Undo an earn or redeem","description":"Voids the event (it stays in history, struck through). Refused if it would take the card below zero.","tags":["Loyalty"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"loyalty:write","x-serveu-errors":["unauthorized","insufficient_scope","api_disabled","business_suspended","invalid_request","not_found","idempotency_key_required","idempotency_conflict","idempotency_in_progress","rate_limited","server_error","already_voided","program_closed","would_go_negative","not_voidable"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"1–100 visible ASCII characters, unique per operation (e.g. your receipt number). A retry with the same key and body gets the first answer (header `Idempotent-Replayed: true`); the same key with another body is `409 idempotency_conflict`. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":200}},"required":["reason"]},"example":{"reason":"Scanned the wrong card"}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"type":"object","properties":{"event":{"$ref":"#/components/schemas/LoyaltyEvent"},"card":{"type":"object","nullable":true,"allOf":[{"$ref":"#/components/schemas/Card"}]}},"required":["event","card"],"additionalProperties":false},"example":{"event":{"id":"c9e1a3b5-d7f9-4b1c-8d3e-5f7a9b1c3d5e","card_id":"5b7d9f1a-3c5e-4f7a-9b1c-3d5e7f9a1b3c","kind":"earn","source":"api","program_type":"stamps","amount":2,"bill_amount":null,"reward":null,"branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","order_id":null,"api_key":{"id":"a9c1e3f5-b7d9-4e1f-8a3c-5e7a9c1e3f5b","name":"Olaya POS"},"reference":"R-10422","reason":null,"voided":true,"voided_at":"2026-11-08T09:41:12.482Z","created_at":"2026-11-08T09:41:12.482Z"},"card":{"id":"5b7d9f1a-3c5e-4f7a-9b1c-3d5e7f9a1b3c","card_number":"•••• 4821 7730","verified":true,"joined_via":"poster","joined_at":"2026-11-08T09:41:12.482Z","balance":3,"visits":11,"program":{"type":"stamps","stamps_per_reward":7,"max_stamps_per_visit":5,"points_per_sar":null,"min_bill":null,"max_points_per_visit":null,"reward_name":{"ar":"قهوة مجانية","en":"Free coffee"}},"progress":{"type":"stamps","stamps_to_next":4,"rewards_available":0,"points_to_next":null,"next_reward_id":null,"affordable_reward_ids":[]},"rewards":[]}}}}},"400":{"description":"`invalid_request`, `idempotency_key_required`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","idempotency_key_required"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"409":{"description":"`idempotency_conflict`, `idempotency_in_progress`, `already_voided`, `program_closed`, `would_go_negative`, `not_voidable`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["idempotency_conflict","idempotency_in_progress","already_voided","program_closed","would_go_negative","not_voidable"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/menu":{"get":{"operationId":"getMenu","summary":"The whole menu","description":"Every category with its items (inactive ones included, `active: false`). One call for a full sync. A key limited to one branch sees only that branch in each item's `branches`.","tags":["Menu"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"menu:read","x-serveu-errors":["unauthorized","insufficient_scope","api_disabled","rate_limited","server_error"],"parameters":[],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"categories":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"external_id":{"nullable":true,"type":"string"},"name":{"type":"object","properties":{"ar":{"type":"string"},"en":{"type":"string"}},"required":["ar","en"],"additionalProperties":false},"sort":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"earns_stamps":{"type":"boolean"},"active":{"type":"boolean"},"items":{"type":"array","items":{"$ref":"#/components/schemas/MenuItem"}}},"required":["id","external_id","name","sort","earns_stamps","active","items"],"additionalProperties":false}}},"required":["categories"],"additionalProperties":false},"example":{"categories":[{"id":"a4b6c8d0-e2f4-4a6b-8c8d-0e2f4a6b8c0d","external_id":"CAT-HOT","name":{"ar":"مشروبات ساخنة","en":"Hot drinks"},"sort":0,"earns_stamps":true,"active":true,"items":[{"id":"f3a5b7c9-d1e3-4f5a-8b7c-9d1e3f5a7b9c","external_id":"POS-1001","category_id":"a4b6c8d0-e2f4-4a6b-8c8d-0e2f4a6b8c0d","name":{"ar":"لاتيه إسباني","en":"Spanish latte"},"description":{"ar":null,"en":"Espresso, milk, condensed milk."},"photo_url":null,"base_price":1700,"calories":210,"prep_minutes":4,"allergens":["milk","caffeine"],"tags":["best_seller"],"reward_eligible":true,"earns_stamps_override":null,"active":true,"sort":0,"sizes":[{"id":"b5c7d9e1-f3a5-4b7c-9d9e-1f3a5b7c9d1e","name":{"ar":"صغير","en":"Small"},"price":1700,"is_default":false},{"id":"c6d8e0f2-a4b6-4c8d-8e0f-2a4b6c8d0e2f","name":{"ar":"وسط","en":"Medium"},"price":2200,"is_default":true}],"option_groups":[{"id":"d7e9f1a3-b5c7-4d9e-9f1a-3b5c7d9e1f3a","name":{"ar":"الحليب","en":"Milk"},"required":true,"min_select":1,"max_select":1,"options":[{"id":"e8f0a2b4-c6d8-4e0f-8a2b-4c6d8e0f2a4b","name":{"ar":"كامل الدسم","en":"Full fat"},"price_delta":0},{"id":"f9a1b3c5-d7e9-4f1a-9b3c-5d7e9f1a3b5c","name":{"ar":"شوفان","en":"Oat"},"price_delta":300}]}],"branches":[{"branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","sold_here":true,"sold_out":false,"stock":null,"stock_updated_at":null}],"updated_at":"2026-11-08T09:41:12.482Z"}]}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`insufficient_scope`, `api_disabled` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["insufficient_scope","api_disabled"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/menu/categories":{"post":{"operationId":"createMenuCategory","summary":"Create a category","description":"Without `external_id`, a retry is idempotent only while its `Idempotency-Key` is remembered (24 hours, best-effort); to make a sync safe to repeat, give everything an `external_id` and use PUT …/by-external-id. Menu writes are business-wide: a key limited to one branch gets `403 forbidden`.","tags":["Menu"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"menu:write","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","business_suspended","invalid_request","idempotency_conflict","idempotency_in_progress","rate_limited","server_error","external_id_taken"],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"1–100 visible ASCII characters, unique per operation (e.g. your receipt number). A retry with the same key and body gets the first answer (header `Idempotent-Replayed: true`); the same key with another body is `409 idempotency_conflict`. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MenuCategoryInput"},"example":{"external_id":"CAT-HOT","name":{"ar":"مشروبات ساخنة","en":"Hot drinks"}}}}},"responses":{"201":{"description":"Created","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MenuCategory"},"example":{"id":"a4b6c8d0-e2f4-4a6b-8c8d-0e2f4a6b8c0d","external_id":"CAT-HOT","name":{"ar":"مشروبات ساخنة","en":"Hot drinks"},"sort":0,"earns_stamps":true,"active":true}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"409":{"description":"`idempotency_conflict`, `idempotency_in_progress`, `external_id_taken`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["idempotency_conflict","idempotency_in_progress","external_id_taken"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/menu/categories/by-external-id/{externalId}":{"put":{"operationId":"upsertMenuCategory","summary":"Create or update a category by your code","description":"Creates the category with this code, or updates the one that has it. Safe to repeat. Unlike an item PUT, `earns_stamps` and `active` keep their current values when left out (a new category starts with both true). Menu writes are business-wide: a key limited to one branch gets `403 forbidden`.","tags":["Menu"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"menu:write","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","business_suspended","invalid_request","idempotency_conflict","idempotency_in_progress","rate_limited","server_error"],"parameters":[{"name":"externalId","in":"path","required":true,"description":"Your system's own code (visible ASCII, case-sensitive).","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"1–100 visible ASCII characters, unique per operation (e.g. your receipt number). A retry with the same key and body gets the first answer (header `Idempotent-Replayed: true`); the same key with another body is `409 idempotency_conflict`. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"object","properties":{"ar":{"type":"string","minLength":1,"maxLength":60},"en":{"type":"string","minLength":1,"maxLength":60}},"required":["ar","en"]},"earns_stamps":{"type":"boolean"},"active":{"type":"boolean"}},"required":["name"]},"example":{"name":{"ar":"مشروبات ساخنة","en":"Hot drinks"},"earns_stamps":true}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MenuCategory"},"example":{"id":"a4b6c8d0-e2f4-4a6b-8c8d-0e2f4a6b8c0d","external_id":"CAT-HOT","name":{"ar":"مشروبات ساخنة","en":"Hot drinks"},"sort":0,"earns_stamps":true,"active":true}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"409":{"description":"`idempotency_conflict`, `idempotency_in_progress`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["idempotency_conflict","idempotency_in_progress"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/menu/categories/{id}":{"patch":{"operationId":"updateMenuCategory","summary":"Update a category","description":"Send only what changes; the rest keeps its value. Menu writes are business-wide: a key limited to one branch gets `403 forbidden`.","tags":["Menu"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"menu:write","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","business_suspended","invalid_request","not_found","idempotency_conflict","idempotency_in_progress","rate_limited","server_error","external_id_taken"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"1–100 visible ASCII characters, unique per operation (e.g. your receipt number). A retry with the same key and body gets the first answer (header `Idempotent-Replayed: true`); the same key with another body is `409 idempotency_conflict`. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MenuCategoryPatch"},"example":{"active":false}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MenuCategory"},"example":{"id":"a4b6c8d0-e2f4-4a6b-8c8d-0e2f4a6b8c0d","external_id":"CAT-HOT","name":{"ar":"مشروبات ساخنة","en":"Hot drinks"},"sort":0,"earns_stamps":true,"active":false}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"409":{"description":"`idempotency_conflict`, `idempotency_in_progress`, `external_id_taken`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["idempotency_conflict","idempotency_in_progress","external_id_taken"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}},"delete":{"operationId":"deleteMenuCategory","summary":"Delete an empty category","description":"Move or delete its items first. Menu writes are business-wide: a key limited to one branch gets `403 forbidden`.","tags":["Menu"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"menu:write","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","business_suspended","invalid_request","not_found","idempotency_conflict","idempotency_in_progress","rate_limited","server_error","category_not_empty"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"1–100 visible ASCII characters, unique per operation (e.g. your receipt number). A retry with the same key and body gets the first answer (header `Idempotent-Replayed: true`); the same key with another body is `409 idempotency_conflict`. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean","enum":[true]}},"required":["deleted"],"additionalProperties":false},"example":{"deleted":true}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"409":{"description":"`idempotency_conflict`, `idempotency_in_progress`, `category_not_empty`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["idempotency_conflict","idempotency_in_progress","category_not_empty"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/menu/items":{"post":{"operationId":"createMenuItem","summary":"Create an item","description":"This is a whole write: every field you leave out takes its default (`active` true, `reward_eligible` false, no description, allergens or tags), and `sizes` or `option_groups` you leave out are removed. Rows sent without an `id` are created new, so to keep a size, option group or option, send its `id` (read the item first). Ids from another item are refused. Without `external_id`, a retry is idempotent only while its `Idempotency-Key` is remembered (24 hours, best-effort); to make a sync safe to repeat, give everything an `external_id` and use PUT …/by-external-id. Photos are managed in the dashboard only. Menu writes are business-wide: a key limited to one branch gets `403 forbidden`.","tags":["Menu"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"menu:write","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","business_suspended","invalid_request","idempotency_conflict","idempotency_in_progress","rate_limited","server_error","external_id_taken","bad_category"],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"1–100 visible ASCII characters, unique per operation (e.g. your receipt number). A retry with the same key and body gets the first answer (header `Idempotent-Replayed: true`); the same key with another body is `409 idempotency_conflict`. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MenuItemInput"},"example":{"category_id":"a4b6c8d0-e2f4-4a6b-8c8d-0e2f4a6b8c0d","name":{"ar":"لاتيه إسباني","en":"Spanish latte"},"base_price":1700,"sizes":[{"name":{"ar":"صغير","en":"Small"},"price":1700},{"name":{"ar":"وسط","en":"Medium"},"price":2200,"is_default":true}],"external_id":"POS-1001"}}}},"responses":{"201":{"description":"Created","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MenuItem"},"example":{"id":"f3a5b7c9-d1e3-4f5a-8b7c-9d1e3f5a7b9c","external_id":"POS-1001","category_id":"a4b6c8d0-e2f4-4a6b-8c8d-0e2f4a6b8c0d","name":{"ar":"لاتيه إسباني","en":"Spanish latte"},"description":{"ar":null,"en":"Espresso, milk, condensed milk."},"photo_url":null,"base_price":1700,"calories":210,"prep_minutes":4,"allergens":["milk","caffeine"],"tags":["best_seller"],"reward_eligible":true,"earns_stamps_override":null,"active":true,"sort":0,"sizes":[{"id":"b5c7d9e1-f3a5-4b7c-9d9e-1f3a5b7c9d1e","name":{"ar":"صغير","en":"Small"},"price":1700,"is_default":false},{"id":"c6d8e0f2-a4b6-4c8d-8e0f-2a4b6c8d0e2f","name":{"ar":"وسط","en":"Medium"},"price":2200,"is_default":true}],"option_groups":[{"id":"d7e9f1a3-b5c7-4d9e-9f1a-3b5c7d9e1f3a","name":{"ar":"الحليب","en":"Milk"},"required":true,"min_select":1,"max_select":1,"options":[{"id":"e8f0a2b4-c6d8-4e0f-8a2b-4c6d8e0f2a4b","name":{"ar":"كامل الدسم","en":"Full fat"},"price_delta":0},{"id":"f9a1b3c5-d7e9-4f1a-9b3c-5d7e9f1a3b5c","name":{"ar":"شوفان","en":"Oat"},"price_delta":300}]}],"branches":[{"branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","sold_here":true,"sold_out":false,"stock":null,"stock_updated_at":null}],"updated_at":"2026-11-08T09:41:12.482Z"}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"409":{"description":"`idempotency_conflict`, `idempotency_in_progress`, `external_id_taken`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["idempotency_conflict","idempotency_in_progress","external_id_taken"]}}}}}]}}}},"422":{"description":"`bad_category`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["bad_category"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/menu/items/by-external-id/{externalId}":{"put":{"operationId":"upsertMenuItem","summary":"Create or update an item by your code","description":"Creates the item with this code, or updates the one that has it; the code in the path wins. This is a whole write: every field you leave out takes its default (`active` true, `reward_eligible` false, no description, allergens or tags), and `sizes` or `option_groups` you leave out are removed. Rows sent without an `id` are created new, so to keep a size, option group or option, send its `id` (read the item first). Ids from another item are refused. Photos are managed in the dashboard only. Menu writes are business-wide: a key limited to one branch gets `403 forbidden`.","tags":["Menu"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"menu:write","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","business_suspended","invalid_request","idempotency_conflict","idempotency_in_progress","rate_limited","server_error","bad_category"],"parameters":[{"name":"externalId","in":"path","required":true,"description":"Your system's own code (visible ASCII, case-sensitive).","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"1–100 visible ASCII characters, unique per operation (e.g. your receipt number). A retry with the same key and body gets the first answer (header `Idempotent-Replayed: true`); the same key with another body is `409 idempotency_conflict`. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"category_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"ar":{"type":"string","minLength":1,"maxLength":80},"en":{"type":"string","minLength":1,"maxLength":80}},"required":["ar","en"]},"description":{"type":"object","properties":{"ar":{"nullable":true,"type":"string","maxLength":300},"en":{"nullable":true,"type":"string","maxLength":300}}},"base_price":{"type":"integer","minimum":0,"maximum":10000000,"description":"Amount in halalas (100 = 1.00 SAR)."},"calories":{"nullable":true,"type":"integer","minimum":0,"maximum":5000},"prep_minutes":{"nullable":true,"type":"integer","minimum":1,"maximum":180},"allergens":{"type":"array","items":{"type":"string","enum":["milk","nuts","gluten","egg","soy","caffeine","sesame","fish","shellfish"]}},"tags":{"type":"array","items":{"type":"string","enum":["best_seller","new","seasonal","vegan","spicy"]}},"reward_eligible":{"type":"boolean"},"earns_stamps_override":{"nullable":true,"type":"boolean"},"active":{"type":"boolean"},"sizes":{"maxItems":8,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"ar":{"type":"string","minLength":1,"maxLength":40},"en":{"type":"string","minLength":1,"maxLength":40}},"required":["ar","en"]},"price":{"type":"integer","minimum":0,"maximum":10000000,"description":"Amount in halalas (100 = 1.00 SAR)."},"is_default":{"type":"boolean"}},"required":["name","price"]}},"option_groups":{"maxItems":8,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"ar":{"type":"string","minLength":1,"maxLength":40},"en":{"type":"string","minLength":1,"maxLength":40}},"required":["ar","en"]},"required":{"type":"boolean"},"min_select":{"type":"integer","minimum":0,"maximum":20},"max_select":{"type":"integer","minimum":1,"maximum":20},"options":{"maxItems":20,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"ar":{"type":"string","minLength":1,"maxLength":40},"en":{"type":"string","minLength":1,"maxLength":40}},"required":["ar","en"]},"price_delta":{"type":"integer","minimum":0,"maximum":1000000,"description":"Amount in halalas (100 = 1.00 SAR)."}},"required":["name"]}}},"required":["name","options"]}}},"required":["category_id","name","base_price"]},"example":{"category_id":"a4b6c8d0-e2f4-4a6b-8c8d-0e2f4a6b8c0d","name":{"ar":"لاتيه إسباني","en":"Spanish latte"},"base_price":1700,"sizes":[{"name":{"ar":"صغير","en":"Small"},"price":1700},{"name":{"ar":"وسط","en":"Medium"},"price":2200,"is_default":true}]}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MenuItem"},"example":{"id":"f3a5b7c9-d1e3-4f5a-8b7c-9d1e3f5a7b9c","external_id":"POS-1001","category_id":"a4b6c8d0-e2f4-4a6b-8c8d-0e2f4a6b8c0d","name":{"ar":"لاتيه إسباني","en":"Spanish latte"},"description":{"ar":null,"en":"Espresso, milk, condensed milk."},"photo_url":null,"base_price":1700,"calories":210,"prep_minutes":4,"allergens":["milk","caffeine"],"tags":["best_seller"],"reward_eligible":true,"earns_stamps_override":null,"active":true,"sort":0,"sizes":[{"id":"b5c7d9e1-f3a5-4b7c-9d9e-1f3a5b7c9d1e","name":{"ar":"صغير","en":"Small"},"price":1700,"is_default":false},{"id":"c6d8e0f2-a4b6-4c8d-8e0f-2a4b6c8d0e2f","name":{"ar":"وسط","en":"Medium"},"price":2200,"is_default":true}],"option_groups":[{"id":"d7e9f1a3-b5c7-4d9e-9f1a-3b5c7d9e1f3a","name":{"ar":"الحليب","en":"Milk"},"required":true,"min_select":1,"max_select":1,"options":[{"id":"e8f0a2b4-c6d8-4e0f-8a2b-4c6d8e0f2a4b","name":{"ar":"كامل الدسم","en":"Full fat"},"price_delta":0},{"id":"f9a1b3c5-d7e9-4f1a-9b3c-5d7e9f1a3b5c","name":{"ar":"شوفان","en":"Oat"},"price_delta":300}]}],"branches":[{"branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","sold_here":true,"sold_out":false,"stock":null,"stock_updated_at":null}],"updated_at":"2026-11-08T09:41:12.482Z"}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"409":{"description":"`idempotency_conflict`, `idempotency_in_progress`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["idempotency_conflict","idempotency_in_progress"]}}}}}]}}}},"422":{"description":"`bad_category`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["bad_category"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/menu/items/by-external-id/{externalId}/stock":{"put":{"operationId":"setItemStockByExternalId","summary":"Set stock by your code","description":"Finds the item by the external_id your system gave it (PUT /menu/items/by-external-id/{externalId}). Last write wins: the number you send replaces ServeU's count, including what orders took off since your last update. ServeU takes stock off when an order is placed (and puts it back if it is rejected, cancelled or expires unpaid — except a reject for `item_unavailable`, which puts nothing back: your next count sets the number), and refuses an order larger than what is left. `quantity: null` stops tracking: the item can then be ordered without a limit. Reading stock (GET /menu, GET /menu/items/{id}) needs `menu:read`. A key limited to one branch may only name its own branch; any other answers `404 not_found`.","tags":["Menu"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"stock:write","x-serveu-errors":["unauthorized","insufficient_scope","api_disabled","business_suspended","invalid_request","not_found","idempotency_conflict","idempotency_in_progress","rate_limited","server_error"],"parameters":[{"name":"externalId","in":"path","required":true,"description":"Your system's own code (visible ASCII, case-sensitive).","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"1–100 visible ASCII characters, unique per operation (e.g. your receipt number). A retry with the same key and body gets the first answer (header `Idempotent-Replayed: true`); the same key with another body is `409 idempotency_conflict`. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"branch_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"quantity":{"nullable":true,"description":"How many are left at this branch (0–100,000). null stops tracking: the item can then be ordered without a limit.","type":"integer","minimum":0,"maximum":100000}},"required":["branch_id","quantity"]},"example":{"branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","quantity":12}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"type":"object","properties":{"item_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"external_id":{"nullable":true,"type":"string"},"branches":{"type":"array","items":{"type":"object","properties":{"branch_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"stock":{"nullable":true,"description":"null = not tracked at this branch.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"stock_updated_at":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"}},"required":["branch_id","stock","stock_updated_at"],"additionalProperties":false}}},"required":["item_id","external_id","branches"],"additionalProperties":false},"example":{"item_id":"f3a5b7c9-d1e3-4f5a-8b7c-9d1e3f5a7b9c","external_id":"POS-1001","branches":[{"branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","stock":12,"stock_updated_at":"2026-11-08T09:41:12.482Z"}]}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"409":{"description":"`idempotency_conflict`, `idempotency_in_progress`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["idempotency_conflict","idempotency_in_progress"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/menu/items/{id}":{"get":{"operationId":"getMenuItem","summary":"Get an item","description":"A key limited to one branch sees only that branch in `branches`.","tags":["Menu"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"menu:read","x-serveu-errors":["unauthorized","insufficient_scope","api_disabled","invalid_request","not_found","rate_limited","server_error"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MenuItem"},"example":{"id":"f3a5b7c9-d1e3-4f5a-8b7c-9d1e3f5a7b9c","external_id":"POS-1001","category_id":"a4b6c8d0-e2f4-4a6b-8c8d-0e2f4a6b8c0d","name":{"ar":"لاتيه إسباني","en":"Spanish latte"},"description":{"ar":null,"en":"Espresso, milk, condensed milk."},"photo_url":null,"base_price":1700,"calories":210,"prep_minutes":4,"allergens":["milk","caffeine"],"tags":["best_seller"],"reward_eligible":true,"earns_stamps_override":null,"active":true,"sort":0,"sizes":[{"id":"b5c7d9e1-f3a5-4b7c-9d9e-1f3a5b7c9d1e","name":{"ar":"صغير","en":"Small"},"price":1700,"is_default":false},{"id":"c6d8e0f2-a4b6-4c8d-8e0f-2a4b6c8d0e2f","name":{"ar":"وسط","en":"Medium"},"price":2200,"is_default":true}],"option_groups":[{"id":"d7e9f1a3-b5c7-4d9e-9f1a-3b5c7d9e1f3a","name":{"ar":"الحليب","en":"Milk"},"required":true,"min_select":1,"max_select":1,"options":[{"id":"e8f0a2b4-c6d8-4e0f-8a2b-4c6d8e0f2a4b","name":{"ar":"كامل الدسم","en":"Full fat"},"price_delta":0},{"id":"f9a1b3c5-d7e9-4f1a-9b3c-5d7e9f1a3b5c","name":{"ar":"شوفان","en":"Oat"},"price_delta":300}]}],"branches":[{"branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","sold_here":true,"sold_out":false,"stock":null,"stock_updated_at":null}],"updated_at":"2026-11-08T09:41:12.482Z"}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`insufficient_scope`, `api_disabled` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["insufficient_scope","api_disabled"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}},"patch":{"operationId":"updateMenuItem","summary":"Update an item","description":"Send only what changes; the rest keeps its value (a one-language `description` keeps the other language). `sizes` or `option_groups`, when sent, replace the whole list — include each existing row's `id` to keep it. `external_id` changes only when you send it. If the item changes while your PATCH runs (for example a size added in the dashboard), your changes are re-applied to the fresh item, up to 3 tries; after that the answer is `409 conflict` — read the item and try again. Photos are managed in the dashboard only. Menu writes are business-wide: a key limited to one branch gets `403 forbidden`.","tags":["Menu"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"menu:write","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","business_suspended","invalid_request","not_found","conflict","idempotency_conflict","idempotency_in_progress","rate_limited","server_error","external_id_taken","bad_category"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"1–100 visible ASCII characters, unique per operation (e.g. your receipt number). A retry with the same key and body gets the first answer (header `Idempotent-Replayed: true`); the same key with another body is `409 idempotency_conflict`. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MenuItemPatch"},"example":{"base_price":1800}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MenuItem"},"example":{"id":"f3a5b7c9-d1e3-4f5a-8b7c-9d1e3f5a7b9c","external_id":"POS-1001","category_id":"a4b6c8d0-e2f4-4a6b-8c8d-0e2f4a6b8c0d","name":{"ar":"لاتيه إسباني","en":"Spanish latte"},"description":{"ar":null,"en":"Espresso, milk, condensed milk."},"photo_url":null,"base_price":1800,"calories":210,"prep_minutes":4,"allergens":["milk","caffeine"],"tags":["best_seller"],"reward_eligible":true,"earns_stamps_override":null,"active":true,"sort":0,"sizes":[{"id":"b5c7d9e1-f3a5-4b7c-9d9e-1f3a5b7c9d1e","name":{"ar":"صغير","en":"Small"},"price":1700,"is_default":false},{"id":"c6d8e0f2-a4b6-4c8d-8e0f-2a4b6c8d0e2f","name":{"ar":"وسط","en":"Medium"},"price":2200,"is_default":true}],"option_groups":[{"id":"d7e9f1a3-b5c7-4d9e-9f1a-3b5c7d9e1f3a","name":{"ar":"الحليب","en":"Milk"},"required":true,"min_select":1,"max_select":1,"options":[{"id":"e8f0a2b4-c6d8-4e0f-8a2b-4c6d8e0f2a4b","name":{"ar":"كامل الدسم","en":"Full fat"},"price_delta":0},{"id":"f9a1b3c5-d7e9-4f1a-9b3c-5d7e9f1a3b5c","name":{"ar":"شوفان","en":"Oat"},"price_delta":300}]}],"branches":[{"branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","sold_here":true,"sold_out":false,"stock":null,"stock_updated_at":null}],"updated_at":"2026-11-08T09:41:12.482Z"}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"409":{"description":"`conflict`, `idempotency_conflict`, `idempotency_in_progress`, `external_id_taken`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["conflict","idempotency_conflict","idempotency_in_progress","external_id_taken"]}}}}}]}}}},"422":{"description":"`bad_category`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["bad_category"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}},"delete":{"operationId":"deleteMenuItem","summary":"Delete an item","description":"Also removes its photo. Past orders keep their own copy of the item. Menu writes are business-wide: a key limited to one branch gets `403 forbidden`.","tags":["Menu"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"menu:write","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","business_suspended","invalid_request","not_found","idempotency_conflict","idempotency_in_progress","rate_limited","server_error"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"1–100 visible ASCII characters, unique per operation (e.g. your receipt number). A retry with the same key and body gets the first answer (header `Idempotent-Replayed: true`); the same key with another body is `409 idempotency_conflict`. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean","enum":[true]}},"required":["deleted"],"additionalProperties":false},"example":{"deleted":true}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"409":{"description":"`idempotency_conflict`, `idempotency_in_progress`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["idempotency_conflict","idempotency_in_progress"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/menu/items/{id}/availability":{"post":{"operationId":"setMenuItemAvailability","summary":"Mark sold out or back","description":"Without `branch_id` it applies to every branch (a key limited to one branch: its own branch). A key limited to one branch may only name its own branch; any other answers `404 not_found`.","tags":["Menu"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"menu:write","x-serveu-errors":["unauthorized","insufficient_scope","api_disabled","business_suspended","invalid_request","not_found","idempotency_conflict","idempotency_in_progress","rate_limited","server_error"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"1–100 visible ASCII characters, unique per operation (e.g. your receipt number). A retry with the same key and body gets the first answer (header `Idempotent-Replayed: true`); the same key with another body is `409 idempotency_conflict`. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sold_out":{"type":"boolean"},"branch_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["sold_out"]},"example":{"sold_out":true,"branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f"}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MenuItem"},"example":{"id":"f3a5b7c9-d1e3-4f5a-8b7c-9d1e3f5a7b9c","external_id":"POS-1001","category_id":"a4b6c8d0-e2f4-4a6b-8c8d-0e2f4a6b8c0d","name":{"ar":"لاتيه إسباني","en":"Spanish latte"},"description":{"ar":null,"en":"Espresso, milk, condensed milk."},"photo_url":null,"base_price":1700,"calories":210,"prep_minutes":4,"allergens":["milk","caffeine"],"tags":["best_seller"],"reward_eligible":true,"earns_stamps_override":null,"active":true,"sort":0,"sizes":[{"id":"b5c7d9e1-f3a5-4b7c-9d9e-1f3a5b7c9d1e","name":{"ar":"صغير","en":"Small"},"price":1700,"is_default":false},{"id":"c6d8e0f2-a4b6-4c8d-8e0f-2a4b6c8d0e2f","name":{"ar":"وسط","en":"Medium"},"price":2200,"is_default":true}],"option_groups":[{"id":"d7e9f1a3-b5c7-4d9e-9f1a-3b5c7d9e1f3a","name":{"ar":"الحليب","en":"Milk"},"required":true,"min_select":1,"max_select":1,"options":[{"id":"e8f0a2b4-c6d8-4e0f-8a2b-4c6d8e0f2a4b","name":{"ar":"كامل الدسم","en":"Full fat"},"price_delta":0},{"id":"f9a1b3c5-d7e9-4f1a-9b3c-5d7e9f1a3b5c","name":{"ar":"شوفان","en":"Oat"},"price_delta":300}]}],"branches":[{"branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","sold_here":true,"sold_out":true,"stock":null,"stock_updated_at":null}],"updated_at":"2026-11-08T09:41:12.482Z"}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"409":{"description":"`idempotency_conflict`, `idempotency_in_progress`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["idempotency_conflict","idempotency_in_progress"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/menu/items/{id}/stock":{"put":{"operationId":"setItemStock","summary":"Set an item's stock at a branch","description":"Last write wins: the number you send replaces ServeU's count, including what orders took off since your last update. ServeU takes stock off when an order is placed (and puts it back if it is rejected, cancelled or expires unpaid — except a reject for `item_unavailable`, which puts nothing back: your next count sets the number), and refuses an order larger than what is left. `quantity: null` stops tracking: the item can then be ordered without a limit. Reading stock (GET /menu, GET /menu/items/{id}) needs `menu:read`. A key limited to one branch may only name its own branch; any other answers `404 not_found`.","tags":["Menu"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"stock:write","x-serveu-errors":["unauthorized","insufficient_scope","api_disabled","business_suspended","invalid_request","not_found","idempotency_conflict","idempotency_in_progress","rate_limited","server_error"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"1–100 visible ASCII characters, unique per operation (e.g. your receipt number). A retry with the same key and body gets the first answer (header `Idempotent-Replayed: true`); the same key with another body is `409 idempotency_conflict`. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"branch_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"quantity":{"nullable":true,"description":"How many are left at this branch (0–100,000). null stops tracking: the item can then be ordered without a limit.","type":"integer","minimum":0,"maximum":100000}},"required":["branch_id","quantity"]},"example":{"branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","quantity":12}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"type":"object","properties":{"item_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"external_id":{"nullable":true,"type":"string"},"branches":{"type":"array","items":{"type":"object","properties":{"branch_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"stock":{"nullable":true,"description":"null = not tracked at this branch.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"stock_updated_at":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"}},"required":["branch_id","stock","stock_updated_at"],"additionalProperties":false}}},"required":["item_id","external_id","branches"],"additionalProperties":false},"example":{"item_id":"f3a5b7c9-d1e3-4f5a-8b7c-9d1e3f5a7b9c","external_id":"POS-1001","branches":[{"branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","stock":12,"stock_updated_at":"2026-11-08T09:41:12.482Z"}]}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"409":{"description":"`idempotency_conflict`, `idempotency_in_progress`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["idempotency_conflict","idempotency_in_progress"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/orders":{"get":{"operationId":"listOrders","summary":"List orders","description":"Newest first. With `updated_since`, oldest change first — loop until `next_cursor` is null to sync.","tags":["Orders"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"orders:read","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","invalid_request","rate_limited","server_error"],"parameters":[{"name":"status","in":"query","required":false,"description":"Comma-separated: awaiting_payment, new, preparing, ready, served, rejected, cancelled, expired. Default: everything except awaiting_payment and expired.","schema":{"type":"string","maxLength":200}},{"name":"branch_id","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["dine_in","pickup","car"]}},{"name":"created_from","in":"query","required":false,"description":"ISO 8601 with a zone, e.g. 2026-11-08T10:00:00Z or 2026-11-08T13:00:00+03:00.","schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},{"name":"created_to","in":"query","required":false,"description":"ISO 8601 with a zone, e.g. 2026-11-08T10:00:00Z or 2026-11-08T13:00:00+03:00.","schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},{"name":"updated_since","in":"query","required":false,"description":"ISO 8601 with a zone, e.g. 2026-11-08T10:00:00Z or 2026-11-08T13:00:00+03:00.","schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` from the previous page.","schema":{"type":"string","maxLength":300,"pattern":"^[A-Za-z0-9_-]+$"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Order"}},"next_cursor":{"nullable":true,"description":"Pass as `cursor` for the next page; null on the last page.","type":"string"}},"required":["data","next_cursor"],"additionalProperties":false},"example":{"data":[{"id":"d1e3f5a7-b9c1-4d3e-8f5a-7b9c1d3e5f7a","number":"A-042","branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","type":"car","status":"ready","table":null,"car":{"plate":"أ ب ج 1234","description":"White Camry"},"note":"Less ice","reject_reason":null,"items":[{"id":"e2f4a6b8-c0d2-4e4f-9a6b-8c0d2e4f6a8b","item_id":"f3a5b7c9-d1e3-4f5a-8b7c-9d1e3f5a7b9c","name":{"ar":"لاتيه إسباني","en":"Spanish latte"},"size":{"ar":"وسط","en":"Medium"},"options":[{"name":{"ar":"شوفان","en":"Oat"},"price_delta":300}],"quantity":2,"unit_price":2500,"line_total":5000,"note":null}],"subtotal":5000,"vat_amount":652,"total":5000,"vat_rate":15,"prices_include_vat":true,"currency":"SAR","paid":{"at":"2026-11-08T09:41:12.482Z","method":"online"},"online_payment":{"status":"paid","method":"mada","mode":"live","late":false},"loyalty_earned":null,"customer":{"card_id":"5b7d9f1a-3c5e-4f7a-9b1c-3d5e7f9a1b3c"},"created_at":"2026-11-08T09:41:12.482Z","acknowledged_at":"2026-11-08T09:41:12.482Z","started_at":"2026-11-08T09:41:12.482Z","ready_at":"2026-11-08T09:41:12.482Z","served_at":null,"rejected_at":null,"updated_at":"2026-11-08T09:41:12.482Z"}],"next_cursor":"eyJ0cyI6IjIwMjYtMTEtMDhUMDk6NDE6MTIuNDgyOTEzKzAwOjAwIiwiaWQiOiJkMWUzZjVhNy1iOWMxLTRkM2UtOGY1YS03YjljMWQzZTVmN2EifQ"}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/orders/summary":{"get":{"operationId":"getOrdersSummary","summary":"Sales summary","description":"The same numbers as the owner dashboard's Orders & sales page: only served and paid orders are sales; days follow the order's finish time. `to` is included and may be at most 92 days after `from`.","tags":["Orders"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"orders:read","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","invalid_request","not_found","rate_limited","server_error"],"parameters":[{"name":"from","in":"query","required":true,"description":"YYYY-MM-DD in the business's time zone.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"to","in":"query","required":true,"description":"YYYY-MM-DD in the business's time zone.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"branch_id","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrdersSummary"},"example":{"from":"2026-11-01","to":"2026-11-07","branch_id":null,"orders":214,"sales":512300,"by_method":{"cash":120000,"card":210300,"apple_pay":90000,"other":0,"online":92000},"avg_prep_seconds":260,"rejected":3,"unpaid":1}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/orders/{id}":{"get":{"operationId":"getOrder","summary":"Get an order","tags":["Orders"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"orders:read","x-serveu-errors":["unauthorized","insufficient_scope","api_disabled","invalid_request","not_found","rate_limited","server_error"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"},"example":{"id":"d1e3f5a7-b9c1-4d3e-8f5a-7b9c1d3e5f7a","number":"A-042","branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","type":"car","status":"ready","table":null,"car":{"plate":"أ ب ج 1234","description":"White Camry"},"note":"Less ice","reject_reason":null,"items":[{"id":"e2f4a6b8-c0d2-4e4f-9a6b-8c0d2e4f6a8b","item_id":"f3a5b7c9-d1e3-4f5a-8b7c-9d1e3f5a7b9c","name":{"ar":"لاتيه إسباني","en":"Spanish latte"},"size":{"ar":"وسط","en":"Medium"},"options":[{"name":{"ar":"شوفان","en":"Oat"},"price_delta":300}],"quantity":2,"unit_price":2500,"line_total":5000,"note":null}],"subtotal":5000,"vat_amount":652,"total":5000,"vat_rate":15,"prices_include_vat":true,"currency":"SAR","paid":{"at":"2026-11-08T09:41:12.482Z","method":"online"},"online_payment":{"status":"paid","method":"mada","mode":"live","late":false},"loyalty_earned":null,"customer":{"card_id":"5b7d9f1a-3c5e-4f7a-9b1c-3d5e7f9a1b3c"},"created_at":"2026-11-08T09:41:12.482Z","acknowledged_at":"2026-11-08T09:41:12.482Z","started_at":"2026-11-08T09:41:12.482Z","ready_at":"2026-11-08T09:41:12.482Z","served_at":null,"rejected_at":null,"updated_at":"2026-11-08T09:41:12.482Z"}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`insufficient_scope`, `api_disabled` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["insufficient_scope","api_disabled"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/orders/{id}/actions":{"post":{"operationId":"actOnOrder","summary":"Move an order along","description":"new → preparing (start) → ready → served (serve; adds the customer's stamps or points), or reject with a reason. Repeating an action that already happened answers `replayed: true`. Rejecting an order paid online refunds it in full. `reject` needs a `reason` and `mark_paid` a `method`; without one the answer is `400 invalid_request`. If the business wants counter orders paid first, `start` (pay before preparing) or `serve` (pay before serving) answers `409 payment_required` until `mark_paid`.","tags":["Orders"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"orders:write","x-serveu-errors":["unauthorized","insufficient_scope","api_disabled","business_suspended","invalid_request","not_found","idempotency_key_required","idempotency_conflict","idempotency_in_progress","rate_limited","server_error","order_not_actionable","payment_required","already_paid"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"1–100 visible ASCII characters, unique per operation (e.g. your receipt number). A retry with the same key and body gets the first answer (header `Idempotent-Replayed: true`); the same key with another body is `409 idempotency_conflict`. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderAction"},"example":{"action":"serve"}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"type":"object","properties":{"replayed":{"type":"boolean"},"order":{"$ref":"#/components/schemas/Order"}},"required":["replayed","order"],"additionalProperties":false},"example":{"replayed":false,"order":{"id":"d1e3f5a7-b9c1-4d3e-8f5a-7b9c1d3e5f7a","number":"A-042","branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","type":"car","status":"served","table":null,"car":{"plate":"أ ب ج 1234","description":"White Camry"},"note":"Less ice","reject_reason":null,"items":[{"id":"e2f4a6b8-c0d2-4e4f-9a6b-8c0d2e4f6a8b","item_id":"f3a5b7c9-d1e3-4f5a-8b7c-9d1e3f5a7b9c","name":{"ar":"لاتيه إسباني","en":"Spanish latte"},"size":{"ar":"وسط","en":"Medium"},"options":[{"name":{"ar":"شوفان","en":"Oat"},"price_delta":300}],"quantity":2,"unit_price":2500,"line_total":5000,"note":null}],"subtotal":5000,"vat_amount":652,"total":5000,"vat_rate":15,"prices_include_vat":true,"currency":"SAR","paid":{"at":"2026-11-08T09:41:12.482Z","method":"online"},"online_payment":{"status":"paid","method":"mada","mode":"live","late":false},"loyalty_earned":2,"customer":{"card_id":"5b7d9f1a-3c5e-4f7a-9b1c-3d5e7f9a1b3c"},"created_at":"2026-11-08T09:41:12.482Z","acknowledged_at":"2026-11-08T09:41:12.482Z","started_at":"2026-11-08T09:41:12.482Z","ready_at":"2026-11-08T09:41:12.482Z","served_at":"2026-11-08T09:41:12.482Z","rejected_at":null,"updated_at":"2026-11-08T09:41:12.482Z"}}}}},"400":{"description":"`invalid_request`, `idempotency_key_required`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request","idempotency_key_required"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"409":{"description":"`idempotency_conflict`, `idempotency_in_progress`, `order_not_actionable`, `payment_required`, `already_paid`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["idempotency_conflict","idempotency_in_progress","order_not_actionable","payment_required","already_paid"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/stock":{"post":{"operationId":"setStockBatch","summary":"Set stock for many items at once","description":"Up to 100 rows, each naming the item by `item_id` or `external_id` (one of them). The whole call counts as one request for the rate limit. A malformed row makes the whole request `400 invalid_request`; otherwise each row succeeds or fails on its own (`results`, in the same order as `items`): an unknown item or a branch of another key is `not_found`, and a branch of another business is `invalid_request` (`not_found` for a key limited to one branch, as any branch but its own). The same item and branch twice: the later row wins. Last write wins: the number you send replaces ServeU's count, including what orders took off since your last update. ServeU takes stock off when an order is placed (and puts it back if it is rejected, cancelled or expires unpaid — except a reject for `item_unavailable`, which puts nothing back: your next count sets the number), and refuses an order larger than what is left. `quantity: null` stops tracking: the item can then be ordered without a limit. Reading stock (GET /menu, GET /menu/items/{id}) needs `menu:read`.","tags":["Menu"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"stock:write","x-serveu-errors":["unauthorized","insufficient_scope","api_disabled","business_suspended","invalid_request","idempotency_conflict","idempotency_in_progress","rate_limited","server_error"],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"1–100 visible ASCII characters, unique per operation (e.g. your receipt number). A retry with the same key and body gets the first answer (header `Idempotent-Replayed: true`); the same key with another body is `409 idempotency_conflict`. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"items":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"object","properties":{"item_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"external_id":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$","description":"Your system's own code for this object (visible ASCII, unique per business)."},"branch_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"quantity":{"nullable":true,"description":"How many are left at this branch (0–100,000). null stops tracking: the item can then be ordered without a limit.","type":"integer","minimum":0,"maximum":100000}},"required":["branch_id","quantity"]}}},"required":["items"]},"example":{"items":[{"external_id":"BEANS-1KG","branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","quantity":40},{"external_id":"MUG-WHITE","branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","quantity":0},{"external_id":"OLD-CODE","branch_id":"8a2d4e6f-1b3c-4d5e-8f70-9a1b2c3d4e5f","quantity":3}]}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The row's position in items (0-based)."},"ok":{"type":"boolean"},"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized","forbidden","insufficient_scope","api_disabled","business_suspended","invalid_request","not_found","conflict","idempotency_key_required","idempotency_conflict","idempotency_in_progress","rate_limited","server_error","no_program","below_min_bill","card_cap_reached","reward_unavailable","not_enough_balance","already_voided","program_closed","would_go_negative","not_voidable","order_not_actionable","payment_required","already_paid","category_not_empty","external_id_taken","bad_category","endpoint_inactive"]},"message":{"type":"string"}},"required":["code","message"],"additionalProperties":false}},"required":["index","ok"],"additionalProperties":false}}},"required":["results"],"additionalProperties":false},"example":{"results":[{"index":0,"ok":true},{"index":1,"ok":true},{"index":2,"ok":false,"error":{"code":"not_found","message":"Not found."}}]}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"409":{"description":"`idempotency_conflict`, `idempotency_in_progress`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["idempotency_conflict","idempotency_in_progress"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/webhook-endpoints":{"get":{"operationId":"listWebhookEndpoints","summary":"List webhook endpoints","description":"At most 10 per business, oldest first. Never includes a secret. Needs a key that isn't limited to one branch.","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"webhooks:manage","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","rate_limited","server_error"],"parameters":[],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}}},"required":["data"],"additionalProperties":false},"example":{"data":[{"id":"b2d4f6a8-c0e2-4a4b-8c6d-8e0a2c4e6a8b","url":"https://pos.example.com/serveu/webhooks","description":"Olaya POS","events":["order.created","order.status_changed"],"branch_id":null,"include_contact":false,"status":"active","pause_reason":null,"failing_since":null,"paused_at":null,"secret_rotating_until":null,"created_at":"2026-11-08T09:41:12.482Z","updated_at":"2026-11-08T09:41:12.482Z"}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"createWebhookEndpoint","summary":"Create a webhook endpoint","description":"The response is the only time the signing secret is shown. The URL must be https:// to a public host (checked with a DNS lookup; a refusal is `400 invalid_request` with `details[0].path` `body.url` and the reason as `message`). `include_contact: true` also needs customers:contact. A business can have 10 endpoints (`409 conflict`, `details.reason: \"limit_reached\"`). Needs a key that isn't limited to one branch. Not idempotent: `Idempotency-Key` is ignored because the response contains a secret. If a retry creates a duplicate, delete it.","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"webhooks:manage","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","business_suspended","invalid_request","conflict","rate_limited","server_error"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointInput"},"example":{"url":"https://pos.example.com/serveu/webhooks","description":"Olaya POS","events":["order.created","order.status_changed"]}}}},"responses":{"201":{"description":"Created","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointWithSecret"},"example":{"id":"b2d4f6a8-c0e2-4a4b-8c6d-8e0a2c4e6a8b","url":"https://pos.example.com/serveu/webhooks","description":"Olaya POS","events":["order.created","order.status_changed"],"branch_id":null,"include_contact":false,"status":"active","pause_reason":null,"failing_since":null,"paused_at":null,"secret_rotating_until":null,"created_at":"2026-11-08T09:41:12.482Z","updated_at":"2026-11-08T09:41:12.482Z","secret":"whsec_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"409":{"description":"`conflict`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["conflict"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/webhook-endpoints/{id}":{"get":{"operationId":"getWebhookEndpoint","summary":"Get a webhook endpoint","description":"Needs a key that isn't limited to one branch.","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"webhooks:manage","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","invalid_request","not_found","rate_limited","server_error"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"},"example":{"id":"b2d4f6a8-c0e2-4a4b-8c6d-8e0a2c4e6a8b","url":"https://pos.example.com/serveu/webhooks","description":"Olaya POS","events":["order.created","order.status_changed"],"branch_id":null,"include_contact":false,"status":"active","pause_reason":null,"failing_since":null,"paused_at":null,"secret_rotating_until":null,"created_at":"2026-11-08T09:41:12.482Z","updated_at":"2026-11-08T09:41:12.482Z"}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}},"patch":{"operationId":"updateWebhookEndpoint","summary":"Update or turn a webhook endpoint on/off","description":"Only the fields you send change; the URL is checked again whenever any field other than `status` is sent. Sending both other fields and `status` saves them in one transaction: either both apply, or neither does. `status: active` turns a paused endpoint back on; paused deliveries are not replayed automatically (resend them from the dashboard's delivery log). While an endpoint includes contact details, editing it needs customers:contact too; turning it on/off, setting `include_contact: false` and deleting it don't. Needs a key that isn't limited to one branch.","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"webhooks:manage","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","business_suspended","invalid_request","not_found","idempotency_conflict","idempotency_in_progress","rate_limited","server_error"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"1–100 visible ASCII characters, unique per operation (e.g. your receipt number). A retry with the same key and body gets the first answer (header `Idempotent-Replayed: true`); the same key with another body is `409 idempotency_conflict`. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointPatch"},"example":{"events":["*"]}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"},"example":{"id":"b2d4f6a8-c0e2-4a4b-8c6d-8e0a2c4e6a8b","url":"https://pos.example.com/serveu/webhooks","description":"Olaya POS","events":["*"],"branch_id":null,"include_contact":false,"status":"active","pause_reason":null,"failing_since":null,"paused_at":null,"secret_rotating_until":null,"created_at":"2026-11-08T09:41:12.482Z","updated_at":"2026-11-08T09:41:12.482Z"}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"409":{"description":"`idempotency_conflict`, `idempotency_in_progress`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["idempotency_conflict","idempotency_in_progress"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}},"delete":{"operationId":"deleteWebhookEndpoint","summary":"Delete a webhook endpoint","description":"Its pending deliveries are dropped. Needs a key that isn't limited to one branch.","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"webhooks:manage","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","business_suspended","invalid_request","not_found","idempotency_conflict","idempotency_in_progress","rate_limited","server_error"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"1–100 visible ASCII characters, unique per operation (e.g. your receipt number). A retry with the same key and body gets the first answer (header `Idempotent-Replayed: true`); the same key with another body is `409 idempotency_conflict`. Kept 24 hours.","schema":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$"}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean","enum":[true]}},"required":["deleted"],"additionalProperties":false},"example":{"deleted":true}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Idempotent-Replayed":{"$ref":"#/components/headers/Idempotent-Replayed"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"409":{"description":"`idempotency_conflict`, `idempotency_in_progress`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["idempotency_conflict","idempotency_in_progress"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/webhook-endpoints/{id}/rotate-secret":{"post":{"operationId":"rotateWebhookSecret","summary":"Rotate the signing secret","description":"For 24 hours every request carries both signatures (rotating again within them drops the oldest secret). Needs a key that isn't limited to one branch. Not idempotent: `Idempotency-Key` is ignored because the response contains a secret. If a retry creates a duplicate, delete it.","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"webhooks:manage","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","business_suspended","invalid_request","not_found","rate_limited","server_error"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointWithSecret"},"example":{"id":"b2d4f6a8-c0e2-4a4b-8c6d-8e0a2c4e6a8b","url":"https://pos.example.com/serveu/webhooks","description":"Olaya POS","events":["order.created","order.status_changed"],"branch_id":null,"include_contact":false,"status":"active","pause_reason":null,"failing_since":null,"paused_at":null,"secret_rotating_until":"2026-11-09T09:41:12.482Z","created_at":"2026-11-08T09:41:12.482Z","updated_at":"2026-11-08T09:41:12.482Z","secret":"whsec_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/webhook-endpoints/{id}/test":{"post":{"operationId":"testWebhookEndpoint","summary":"Send a signed test event (ping)","description":"Sent now and answered with the result; never retried and never counts toward pausing; works on a paused endpoint (`409 endpoint_inactive` on a disabled one). 10 per endpoint per minute (`429 rate_limited`). Needs a key that isn't limited to one branch.","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"x-serveu-scope":"webhooks:manage","x-serveu-errors":["unauthorized","forbidden","insufficient_scope","api_disabled","business_suspended","invalid_request","not_found","rate_limited","server_error","endpoint_inactive"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"delivery_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The test delivery (see the dashboard's delivery log)."},"ok":{"type":"boolean","description":"true when your endpoint answered 2xx."},"status_code":{"nullable":true,"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"error":{"nullable":true,"description":"null on success; otherwise e.g. `http_500`, `timeout`, `dns_failed`. `not_sent`: a background pass picked the test event up first (see the delivery log). `stale`: sent, but another pass's result was recorded.","type":"string"}},"required":["delivery_id","ok","status_code","error"],"additionalProperties":false},"example":{"delivery_id":"c4e6a8b0-d2f4-4c6e-8a0b-2d4f6a8c0e2f","ok":true,"status_code":204,"error":null}}}},"400":{"description":"`invalid_request`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_request"]}}}}}]}}}},"401":{"description":"`unauthorized`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"WWW-Authenticate":{"$ref":"#/components/headers/WWW-Authenticate"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]}}}}}]}}}},"403":{"description":"`forbidden`, `insufficient_scope`, `api_disabled`, `business_suspended` RateLimit headers are not sent with api_disabled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["forbidden","insufficient_scope","api_disabled","business_suspended"]}}}}}]}}}},"404":{"description":"`not_found`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]}}}}}]}}}},"409":{"description":"`endpoint_inactive`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["endpoint_inactive"]}}}}}]}}}},"429":{"description":"`rate_limited`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"RateLimit-Limit":{"$ref":"#/components/headers/RateLimit-Limit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimit-Remaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]}}}}}]}}}},"default":{"$ref":"#/components/responses/Error"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"serveu_live_…"}},"schemas":{"Business":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"slug":{"type":"string"},"name":{"type":"object","properties":{"ar":{"type":"string"},"en":{"type":"string"}},"required":["ar","en"],"additionalProperties":false},"currency":{"type":"string"},"timezone":{"type":"string"},"prices_include_vat":{"type":"boolean"},"vat_rate":{"type":"number"},"paid_gate":{"type":"string","enum":["none","before_served","before_start"],"description":"When counter orders must be paid. none: any time. before_served: `serve` answers 409 payment_required until the order is paid. before_start: `start` does too, so mark_paid first (orders paid online are already paid)."},"program":{"nullable":true,"type":"object","properties":{"type":{"type":"string","enum":["stamps","points"]}},"required":["type"],"additionalProperties":false},"key":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"branch_id":{"nullable":true,"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["id","name","scopes","branch_id"],"additionalProperties":false}},"required":["id","slug","name","currency","timezone","prices_include_vat","vat_rate","paid_gate","program","key"],"additionalProperties":false},"Branch":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"ar":{"type":"string"},"en":{"type":"string"}},"required":["ar","en"],"additionalProperties":false},"order_types":{"type":"object","properties":{"dine_in":{"type":"boolean"},"pickup":{"type":"boolean"},"car":{"type":"boolean"}},"required":["dine_in","pickup","car"],"additionalProperties":false},"open_now":{"type":"boolean"},"paused":{"type":"boolean"}},"required":["id","name","order_types","open_now","paused"],"additionalProperties":false},"Order":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"number":{"nullable":true,"description":"Per-branch daily number, e.g. A-042. Null while awaiting online payment.","type":"string"},"branch_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"type":{"type":"string","enum":["dine_in","pickup","car"]},"status":{"type":"string","enum":["awaiting_payment","new","preparing","ready","served","rejected","cancelled","expired"]},"table":{"nullable":true,"type":"object","properties":{"label":{"type":"string"}},"required":["label"],"additionalProperties":false},"car":{"nullable":true,"type":"object","properties":{"plate":{"nullable":true,"type":"string"},"description":{"nullable":true,"type":"string"}},"required":["plate","description"],"additionalProperties":false},"note":{"nullable":true,"type":"string"},"reject_reason":{"nullable":true,"type":"string","enum":["item_unavailable","closing_soon","suspicious","cancelled_by_customer","other"]},"items":{"type":"array","items":{"$ref":"#/components/schemas/OrderItem"}},"subtotal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount in halalas (100 = 1.00 SAR)."},"vat_amount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount in halalas (100 = 1.00 SAR)."},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount in halalas (100 = 1.00 SAR)."},"vat_rate":{"type":"number"},"prices_include_vat":{"type":"boolean"},"currency":{"type":"string"},"paid":{"nullable":true,"type":"object","properties":{"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"},"method":{"type":"string","enum":["cash","card","apple_pay","other","online"]}},"required":["at","method"],"additionalProperties":false},"online_payment":{"nullable":true,"description":"The order's online payment: the attempt that paid if there is one, otherwise the most relevant late or latest attempt. Null if the order never went to online checkout.","type":"object","properties":{"status":{"type":"string"},"method":{"nullable":true,"type":"string"},"mode":{"type":"string","enum":["test","live"],"description":"test = the business's provider sandbox; not real money."},"late":{"type":"boolean","description":"True for a charge that doesn't count: it arrived after the payment deadline, the order was already paid (at the counter or by another attempt), the business was suspended, or the amount or order didn't match. Late charges are refunded automatically, except mismatches, which the owner refunds by hand (status refund_failed). Also true for an attempt ServeU couldn't check with the payment provider (status refund_failed): the customer may not have been charged, so the owner checks the provider's dashboard and refunds by hand if there was a charge; once resolved it reads refunded even if no money moved."}},"required":["status","method","mode","late"],"additionalProperties":false},"loyalty_earned":{"nullable":true,"description":"Stamps or points this order earned when served.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"customer":{"nullable":true,"description":"Null when the order has no customer (for example after they deleted their data).","type":"object","properties":{"card_id":{"nullable":true,"description":"The customer's loyalty card at this business: how you identify them here.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"description":"Only with the customers:contact scope.","nullable":true,"type":"string"},"phone":{"description":"E.164. Only with the customers:contact scope.","nullable":true,"type":"string"}},"required":["card_id"],"additionalProperties":false},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"},"acknowledged_at":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"},"started_at":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"},"ready_at":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"},"served_at":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"},"rejected_at":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"}},"required":["id","number","branch_id","type","status","table","car","note","reject_reason","items","subtotal","vat_amount","total","vat_rate","prices_include_vat","currency","paid","online_payment","loyalty_earned","customer","created_at","acknowledged_at","started_at","ready_at","served_at","rejected_at","updated_at"],"additionalProperties":false},"OrderItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"item_id":{"nullable":true,"description":"The menu item, or null if it was deleted since.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"ar":{"type":"string"},"en":{"type":"string"}},"required":["ar","en"],"additionalProperties":false},"size":{"nullable":true,"type":"object","properties":{"ar":{"type":"string"},"en":{"type":"string"}},"required":["ar","en"],"additionalProperties":false},"options":{"type":"array","items":{"type":"object","properties":{"name":{"type":"object","properties":{"ar":{"type":"string"},"en":{"type":"string"}},"required":["ar","en"],"additionalProperties":false},"price_delta":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount in halalas (100 = 1.00 SAR)."}},"required":["name","price_delta"],"additionalProperties":false}},"quantity":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unit_price":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount in halalas (100 = 1.00 SAR)."},"line_total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount in halalas (100 = 1.00 SAR)."},"note":{"nullable":true,"type":"string"}},"required":["id","item_id","name","size","options","quantity","unit_price","line_total","note"],"additionalProperties":false},"OrderAction":{"type":"object","properties":{"action":{"type":"string","enum":["start","ready","serve","reject","mark_paid"]},"reason":{"description":"Required for reject.","type":"string","enum":["item_unavailable","closing_soon","suspicious","cancelled_by_customer","other"]},"method":{"description":"Required for mark_paid.","type":"string","enum":["cash","card","apple_pay","other"]}},"required":["action"]},"OrdersSummary":{"type":"object","properties":{"from":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"YYYY-MM-DD in the business's time zone."},"to":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"YYYY-MM-DD in the business's time zone."},"branch_id":{"nullable":true,"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"orders":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sales":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount in halalas (100 = 1.00 SAR)."},"by_method":{"type":"object","additionalProperties":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount in halalas (100 = 1.00 SAR)."},"description":"cash, card, apple_pay, other, online — they add up to sales."},"avg_prep_seconds":{"nullable":true,"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"rejected":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unpaid":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["from","to","branch_id","orders","sales","by_method","avg_prep_seconds","rejected","unpaid"],"additionalProperties":false},"Card":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"card_number":{"type":"string","description":"Masked, e.g. •••• 4821 7730. The full number is never returned."},"verified":{"type":"boolean","description":"False until the customer confirms their phone (cards made at the counter or by the API)."},"joined_via":{"type":"string","enum":["poster","table","counter","order","api"]},"joined_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"},"balance":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Stamps or points, depending on program.type."},"visits":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"program":{"nullable":true,"type":"object","properties":{"type":{"type":"string","enum":["stamps","points"]},"stamps_per_reward":{"nullable":true,"description":"Stamps programs only (null for points).","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"max_stamps_per_visit":{"nullable":true,"description":"Stamps programs only (null for points).","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"points_per_sar":{"nullable":true,"description":"Points programs only (null for stamps).","type":"number"},"min_bill":{"nullable":true,"description":"Points programs only (null for stamps): a smaller bill earns nothing.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"max_points_per_visit":{"nullable":true,"description":"Points programs only (null for stamps).","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"reward_name":{"nullable":true,"type":"object","properties":{"ar":{"type":"string"},"en":{"type":"string"}},"required":["ar","en"],"additionalProperties":false}},"required":["type","stamps_per_reward","max_stamps_per_visit","points_per_sar","min_bill","max_points_per_visit","reward_name"],"additionalProperties":false},"progress":{"type":"object","properties":{"type":{"type":"string","enum":["stamps","points","none"]},"stamps_to_next":{"nullable":true,"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"rewards_available":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"points_to_next":{"nullable":true,"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"next_reward_id":{"nullable":true,"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"affordable_reward_ids":{"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}},"required":["type","stamps_to_next","rewards_available","points_to_next","next_reward_id","affordable_reward_ids"],"additionalProperties":false},"rewards":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"ar":{"type":"string"},"en":{"type":"string"}},"required":["ar","en"],"additionalProperties":false},"cost_points":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","cost_points"],"additionalProperties":false}},"customer":{"description":"The customer's contact details. Only with the customers:contact scope; without it there is no `customer` key. The card's `id` is how you identify this customer at this business.","type":"object","properties":{"name":{"nullable":true,"description":"Null when the customer hasn't given a name.","type":"string"},"phone":{"type":"string","description":"E.164."}},"required":["name","phone"],"additionalProperties":false}},"required":["id","card_number","verified","joined_via","joined_at","balance","visits","program","progress","rewards"],"additionalProperties":false},"LoyaltyEvent":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"card_id":{"nullable":true,"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"kind":{"type":"string","enum":["earn","redeem","adjust"]},"source":{"type":"string","enum":["counter","order","dashboard","switch","api"]},"program_type":{"type":"string","enum":["stamps","points"]},"amount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Positive for earn, negative for redeem."},"bill_amount":{"nullable":true,"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount in halalas (100 = 1.00 SAR)."},"reward":{"nullable":true,"type":"object","properties":{"id":{"nullable":true,"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"ar":{"type":"string"},"en":{"type":"string"}},"required":["ar","en"],"additionalProperties":false}},"required":["id","name"],"additionalProperties":false},"branch_id":{"nullable":true,"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"order_id":{"nullable":true,"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"api_key":{"nullable":true,"description":"The API key that made this event, if any.","type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"reference":{"nullable":true,"description":"The POS receipt number sent with the request.","type":"string"},"reason":{"nullable":true,"type":"string"},"voided":{"type":"boolean"},"voided_at":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"}},"required":["id","card_id","kind","source","program_type","amount","bill_amount","reward","branch_id","order_id","api_key","reference","reason","voided","voided_at","created_at"],"additionalProperties":false},"MenuCategory":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"external_id":{"nullable":true,"type":"string"},"name":{"type":"object","properties":{"ar":{"type":"string"},"en":{"type":"string"}},"required":["ar","en"],"additionalProperties":false},"sort":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"earns_stamps":{"type":"boolean"},"active":{"type":"boolean"}},"required":["id","external_id","name","sort","earns_stamps","active"],"additionalProperties":false},"MenuItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"external_id":{"nullable":true,"type":"string"},"category_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"ar":{"type":"string"},"en":{"type":"string"}},"required":["ar","en"],"additionalProperties":false},"description":{"type":"object","properties":{"ar":{"nullable":true,"type":"string"},"en":{"nullable":true,"type":"string"}},"required":["ar","en"],"additionalProperties":false},"photo_url":{"nullable":true,"type":"string"},"base_price":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount in halalas (100 = 1.00 SAR)."},"calories":{"nullable":true,"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"prep_minutes":{"nullable":true,"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"allergens":{"type":"array","items":{"type":"string","enum":["milk","nuts","gluten","egg","soy","caffeine","sesame","fish","shellfish"]}},"tags":{"type":"array","items":{"type":"string","enum":["best_seller","new","seasonal","vegan","spicy"]}},"reward_eligible":{"type":"boolean"},"earns_stamps_override":{"nullable":true,"type":"boolean"},"active":{"type":"boolean"},"sort":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sizes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"ar":{"type":"string"},"en":{"type":"string"}},"required":["ar","en"],"additionalProperties":false},"price":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount in halalas (100 = 1.00 SAR)."},"is_default":{"type":"boolean"}},"required":["id","name","price","is_default"],"additionalProperties":false}},"option_groups":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"ar":{"type":"string"},"en":{"type":"string"}},"required":["ar","en"],"additionalProperties":false},"required":{"type":"boolean"},"min_select":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"max_select":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"options":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"ar":{"type":"string"},"en":{"type":"string"}},"required":["ar","en"],"additionalProperties":false},"price_delta":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount in halalas (100 = 1.00 SAR)."}},"required":["id","name","price_delta"],"additionalProperties":false}}},"required":["id","name","required","min_select","max_select","options"],"additionalProperties":false}},"branches":{"type":"array","items":{"type":"object","properties":{"branch_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"sold_here":{"type":"boolean"},"sold_out":{"type":"boolean"},"stock":{"nullable":true,"description":"How many are left at this branch, as your system last set it minus what orders took off since. null = not tracked.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"stock_updated_at":{"nullable":true,"description":"When your system last set the number (orders don't change it). null = not tracked.","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"}},"required":["branch_id","sold_here","sold_out","stock","stock_updated_at"],"additionalProperties":false}},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"}},"required":["id","external_id","category_id","name","description","photo_url","base_price","calories","prep_minutes","allergens","tags","reward_eligible","earns_stamps_override","active","sort","sizes","option_groups","branches","updated_at"],"additionalProperties":false},"MenuItemInput":{"type":"object","properties":{"category_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"external_id":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$","description":"Your system's own code for this object (visible ASCII, unique per business)."},"name":{"type":"object","properties":{"ar":{"type":"string","minLength":1,"maxLength":80},"en":{"type":"string","minLength":1,"maxLength":80}},"required":["ar","en"]},"description":{"type":"object","properties":{"ar":{"nullable":true,"type":"string","maxLength":300},"en":{"nullable":true,"type":"string","maxLength":300}}},"base_price":{"type":"integer","minimum":0,"maximum":10000000,"description":"Amount in halalas (100 = 1.00 SAR)."},"calories":{"nullable":true,"type":"integer","minimum":0,"maximum":5000},"prep_minutes":{"nullable":true,"type":"integer","minimum":1,"maximum":180},"allergens":{"type":"array","items":{"type":"string","enum":["milk","nuts","gluten","egg","soy","caffeine","sesame","fish","shellfish"]}},"tags":{"type":"array","items":{"type":"string","enum":["best_seller","new","seasonal","vegan","spicy"]}},"reward_eligible":{"type":"boolean"},"earns_stamps_override":{"nullable":true,"type":"boolean"},"active":{"type":"boolean"},"sizes":{"maxItems":8,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"ar":{"type":"string","minLength":1,"maxLength":40},"en":{"type":"string","minLength":1,"maxLength":40}},"required":["ar","en"]},"price":{"type":"integer","minimum":0,"maximum":10000000,"description":"Amount in halalas (100 = 1.00 SAR)."},"is_default":{"type":"boolean"}},"required":["name","price"]}},"option_groups":{"maxItems":8,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"ar":{"type":"string","minLength":1,"maxLength":40},"en":{"type":"string","minLength":1,"maxLength":40}},"required":["ar","en"]},"required":{"type":"boolean"},"min_select":{"type":"integer","minimum":0,"maximum":20},"max_select":{"type":"integer","minimum":1,"maximum":20},"options":{"maxItems":20,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"ar":{"type":"string","minLength":1,"maxLength":40},"en":{"type":"string","minLength":1,"maxLength":40}},"required":["ar","en"]},"price_delta":{"type":"integer","minimum":0,"maximum":1000000,"description":"Amount in halalas (100 = 1.00 SAR)."}},"required":["name"]}}},"required":["name","options"]}}},"required":["category_id","name","base_price"]},"MenuItemPatch":{"type":"object","properties":{"category_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"external_id":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$","description":"Your system's own code for this object (visible ASCII, unique per business)."},"name":{"type":"object","properties":{"ar":{"type":"string","minLength":1,"maxLength":80},"en":{"type":"string","minLength":1,"maxLength":80}},"required":["ar","en"]},"description":{"type":"object","properties":{"ar":{"nullable":true,"type":"string","maxLength":300},"en":{"nullable":true,"type":"string","maxLength":300}}},"base_price":{"type":"integer","minimum":0,"maximum":10000000,"description":"Amount in halalas (100 = 1.00 SAR)."},"calories":{"nullable":true,"type":"integer","minimum":0,"maximum":5000},"prep_minutes":{"nullable":true,"type":"integer","minimum":1,"maximum":180},"allergens":{"type":"array","items":{"type":"string","enum":["milk","nuts","gluten","egg","soy","caffeine","sesame","fish","shellfish"]}},"tags":{"type":"array","items":{"type":"string","enum":["best_seller","new","seasonal","vegan","spicy"]}},"reward_eligible":{"type":"boolean"},"earns_stamps_override":{"nullable":true,"type":"boolean"},"active":{"type":"boolean"},"sizes":{"maxItems":8,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"ar":{"type":"string","minLength":1,"maxLength":40},"en":{"type":"string","minLength":1,"maxLength":40}},"required":["ar","en"]},"price":{"type":"integer","minimum":0,"maximum":10000000,"description":"Amount in halalas (100 = 1.00 SAR)."},"is_default":{"type":"boolean"}},"required":["name","price"]}},"option_groups":{"maxItems":8,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"ar":{"type":"string","minLength":1,"maxLength":40},"en":{"type":"string","minLength":1,"maxLength":40}},"required":["ar","en"]},"required":{"type":"boolean"},"min_select":{"type":"integer","minimum":0,"maximum":20},"max_select":{"type":"integer","minimum":1,"maximum":20},"options":{"maxItems":20,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"ar":{"type":"string","minLength":1,"maxLength":40},"en":{"type":"string","minLength":1,"maxLength":40}},"required":["ar","en"]},"price_delta":{"type":"integer","minimum":0,"maximum":1000000,"description":"Amount in halalas (100 = 1.00 SAR)."}},"required":["name"]}}},"required":["name","options"]}}}},"MenuCategoryInput":{"type":"object","properties":{"external_id":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$","description":"Your system's own code for this object (visible ASCII, unique per business)."},"name":{"type":"object","properties":{"ar":{"type":"string","minLength":1,"maxLength":60},"en":{"type":"string","minLength":1,"maxLength":60}},"required":["ar","en"]},"earns_stamps":{"type":"boolean"},"active":{"type":"boolean"}},"required":["name"]},"MenuCategoryPatch":{"type":"object","properties":{"external_id":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[!-~]+$","description":"Your system's own code for this object (visible ASCII, unique per business)."},"name":{"type":"object","properties":{"ar":{"type":"string","minLength":1,"maxLength":60},"en":{"type":"string","minLength":1,"maxLength":60}},"required":["ar","en"]},"earns_stamps":{"type":"boolean"},"active":{"type":"boolean"}}},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized","forbidden","insufficient_scope","api_disabled","business_suspended","invalid_request","not_found","conflict","idempotency_key_required","idempotency_conflict","idempotency_in_progress","rate_limited","server_error","no_program","below_min_bill","card_cap_reached","reward_unavailable","not_enough_balance","already_voided","program_closed","would_go_negative","not_voidable","order_not_actionable","payment_required","already_paid","category_not_empty","external_id_taken","bad_category","endpoint_inactive"]},"message":{"type":"string","description":"English, for logs and developers; branch on `code`."},"details":{"description":"For invalid_request: `[{ path, message }]`, e.g. path `body.stamps`."},"request_id":{"nullable":true,"type":"string"}},"required":["code","message","request_id"],"additionalProperties":false}},"required":["error"],"additionalProperties":false},"WebhookEndpoint":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"url":{"type":"string","description":"HTTPS URL ServeU POSTs events to."},"description":{"nullable":true,"type":"string"},"events":{"type":"array","items":{"anyOf":[{"type":"string","enum":["order.created","order.status_changed","order.paid","order.refunded","card.created","loyalty.earned","loyalty.redeemed","loyalty.voided","loyalty.adjusted","card.reward_ready","menu.item_availability_changed","customer.data_deleted","stock.changed","stock.depleted"]},{"type":"string","enum":["*"]}]},"description":"Subscribed event types, or [\"*\"] for all."},"branch_id":{"nullable":true,"description":"Only events from this branch (plus events with no branch, such as card.created).","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"include_contact":{"type":"boolean","description":"Adds the customer's name and phone to order, card and loyalty payloads."},"status":{"type":"string","enum":["active","paused","disabled"],"description":"paused = 3 days of failed deliveries or a 410 Gone answer; turn it back on with PATCH status=active."},"pause_reason":{"nullable":true,"description":"Why it is paused; null unless status is paused.","type":"string","enum":["failures","gone"]},"failing_since":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"},"paused_at":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"},"secret_rotating_until":{"nullable":true,"description":"Until then, requests carry two signatures (the new and the previous secret).","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"}},"required":["id","url","description","events","branch_id","include_contact","status","pause_reason","failing_since","paused_at","secret_rotating_until","created_at","updated_at"],"additionalProperties":false},"WebhookEndpointWithSecret":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"url":{"type":"string","description":"HTTPS URL ServeU POSTs events to."},"description":{"nullable":true,"type":"string"},"events":{"type":"array","items":{"anyOf":[{"type":"string","enum":["order.created","order.status_changed","order.paid","order.refunded","card.created","loyalty.earned","loyalty.redeemed","loyalty.voided","loyalty.adjusted","card.reward_ready","menu.item_availability_changed","customer.data_deleted","stock.changed","stock.depleted"]},{"type":"string","enum":["*"]}]},"description":"Subscribed event types, or [\"*\"] for all."},"branch_id":{"nullable":true,"description":"Only events from this branch (plus events with no branch, such as card.created).","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"include_contact":{"type":"boolean","description":"Adds the customer's name and phone to order, card and loyalty payloads."},"status":{"type":"string","enum":["active","paused","disabled"],"description":"paused = 3 days of failed deliveries or a 410 Gone answer; turn it back on with PATCH status=active."},"pause_reason":{"nullable":true,"description":"Why it is paused; null unless status is paused.","type":"string","enum":["failures","gone"]},"failing_since":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"},"paused_at":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"},"secret_rotating_until":{"nullable":true,"description":"Until then, requests carry two signatures (the new and the previous secret).","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"ISO 8601 UTC, e.g. 2026-11-08T10:00:00.123Z"},"secret":{"type":"string","format":"starts_with","pattern":"^whsec_.*","description":"Signing secret. Shown only in this response — store it now."}},"required":["id","url","description","events","branch_id","include_contact","status","pause_reason","failing_since","paused_at","secret_rotating_until","created_at","updated_at","secret"],"additionalProperties":false},"WebhookEndpointInput":{"type":"object","properties":{"url":{"type":"string","maxLength":2000,"description":"https:// (port 443 or 8443) to a public host name; checked with a DNS lookup."},"description":{"nullable":true,"type":"string","minLength":1,"maxLength":100},"events":{"minItems":1,"maxItems":20,"type":"array","items":{"anyOf":[{"type":"string","enum":["order.created","order.status_changed","order.paid","order.refunded","card.created","loyalty.earned","loyalty.redeemed","loyalty.voided","loyalty.adjusted","card.reward_ready","menu.item_availability_changed","customer.data_deleted","stock.changed","stock.depleted"]},{"type":"string","enum":["*"]}]},"description":"Event types to receive, or [\"*\"] for all (including types added later)."},"branch_id":{"description":"Only events from this branch (plus events with no branch).","nullable":true,"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"include_contact":{"description":"Needs the customers:contact permission too.","type":"boolean"}},"required":["url","events"]},"WebhookEndpointPatch":{"type":"object","properties":{"url":{"type":"string","maxLength":2000,"description":"https:// (port 443 or 8443) to a public host name; checked with a DNS lookup."},"description":{"nullable":true,"type":"string","minLength":1,"maxLength":100},"events":{"minItems":1,"maxItems":20,"type":"array","items":{"anyOf":[{"type":"string","enum":["order.created","order.status_changed","order.paid","order.refunded","card.created","loyalty.earned","loyalty.redeemed","loyalty.voided","loyalty.adjusted","card.reward_ready","menu.item_availability_changed","customer.data_deleted","stock.changed","stock.depleted"]},{"type":"string","enum":["*"]}]},"description":"Event types to receive, or [\"*\"] for all (including types added later)."},"branch_id":{"description":"Only events from this branch (plus events with no branch).","nullable":true,"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"include_contact":{"description":"Needs the customers:contact permission too.","type":"boolean"},"status":{"description":"active turns a paused or disabled endpoint back on.","type":"string","enum":["active","disabled"]}}}},"headers":{"X-Request-Id":{"description":"This request's id. Quote it when you contact support.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Requests allowed per window for this key.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests left in this window.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the window resets.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"Idempotent-Replayed":{"description":"`true` when this is the stored answer to an earlier request with the same Idempotency-Key.","schema":{"type":"string","enum":["true"]}},"WWW-Authenticate":{"description":"`Bearer`.","schema":{"type":"string"}}},"responses":{"Error":{"description":"Error (`server_error` and anything not listed). `error.code` is one of the documented codes.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}