Entegrasyon
Sipariş vermek
Sepeti fiyatlandırmak, siparişi mutfağa göndermek, isteği güvenle yeniden denemek ve siparişi takip etmek.
Sipariş çağrıları bir sepeti fiyatlandırır, siparişi doğrudan mekanın mutfağına gönderir ve mekan hesabı kapatana kadar siparişi takip etmenizi sağlar. Bu rehberdeki her çağrı için anahtarın Sipariş gönderebilir izni olmalıdır.
Uyarı: Ayrı bir test ortamı yoktur. Gerçek bir anahtarla verilen her sipariş gerçek bir sipariştir: mutfakta fişi basılır ve mekanın çalışanlarına bildirilir. API bir siparişi iptal edemez; yanlışlıkla verilen sipariş mekanın kasasından iptal edilir. Geliştirirken kendi işlettiğiniz bir mekanı kullanın, çalışanlarınıza haber verin ve sipariş olması gerekmeyen her şeyi sepeti fiyatlandırarak deneyin.
Akış#
- Siteniz menüyü gösterir ve misafir sepetini oluşturur.
- Sunucunuz sepeti
POST /venues/{venueId}/orders/previewile fiyatlandırır ve toplamı misafire gösterir. - Misafir onaylayınca sunucunuz aynı gövdeyi
POST /venues/{venueId}/ordersile gönderir. - Sipariş onay beklemeden mutfağa düşer. Siteniz siparişin durumunu webhook'larla ya da
GET /orders/{orderId}ile izler. - Misafir ödemesini mekanda yapar.
Sipariş türleri#
type | Gerekenler | Ne olur |
|---|---|---|
DineIn | tableId, mekanın masalarından biri. customer ve paymentMethod gönderilmez. | Sipariş masanın açık hesabına eklenir ya da yeni bir hesap açar. |
Takeaway | customer.name ve customer.phone. tableId gönderilmez. | Müşteri siparişi mekandan alır. |
Delivery | customer.name, customer.phone ve customer.address. tableId gönderilmez. | Mekan siparişi müşteriye götürür. |
Sepet#
Bir sipariş 1 ile 30 arasında satırdan oluşur. Her satır menüden bir ürünü bir porsiyonunda adlandırır; seçilen ekstraları ve çıkarılan malzemeleri de taşıyabilir:
{
"productId": "5d2c8a41-7b0e-4c36-8f1d-9e4a6b3c2d10",
"portionId": "a8e1f6c3-2d94-4b70-b5a6-1c7d9e0f3a24",
"quantity": 2,
"note": "Köfteler ayrı paketlensin.",
"extraIds": ["f1a2b3c4-d5e6-4f70-8192-a3b4c5d6e7f8", "b4c5d6e7-f8a9-4b1a-8c2d-3e4f5a6b7c8d"],
"removedIngredientIds": ["b7c8d9e0-f1a2-4b3c-8d4e-5f6a7b8c9d0e"]
}| Sınır | Değer |
|---|---|
| Satır sayısı | 1 ile 30 arası |
Bir satırın adedi (quantity) | 1 ile 20 arası |
| Bir satırın ekstraları | En fazla 20 |
| Bir satırdan çıkarılan malzemeler | En fazla 20 |
| Satır notu | En fazla 200 karakter |
| Siparişin notu | En fazla 300 karakter |
| Müşterinin adı, telefonu, adresi | En fazla 100, 30 ve 300 karakter |
Ekstralar ve çıkarılan malzemeler satırın her adedi için geçerlidir. Aynı ürünün adetleri farklı seçimlerle istenecekse her biri ayrı bir satır olarak gönderilir.
Bu kurallara uymayan bir istek 400 PUBLIC_API_ORDER_INVALID ile yanıtlanır. validationErrors, bulunan her sorunu istekteki yoluyla listeler: lines[1].extraIds gibi.
Önce fiyatlandırın#
İstekte fiyat yoktur. Cibusy her satırı menü fiyatı ve ekstralarıyla fiyatlar, mekanın otomatik kampanyalarını ve hizmet bedelini uygular ve sonucu yanıtta söyler.
POST /venues/{venueId}/orders/preview siparişle aynı gövdeyi alır ve sepeti sipariş vermeden fiyatlandırır:
curl -X POST "https://api.cibusy.com/public/v1/venues/3fa85f64-5717-4562-b3fc-2c963f66afa6/orders/preview" \
-H "X-Api-Key: $CIBUSY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "DineIn",
"tableId": "2f4e6a8c-0b1d-4c3e-9f5a-7b9d1e3c5a70",
"note": "Bir misafirin fıstık alerjisi var.",
"lines": [
{
"productId": "5d2c8a41-7b0e-4c36-8f1d-9e4a6b3c2d10",
"portionId": "a8e1f6c3-2d94-4b70-b5a6-1c7d9e0f3a24",
"quantity": 2,
"note": "Köfteler ayrı paketlensin.",
"extraIds": [
"f1a2b3c4-d5e6-4f70-8192-a3b4c5d6e7f8",
"b4c5d6e7-f8a9-4b1a-8c2d-3e4f5a6b7c8d"
],
"removedIngredientIds": [
"b7c8d9e0-f1a2-4b3c-8d4e-5f6a7b8c9d0e"
]
}
]
}'Yanıtın data alanı:
{
"lines": [
{
"productId": "5d2c8a41-7b0e-4c36-8f1d-9e4a6b3c2d10",
"portionId": "a8e1f6c3-2d94-4b70-b5a6-1c7d9e0f3a24",
"quantity": 2,
"unitPrice": 360,
"lineTotal": 720
}
],
"subtotal": 720,
"discount": 72,
"serviceFee": 32.4,
"total": 680.4,
"currency": "TRY"
}subtotal, satırların ekstralarıyla birlikte menü fiyatıdır.discountkampanyaların düştüğü tutar,serviceFeemekanın hizmet bedelidir.total = subtotal - discount + serviceFee.- Fiyatlandırma sepeti bir sipariş gibi kontrol eder: ürünler, porsiyonlar, seçimler ve stok. Mekanın o an açık olup olmadığına ise bakmaz.
- Masada verilen bir sipariş zaten açık bir hesaba eklenirse, bütün hesaba bakan bir kampanya siparişi hesaba eklendikten sonra farklı fiyatlayabilir. Geçerli olan, siparişin yanıtındaki
totalsdeğerleridir.
Sitenizde kendi fiyat hesabınızı yapmayın; misafire her zaman sunucunun söylediği tutarı gösterin.
Siparişi göndermek#
Sipariş POST /venues/{venueId}/orders ile verilir ve her istekte bir Idempotency-Key başlığı ister:
curl -X POST "https://api.cibusy.com/public/v1/venues/3fa85f64-5717-4562-b3fc-2c963f66afa6/orders" \
-H "X-Api-Key: $CIBUSY_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"type": "Takeaway",
"customer": {
"name": "Ayşe Yılmaz",
"phone": "+905321112233"
},
"paymentMethod": "Card",
"lines": [
{
"productId": "5d2c8a41-7b0e-4c36-8f1d-9e4a6b3c2d10",
"portionId": "a8e1f6c3-2d94-4b70-b5a6-1c7d9e0f3a24",
"quantity": 2,
"note": "Köfteler ayrı paketlensin.",
"extraIds": [
"f1a2b3c4-d5e6-4f70-8192-a3b4c5d6e7f8",
"b4c5d6e7-f8a9-4b1a-8c2d-3e4f5a6b7c8d"
],
"removedIngredientIds": [
"b7c8d9e0-f1a2-4b3c-8d4e-5f6a7b8c9d0e"
]
}
]
}'Başarılı ilk yanıt 201 Created olur. data içinde sipariş (order) ve bu çağrının eklediği satırların kimlikleri (addedLineIds) bulunur.
- Doğrudan mutfağa gider. Onay adımı yoktur. Sipariş verildiği an mutfak fişleri basılır ve mekanın çalışanlarına, QR menüden gelen bir sipariş gibi bildirilir. Anahtarın adı siparişin üzerinde görünür.
- Ödeme mekanda alınır. API üzerinden hiçbir ödeme alınmaz.
paymentMethod(Cash,Cardya daMealCard) gel-al ve paket siparişlerde müşterinin nasıl ödemek istediğine dair bir ipucudur; siparişi teslim edene yol gösterir.paymentStatusise mekanın kasada kaydettiğini izler. - Mekan sipariş alıyor olmalı. Etkin bir abonelik, yoğunluk bildirimi olmaması ve çalışma saatleri içinde olmak gerekir. Aksi halde yanıt
409olur:PUBLIC_API_ORDERING_UNAVAILABLE,PLACE_IS_BUSYya daOUTSIDE_WORKING_HOURS. Sipariş düğmesini göstermeden önce mekanın sipariş durumuna bakabilirsiniz.
Güvenle yeniden denemek#
Her siparişle bir Idempotency-Key gönderin: sipariş başına bir kez ürettiğiniz, 8 ile 64 karakterlik, yalnız harf, rakam, - ve _ içeren bir değer. Bir UUID uygundur.
Bir istek zaman aşımına uğrarsa ya da bağlantı koparsa aynı isteği aynı anahtarla tekrar gönderin. İlk çağrının verdiği siparişi mekandaki şimdiki haliyle alırsınız; ilk yanıt 201 iken bu yanıt 200 olur. Hiçbir şey iki kez sipariş edilmez. Yeni bir sipariş için yeni bir anahtar üretin.
import { randomUUID } from 'node:crypto';
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function placeOrder(venueId, basket) {
// Sipariş başına bir kez üretilir ve her denemede aynı kalır.
const idempotencyKey = randomUUID();
for (let attempt = 1; ; attempt++) {
let response;
try {
response = await fetch(`https://api.cibusy.com/public/v1/venues/${venueId}/orders`, {
method: 'POST',
headers: {
'X-Api-Key': process.env.CIBUSY_API_KEY,
'Content-Type': 'application/json',
'Idempotency-Key': idempotencyKey,
},
body: JSON.stringify(basket),
signal: AbortSignal.timeout(15_000),
});
} catch (error) {
// Zaman aşımı ya da kopan bağlantı: sipariş verilmiş olabilir, aynı anahtarla tekrar sorun.
if (attempt === 3) throw error;
await wait(attempt * 2_000);
continue;
}
const body = await response.json();
const stillWorking = body.errorCode === 'ORDER_CREATION_IN_PROGRESS';
if ((response.status >= 500 || stillWorking) && attempt < 3) {
await wait(attempt * 2_000);
continue;
}
// 201: yeni sipariş. 200: bu anahtarla daha önce verilmiş sipariş.
return body;
}
}- Bir tekrar, mekanın çalışma saatlerine ve aboneliğine yeniden bakılmadan yanıtlanır, çünkü sipariş zaten vardır.
Idempotency-Key, onu gönderen API anahtarı ve mekan için hatırlanır. Aynı değer farklı bir sepetle gönderilirse yeni bir sipariş verilmez; ilk sipariş döner.409ORDER_CREATION_IN_PROGRESS, aynı değerle gönderilmiş bir isteğin hala işlendiğini söyler. İsteği aynı değerle tekrar gönderin; siparişi alırsınız.- İlk yanıttaki (
201)addedLineIdslistesini saklayın. O yanıtta liste tam olarak bu çağrının yazdığı satırlardır. Bir tekrarın yanıtında (200) ise en iyi tahmindir: ilk çağrının kaydedilmesinden önceki 15 saniye içinde siparişe eklenen satırlar. Bir masanın hesabına eklenen siparişte, o aralıkta başka birinin aynı hesaba eklediği bir satırı da içerebilir.201yanıtını hiç almadıysanız tekrarın verdiği kimlikleri kesin değil, olası sayın.
Siparişi takip etmek#
GET /orders/{orderId} siparişi mekandaki şimdiki haliyle okur. GET /orders, API üzerinden verilen siparişleri en yeni önce ve sayfa sayfa listeler; status ile açık (open, varsayılan), kapanmış (closed) ya da bütün (all) siparişleri seçersiniz.
Mekanın her anahtarı, mekanın diğer anahtarlarıyla verilmiş siparişleri de okuyabilir. Siparişleri tekrar tekrar sorgulamak yerine webhook kullanın: sipariş değiştikçe sunucunuza bildirim gelir.
Sipariş durumu#
status siparişin satırlarından ve hesabından hesaplanır; uyan ilk kural geçerlidir:
status | Ne zaman |
|---|---|
Cancelled | Sipariş iptal edildi ya da üzerindeki her satır silindi. |
Completed | Mekan hesabı kapattı. |
OnTheWay | Paket sipariş mekandan çıktı. |
Served | Her satır servis edildi. |
Ready | Her satır hazır ya da zaten servis edildi. |
Preparing | Mutfak satırlardan en az birine başladı. |
Received | Mekan siparişi aldı, mutfak henüz başlamadı. |
Her satırın da kendi durumu vardır: Pending, Preparing, Ready, Served ya da Cancelled. İptal edilmiş bir siparişin satırları da Cancelled okunur.
Ödeme durumu#
paymentStatus, mekanda hiçbir şey ödenmediyse Unpaid, hesap ödendiyse Paid, arada PartiallyPaid olur. totals.paid ödenen tutar, totals.remaining müşterinin hala ödemesi gereken tutardır.
Masadaki hesaplar#
Masada verilen ve zaten açık olan bir hesaba eklenen sipariş, bütün hesap olarak döner: o masada başkalarının sipariş ettiği satırlar da lines içindedir. Yanıttaki addedLineIds, bu satırlardan hangilerini sizin çağrınızın yazdığını söyler.