Satış kapanınca Restroid’e nasıl gönderilir
Restroid sizin satış ekranınızı çekmez. Fiş kapandıktan sonra sizin sunucunuz Restroid Cloud’a bir POST atar. Bu sayfa o isteğin ne zaman, nereye ve hangi gövdeyle gideceğini anlatır.
Ne zaman göndermelisiniz
Misafir ödedi, fiş kapandı, tutar kesinleşti — o anda, bir kez. Kayıt Cloud Finans → Siparişler listesine düşer. Açık adisyon, taslak veya iptal edilmemiş ara kayıt göndermeyin. Aynı externalId tekrarında Restroid stoğu ikinci kez düşürmez; 202 ile duplicate: true döner. Eşzamanlı çift gönderimde 409 alırsanız kısa süre sonra bir kez daha deneyin.
Göndermeden önce
- Ortak kaydı süper admin panelinde status = active olmalı.
- Kapsamda sales_inbound işaretli olmalı. Stok düşsün istiyorsanız stock; kasa / muhasebe yazılsın istiyorsanız accounting veya cash da açık olmalı.
- Satışın yapıldığı restoran bu ortağa bağlanmış olmalı.
- restaurantId’yi tahmin etmeyin: GET /restaurants yanıtındaki id’yi kullanın.
- İsteği sunucunuzdan atın. Api-Key tarayıcıya, APK’ya veya kasiyer cihazına konmaz.
Anahtar ve ilk bağlantı için Başlangıç, ürün eşlemesi için Ürün listesi ve ayarlar, kapsam listesi için Kapsamlar.
İstek
Canlı adres: POST https://cloud.restroid.com/api/public/partner/v1/hooks/sale-created
Geliştirme ortamı aynı yolu cloud.restroid.dev üzerinde kullanır. Eşdeğer yol: /hooks/sale.created.
Başlıklar
| Başlık | Değer |
|---|---|
| Api-Key | Süper adminin verdiği rkp_… anahtarı |
| Content-Type | application/json |
| Accept | application/json |
X-Api-Key veya Authorization: Bearer rkp_… de kabul edilir. Oturum çerezi yoktur.
Örnek (curl)
curl -sS -X POST https://cloud.restroid.com/api/public/partner/v1/hooks/sale-created \
-H "Api-Key: rkp_..." \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"restaurantId": "3f2a1c0e-1111-4222-a333-444455556666",
"externalId": "FIS-20260828-00412",
"occurredAt": "2026-08-28T14:05:00+03:00",
"currency": "TRY",
"total": 185.5,
"items": [
{
"productId": "a1b2c3d4-0000-0000-0000-000000000001",
"plu": "101",
"name": "Adana",
"qty": 1,
"amount": 185.5
}
],
"payments": [
{ "method": "cash", "amount": 185.5 }
]
}'Gövde alanları
| Alan | Zorunlu | Anlamı |
|---|---|---|
| restaurantId | Evet | GET /restaurants ile aldığınız Restroid restoran UUID’si. |
| externalId | Evet | Sizin fiş / sipariş numaranız. Partner + fiş için tek olmalı. |
| total | Evet | Kapanan fişin toplam tutarı. Sayı olmalı (string kabul edilmez). |
| items | Evet | En az bir satır. name dolu ve qty (veya quantity) 0’dan büyük olmayan satır yok sayılır; hepsi elenirse 400 döner. |
| occurredAt | Hayır | ISO-8601 kapanış anı. Yoksa Restroid o anı yazar. |
| currency | Hayır | Varsayılan TRY. Büyük harfe çevrilir. |
| payments | Hayır | Ödeme kırılımı. method: cash/nakit → nakit kasa; card/kart → banka/kart hesabı; havale; yemek kartı adı. Yoksa ve closeMode=paid ise toplam nakit sayılır. |
| closeMode | Hayır | paid (varsayılan), cancelled / iptal, complimentary / ikram, waste / zayi. İkram ve zayi sipariş listesine düşer; kasa yazılmaz. İptal stok düşmez. |
items[]
| Alan | Zorunlu | Anlamı |
|---|---|---|
| name | Evet | Satır adı. Boş satır atlanır. |
| qty | Evet* | Miktar. quantity adı da kabul edilir. 0 veya geçersizse satır atlanır. |
| productId | Hayır | GET /products yanıtındaki id. Restroid kart UUID’si. Sizin iç ürün kodunuz değil. |
| plu | Hayır | GET /products yanıtındaki plu. Stok satırında plu varsa o, yoksa productId, o da yoksa name kullanılır. |
| amount | Hayır | Satır tutarı. Yoksa 0 yazılır; fiş toplamı yine total’den alınır. |
payments[]
| Alan | Zorunlu | Anlamı |
|---|---|---|
| amount | Evet* | Pozitif sayı. Geçersiz satırlar elenir. |
| method | Hayır | cash, card, havale veya yemek kartı adı. Cloud’daki hesaba buna göre yazılır. |
productId / plu / name Restroid listesinden gelir. Hangi alanın ne olduğu: Ürün listesi alanları.
Kısmi iade yoktur. Tüm fişi geri almak için POST /hooks/sale-cancelled kullanın. Yanlış fişi ikinci bir satış gibi göndermeyin.
Restroid bu istekle ne yazar
İstek kabul edilince Restroid kendi defterine işler. Sizin POS veritabanınızı değiştirmez. Yazılanlar açık kapsamlara bağlıdır:
| Açık kapsam | Yazılan |
|---|---|
| stock | Şubenin ilk aktif deposuna her kalem için stok çıkışı (stock_ledger, direction=out). Not: partner-sale {externalId}. |
| accounting veya cash | Her ödeme satırı kendi hesabına POS_SALE yazar (nakit / kart / yemek kartı). closeMode paid değilse yazılmaz. |
| sales_inbound (her zaman) | Finans → Siparişler listesine düşer (sales.closed). posted.inbox = true. |
Depo veya şube yoksa ilgili yazım atlanır; istek yine 202 olabilir. İkram/zayi kapanışında stok düşer, kasa yazılmaz.
Yanıtlar
Kabul (202)
{
"accepted": true,
"event": "sale.created",
"restaurantId": "3f2a1c0e-1111-4222-a333-444455556666",
"externalId": "FIS-20260828-00412",
"posted": { "stock": 1, "accounting": true, "inbox": true }
}posted.stock yazılan stok satırı sayısıdır. posted.accounting kasa / muhasebe kaydının oluşup oluşmadığıdır. posted.inbox Siparişler listesine düştüğünü gösterir.
Aynı fiş ikinci kez (202)
{
"accepted": true,
"duplicate": true,
"event": "sale.created",
"restaurantId": "3f2a1c0e-1111-4222-a333-444455556666",
"externalId": "FIS-20260828-00412"
}Bunu başarı sayın; stoğu tekrar düşürmeyin, kullanıcıya hata göstermeyin.
Hatalar
| HTTP | error | Ne anlama gelir |
|---|---|---|
| 400 | restaurantId zorunlu. | Gövdede restoran kimliği yok veya boş. |
| 400 | externalId, total ve items zorunlu. | Fiş no, toplam veya geçerli kalem eksik. name/qty elenmiş olabilir. |
| 401 | Api-Key geçersiz veya eksik. | Başlık yok, yanlış veya döndürülmüş. |
| 403 | Bu entegrasyonun kullanım izni kapalı. | Henüz active değil (draft/suspended). |
| 409 | Bu fiş şu anda işleniyor. | Aynı externalId eşzamanlı; kısa süre sonra tekrar. |
| 413 | İstek gövdesi çok büyük. | 256 KB sınırı. |
| 429 | Çok fazla istek. | Retry-After kadar bekleyin. |
| 403 | Bu anahtar «sales_inbound» kapsamına yetkili değil. | Satış yazma kapsamı kapalı. |
| 403 | Bu restoran bu entegrasyona bağlı değil. | restaurantId bağlanmamış veya yanlış UUID. |
Satışı iptal etmek
Daha önce kabul edilen fişi geri almak için aynı externalId ile POST /hooks/sale-cancelled atın. Restroid stok girişini yazar ve satışın POS_SALE grubunu siler (ayrı CASH_OUT satırı atılmaz). Kabul edilmemiş fiş 404 döner. Aynı iptal ikinci kez duplicate: true olur.
curl -sS -X POST https://cloud.restroid.com/api/public/partner/v1/hooks/sale-cancelled \
-H "Api-Key: rkp_..." -H "Content-Type: application/json" \
-d '{
"restaurantId": "3f2a1c0e-1111-4222-a333-444455556666",
"externalId": "FIS-20260828-00412"
}'{
"accepted": true,
"event": "sale.cancelled",
"restaurantId": "…",
"externalId": "FIS-20260828-00412",
"reversed": { "stock": 1, "accounting": true }
}Z raporu bu uç değildir
Fiş kapanışı gün sonu değildir. Kasiyer «Z al / günü kapat» dediğinde ayrı istek gider: POST /hooks/z-report-created. X raporu yazılmaz. Öğle nakit teslim cash-shift-closed, çekmece cash-in / cash-out iledir.
Bundan sonra Restroid size ne gönderir
Satış isteğinin kendisi sizin webhook adresinize gitmez. Stok veya muhasebe yazıldıysa ve webhook açıksa Restroid ayrıca sizin URL’nize stock.changed / accounting.posted POST edebilir. Bu, satışın kopyası değildir; Restroid defterinin güncellendiğinin haberidir. Ayrıntı: Webhook (Restroid → siz).
Sık yapılan hatalar
- Webhook bekleyip satışı hiç POST etmemek — Restroid satışınızı bilemez.
- restaurantId olarak kendi şube kodunuzu göndermek. Restroid UUID gerekir.
- total’i "185,50" veya "185.5" string göndermek. Sayı olmalı: 185.5
- items içinde yalnız productId verip name’i boş bırakmak. name zorunludur.
- Her masa değişikliğinde aynı externalId ile basmak. Yalnız kapanışta bir kez.
- Anahtarı kasiyer uygulamasına gömmek. İstek sizin backend’inizden çıkmalı.
Hazırlık istekleri
Satıştan önce restoran kimliğini ve ürün eşlemesini alın.
curl -sS https://cloud.restroid.com/api/public/partner/v1/restaurants \
-H "Api-Key: rkp_..." -H "Accept: application/json"
curl -sS https://cloud.restroid.com/api/public/partner/v1/restaurants/RESTORAN_UUID/products \
-H "Api-Key: rkp_..." -H "Accept: application/json"Tüm yollar API referansı sayfasında.
