Restaurant menu and takeaway orders
Connect API · https://api.conciar.com/connect/v1
Ordering for pickup from a customer app. Money is {amount, minor, currency}, VAT included. Guests and signed-in members can both order; with a bearer token the order counts towards the member's stamps and points.
INFO
La referencia de la API está en inglés.
Get the menu
The menu that applies now (or the first menu when none does), with categories, items and option groups. Items not available today or not sold on this channel are left out; items sold out on this channel stay in with out_of_stock: true. Names follow Accept-Language; translations holds the other languages.
Códigos de estado
404MENU_NOT_FOUND — the restaurant has no menu.
Conviene saber
- Order with an item's id (not product_id) and option ids. maximum_selections 0 means no maximum.
- stamp_eligible is the deprecated name of earns_stamps and always has the same value.
curl "https://api.conciar.com/connect/v1/store/restaurant/menu" \
-H "Accept: application/json" \
-H "X-Api-Key: pk_your_publishable_key" \
-H "X-Sales-Channel: cnct_ch_your_channel_token"{
"data": {
"id": 3,
"name": "All day",
"start_at": null,
"end_at": null,
"categories": [
{
"id": 12,
"code": "mains",
"name": "Mains",
"color": null,
"translations": {},
"items": [
{
"id": 101,
"product_id": 9001,
"sku": "EX-BURGER",
"name": "Example burger",
"description": null,
"story": null,
"translations": {},
"image_url": null,
"out_of_stock": false,
"earns_stamps": true,
"stamp_reward_eligible": true,
"stamp_eligible": true,
"earns_points": true,
"available_from": null,
"available_until": null,
"price": {
"amount": "12.50",
"minor": 1250,
"currency": "EUR"
},
"option_groups": [
{
"id": 40,
"code": "extras",
"name": "Extras",
"translations": {},
"is_required": false,
"minimum_selections": 0,
"maximum_selections": 3,
"included_selections": 0,
"rank": 1,
"options": [
{
"id": 501,
"name": "Extra cheese",
"translations": {},
"is_default": false,
"rank": 1,
"extra_price": {
"amount": "1.00",
"minor": 100,
"currency": "EUR"
}
}
]
}
]
}
]
}
]
}
}Get pickup hours and slots
Opening hours, holiday hours for the next 14 days and the pickup rules: whether ASAP is allowed, the lead time, the slot size, the last-order cutoff and how many days ahead customers may order.
curl "https://api.conciar.com/connect/v1/store/restaurant/pickup-info" \
-H "Accept: application/json" \
-H "X-Api-Key: pk_your_publishable_key" \
-H "X-Sales-Channel: cnct_ch_your_channel_token"{
"data": {
"store": {
"sales_channel_token": "cnct_ch_your_channel_token",
"name": "Bistro Example",
"address": "Example Street 1, 1000 AA Example City"
},
"timezone": "Europe/Amsterdam",
"operating_hours": {
"monday": {
"isOpen": true,
"is24Hours": false,
"timeSlots": [
{
"openTime": "11:00",
"closeTime": "22:00"
}
]
},
"tuesday": {
"isOpen": true,
"is24Hours": false,
"timeSlots": [
{
"openTime": "11:00",
"closeTime": "22:00"
}
]
},
"wednesday": {
"isOpen": true,
"is24Hours": false,
"timeSlots": [
{
"openTime": "11:00",
"closeTime": "22:00"
}
]
},
"thursday": {
"isOpen": true,
"is24Hours": false,
"timeSlots": [
{
"openTime": "11:00",
"closeTime": "22:00"
}
]
},
"friday": {
"isOpen": true,
"is24Hours": false,
"timeSlots": [
{
"openTime": "11:00",
"closeTime": "23:00"
}
]
},
"saturday": {
"isOpen": true,
"is24Hours": false,
"timeSlots": [
{
"openTime": "12:00",
"closeTime": "23:00"
}
]
},
"sunday": {
"isOpen": false,
"is24Hours": false,
"timeSlots": []
}
},
"holiday_hours": [],
"is_open_now": true,
"asap_enabled": true,
"lead_time_minutes": 15,
"slot_minutes": 15,
"last_order_minutes_before_close": 10,
"max_days_ahead": 0
}
}Place a takeaway order
Creates the order and starts its payment. Redirect methods return payment.payment_url (send the customer there); Apple Pay and Google Pay return the wallet details to show the sheet, then charge with POST …/payment. An order fully paid by a reward or points needs no payment (payment: null). Unpaid orders expire after 30 minutes (the default).
Límite de peticiones: 10/min per key (a publishable key: per key and IP); 60/min per store (organization and sales channel)
Cuerpo
itemsarrayobligatorio1–50 lines.
items[].item_idintegerobligatorioMenu item id.
items[].qtyinteger1–99, default 1.
items[].optionsinteger[]Option ids, up to 30, no duplicates.
pickup_atstringDate-time on the slot grid; leave out for as soon as possible.
customer_notesstringMax 500.
customer.first_namestringRequired for guests (no bearer token). Max 100.
customer.last_namestringMax 100.
customer.emailstringRequired for guests. Max 255.
payment_method_keystringobligatorioA key from GET /store/payment-methods, e.g. ideal, applepay.
payment_service_provider_keystringPick the provider; otherwise the first enabled one.
payment_method_dataobjectOptional. For visa, mastercard and amex its card_token is passed to the provider.
return_urlstringRequired except for applepay and google_pay. Where the provider sends the customer after paying. Max 2048.
redeem_rewardbooleanMembers: spend a full stamp card.
redeem_pointsintegerMembers: spend exactly this many points (1–100000000).
use_pointsbooleanMembers: spend as many points as allowed.
phone, birth_date, billing_addressmixedOnly when the method's requires list asks for them (e.g. Klarna). phone max 30, birth_date max 10. billing_address: street (max 100), house_number (max 10), house_number_suffix (max 10), postcode (max 10), city (max 100), country (ISO-2).
Cabeceras
Idempotency-Keystring1–64 characters. A retry with the same key and body within 24 hours returns the same order instead of a new one.
Códigos de estado
409IDEMPOTENCY_KEY_REUSED (same key, different body) or IDEMPOTENCY_KEY_IN_PROGRESS.422Validation (including an Idempotency-Key that is empty or longer than 64), or a code in message: STORE_CLOSED, INVALID_PICKUP_TIME, ITEM_UNAVAILABLE, INVALID_OPTIONS, NO_REWARD_AVAILABLE, NO_ELIGIBLE_ITEM, INSUFFICIENT_POINTS, POINTS_DISABLED, BELOW_MIN_REDEMPTION, EXCEEDS_MAX, NOTHING_TO_PAY, PAYMENT_METHOD_UNAVAILABLE, PAYMENT_DETAILS_REQUIRED, PAYMENT_FAILED. errors points at the field.
Conviene saber
- Keep order_token: it is the guest's only way to read, pay or cancel the order (header X-Order-Token).
- status: awaiting_payment, scheduled, received, preparing, ready, collected or cancelled. pickup_number is set once the order is paid.
- For applepay and google_pay, payment is {type: wallet, method, amount, merchant} — what the native payment sheet needs; then charge the token with POST …/payment.
curl -X POST "https://api.conciar.com/connect/v1/store/restaurant/orders" \
-H "Accept: application/json" \
-H "X-Api-Key: pk_your_publishable_key" \
-H "X-Sales-Channel: cnct_ch_your_channel_token" \
-H "Idempotency-Key: order-2026-10-16-0001" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"item_id": 101,
"qty": 2,
"options": [
501
]
}
],
"customer": {
"first_name": "Alex",
"email": "alex@example.com"
},
"payment_method_key": "ideal",
"return_url": "https://www.example.com/order/return"
}'{
"data": {
"order": {
"reference": "EXAMPLE-0001",
"pickup_number": null,
"pickup_name": "Alex",
"store": {
"sales_channel_token": "cnct_ch_your_channel_token",
"name": "Bistro Example"
},
"status": "awaiting_payment",
"pickup_at": "2026-10-16T12:30:00+02:00",
"release_at": null,
"created_at": "2026-10-16T11:58:12+02:00",
"customer_notes": null,
"lines": [
{
"item_id": 101,
"name": "Example burger",
"image_url": null,
"qty": 2,
"selections": [
"Extra cheese"
],
"option_ids": [
501
],
"unit_price": {
"amount": "12.50",
"minor": 1250,
"currency": "EUR"
},
"total_price": {
"amount": "25.00",
"minor": 2500,
"currency": "EUR"
}
}
],
"subtotal": {
"amount": "25.00",
"minor": 2500,
"currency": "EUR"
},
"discount": {
"amount": "0.00",
"minor": 0,
"currency": "EUR"
},
"total": {
"amount": "25.00",
"minor": 2500,
"currency": "EUR"
},
"reward_redeemed": false,
"points_redeemed": 0,
"points_discount": {
"amount": "0.00",
"minor": 0,
"currency": "EUR"
},
"loyalty": {
"stamps_earned": 0,
"points_earned": 0
}
},
"order_token": "ot_example_order_token",
"payment": {
"type": "redirect",
"payment_url": "https://payment-provider.example/checkout/…",
"transaction_key": "example-transaction-key"
}
}
}Get an order
Poll this for the order status (every 5–10 seconds is plenty).
Límite de peticiones: 30/min per key (a publishable key: per key and IP)
Parámetros de ruta
referencestringobligatorioThe order reference.
Cabeceras
X-Order-TokenstringThe order_token, when there is no bearer token.
Códigos de estado
404ORDER_NOT_FOUND.
Conviene saber
- Send either the bearer token of the customer who placed the order or the header X-Order-Token with the order_token returned at placement. Anything else is 404 ORDER_NOT_FOUND.
curl "https://api.conciar.com/connect/v1/store/restaurant/orders/EXAMPLE-0001" \
-H "Accept: application/json" \
-H "X-Api-Key: pk_your_publishable_key" \
-H "X-Sales-Channel: cnct_ch_your_channel_token" \
-H "X-Order-Token: ot_example_order_token"{
"data": {
"reference": "EXAMPLE-0001",
"pickup_number": 17,
"pickup_name": "Alex",
"store": {
"sales_channel_token": "cnct_ch_your_channel_token",
"name": "Bistro Example"
},
"status": "preparing",
"pickup_at": "2026-10-16T12:30:00+02:00",
"release_at": null,
"created_at": "2026-10-16T11:58:12+02:00",
"customer_notes": null,
"lines": [
{
"item_id": 101,
"name": "Example burger",
"image_url": null,
"qty": 2,
"selections": [
"Extra cheese"
],
"option_ids": [
501
],
"unit_price": {
"amount": "12.50",
"minor": 1250,
"currency": "EUR"
},
"total_price": {
"amount": "25.00",
"minor": 2500,
"currency": "EUR"
}
}
],
"subtotal": {
"amount": "25.00",
"minor": 2500,
"currency": "EUR"
},
"discount": {
"amount": "0.00",
"minor": 0,
"currency": "EUR"
},
"total": {
"amount": "25.00",
"minor": 2500,
"currency": "EUR"
},
"reward_redeemed": false,
"points_redeemed": 0,
"points_discount": {
"amount": "0.00",
"minor": 0,
"currency": "EUR"
},
"loyalty": {
"stamps_earned": 0,
"points_earned": 0
}
}
}Pay or retry payment
Starts a new payment for an order awaiting payment, or charges Apple Pay / Google Pay. With apple_pay_token or google_pay_token the charge happens in this call: 200 when paid, 202 when pending, 422 PAYMENT_FAILED when declined (the order stays payable).
Límite de peticiones: 10/min per key (a publishable key: per key and IP); 120/min per store (shared by payment and cancel)
Parámetros de ruta
referencestringobligatorioThe order reference.
Cuerpo
payment_method_keystringobligatorioPayment method key.
payment_service_provider_keystringProvider key.
payment_method_dataobjectOptional. For visa, mastercard and amex its card_token is passed to the provider.
return_urlstringRequired except for applepay and google_pay. Max 2048.
apple_pay_tokenobject|stringThe PKPaymentToken (object, JSON or base64).
google_pay_tokenstringtokenizationData.token (JSON or base64).
customer.first_name, customer.last_namestringMax 100 each. Only for methods that require a name; defaults to the order's.
phone, birth_date, billing_addressmixedOnly when the method's requires list asks for them. Same fields as when placing the order.
Códigos de estado
200Wallet token charged and paid: {data: {status: "paid", order, payment}}.202Wallet token charged, still pending at the provider: {data: {status: "pending", order, payment}}.404ORDER_NOT_FOUND.409PAYMENT_FAILED — another payment for this order is in progress.422Validation, or ORDER_NOT_PAYABLE, PAYMENT_METHOD_UNAVAILABLE, PAYMENT_DETAILS_REQUIRED, INVALID_WALLET_TOKEN or PAYMENT_FAILED (a declined wallet charge also carries data with the order).
Conviene saber
- Send either the bearer token of the customer who placed the order or the header X-Order-Token with the order_token returned at placement. Anything else is 404 ORDER_NOT_FOUND.
curl -X POST "https://api.conciar.com/connect/v1/store/restaurant/orders/EXAMPLE-0001/payment" \
-H "Accept: application/json" \
-H "X-Api-Key: pk_your_publishable_key" \
-H "X-Sales-Channel: cnct_ch_your_channel_token" \
-H "X-Order-Token: ot_example_order_token" \
-H "Content-Type: application/json" \
-d '{
"payment_method_key": "ideal",
"return_url": "https://www.example.com/order/return"
}'{
"data": {
"payment": {
"type": "redirect",
"payment_url": "https://payment-provider.example/checkout/…",
"transaction_key": "example-transaction-key"
}
}
}Cancel an unpaid order
Only while the order is awaiting payment. Releases any reward or points held for it.
Límite de peticiones: 10/min per key (a publishable key: per key and IP); 120/min per store (shared by payment and cancel)
Parámetros de ruta
referencestringobligatorioThe order reference.
Códigos de estado
404ORDER_NOT_FOUND.422ORDER_NOT_CANCELLABLE — already paid or no longer awaiting payment.
Conviene saber
- Send either the bearer token of the customer who placed the order or the header X-Order-Token with the order_token returned at placement. Anything else is 404 ORDER_NOT_FOUND.
curl -X POST "https://api.conciar.com/connect/v1/store/restaurant/orders/EXAMPLE-0001/cancel" \
-H "Accept: application/json" \
-H "X-Api-Key: pk_your_publishable_key" \
-H "X-Sales-Channel: cnct_ch_your_channel_token" \
-H "X-Order-Token: ot_example_order_token"{
"data": {
"reference": "EXAMPLE-0001",
"pickup_number": null,
"pickup_name": "Alex",
"store": {
"sales_channel_token": "cnct_ch_your_channel_token",
"name": "Bistro Example"
},
"status": "cancelled",
"pickup_at": "2026-10-16T12:30:00+02:00",
"release_at": null,
"created_at": "2026-10-16T11:58:12+02:00",
"customer_notes": null,
"lines": [
{
"item_id": 101,
"name": "Example burger",
"image_url": null,
"qty": 2,
"selections": [
"Extra cheese"
],
"option_ids": [
501
],
"unit_price": {
"amount": "12.50",
"minor": 1250,
"currency": "EUR"
},
"total_price": {
"amount": "25.00",
"minor": 2500,
"currency": "EUR"
}
}
],
"subtotal": {
"amount": "25.00",
"minor": 2500,
"currency": "EUR"
},
"discount": {
"amount": "0.00",
"minor": 0,
"currency": "EUR"
},
"total": {
"amount": "25.00",
"minor": 2500,
"currency": "EUR"
},
"reward_redeemed": false,
"points_redeemed": 0,
"points_discount": {
"amount": "0.00",
"minor": 0,
"currency": "EUR"
},
"loyalty": {
"stamps_earned": 0,
"points_earned": 0
}
}
}Ask for the bill at a table
A guest at a table asks for the bill from their phone. The token comes from the table's QR code. Calling it again keeps the first time.
Límite de peticiones: 120/min per store
Parámetros de ruta
tokenstringobligatorioThe table's QR token: the table id, a dot and 24 characters.
Códigos de estado
404Unknown table (or a table of another organization).422{status: false, message: "This table has no open visit."}
curl -X POST "https://api.conciar.com/connect/v1/store/restaurant/table/12.0123456789abcdef01234567/bill-request" \
-H "Accept: application/json" \
-H "X-Api-Key: pk_your_publishable_key" \
-H "X-Sales-Channel: cnct_ch_your_channel_token"{
"status": true,
"bill_requested_at": "2026-10-16T21:14:03+02:00"
}Call a waiter to a table
A guest at a table calls a waiter from their phone. The token comes from the table's QR code. Waiters see the call until one of them handles it.
Límite de peticiones: 120/min per store
Parámetros de ruta
tokenstringobligatorioThe table's QR token: the table id, a dot and 24 characters.
Códigos de estado
404Unknown table (or a table of another organization).
Conviene saber
- Unlike the bill request, it does not need an open visit at the table.
curl -X POST "https://api.conciar.com/connect/v1/store/restaurant/table/12.0123456789abcdef01234567/assistance-request" \
-H "Accept: application/json" \
-H "X-Api-Key: pk_your_publishable_key" \
-H "X-Sales-Channel: cnct_ch_your_channel_token"{
"status": true,
"assistance_requested_at": "2026-10-16T21:14:03+02:00"
}