Bi Express API

Sitenizden Bi Express'e kargo oluşturun, takip edin ve kurye zimmetinden önce iptal edin. Kargo durumu değiştiğinde webhook ile haber alın.

Bölgeler

7 teslimat bölgesi vardır: Lefkoşa, Gazimağusa, Girne, Güzelyurt, İskele, Lefke ve Karpaz. Her bölgenin köy/mahalle listesi /cities yanıtında gelir:

[ { "id": 3, "name": "Girne", "places": [ { "id": 101, "name": "Alsancak" }, { "id": 102, "name": "Çatalköy" } ] } ]

id'leri sabit kodlamayın; listeyi günde bir kez çekip önbelleğe alın.

Uç noktalar

Yöntem Yol Ne yapar
GET /cities Teslimat bölgeleri ve köy/mahalleleri (id, name, places[])
GET /package-types Paket tipleri (id, name, price)
POST /cargoes Kargo oluşturur
GET /cargoes/{code} Kargo durumu ve geçmişi
POST /cargoes/{code}/cancel Kargoyu iptal eder (zimmetten önce)

Kargo oluştur: POST /cargoes

Alan Tip Zorunlu Not
full_name string ≤255 evet Alıcı adı
phone string ≤20 evet Alıcı telefonu
address string ≤2000 evet Açık adres
city_id int evet /cities listesinden
place_id int hayır Köy/mahalle; city_id bölgesine ait olmalı (aksi 422)
package_type_id int hayır /package-types listesinden; kargo ücreti buradan hesaplanır
packages_count int 1–1000 hayır Koli adedi
is_payment_on_delivery bool hayır Kapıda ödeme
package_price sayı ≥0 is_payment_on_delivery false değilse evet Kapıda tahsil edilecek tutar
is_exchange / is_return bool hayır Değişim / iade gönderisi
desc string ≤1000 hayır Kurye notu
external_ref string ≤100 önerilir Sizin sipariş numaranız

Tekrar güvenliği: Aynı external_ref ile tekrar istek atarsanız yeni kargo açılmaz; mevcut kargo 200 ile döner (ilk oluşturmada 201). Ağ hatasında isteği güvenle tekrarlayabilirsiniz.

curl -X POST https://bi.express/api/v1/cargoes \
  -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"full_name":"Ayşe Yılmaz","phone":"05331234567","address":"Ortaköy, Lefkoşa",
       "city_id":1,"package_type_id":2,"is_payment_on_delivery":true,
       "package_price":450,"external_ref":"WC-1042"}'
{
  "code": "K7Q2M9XA",
  "external_ref": "WC-1042",
  "delivery_code": "4821",
  "tracking_url": "https://bi.express/takip?kod=K7Q2M9XA",
  "status": "Pending",
  "status_label": "Kargo oluşturuldu",
  "cancelable": true,
  "courier": null
}

delivery_code, alıcının teslimatta kuryeye söylediği 4 haneli koddur. Alıcıya iletin.

courier: kargo bir kuryeye zimmetlenince {"name": "Ali Veli", "phone": "05331112233"}, zimmetlenmemişse null. Telefon kayıtlı değilse phone alanı null olur. cancelable: şu an POST /cancel ile iptal edilebilir mi.

Kargo sorgula: GET /cargoes/{code}

Yukarıdaki alanlara ek olarak city, place (yoksa null) ve history döner. history en yeni olay başta olacak şekilde sıralıdır:

{ "...": "...", "city": "Lefkoşa", "place": "Gönyeli",
  "history": [ { "status": "Received", "status_label": "Teslim alındı", "note": null, "at": "2026-11-04T10:12:00+02:00" } ] }

İptal: POST /cargoes/{code}/cancel

Kargo yalnızca "Kargo oluşturuldu" durumundaysa ve henüz bir kuryeye zimmetlenmediyse iptal edilebilir. Aksi halde 409 döner; bu durumda iptal için Bi Express ile iletişime geçin.

Durumlar

status Anlamı
Pending Kargo oluşturuldu
Received Teslim alındı (depoda)
InTransfer Transferde
OutForDelivery Dağıtımda
Delivered Teslim edildi (son durum)
Returned İade edildi (son durum)
Canceled İptal edildi (son durum)

Hatalar

Kod Ne zaman
401 Token yok ya da geçersiz
403 Token bir gönderici firmaya ait değil
404 Kargo yok ya da başka bir firmaya ait
409 İptal artık mümkün değil
422 Doğrulama hatası: {"message": "...", "errors": {"alan": ["..."]}}
429 İstek limiti aşıldı; Retry-After başlığındaki süre kadar bekleyin

Webhook

Bi Express yöneticisi firmanız için bir webhook URL (yalnızca https) ve bir imza anahtarı (secret) tanımlar. Şu durumlarda bu adrese POST atılır:

event Ne zaman
cargo.status_changed Kargo oluşturulduğunda ve durumu her değiştiğinde
cargo.courier_assigned Kargo bir kuryeye zimmetlendiğinde (durum değişmeden). Bu andan itibaren iptal edilemez
{
  "event": "cargo.status_changed",
  "event_id": "9b2f4c1e-6a7d-4e3b-8f0a-2c5d1e7b9a40",
  "code": "K7Q2M9XA",
  "external_ref": "WC-1042",
  "status": "Delivered",
  "status_label": "Teslim edildi",
  "note": null,
  "cancelable": false,
  "courier": { "name": "Ali Veli", "phone": "05331112233" },
  "tracking_url": "https://bi.express/takip?kod=K7Q2M9XA",
  "at": "2026-11-04T15:40:00+02:00"
}

event_id her bildirim için benzersiz bir metindir (UUID); tekrar denemelerde aynı kalır.

Başlıklar: X-BiExpress-Event, X-BiExpress-Timestamp (unix saniye), X-BiExpress-Signature.

İmza doğrulama: hex(HMAC-SHA256(timestamp + "." + ham_gövde, secret)) değeri X-BiExpress-Signature başlığına eşit olmalı. Gövdeyi JSON'a çevirmeden önce ham haliyle imzalayın. 5 dakikadan eski timestamp'leri reddedin.

$body = file_get_contents('php://input');
$ts   = $_SERVER['HTTP_X_BIEXPRESS_TIMESTAMP'] ?? '';
$sig  = $_SERVER['HTTP_X_BIEXPRESS_SIGNATURE'] ?? '';
$ok   = abs(time() - (int) $ts) < 300
     && hash_equals(hash_hmac('sha256', $ts.'.'.$body, BIEXPRESS_WEBHOOK_SECRET), $sig);
if (! $ok) { http_response_code(401); exit; }
$event = json_decode($body, true);
// event_id ile tekrarları ayıklayın, sonra siparişi güncelleyin
http_response_code(200);

Teslim garantisi: 10 saniye içinde 2xx dönmezseniz istek tekrar denenir. Yaklaşık 30 sn, 2 dk, 10 dk, 30 dk ve 1 saat aralıklarla toplam 6 deneme yapılır. Yönlendirmeler (3xx) izlenmez. Aynı olay birden fazla kez gelebilir; event_id ile tekrarları ayıklayın.

Not: cancelable ve courier alanları bildirimin gönderildiği andaki durumu gösterir. İptal edip edemeyeceğinizi kesin olarak POST /cancel yanıtı belirler.