Delivery Partner API
Kurye firmaları ŞimdiSöyle restoranlarından teslimat işi alır. İşleri kendi yazılımınla API ve webhook üzerinden yönetebilirsin. Yazılımın yoksa firma paneli yeterli.
Başlangıç
- Firma olarak kaydol; yönetici onayından sonra panele girersin.
- Panelde Entegrasyon bölümünden API anahtarı üret. Anahtar yalnızca bir kez gösterilir.
- Restoranlar sana çalışma isteği gönderir, sen onaylarsın. Onaylı restoranlar “Kurye çağır” der ve iş sana gelir.
Her istekte anahtarı gönder. Adres: https://simdisoyle.com/api/partner/v1
curl https://simdisoyle.com/api/partner/v1/me \
-H "Authorization: Bearer ssk_live_..."İş akışı
offered ──► accepted ──► assigned ──► picked_up ──► delivered
│ │ │ └──► (failed bildirilir)
├─► rejected └──► cancelled
└─► expired (5 dk içinde yanıt yoksa)- Teklife 5 dakika içinde yanıt vermezsen süre dolar ve restoran başka firma seçer.
- Müşteri adı ve telefonu iş kabul edilene kadar gizlidir.
- Mutfak hazırlamadan kurye siparişi alamaz:
pickup.readytrue olmalı, aksi halde409 order_not_readydöner. - Her adım tekrar çağrılabilir. Aynı isteği ikinci kez göndermek hata vermez, işin güncel halini döner.
İstekler
| İstek | Ne yapar |
|---|---|
GET /me | Anahtarın hangi firmaya ait olduğunu gösterir. |
GET /jobs?status=open | open, offered, closed ya da all. |
GET /jobs/{id} | Tek işi getirir. |
POST /jobs/{id}/accept | Kabul eder. İsteğe bağlı fee_cents. |
POST /jobs/{id}/reject | Reddeder. İsteğe bağlı reason. |
POST /jobs/{id}/assign | courier_name (zorunlu), courier_phone. Henüz kabul edilmediyse önce kabul eder. |
POST /jobs/{id}/picked-up | Kurye siparişi aldı. |
POST /jobs/{id}/delivered | Teslim edildi. |
POST /jobs/{id}/failed | Teslim edilemedi. reason gönder. |
POST /jobs/{id}/cancel | Kurye almadan önce işi bırakır. reason gönder. |
POST /jobs/{id}/location | lat, lng gönderir. |
POST /webhook/test | Webhook adresine test olayı yollar. |
Örnek: kurye ata
curl -X POST https://simdisoyle.com/api/partner/v1/jobs/job_8f3a2c19d04e7b61/assign \
-H "Authorization: Bearer ssk_live_..." \
-H "Content-Type: application/json" \
-d '{"courier_name":"Mehmet Yılmaz","courier_phone":"05321234567"}'İş nesnesi
{
"job": {
"id": "job_8f3a2c19d04e7b61",
"status": "accepted",
"reference": "1042",
"created_at": "2026-10-17T09:12:03.000Z",
"expires_at": null,
"pickup": {
"name": "Lezzet Sofrası",
"address": "Atatürk Cd. No:12, Moda Mah., Kadıköy, İstanbul",
"phone": "02161234567",
"latitude": 40.9871,
"longitude": 29.0253,
"ready": false
},
"dropoff": {
"address": "Bahariye Cd. 45/3 Kadıköy",
"customer_name": "Ayşe K.",
"customer_phone": "05551112233",
"note": "Zili çalmayın, arayın"
},
"payment": { "method": "cash_on_delivery", "collect_cents": 18500 },
"order": { "total_cents": 18500, "items_count": 3, "scheduled_for": null },
"courier": null,
"fee_cents": null,
"accepted_at": "2026-10-17T09:13:10.000Z",
"assigned_at": null,
"picked_up_at": null,
"delivered_at": null,
"closed_at": null,
"close_reason": null,
"issue": null
}
}Tutarlar kuruş cinsindendir. payment.method: prepaid (tahsilat yok), cash_on_delivery, card_on_delivery.
Webhook
Panelde bir https adresi kaydedersen olaylar oraya POST edilir. Kaydederken bir imza anahtarı (whsec_…) bir kez gösterilir.
POST https://firmaniz.com/webhooks/simdisoyle
Content-Type: application/json
X-SimdiSoyle-Event: job.offered
X-SimdiSoyle-Delivery: evt_a1b2c3d4e5f6a7b8c9d0
X-SimdiSoyle-Signature: t=1760692323,v1=5b1e...
{
"id": "evt_a1b2c3d4e5f6a7b8c9d0",
"type": "job.offered",
"created": "2026-10-17T09:12:03.000Z",
"data": { "job": { ... } }
}job.offered | Restoran sana yeni bir iş teklif etti. Süre dolmadan kabul et ya da reddet. |
job.accepted | İş kabul edildi. Müşteri adı ve telefonu artık işte görünür. |
job.rejected | İş reddedildi. |
job.assigned | Bir kurye atandı. |
job.ready | Mutfak siparişi hazırladı; kurye alabilir. |
job.picked_up | Kurye siparişi aldı. |
job.delivered | Sipariş teslim edildi. |
job.failed | Teslim edilemedi. Sonraki adıma restoran karar verir. |
job.cancelled | İş iptal edildi (restoran ya da sen). |
order.amount_changed | Teslimatta ürün reddi nedeniyle sipariş tutarı değişti. job.payment.collect_cents yeni tahsilat tutarıdır; change alanında çıkarılan ürünler ve yeni toplam vardır. |
job.expired | Teklife süresinde yanıt verilmedi. |
ping | Panelden gönderilen test olayı. |
İmzayı doğrula
İmza, t + "." + ham_gövde metninin HMAC-SHA256 değeridir (anahtar: imza anahtarın). Ham gövdeyi değiştirmeden kullan; zaman damgası 5 dakikadan eskiyse reddet.
import crypto from "crypto";
function verify(rawBody, header, secret) {
const p = Object.fromEntries(header.split(",").map((x) => x.split("=")));
if (Math.abs(Date.now() / 1000 - Number(p.t)) > 300) return false;
const mac = crypto.createHmac("sha256", secret).update(p.t + "." + rawBody).digest("hex");
return crypto.timingSafeEqual(Buffer.from(mac), Buffer.from(p.v1));
}- 2xx dönersen olay iletilmiş sayılır. 8 saniye içinde yanıt ver.
- Başarısız olursa 1, 5, 30, 120 ve 360 dakika sonra yeniden denenir (toplam 6 deneme).
- Aynı olay birden fazla gelebilir.
X-SimdiSoyle-Deliverydeğerine göre tekrarı yoksay. - Yönlendirme (redirect) izlenmez. Adres herkese açık bir https adresi olmalı.
- Olay sırası garanti değildir; sıra karışırsa işi
GET /jobs/{id}ile oku.
Hatalar ve limitler
{ "error": { "code": "order_not_ready", "message": "Sipariş henüz hazır değil." } }401 unauthorized: anahtar eksik ya da geçersiz.404 job_not_found: iş yok ya da sana ait değil.409 invalid_state,job_expired,order_not_ready: işin durumu bu adıma uygun değil.429 rate_limited: dakikada en fazla 240 istek.