packet.created ✓ CanlıRestomenum'da yeni bir paket sipariş oluşunca eklentinin webhookUrl'ine imzalı POST edilir. Bu, paket/kurye eklentilerinin temel event'idir. Aşağıdaki şema canlı (authoritative) payload'ı tanımlar.
POST {webhookUrl}
Content-Type: application/json
X-Restomenum-Signature: t=<unixSec>,v1=<HMAC_SHA256(webhookSecret, "<t>.<rawBody>")>"<t>.<rawBody>"), ±5 dk replay toleransı. webhookSecret kurulumda (OAuth exchange) verilir — bkz. imza şeması ve token exchange.id tekrar gelebilir (retry) → idempotency için id'yi dedup et.| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| id | string | ✓ | Idempotency anahtarı. Aynı id tekrar gelebilir → dedup et. |
| type | string | ✓ | packet.created |
| version | string | ✓ | Envelope şema versiyonu ("1"). |
| environment | "sandbox" | "production" | ✓ | Teslimin ortamı (test mağazası = "sandbox") — imzalı gövdede; header kopyasını değil bunu kullan. |
| tenantId | string | ✓ | Restoran (tenant) id. |
| occurredAt | number | ✓ | Oluşma zamanı (unix ms). |
| data | object | ✓ | Event'e özel gövde (aşağıda). |
| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| packetId | string | ✓ | Paket id (statü callback'lerinde kullanılır). |
| docNo | number | ✓ | Günlük sipariş no. |
| orderCode | string | – | Sipariş kodu (örn. "A12"). |
| total | number | ✓ | Paket toplamı. |
| paid | number | ✓ | Ödenen tutar. |
| totalDiscount | number | – | İndirim toplamı (türetilmiş). |
| paymentNote | string | – | Ödeme notu (örn. "Kapıda nakit"). |
| isScheduled | boolean | ✓ | İleri tarihli sipariş mi? |
| scheduledDate | number | null | – | İleri tarihliyse zaman, değilse null. |
| note | string | – | Müşteri/sipariş notu. |
| entegrasyon | string | – | Sipariş kanalı — string kod: packet (manuel/telefon), yemeksepeti, getir, trendyol … |
| orders[] | array | ✓ | Sipariş satırları (id, title, quantity, options[], extra, discount, note, lineTotalDecimal, product). title = ürün adı, kökten direkt oku; options = nesne dizisi { id, title, price } (eskiden düz ad dizisi); price katalogtan gelir, lineTotalDecimal'a platformca dahildir; product tam ürün objesi de gelir. lineTotalDecimal'ı Restomenum hesaplar. |
| payments[] | array | ✓ | Ödeme kırılımı ({ methodId, title, amount, cash, isDiscount }) — packets/get ile birebir aynı satır. Tahsilat yoksa boş; paid bu satırların toplamıdır (aşağı bkz). |
| customer | object | – | ⚠️ PII alanları yalnız customers:read + consent ile DOLU gelir (aşağı bkz). |
| callbackUrls | object | – | ⚠️ Yalnız packets:status ile EKLENİR (aşağı bkz). |
{
"id": "evt_9f2a7c1b",
"type": "packet.created",
"version": "1",
"environment": "sandbox",
"tenantId": "tnt_123",
"occurredAt": 1730000000000,
"data": {
"packetId": "1780633662954",
"docNo": 42,
"orderCode": "A12",
"total": 145,
"paid": 0,
"totalDiscount": 0,
"paymentNote": "Kapıda nakit",
"isScheduled": false,
"scheduledDate": null,
"note": "Zili çalma",
"entegrasyon": "packet",
"orders": [
{
"id": "ord_1",
"title": "Lahmacun",
"quantity": 2,
"options": [
{
"id": "1693060234801",
"title": "Acılı",
"price": 0
},
{
"id": "1693060234802",
"title": "Bol soğan",
"price": 0
}
],
"extraDecimal": 0,
"discountDecimal": 0,
"note": "",
"lineTotalDecimal": 60,
"product": {
"title": "Lahmacun"
}
}
],
"payments": [],
"customer": {
"id": "cust_9",
"name": "Ahmet Yılmaz",
"phone": "05xxxxxxxxx",
"address": "Atatürk Cad. No:5",
"addressDescription": "2. kat",
"region": "Kadıköy",
"call": "05xxxxxxxxx"
},
"callbackUrls": {
"pickup": "https://plugins.restomenum.app/plugin-api/packets/{tenantId}/{pluginId}/{packetId}/pickup?token=…",
"delivered": "https://plugins.restomenum.app/plugin-api/packets/{tenantId}/{pluginId}/{packetId}/delivered?token=…",
"cancel": "https://plugins.restomenum.app/plugin-api/packets/{tenantId}/{pluginId}/{packetId}/cancel?token=…"
}
}
}payments[], paketin ödeme satırlarını taşır ve orders:read ile gelir. Aynı satır şekli packets/get, tables/get ve packet.created yüzeylerinde birebir aynıdır. İç alanlar (created = işlemi yapan personel, log, description) gönderilmez.
// payments[] satırı — allowlist (packets/get · tables/get · packet.created BİREBİR AYNI)
{
"methodId": string | null, // tenant'ın ödeme yöntemi id'si; tanımlı yönteme bağlı değilse null
"title": string, // yöntemin başlığı (tenant tanımı) — gösterim için
"amount": number, // satır tutarı
"cash": boolean, // yöntem NAKİT mi → CASH / NON_CASH ayrımı YALNIZ buradan okunur
"cashDeclared": boolean, // cash BEYAN mı, yoksa platformun güvenli varsayımı mı
"isDiscount": boolean // true → indirim satırı (tahsilat DEĞİL), satır listede KALIR
}| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| methodId | string | null | ✓ | Tenant'ın ödeme yöntemi id'si — geçerli id'ler payment-methods/list'ten gelir. Satır tanımlı bir yönteme bağlı değilse null (satırın kendi uuid'si sızdırılmaz). |
| title | string | ✓ | Yöntemin tenant tanımındaki başlığı (örn. "nakit"). Gösterim içindir. |
| amount | number | ✓ | Satır tutarı. Tüm satırların toplamı paid'e eşittir (indirim satırları dahil). |
| cash | boolean | ✓ | Yöntem nakit mi. Mali CASH/NON_CASH ayrımının tek doğru kaynağı budur; tenant tanımında işaretli değilse false gelir. |
| cashDeclared | boolean | ✓ | cash bir beyan mı, yoksa platformun güvenli varsayımı mı? false → yöntem kaydında nakitlik alanı hiç doğmamış. Mali damgalamada bu ayrım kritiktir — bkz. aşağıdaki uyarı. |
| isDiscount | boolean | ✓ | true → satır bir indirimdir, tahsilat değildir. Satır listeden düşürülmez; totalDiscount bu satırlardan türetilir. |
cash bayrağından oku — methodId veya title METNİNDEN çıkarma. Id'ler tenant'a özeldir ("29-cash" gibi bir id nakit olmayabilir, "kart" adlı bir yöntem nakit işaretli olabilir). Ayrıntı için payment-methods/list.cashDeclared:false ise cash bir varsayımdır. Yöntem kaydında nakitlik alanı hiç doğmamıştır (genelde kiracı açılışında oluşan varsayılan yöntemler). Almanya'da ödeme tipi (Bar/Unbar) imzalanan fişin güvence altına alınan verisidir (ZAHLART_TYP): cashDeclared:false görürsen varsayıma dayalı sınıflandırmayı damgalama, kiracıdan beyan iste.methodId taşıyor (teslimat entegrasyonlarının ürettiği sözde-yöntemler). O satırlarda join edecek hedef YOKTUR → nakitlik bilgisini satırdan oku.// Satır kimliği + korelasyon alanı — aynı satırda döner
{
"lineId": string | null, // KALICI satır kimliği; eski/panel satırlarında null (id'ye FALLBACK YOK)
"metadata": [ { key, value, by } ] | null // opak korelasyon DİZİSİ; by = yazar (platform damgalar)
}lineId ≠ methodId. lineId satırın kalıcı kimliğidir; methodId ödeme yönteminin id'sidir. Panel/yerli akışta veya bu sürümden önce yazılmış satırlarda lineId ve metadata null döner ve yazmadaki payments[].id'ye fallback yapılmaz — o alan yöntem id'si de olabildiği için iki farklı satırı aynı kimlikle gösterirdi. Kimlik uydurmak yerine "bilinmiyor" denir. Kurallar: Satır kimliği & metadata.cancelPayments[] — iptal edilen tahsilatlar. payments[] ile birebir aynı şekil (yeni bir tip öğrenmene gerek yok). Satır void'i (cancels) yayınlanırken ödeme void'inin yayınlanmaması doğrudan bir asimetriydi: iptal edilmiş bir tahsilat tüketiciye hiç görünmüyor, defterdeki "ödenmiş" tutar POS'takinden sapıyordu. ⚠️ paid aktif ödemelerin toplamıdır — bu liste ona dahil değildir. (Sandbox'ta canlı, production'a dağıtılmadı.)sum(amount) === paid korunur. Mali toplamda isDiscount:true satırlarını tahsilat gibi sayma; ama listeden atarsan toplam paid'i tutmaz.| Scope | Etki |
|---|---|
| events:subscribe + packet.created | Webhook'u almak için zorunlu (manifest events[] + scope). |
| customers:read yoksa | customer objesindeki PII alanları silinir (name, phone, address, email, tckn, vergino). id / region / call / addressDescription kalır. |
| packets:status yoksa | callbackUrls hiç eklenmez. |
customers:read eklemek kurulumda re-consent tetikler. Bkz. customers:read.Paket durumunu Restomenum'a bildirmek için callbackUrls'ten ilgili URL'e POST at (token query string'te). Bu URL'leri sen üretmezsin — platform üretip payload'a ekler, sen uygun anda çağırırsın (örn. aksiyon butonu / actionUrl çalışınca).
# Statü bildirimi — token query string'te, gövde boş/serbest
POST https://plugins.restomenum.app/plugin-api/packets/{tenantId}/{pluginId}/{packetId}/pickup?token=…
POST …/{packetId}/delivered?token=…
POST …/{packetId}/cancel?token=…
# pickup → yolda · delivered → teslim edildi · cancel → iptal (terminal — sonrası değişmez)pickup → yolda delivered → teslim edildi cancel → iptal (terminal durum sonrası değişmez)