Kurumsal API
Başlarken
- Kurumsal hesap açın. API anahtarınızı ve webhook gizli anahtarınızı size ileteceğiz.
- Tüm isteklerde anahtarı başlıkta gönderin:
Authorization: Bearer yk_live_… - Adres:
https://muhurkurye.com/api/v1· JSON · UTF-8. Tutarlar kuruş (tam sayı) cinsindendir. - API siparişleri cari hesabınıza işlenir ve ay sonunda tek faturada toplanır. Sınır: anahtar başına dakikada 120 istek.
curl https://muhurkurye.com/api/v1/ping -H "Authorization: Bearer $KURYE_API_KEY"
Uç noktalar
POST/quotes
lat/lng göndermenizi öneririz; yalnız address gönderirseniz adres harita servisinden çözülür.POST/orders
201). externalRef sizin kayıt numaranızdır: aynı referansla tekrar gönderirseniz yeni sipariş açılmaz, mevcut sipariş 200 ve "duplicate": true ile döner. Ağ hatasında güvenle tekrar deneyebilirsiniz.{
"externalRef": "ERP-2026-0042",
"pickup": {
"address": "Kılıçlı Mah. Şile Cad. No: 8A, Beykoz/İstanbul",
"lat": 41.1295, "lng": 29.1135,
"details": "Kat 2, resepsiyon",
"contactName": "Ayşe Yılmaz", "contactPhone": "+905321112233"
},
"dropoff": {
"address": "Levent Mah., Büyükdere Cad., Beşiktaş/İstanbul",
"contactName": "Ali Demir", "contactPhone": "+905334445566"
},
"serviceLevel": "acil",
"roundTrip": false,
"weightKg": null,
"largePackage": false,
"declaredValueKurus": 2500000,
"deliveryCode": true,
"scheduledPickupAt": null,
"packageDescription": "Sözleşme (2 nüsha)",
"customerNote": "İmzalı nüshayı geri getirin"
}serviceLevel: "standart" (varsayılan), "acil" (60 dk, ek ücretli) veya "ekonomi" (gün içinde, indirimli; yalnızca Pazartesi–Cumartesi 07:00–14:00 arası alışlarda). Eski "urgent": true alanı hâlâ kabul edilir. 20 kg üzeri gönderiler 400 ile reddedilir. declaredValueKurus: gönderi değeri (kuruş); 1.000 TL üstü kısım için sigorta ücreti fiyata eklenir. deliveryCode: true ise alıcıya SMS ile 4 haneli teslim kodu gider, kurye kodu almadan teslim edemez; kod oluşturma yanıtında order.deliveryCode olarak da döner. promoCode: kampanya kodu (geçersizse 400, alan promoCode).
Yanıt:
{
"order": {
"id": "0d6c…",
"orderNo": "YK-1042",
"externalRef": "ERP-2026-0042",
"status": "beklemede",
"statusLabel": "Beklemede",
"subtotalKurus": 92050,
"vatKurus": 18410,
"totalKurus": 110460,
"trackingUrl": "https://panel.muhurkurye.com/takip/…",
"proofOfDelivery": null
},
"quote": { "lines": [ … ], "totalKurus": 110460 }
}GET/orders/{id}
GET/orders
status, externalRef, limit (en fazla 200).POST/orders/{id}/cancel
beklemede veya onaylandi) iptal eder. Gövde: { "reason": "…" }. Daha sonra 409 döner.Sipariş durumları
beklemede → onaylandi → kuryeye_atandi → alindi → yolda → teslim_edildi · iptal · sorunlu
Teslim edilemezse: yolda → geri_donuyor → geri_teslim (paket göndericiye iade edilir; failedReason: alici_yok, adres_bulunamadi, alici_reddetti, kapali, diger; dönüş ayağı ücreti eklenir).
Hatalar
Hata yanıtları { "error": "Türkçe açıklama", "field": "pickup" } biçimindedir. Kodlar: 400 geçersiz istek, 401 anahtar hatalı, 403 KVKK onayı eksik, 404 bulunamadı, 409 çakışma, 422 adres çözülemedi, 429 hız sınırı.
Webhook
Sipariş oluştuğunda (order.created) ve durumu her değiştiğinde (order.status_changed) adresinize POST gönderilir. 2xx dışı yanıtta üstel bekleme ile 8 kez tekrar denenir; aynı olay birden fazla gelebilir, id ile ayıklayın. İmzayı mutlaka doğrulayın:
{
"id": 1842,
"event": "order.status_changed",
"occurredAt": "2026-10-10T09:41:12Z",
"order": {
"id": "0d6c…", "orderNo": "YK-1042", "externalRef": "ERP-2026-0042",
"status": "teslim_edildi", "previousStatus": "yolda", "totalKurus": 110460,
"trackingUrl": "https://panel.muhurkurye.com/takip/…", "deliveredAt": "2026-10-10T09:41:10Z",
"proofOfDelivery": { "receiverName": "Resepsiyon - Zeynep" }, "cancelReason": null
}
}İmza doğrulama örneği (Node.js):
import crypto from "node:crypto";
// Express örneği: gövdeyi ham (string) olarak alın
app.post("/kurye-webhook", express.text({ type: "application/json" }), (req, res) => {
const ts = req.header("X-Webhook-Timestamp");
const sig = req.header("X-Webhook-Signature"); // "v1=<hex>"
const expected = "v1=" + crypto
.createHmac("sha256", process.env.KURYE_WEBHOOK_SECRET)
.update(`${ts}.${req.body}`)
.digest("hex");
const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300; // 5 dk
if (!fresh || !crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
return res.status(401).end();
}
const event = JSON.parse(req.body);
// event.id ile tekrarları ayıklayın (aynı olay birden fazla gelebilir)
console.log(event.event, event.order.orderNo, event.order.previousStatus, "→", event.order.status);
res.status(200).end();
});

