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.
- Adres:
https://bi.express/api/v1 - Biçim: JSON. Her istekte
Accept: application/jsongönderin. - Kimlik:
Authorization: Bearer <token>. Token'ı Bi Express yöneticisi firmanız için üretir (admin paneli → Firmalar → firma → "API token oluştur"); her firmanın tek bir aktif token'ı olur. Yeni token üretildiğinde eskisi geçersizleşir. - Ücret: Kargo ücretini Bi Express belirler; istekte gönderilen ücret dikkate alınmaz.
package_type_idgönderilmezse varsayılan paket tipinin fiyatı uygulanır. - Limit: Token başına dakikada 60 istek. Aşılırsa
429döner. - Her token yalnızca kendi firmasının kargolarını görür ve yönetir.
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.