Menu & item mapping
Fetch the menu, map your products by id, update price and availability.
The endpoints on this page exist for restaurant businesses only; calling them with a Çarşı key returns 404 not_available_for_vertical. To route an order into your own system you must know which of your products corresponds to the product on the platform. GET /menu returns the menu with identifiers, and order lines carry the same identifiers. You build the mapping once and every order resolves itself afterwards.
id.Each row links to the full definition in the API reference — fields, response codes and the try-it console.
Fetch the menu
{
"merchantId": "cm_ornek_isletme",
"itemCount": 59,
"generatedAt": "2026-01-31T10:00:00.000Z",
"categories": [
{ "id": "cm_ornek_kategori", "name": "Ana Yemekler", "sortOrder": 1, "active": true,
"items": [
{ "id": "cm_ornek_urun", // order lines carry THIS id
"name": "Örnek Ürün", "description": null, "price": 260, "originalPrice": null,
"calories": null, "image": null, "available": true, "popular": false,
"prepMinutes": 15, "sortOrder": 1, "approvalStatus": "approved",
"modifierGroups": [
{ "name": "Boy Seçimi", "minSelect": 1, "maxSelect": 1, "singleChoice": true,
"choices": [ { "id": "cm_ornek_secenek_1", "name": "Küçük", "price": 0 },
{ "id": "cm_ornek_secenek_2", "name": "Büyük", "price": 20 } ] }
],
"updatedAt": "2026-01-31T09:00:00.000Z" }
] }
]
}What the fields mean
| Alan | Tip | Açıklama |
|---|---|---|
id | string | The product id on the platform. The mapping key: identical to items[].id on order lines. Mapping is done with this id only. |
available | boolean | When false, customers cannot order it. |
approvalStatus | enum | Customers see only approved items. pending/rejected items are listed so you can build the mapping in advance; no orders arrive for them. |
active | boolean | At category level: items in an inactive category are not shown. |
price | number | The current selling price; in ₺, VAT included. choices[].price is the amount added to the line price. |
choices[].id | string | The option id; it arrives on the order line as selectedOptions[].choiceId. |
Do not refetch for nothing: ETag
Menus change rarely but are polled often. Store the ETag from the response and send it back as If-None-Match. If nothing changed you get a bodiless 304 Not Modified. A 304 response also consumes one request from the rate limit; choose the polling interval knowing that the menu rarely changes. If-None-Match accepts multiple values, the W/ prefix and *.
# 1) First fetch - store the ETag
curl -D- "https://api.supergelsin.com/api/partner/v1/menu" \
-H "Authorization: Basic $(printf '%s:%s' "$API_KEY" "$API_SECRET" | base64)" \
-H "X-Integrator: Ornek POS" \
-H "X-Operator: kasiyer_01"
# < ETag: "sA5f-91rsUIX3qA5UxNoxqL7XGzJCIjj"
# 2) Subsequent polls - 304 with no body if unchanged
curl -D- "https://api.supergelsin.com/api/partner/v1/menu" \
-H "Authorization: Basic $(printf '%s:%s' "$API_KEY" "$API_SECRET" | base64)" \
-H "X-Integrator: Ornek POS" \
-H "X-Operator: kasiyer_01" \
-H 'If-None-Match: "sA5f-91rsUIX3qA5UxNoxqL7XGzJCIjj"'
# < HTTP/1.1 304 Not ModifiedUpdating the menu
This API updates price and availability. Creating products or changing name, image or description is not available here — menu content is managed in the partner console. All three endpoints are bulk (up to 100 items per request; more returns 400 too_many_items) and return per-item results; one failure does not affect the others.
curl -X PUT "https://api.supergelsin.com/api/partner/v1/menu/items/status" \
-H "Authorization: Basic $(printf '%s:%s' "$API_KEY" "$API_SECRET" | base64)" \
-H "X-Integrator: Ornek POS" \
-H "X-Operator: kasiyer_01" \
-H "Content-Type: application/json" \
-d '{ "items": [{ "id": "cm_ornek_urun", "available": false }] }'
# { "total": 1, "applied": 1, "pendingReview": 0, "failed": 0,
# "results": [{ "id": "cm_ornek_urun", "status": "applied" }] }Availability changes are applied immediately. Closing a sold-out item prevents an order that would only be cancelled; this is the write endpoint you will use most. An item suspected of being a restricted product returns pending_review and does not appear on sale until it is approved.
curl -X PUT "https://api.supergelsin.com/api/partner/v1/menu/items/price" \
-H "Authorization: Basic $(printf '%s:%s' "$API_KEY" "$API_SECRET" | base64)" \
-H "X-Integrator: Ornek POS" \
-H "X-Operator: kasiyer_01" \
-H "Content-Type: application/json" \
-d '{ "items": [{ "id": "cm_ornek_urun", "price": 139.50 }] }'
# Discount: applied immediately
# { "applied": 1, "pendingReview": 0 }
# Above-threshold increase: under review, the live price does not change
# { "applied": 0, "pendingReview": 1, "results": [{ "status": "pending_review" }] }Menu writes are synchronous: when the response arrives the work is done, per-item outcomes are in results and there is no batch id to poll. A single request carries at most 100 items; split larger lists. The item-count cap is applied after schema validation: a request that exceeds the cap and also contains an invalid item receives invalid_body instead of too_many_items. Çarşı catalogue writes, which can carry up to a thousand items, run asynchronously with 202 and a batchId — keep this difference in mind if one client drives both verticals.
pending_review — the live price does not change. The same rule applies in the partner console; the API does not bypass it.originalPrice (the struck-through, pre-discount price) cannot be written. The platform computes it from its own price history. If you send the field the request is not rejected; the value is ignored. If the price is already at the requested value nothing is written and the item returns applied; the ETag of the menu does not change. The same id cannot be sent twice in one request.curl -X PUT "https://api.supergelsin.com/api/partner/v1/menu/categories/status" \
-H "Authorization: Basic $(printf '%s:%s' "$API_KEY" "$API_SECRET" | base64)" \
-H "X-Integrator: Ornek POS" \
-H "X-Operator: kasiyer_01" \
-H "Content-Type: application/json" \
-d '{ "categories": [{ "id": "cm_ornek_kategori", "active": false }] }'Always check the per-item results
HTTP 200 does not mean "everything succeeded". Each item carries its own status:
| Alan | Tip | Açıklama |
|---|---|---|
applied | status | Applied and live. |
pending_review | status | Accepted but under review; the live version is preserved. Show it as "pending" on your side. |
not_found | status | No such record for this business — refresh the id and the menu. |
invalid | status | Invalid value (e.g. price ≤ 0); message gives the reason. |
Recommended mapping flow
- Fetch the menu and build an
id → your product idtable. - When an order arrives, resolve
items[].idthrough that table. - If an id does not match, refresh the menu (a new product may have been added); if it still does not match, report it to your operations team instead of leaving the order unrecorded.
- Poll the menu periodically (e.g. every 15 minutes) with
If-None-Match; a304response carries no body but still consumes one request from the rate limit.
clientReferenceId.