{"openapi":"3.1.0","info":{"title":"getsauce","description":"Explore 778 New York restaurants on Sauce. Search by delivery address, browse live menus, and get accurate quotes before ordering.","version":"0.1.0","x-guidance":"# getsauce\n\n778 real New York restaurants that take orders through Sauce (getsauce.com) — from Di Fara\nPizza to a hundred bagel shops — indexed so an agent can find the ones that will actually\ndeliver to a given address, and quote the real total before ordering.\n\n## Start with the address\n\nDelivery is geofenced, not radial. 710 of the 856 zones in this catalog are polygons; a store\nhalf a mile away may still refuse your block. So the first call is always the address:\n\n    GET /api/restaurants?address=277 Bedford Ave, Brooklyn, NY 11211\n\nThat filters 778 storefronts down to the ones whose delivery zone actually contains the\ndestination, sorted nearest first. Pass `lat` and `lng` instead if you already have\ncoordinates — it skips geocoding and is faster.\n\n## Quote before you commit\n\nAdd the planned subtotal and the response tells you what the order really costs:\n\n    GET /api/restaurants?address=...&subtotal=35\n\nEach result then carries `fees` (resolved from fixed or percentage), `zone.minSubtotal`,\n`belowMinimum` and `smallOrderFee`. This matters: across the catalog a $35 order carries a median 33% markup\nonce fees, tax and the default tip land, and the 90th-percentile fee is five times the median.\nDo not assume a typical fee — read the store's.\n\n## Looking for a dish, not a restaurant?\n\nDo not fetch menus one by one. 95k items are indexed across every store:\n\n    GET /api/items?address=...&q=chicken shawarma\n\nOne call returns matching items with the restaurant, distance, ETA and fees attached, filtered\nto stores that deliver to the address. Add `format=wrap` (derived: wrap, bowl, platter, slice,\npita, hero, ...), `maxPrice`, or `sort=price`.\n\n`price` is the EFFECTIVE minimum — base plus the cheapest mandatory choices. Sauce\nstub-prices some items (a $1.00 base with a required $18.20 size), so `basePrice` on its own\nis not what anyone pays. Sort and filter on `price`; `stubBasePrice: true` marks the items\nwhere the two diverge.\n\n## Is it open?\n\nEvery result carries `openNow`, computed from the store's posted schedule in its own\ntimezone — not guessed. Filter with:\n\n    GET /api/restaurants?address=...&openNow=true\n\n`null` means the store publishes no hours: unknown, not closed, so those are kept. Results\nalso carry `localTime`, `closesAt` and `opensAt` as local wall clock (\"Mon 21:45\").\n\nOne honest limit: this is the *posted schedule*. A store can be inside its hours and still\nhave paused ordering. That flag is live state we refuse to bake, so ask for it explicitly:\n\n    GET /api/restaurants/{slug}?live=true\n\nThat returns `temporarilyPaused` (the raw manual pause bit — note a store closed until\nWednesday is NOT paused, it is merely shut) and `orderableNow`, which is the composite you\nactually want: open per schedule AND not paused. Both are null when anything is unknown.\n\n## Getting a real total\n\nDo not assemble it yourself — the inputs live in three different documents upstream:\n\n    GET /api/quote?slug=zaab-zaab-williamsburg&subtotal=47&address=277 Bedford Ave, Brooklyn, NY 11211\n\nReturns subtotal, every applicable fee, tax, tip presets, and the total, with a `checksum`\nyou can verify. Two bases are called out explicitly and they are not equally certain:\n`tax.baseVerified` is true (subtotal only — confirmed against a live order), while\n`tip.baseVerified` is false (we compute on subtotal, but Sauce has not confirmed it — worth\nabout a dollar on a $50 order). Works for pickup too, with no address.\n\n## Endpoints (reads are free and unauthenticated; ordering is paid)\n\n    POST /api/orders                      paid order — verified DID or payer wallet must be allowlisted\n    GET  /api/orders/history              your past orders + recentDestinations (SIWX)\n    GET  /api/orders/{id}                 retrieve one of your orders (SIWX)\n    GET /api/quote                        full priced total for an order — use this, do not add up fees by hand\n    GET /api/items                        cross-restaurant item search — start here for a dish\n    GET /api/restaurants                  search by address; see query params above\n    GET /api/restaurants/{slug}           full detail: fees, tips, zones, POS\n    GET /api/restaurants/{slug}/menu      menu, slim by default with modifier choices resolved\n                                          inline. view=full for raw Sauce; q= / section= to filter\n    GET /api/boroughs                     borough list with counts\n\n## Ordering and payment\n\nOrdering is live and paid over x402 (and MPP where your wallet supports it). The flow:\n\n1. Find a store and confirm it is open: `/api/restaurants?address=...&openNow=true`\n2. Pick items: `/api/restaurants/{slug}/menu` — note any group with `required: true`\n3. Check the total you are about to be charged: `/api/quote?slug=...&subtotal=...&address=...`\n4. Place it:\n\n    POST /api/orders\n    {\n      \"slug\": \"12-chairs-cafe\",\n      \"items\": [{\"itemId\": \"<id from the menu>\", \"quantity\": 1}],\n      \"fulfillment\": \"delivery\",\n      \"address\": \"277 Bedford Ave, Brooklyn, NY 11211\",\n      \"customer\": {\"name\": \"...\", \"phone\": \"+1...\"},\n      \"clientRequestId\": \"<generate a fresh UUID>\"\n    }\n\nThe 402 challenge is the real order total for exactly those items — the same arithmetic\n`/api/quote` returns, so you can verify the amount before paying. Settle it and the response\nis your confirmed order with an id and an ETA. No API key is required. Follow the\n`X-Agent-Identity` challenge on the 402; AgentCash does this automatically. The verified DID,\nor the verified payer wallet when no DID is supplied, must have an enabled `OrderAccessGrant`.\nA denied identity receives 403 and its payment is not settled. Retrieve the order later with\n`GET /api/orders/{id}`.\n\nGenerate a fresh UUID for `clientRequestId` for every new order and keep it with your trace.\nReusing a completed UUID returns 409 before a payment challenge. If a response was lost, do not\nretry the paid request with a new UUID: call `GET /api/orders/history` and match the original\n`clientRequestId`. This prevents a retry from paying again or returning a different order.\n\nTwo things to get right before you pay:\n\n- **Check `openNow`.** Orders to a closed store are rejected with a 409.\n- **Resolve required choices.** 89% of menus have at least one mandatory modifier group. Omit\n  them and you are charged the cheapest legal option rather than what you meant to order.\n\n## \"Send it to my usual address\"\n\nWhen the human says *the usual*, *same as last time*, *my address*, *last address*, or gives you\na name and phone but no street — do NOT ask them to retype it. Look it up:\n\n    GET /api/orders/history        (SIWX, free)\n\n`recentDestinations` comes back newest-first, each entry an address + phone + name pair with\nhow many times it has been used. `recentDestinations[0]` IS the last address. Take the\n`address` and `phone` straight from it and put them in your next `POST /api/orders`.\n\n    recentDestinations: [\n      { address: \"277 Bedford Ave, Brooklyn, NY 11211\", phone: \"+1...\", name: \"...\",\n        lastUsedAt: \"2026-08-03T18:45:25Z\", orderCount: 4 }\n    ]\n\nRules of thumb:\n\n- Empty `recentDestinations` means this identity has never ordered. Only then ask the human.\n- `address: null` was a pickup order — do not use it as a delivery address.\n- More than one entry? Prefer the most recent, but say which you picked. If they asked for\n  \"home\" or \"the office\" and you have several, ask rather than guess — a misdelivered order\n  cannot be cancelled.\n- The address still has to be in range for the restaurant you chose. Re-check it against\n  `/api/restaurants?address=...`; a past address is not automatically deliverable today.\n\nHistory is scoped to customer identity, not necessarily the payment account. When the client\nsends a verified `X-Agent-Identity` proof, its DID owns the order; otherwise the verified wallet\nis the compatibility identifier. The response records `payer` separately, so delegated wallets\nand SPT-backed payment can change without changing who can retrieve the order. You can only see\nyour own orders, and `GET /api/orders/{id}` uses the same identity boundary.\n\nThere is no cancel or refund endpoint. That is not an omission on our side — Sauce's own\nstorefront API has none either. An order placed cannot be taken back in code.\n\n## Things worth knowing\n\n- 138 storefronts share a kitchen with another brand — 386 Canal St runs four. They have\n  separate ids, menus and payouts, so they are separate entries here, not duplicates.\n- 89% of menus contain at least one required modifier group. You cannot add most items to a\n  cart without resolving a mandatory choice first. The slim menu view resolves the choices\n  inline — Sauce itself returns modifier groups with an empty options array and hides the real\n  choices in the top-level items array.\n- 305 stores enforce a minimum tip. Sending zero is not always allowed.\n- `zone.minSubtotal` is NOT a blocker. Below it, Sauce still accepts the order and charges a\n  small-order fee instead — `belowMinimum` plus `smallOrderFee` tell you the real cost. Do not\n  reject a restaurant for being under its minimum.\n- Tax applies to the item subtotal only. Fees and tips are not taxed.\n- Hours are real data, not inference: overnight windows are explicit (Sun 11:30 -> Mon 03:45)\n  and daylight saving is handled by comparing wall clock in the store's IANA zone.\n- Prices are decimal USD, matching Sauce. Convert to minor units at your own boundary.\n"},"servers":[{"url":"https://getsauce-kappa.vercel.app"}],"tags":[{"name":"Boroughs"},{"name":"Health"},{"name":"Items"},{"name":"Orders"},{"name":"Quote"},{"name":"Restaurants"}],"paths":{"/api/restaurants":{"get":{"operationId":"restaurants","summary":"Find restaurants that will actually deliver to an address. Delivery areas are geofenced polygons, not radii, so pass address (or lat/lng) to filter 778 storefronts down to the orderable ones, nearest first. Add subtotal to get resolved fees and minimum checks.","tags":["Restaurants"],"security":[],"parameters":[{"in":"query","name":"address","schema":{"description":"Delivery address, e.g. '277 Bedford Ave, Brooklyn, NY 11211'. US street addresses only.","type":"string"},"description":"Delivery address, e.g. '277 Bedford Ave, Brooklyn, NY 11211'. US street addresses only."},{"in":"query","name":"lat","schema":{"description":"Destination latitude; skips geocoding","type":"number"},"description":"Destination latitude; skips geocoding"},{"in":"query","name":"lng","schema":{"description":"Destination longitude; skips geocoding","type":"number"},"description":"Destination longitude; skips geocoding"},{"in":"query","name":"search","schema":{"description":"Free-text match over name, street and borough","type":"string"},"description":"Free-text match over name, street and borough"},{"in":"query","name":"borough","schema":{"description":"Exact borough from /api/boroughs","type":"string"},"description":"Exact borough from /api/boroughs"},{"in":"query","name":"fulfillment","schema":{"default":"delivery","type":"string","enum":["delivery","pickup","any"]}},{"in":"query","name":"subtotal","schema":{"description":"Planned order subtotal in USD. Supply it to get resolved fees and minimum checks.","type":"number","minimum":0},"description":"Planned order subtotal in USD. Supply it to get resolved fees and minimum checks."},{"in":"query","name":"maxMiles","schema":{"type":"number","exclusiveMinimum":0}},{"in":"query","name":"includeUndeliverable","schema":{"description":"Keep stores that will not deliver to the destination","default":false,"anyOf":[{"type":"boolean"},{"type":"string"}]},"description":"Keep stores that will not deliver to the destination"},{"in":"query","name":"includeVariants","schema":{"description":"Include catering and seasonal menu variants of the same kitchen","default":false,"anyOf":[{"type":"boolean"},{"type":"string"}]},"description":"Include catering and seasonal menu variants of the same kitchen"},{"in":"query","name":"openNow","schema":{"description":"Keep only stores open now per their posted schedule. Stores with no published hours are kept, since unknown is not closed.","default":false,"anyOf":[{"type":"boolean"},{"type":"string"}]},"description":"Keep only stores open now per their posted schedule. Stores with no published hours are kept, since unknown is not closed."},{"in":"query","name":"limit","schema":{"default":20,"type":"integer","minimum":1,"maximum":100}},{"in":"query","name":"offset","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"origin":{"anyOf":[{"type":"object","properties":{"lat":{"type":"number"},"lng":{"type":"number"},"matchedAddress":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["lat","lng","matchedAddress"],"additionalProperties":false},{"type":"null"}],"description":"Resolved destination. Null when no address or coordinates were supplied."},"restaurants":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string","description":"Stable id; use it for /api/restaurants/{slug} and ordering"},"name":{"type":"string"},"borough":{"type":"string"},"address":{"type":"string","description":"Formatted street address"},"lat":{"type":"number"},"lng":{"type":"number"},"phone":{"type":"string"},"pos":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Backing POS: Sauce, Toast, Square, Otter, ..."},"pickup":{"type":"boolean"},"delivery":{"type":"boolean"},"etaMinutes":{"anyOf":[{"type":"number"},{"type":"null"}]},"menuApi":{"type":"string","description":"Public menu endpoint — no auth required"},"distanceMiles":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Straight-line distance from the destination"},"deliversHere":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"True when the destination falls inside one of this store's delivery zones"},"zone":{"anyOf":[{"type":"object","properties":{"type":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Polygonal or Radial"},"minSubtotal":{"type":"number","description":"Order subtotal required before this zone will deliver"},"deliveryPrice":{"type":"number"},"radiusMiles":{"type":"number"}},"required":["type","minSubtotal","deliveryPrice"],"additionalProperties":false},{"type":"null"}],"description":"The zone that would apply to this destination"},"openNow":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Open right now per the posted schedule, in the store's own timezone. null means the store publishes no hours — unknown, not closed. Does NOT reflect a temporary pause; see /api/restaurants/{slug}?live=true for that."},"localTime":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Current wall clock at the store, e.g. 'Mon 19:05'"},"closesAt":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"End of the current open window, local wall clock"},"opensAt":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Start of the next open window, local wall clock"},"belowMinimum":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Subtotal is under the zone minimum. NOT a blocker — Sauce still accepts the order and charges a SmallOrderFee instead. See smallOrderFee for the actual cost."},"smallOrderFee":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Extra charged for being under the zone minimum, or null when none applies"},"fees":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","description":"ServiceFee | SmallOrderFee | DynamicDeliveryFee | DeliveryFee"},"name":{"type":"string"},"amount":{"type":"number","description":"USD, already resolved from fixed or percentage"}},"required":["type","name","amount"],"additionalProperties":false}},{"type":"null"}],"description":"Only returned when subtotal is supplied"}},"required":["slug","name","borough","address","lat","lng","phone","pos","pickup","delivery","etaMinutes","menuApi","distanceMiles","deliversHere","zone","openNow","localTime","closesAt","opensAt","belowMinimum","smallOrderFee","fees"],"additionalProperties":false}},"total":{"type":"number","description":"Matches before pagination"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["origin","restaurants","total","limit","offset"],"additionalProperties":false}}}}}}},"/api/restaurants/{slug}":{"get":{"operationId":"restaurants_detail","summary":"Full detail for one storefront: every fee with its fixed/percentage shape, tip config including any enforced minimum, all delivery zones, and the backing POS.","tags":["Restaurants"],"security":[],"parameters":[{"in":"query","name":"live","schema":{"description":"Fetch the store's live config to report acceptingOrders. One extra upstream call; posted hours are served from local data either way.","default":false,"anyOf":[{"type":"boolean"},{"type":"string"}]},"description":"Fetch the store's live config to report acceptingOrders. One extra upstream call; posted hours are served from local data either way."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string","description":"Stable id; use it for /api/restaurants/{slug} and ordering"},"name":{"type":"string"},"borough":{"type":"string"},"address":{"type":"string","description":"Formatted street address"},"lat":{"type":"number"},"lng":{"type":"number"},"phone":{"type":"string"},"pos":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Backing POS: Sauce, Toast, Square, Otter, ..."},"pickup":{"type":"boolean"},"delivery":{"type":"boolean"},"etaMinutes":{"anyOf":[{"type":"number"},{"type":"null"}]},"menuApi":{"type":"string","description":"Public menu endpoint — no auth required"},"locationId":{"type":"string"},"merchantId":{"type":"string"},"currency":{"type":"string"},"curbside":{"type":"boolean"},"catering":{"type":"boolean"},"scheduling":{"type":"boolean"},"fees":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"appliesToPickup":{"type":"boolean"},"appliesToDelivery":{"type":"boolean"},"fixed":{"anyOf":[{"type":"number"},{"type":"null"}]},"percentage":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["type","name","appliesToPickup","appliesToDelivery","fixed","percentage"],"additionalProperties":false}},"tips":{"anyOf":[{},{"type":"null"}]},"tax":{"anyOf":[{"type":"object","properties":{"rate":{"type":"number"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"roundingType":{"anyOf":[{"type":"string"},{"type":"null"}]},"calculationStrategy":{"anyOf":[{"type":"string"},{"type":"null"}]},"base":{"type":"string","description":"subtotal — fees and tips are not taxed"}},"required":["rate","name","roundingType","calculationStrategy","base"],"additionalProperties":false},{"type":"null"}],"description":"Tax rule, joined from the menu payload so you do not need a second fetch"},"deliveryZones":{"type":"array","items":{"type":"object","properties":{"type":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Polygonal or Radial"},"minSubtotal":{"type":"number","description":"Order subtotal required before this zone will deliver"},"deliveryPrice":{"type":"number"},"radiusMiles":{"type":"number"}},"required":["type","minSubtotal","deliveryPrice"],"additionalProperties":false}},"openNow":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Open per the posted schedule. Same field as search."},"localTime":{"anyOf":[{"type":"string"},{"type":"null"}]},"closesAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"opensAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"hours":{"anyOf":[{"type":"object","properties":{"timeZone":{"anyOf":[{"type":"string"},{"type":"null"}]},"override":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Set when a dated special-hours rule applies today"},"periods":{"type":"array","items":{},"description":"Weekly schedule as published by Sauce"}},"required":["timeZone","override","periods"],"additionalProperties":false},{"type":"null"}]},"temporarilyPaused":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Live MANUAL pause bit, only with ?live=true. Not the same as closed: a store shut until Wednesday is unpaused and reads false. null when not requested or upstream failed."},"orderableNow":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"The field you probably want: open per schedule AND not paused. null whenever either half is unknown — never a guess."},"menuUrl":{"type":"string"},"locationApi":{"type":"string"}},"required":["slug","name","borough","address","lat","lng","phone","pos","pickup","delivery","etaMinutes","menuApi","locationId","merchantId","currency","curbside","catering","scheduling","fees","tips","tax","deliveryZones","openNow","localTime","closesAt","opensAt","hours","temporarilyPaused","orderableNow","menuUrl","locationApi"],"additionalProperties":false}}}}}}},"/api/restaurants/{slug}/menu":{"get":{"operationId":"restaurants_menu","summary":"Menu for one storefront. Defaults to a slim view with modifier choices resolved inline; pass view=full for the raw Sauce payload, or q=/section= to filter.","tags":["Restaurants"],"security":[],"parameters":[{"in":"query","name":"q","schema":{"description":"Filter items by name/section before returning","type":"string"},"description":"Filter items by name/section before returning"},{"in":"query","name":"section","schema":{"description":"Only this section","type":"string"},"description":"Only this section"},{"in":"query","name":"view","schema":{"default":"slim","description":"slim returns sections with id/name/price/format and resolved modifier choices — a full menu can exceed 80KB on one line and blow an agent's tool-result limit. full is the raw Sauce payload.","type":"string","enum":["slim","full"]},"description":"slim returns sections with id/name/price/format and resolved modifier choices — a full menu can exceed 80KB on one line and blow an agent's tool-result limit. full is the raw Sauce payload."},{"in":"query","name":"limit","schema":{"default":120,"type":"integer","minimum":1,"maximum":500}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{}}}}}}},"/api/items":{"get":{"operationId":"items","summary":"Search 106k menu items across every restaurant at once, filtered to the ones that deliver to an address. This is the 'who near me sells a chicken shawarma wrap' query — one call instead of fetching menus store by store.","tags":["Items"],"security":[],"parameters":[{"in":"query","name":"q","schema":{"description":"Free-text over item name, section and description","type":"string"},"description":"Free-text over item name, section and description"},{"in":"query","name":"format","schema":{"description":"Derived format filter, e.g. wrap, bowl, slice, platter","type":"string"},"description":"Derived format filter, e.g. wrap, bowl, slice, platter"},{"in":"query","name":"address","schema":{"description":"Delivery address — restricts results to stores that deliver there","type":"string"},"description":"Delivery address — restricts results to stores that deliver there"},{"in":"query","name":"lat","schema":{"type":"number"}},{"in":"query","name":"lng","schema":{"type":"number"}},{"in":"query","name":"slug","schema":{"description":"Restrict to a single restaurant","type":"string"},"description":"Restrict to a single restaurant"},{"in":"query","name":"maxPrice","schema":{"type":"number","exclusiveMinimum":0}},{"in":"query","name":"subtotal","schema":{"description":"Planned subtotal, to resolve fees","type":"number","minimum":0},"description":"Planned subtotal, to resolve fees"},{"in":"query","name":"inStockOnly","schema":{"default":true,"anyOf":[{"type":"boolean"},{"type":"string"}]}},{"in":"query","name":"includeUndeliverable","schema":{"default":false,"anyOf":[{"type":"boolean"},{"type":"string"}]}},{"in":"query","name":"includeVariants","schema":{"description":"Include catering and seasonal variants. Off by default so this endpoint agrees with /api/restaurants about what is orderable.","default":false,"anyOf":[{"type":"boolean"},{"type":"string"}]},"description":"Include catering and seasonal variants. Off by default so this endpoint agrees with /api/restaurants about what is orderable."},{"in":"query","name":"openNow","schema":{"description":"Keep only items from stores open now per posted hours","default":false,"anyOf":[{"type":"boolean"},{"type":"string"}]},"description":"Keep only items from stores open now per posted hours"},{"in":"query","name":"sort","schema":{"default":"distance","description":"price sorts on the effective minimum, not the stub base","type":"string","enum":["distance","price"]},"description":"price sorts on the effective minimum, not the stub base"},{"in":"query","name":"limit","schema":{"default":20,"type":"integer","minimum":1,"maximum":100}},{"in":"query","name":"offset","schema":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"origin":{"anyOf":[{"type":"object","properties":{"lat":{"type":"number"},"lng":{"type":"number"},"matchedAddress":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["lat","lng","matchedAddress"],"additionalProperties":false},{"type":"null"}]},"items":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"price":{"type":"number","description":"Effective minimum price in USD: base plus the cheapest required choices. Sort and compare on this — Sauce stub-prices some items (a $1 base with a mandatory $18 size)."},"basePrice":{"type":"number","description":"Raw base price as Sauce reports it. Often not what you pay."},"requiredChoicesAdd":{"type":"number","description":"Amount the cheapest mandatory choices add to basePrice"},"stubBasePrice":{"type":"boolean","description":"basePrice is a placeholder (<= $1) and meaningless on its own"},"section":{"type":"string","description":"Menu section — often the only thing distinguishing two items with the same name"},"format":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"DERIVED from item and section names (wrap, bowl, platter, ...), not supplied by Sauce"},"description":{"anyOf":[{"type":"string"},{"type":"null"}]},"inStock":{"type":"boolean"},"itemId":{"type":"string"},"requiresChoices":{"type":"boolean","description":"Item has modifier groups; some are mandatory. Fetch the menu to resolve them."},"taxRate":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Store tax rate percent, applied to subtotal only"},"restaurant":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"borough":{"type":"string"},"address":{"type":"string"},"distanceMiles":{"anyOf":[{"type":"number"},{"type":"null"}]},"deliversHere":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"etaMinutes":{"anyOf":[{"type":"number"},{"type":"null"}]},"openNow":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"closesAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"opensAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"zone":{"anyOf":[{"type":"object","properties":{"minSubtotal":{"type":"number"},"deliveryPrice":{"type":"number"}},"required":["minSubtotal","deliveryPrice"],"additionalProperties":false},{"type":"null"}]},"fees":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","description":"ServiceFee | SmallOrderFee | DynamicDeliveryFee | DeliveryFee"},"name":{"type":"string"},"amount":{"type":"number","description":"USD, already resolved from fixed or percentage"}},"required":["type","name","amount"],"additionalProperties":false}},{"type":"null"}]},"menuUrl":{"type":"string"}},"required":["slug","name","borough","address","distanceMiles","deliversHere","etaMinutes","openNow","closesAt","opensAt","zone","fees","menuUrl"],"additionalProperties":false}},"required":["name","price","basePrice","requiredChoicesAdd","stubBasePrice","section","format","description","inStock","itemId","requiresChoices","taxRate","restaurant"],"additionalProperties":false}},"total":{"type":"number"},"restaurantCount":{"type":"number","description":"Distinct restaurants represented in the full match set"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["origin","items","total","restaurantCount","limit","offset"],"additionalProperties":false}}}}}}},"/api/quote":{"get":{"operationId":"quote","summary":"Complete priced quote for an order: subtotal, every applicable fee, tax, tip options and the total. The inputs live in three different documents upstream (fees on the location, tax on the menu, minimum on the delivery zone) — this assembles them so you do not have to. Tax base is confirmed; tip base is flagged as an assumption.","tags":["Quote"],"security":[],"parameters":[{"in":"query","name":"slug","schema":{"type":"string","description":"Restaurant slug from /api/restaurants or /api/items"},"required":true,"description":"Restaurant slug from /api/restaurants or /api/items"},{"in":"query","name":"subtotal","schema":{"type":"number","minimum":0,"description":"Sum of item prices, before fees and tax"},"required":true,"description":"Sum of item prices, before fees and tax"},{"in":"query","name":"fulfillment","schema":{"default":"delivery","type":"string","enum":["delivery","pickup"]}},{"in":"query","name":"address","schema":{"description":"Destination — required for a delivery quote","type":"string"},"description":"Destination — required for a delivery quote"},{"in":"query","name":"lat","schema":{"type":"number"}},{"in":"query","name":"lng","schema":{"type":"number"}},{"in":"query","name":"tipPercent","schema":{"description":"Defaults to the store's own default tip percent","type":"number","minimum":0,"maximum":100},"description":"Defaults to the store's own default tip percent"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"restaurant":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"address":{"type":"string"}},"required":["slug","name","address"],"additionalProperties":false},"destination":{"anyOf":[{"type":"object","properties":{"lat":{"type":"number"},"lng":{"type":"number"},"matchedAddress":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["lat","lng","matchedAddress"],"additionalProperties":false},{"type":"null"}]},"quote":{"type":"object","properties":{"fulfillment":{"type":"string"},"currency":{"type":"string"},"subtotal":{"type":"number"},"fees":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","description":"ServiceFee | SmallOrderFee | DynamicDeliveryFee | DeliveryFee"},"name":{"type":"string"},"amount":{"type":"number","description":"USD, already resolved from fixed or percentage"}},"required":["type","name","amount"],"additionalProperties":false}},"feesTotal":{"type":"number"},"tax":{"anyOf":[{"type":"object","properties":{"rate":{"type":"number"},"base":{"type":"string"},"baseVerified":{"type":"boolean","description":"true — confirmed against a live Sauce order"},"amount":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["rate","base","baseVerified","amount"],"additionalProperties":false},{"type":"null"}]},"totalBeforeTip":{"type":"number"},"tip":{"type":"object","properties":{"percent":{"type":"number"},"amount":{"type":"number"},"base":{"type":"string"},"baseVerified":{"type":"boolean","description":"false — the tip base is our assumption, worth ~$1 on a $50 order"},"defaultPercent":{"anyOf":[{"type":"number"},{"type":"null"}]},"minPercent":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Some stores reject tips below this"},"presets":{"type":"array","items":{"type":"object","properties":{"percent":{"type":"number"},"amount":{"type":"number"}},"required":["percent","amount"],"additionalProperties":false}}},"required":["percent","amount","base","baseVerified","defaultPercent","minPercent","presets"],"additionalProperties":false},"total":{"type":"number"},"checksum":{"type":"object","properties":{"formula":{"type":"string"},"sums":{"type":"boolean"}},"required":["formula","sums"],"additionalProperties":false},"zone":{"anyOf":[{"type":"object","properties":{"minSubtotal":{"type":"number"},"deliveryPrice":{"type":"number"},"belowMinimum":{"type":"boolean"}},"required":["minSubtotal","deliveryPrice","belowMinimum"],"additionalProperties":false},{"type":"null"}]},"notes":{"type":"array","items":{"type":"string"}}},"required":["fulfillment","currency","subtotal","fees","feesTotal","tax","totalBeforeTip","tip","total","checksum","zone","notes"],"additionalProperties":false}},"required":["restaurant","destination","quote"],"additionalProperties":false}}}}}}},"/api/orders":{"post":{"operationId":"orders","summary":"Place an order. The 402 amount is the real total for the submitted items, fees, tax and tip. The verified DID or payer wallet must be allowlisted. Generate a fresh clientRequestId UUID for each new order. Reuse is rejected before payment; recover the original through /api/orders/history.","tags":["Orders"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0","max":"500.00"},"protocols":[{"x402":{}}]},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string","description":"Restaurant slug from /api/restaurants or /api/items"},"items":{"minItems":1,"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","description":"Item id from /api/restaurants/{slug}/menu or /api/items"},"quantity":{"default":1,"type":"integer","minimum":1,"maximum":50},"choices":{"description":"Selections for required modifier groups; cheapest is assumed if omitted","type":"array","items":{"type":"object","properties":{"modifierGroupId":{"type":"string"},"modifierId":{"type":"string"}},"required":["modifierGroupId","modifierId"]}}},"required":["itemId"]}},"fulfillment":{"default":"delivery","type":"string","enum":["delivery","pickup"]},"address":{"description":"Delivery address — required for delivery","type":"string"},"lat":{"type":"number"},"lng":{"type":"number"},"customer":{"type":"object","properties":{"name":{"type":"string","minLength":1},"phone":{"type":"string","minLength":7,"description":"Contact number for the restaurant and driver"},"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"required":["name","phone"]},"tipPercent":{"type":"number","minimum":0,"maximum":100},"notes":{"description":"Kitchen instructions","type":"string","maxLength":400},"clientRequestId":{"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":"Fresh UUID for this order. Reuse is rejected without settlement; recover the original through /api/orders/history"}},"required":["slug","items","customer","clientRequestId"]}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"clientRequestId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Client UUID used to correlate retries with this authenticated order"},"identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Customer identity: verified X-Agent-Identity DID, or legacy wallet fallback"},"payer":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Account that settled payment; distinct from identifier when delegated or using SPT"},"placedAt":{"type":"string"},"status":{"type":"string"},"restaurant":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"phone":{"type":"string"},"address":{"type":"string"}},"required":["slug","name","phone","address"],"additionalProperties":false},"fulfillment":{"type":"string"},"destination":{"anyOf":[{"type":"string"},{"type":"null"}]},"customer":{"type":"object","properties":{"name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"}},"required":["name","phone"],"additionalProperties":false},"lines":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string"},"name":{"type":"string"},"quantity":{"type":"number"},"unitPrice":{"type":"number"},"lineTotal":{"type":"number"},"choices":{"type":"array","items":{"type":"object","properties":{"modifierGroupId":{"type":"string"},"modifierId":{"type":"string"}},"required":["modifierGroupId","modifierId"],"additionalProperties":false}}},"required":["itemId","name","quantity","unitPrice","lineTotal","choices"],"additionalProperties":false}},"quote":{"description":"The priced breakdown that was charged"},"etaMinutes":{"anyOf":[{"type":"number"},{"type":"null"}]},"notes":{"type":"string"}},"required":["id","clientRequestId","identifier","payer","placedAt","status","restaurant","fulfillment","destination","customer","lines","quote","etaMinutes"],"additionalProperties":false}}}},"402":{"description":"Payment Required"}}}},"/api/orders/history":{"get":{"operationId":"orders_history","summary":"Your orders, newest first, plus recentDestinations for requests such as 'send it to my usual address.' Free and SIWX-scoped, with durable DID identity independent of the payer. Match clientRequestId here to recover a completed order after a lost response without retrying payment.","tags":["Orders"],"security":[{"siwx":[]}],"parameters":[{"in":"query","name":"limit","schema":{"default":20,"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"identifier":{"type":"string","description":"Authenticated DID, or SIWX wallet fallback"},"orders":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"clientRequestId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Client UUID used to correlate retries with this authenticated order"},"identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Customer identity: verified X-Agent-Identity DID, or legacy wallet fallback"},"payer":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Account that settled payment; distinct from identifier when delegated or using SPT"},"placedAt":{"type":"string"},"status":{"type":"string"},"restaurant":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"phone":{"type":"string"},"address":{"type":"string"}},"required":["slug","name","phone","address"],"additionalProperties":false},"fulfillment":{"type":"string"},"destination":{"anyOf":[{"type":"string"},{"type":"null"}]},"customer":{"type":"object","properties":{"name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"}},"required":["name","phone"],"additionalProperties":false},"lines":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string"},"name":{"type":"string"},"quantity":{"type":"number"},"unitPrice":{"type":"number"},"lineTotal":{"type":"number"},"choices":{"type":"array","items":{"type":"object","properties":{"modifierGroupId":{"type":"string"},"modifierId":{"type":"string"}},"required":["modifierGroupId","modifierId"],"additionalProperties":false}}},"required":["itemId","name","quantity","unitPrice","lineTotal","choices"],"additionalProperties":false}},"quote":{"description":"The priced breakdown that was charged"},"etaMinutes":{"anyOf":[{"type":"number"},{"type":"null"}]},"notes":{"type":"string"}},"required":["id","clientRequestId","identifier","payer","placedAt","status","restaurant","fulfillment","destination","customer","lines","quote","etaMinutes"],"additionalProperties":false}},"total":{"type":"number","description":"Orders this identity has placed, before the limit"},"recentDestinations":{"type":"array","items":{"type":"object","properties":{"address":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"null for a pickup order"},"phone":{"type":"string"},"name":{"type":"string"},"lastUsedAt":{"type":"string"},"orderCount":{"type":"number"}},"required":["address","phone","name","lastUsedAt","orderCount"],"additionalProperties":false},"description":"Distinct address + phone pairs this identity has ordered to, most recently used first. Resolve 'my usual address' from recentDestinations[0] rather than re-asking the human."}},"required":["identifier","orders","total","recentDestinations"],"additionalProperties":false}}}},"402":{"description":"Authentication Required"}}}},"/api/orders/{orderId}":{"get":{"operationId":"orders_detail","summary":"Retrieve one of your own orders by id. Requires SIWX; X-Agent-Identity may identify you independently of the payer.","tags":["Orders"],"security":[{"siwx":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"clientRequestId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Client UUID used to correlate retries with this authenticated order"},"identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Customer identity: verified X-Agent-Identity DID, or legacy wallet fallback"},"payer":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Account that settled payment; distinct from identifier when delegated or using SPT"},"placedAt":{"type":"string"},"status":{"type":"string"},"restaurant":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"phone":{"type":"string"},"address":{"type":"string"}},"required":["slug","name","phone","address"],"additionalProperties":false},"fulfillment":{"type":"string"},"destination":{"anyOf":[{"type":"string"},{"type":"null"}]},"customer":{"type":"object","properties":{"name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"}},"required":["name","phone"],"additionalProperties":false},"lines":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string"},"name":{"type":"string"},"quantity":{"type":"number"},"unitPrice":{"type":"number"},"lineTotal":{"type":"number"},"choices":{"type":"array","items":{"type":"object","properties":{"modifierGroupId":{"type":"string"},"modifierId":{"type":"string"}},"required":["modifierGroupId","modifierId"],"additionalProperties":false}}},"required":["itemId","name","quantity","unitPrice","lineTotal","choices"],"additionalProperties":false}},"quote":{"description":"The priced breakdown that was charged"},"etaMinutes":{"anyOf":[{"type":"number"},{"type":"null"}]},"notes":{"type":"string"}},"required":["id","clientRequestId","identifier","payer","placedAt","status","restaurant","fulfillment","destination","customer","lines","quote","etaMinutes"],"additionalProperties":false}}}},"402":{"description":"Authentication Required"}}}},"/api/boroughs":{"get":{"operationId":"boroughs","summary":"Borough coverage with storefront counts. Use a name as the borough filter.","tags":["Boroughs"],"security":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"boroughs":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"restaurantCount":{"type":"number"}},"required":["name","restaurantCount"],"additionalProperties":false}}},"required":["boroughs"],"additionalProperties":false}}}}}}},"/api/health":{"get":{"operationId":"health","summary":"Database connectivity and active catalog readiness.","tags":["Health"],"security":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"catalog":{"type":"object","properties":{"generation":{"type":"string"},"restaurants":{"type":"number"},"items":{"type":"number"}},"required":["generation","restaurants","items"],"additionalProperties":false}},"required":["ok","catalog"],"additionalProperties":false}}}}}}}},"components":{"securitySchemes":{"siwx":{"type":"apiKey","in":"header","name":"SIGN-IN-WITH-X"}}}}