Şube Mobil API — Geliştirici Rehberi
Şube (acente) mobil uygulaması · Bearer kimlik doğrulama
Şube Mobil API Rehberi
Şube (acente) mobil uygulamasını geliştirenler için. Uygulama, web şube panelindeki (B01–B17, kuryeler,
bölgeler, depolar) ekranlarla aynı uçları kullanır. Alan ve şema ayrıntıları için API Referansı'na
bakın (üstten "Şube Mobil API"yi seçin).
1. Hızlı başlangıç
Dört istekle ilk akışı preprod ortamında deneyin. Şifre yerine kendi test şifrenizi yazın.
Giriş yapın, token alın.X-Client-Type: mobile başlığı şarttır; yoksa token yanıtta gelmez.
Yanıttaki data.accessToken değerini saklayın (8 saat geçerli). 409 AGENCY_SELECTION_REQUIRED gelirse
error.agencies listesinden bir id seçip aynı isteğe "agencyId" ekleyin.
Oturumu doğrulayın. Yetkiler (capabilities) buradan gelir.
Bir yazma isteği gönderin (kurye ata). Gönderi ve kurye kimliklerini
GET branch/preparation ve GET branch/dispatch/options?shipmentId=… yanıtlarından alın.
Her yazma isteğinde yeni bir Idempotency-Key üretin.
Aynı komutu aynı anahtarla tekrar çalıştırın: yanıt 200 ve data.replayed: true olur, ikinci bir zimmet açılmaz.
2. Ortamlar ve hesaplar
Ortam
Base URL
Kullanım
Preprod (test)
https://api-mobile.preprod.jetdiji.com
Geliştirme ve test. Önce burada çalışın.
Canlı
https://api-mobile.jetdiji.com
Mağaza sürümü.
Yollar iki ortamda aynıdır: /api/portal/v1/....
Hesaplar ve token'lar ortamlar arasında geçmez.
Swagger'daki / ("Aynı origin") sunucusu yalnız doküman panelin kendi alan adında açıldığında kullanılır.
"Try it out" yalnız test ortamlarında çalışır.
Test hesabı: JetDiji ekibinden isteyin. Tüm düğmeleri deneyebilmek için AGENCY_ADMIN rolü
isteyin; yalnız operasyon akışını görmek için AGENCY_OPERATOR yeterlidir (bkz. Roller).
Şube seçimi (409). Kullanıcının birden çok şube yetkisi varsa ya da kullanıcı SYSTEM_OWNER ise
(tek şube olsa bile) yanıt 409 AGENCY_SELECTION_REQUIRED + error.agencies[] olur. Kullanıcıya listeyi
gösterin, seçilen id'yi agencyId olarak ekleyip aynı isteği tekrarlayın. SYSTEM_OWNER tüm aktif
şubeleri seçebilir; şube rolü olmadan da şube seçerek bağlanabilir.
Sonraki tüm isteklerde Authorization: Bearer <accessToken>. Token, web çerezindekiyle aynı HS256 JWT'dir.
POSTagency-auth/logout — sunucu oturumu LOGGED_OUT yapar; token
artık geçmez. Token geçersiz ya da eksik olsa da 200 döner. Ardından token'ı cihazdan silin.
Token süresi
Oturum 8 saat geçerlidir (JWT exp + sunucudaki portal_user_sessions.expiresAt).
Süre dolunca, oturum iptal edilince ya da şube / kullanıcı pasifleşince tüm uçlar 401 UNAUTHENTICATED döner →
giriş ekranı.
Yenileme (refresh) ucu yoktur; süre dolunca yeniden giriş gerekir.
Giriş hataları
HTTP
Kod
Ne yapmalı
400
INVALID_JSON, INVALID_EMAIL, PASSWORD_REQUIRED
Formu düzeltin. Bozuk JSON artık 500 değil 400 döner.
401
INVALID_CREDENTIALS
Yanlış şifrede error.remainingAttempts ve error.lockedUntil: null gelir; kalan hakkı gösterin. Kayıtsız e-postada ek alan yoktur.
423
ACCOUNT_TEMPORARILY_LOCKED
5 hatalı denemede hesap 15 dakika kilitlenir. error.lockedUntil'e kadar bekletin. Kilitlenme anında error.remainingAttempts: 0.
Kullanıcı pasif / davet tamamlanmamış / aktif şube yetkisi yok / seçilen şubeye yetki yok. Mesajı gösterin.
409
AGENCY_SELECTION_REQUIRED
Şube seçtirin, agencyId ile tekrarlayın.
500
LOGIN_FAILED
Beklenmeyen hata; tekrar deneyin.
Hata ek alanları (remainingAttempts, lockedUntil, agencies) error içindedir.
Üst seviye kopyaları ve 409'daki data.agencies yalnız eski web uyumluluğu içindir; mobil error.* okur.
Diğer notlar
E-posta küçük harfe çevrilir. Davetli (INVITED) kullanıcı ilk girişte ACTIVE olur.
Şifre değiştirme: şube API'sinde şifre değiştirme ucu yoktur. mustChangePassword: true gelirse
bunu kullanıcıya bilgi olarak gösterin.
Token saklama: iOS Keychain / Android Keystore (EncryptedSharedPreferences). Düz dosyaya ya da
AsyncStorage'a yazmayın; token'ı loglamayın.
Web çerezi (jetdiji_agency_session, httpOnly) de desteklenir ama mobilde kullanılmaz.
Yetki ve düğme gösterimi için Roller bölümüne bakın.
4. Hata yönetimi
Tüm uçlar (kimlik, acente, şube) aynı zarfı döner:
{
"success": false,
"error": {
"code": "DISPATCH_NOT_READY",
"message": "Gönderi artık dağıtıma hazırlık adımında değil. Ekranı yenileyin.",
"shipmentNumber": "JD2026100300123"
},
"code": "DISPATCH_NOT_READY",
"message": "Gönderi artık dağıtıma hazırlık adımında değil. Ekranı yenileyin."
}
Yalnız error.code'a bakın.error.message varsa kullanıcıya doğrudan gösterilebilir;
yoksa kod için kendi çevirinizi kullanın. Üst seviye code / message eski web uyumluluğu içindir.
Uca özgü ek alanlar error içindedir (eski error.details kaldırıldı): shipmentNumber,
transferId, transferNumber, max, variables, allowed,
reason, issues, minLength / maxLength; login'de remainingAttempts,
lockedUntil, agencies.
Bozuk JSON: JSON gövde okuyan tüm uçlarda bozuk / boş / nesne olmayan gövde → 400 INVALID_JSON
(eski INVALID_BODY kaldırıldı). İstisna: transfers/incoming/{id}/confirm boş gövdeyi {} sayar.
Şema hatası (geçerli JSON, yanlış alan): zod kullanan uçlarda (transfer, etiket, sayım) 422
VALIDATION_FAILED + error.issues: [{ path, code, message }]; diğer uçlarda uca özgü 400 kodları
(ör. DISPATCH_INVALID_INPUT, CARD_OWNER_TYPE_INVALID).
Başarı: { "success": true, "data": ... }. Yazma uçlarında ayrıca üst seviye replayed /
idempotent gelir (eski web uyumluluğu; mobil data.replayed okur).
İstemci ne yapmalı
HTTP
Anlam
İstemci davranışı
401
Oturum yok / süresi doldu
Token'ı silin, giriş ekranına dönün.
403
Yetki yok (FORBIDDEN)
error.message ile yetki mesajı gösterin; düğmeyi pasif tutun. Kuyruktan çıkarın, tekrar denemeyin.
404
Kayıt bu şubede yok
Mesajı gösterin, listeyi yenileyin.
409
Durum değişti / çakışma
error.message'ı gösterin ve ekranı yenileyin. Tekrar denemeyin.
422
Alan doğrulama hatası
error.issues[].path ile ilgili alanın altında hata gösterin.
423
Hesap kilitli (yalnız login)
error.lockedUntil'e kadar girişi kapatın.
429
Çok fazla istek
Şube uçları bugün 429 dönmez. Gelirse bir süre bekleyip aynı anahtarla tekrar deneyin.
5xx / ağ hatası
Sunucu ya da bağlantı sorunu
Aynı Idempotency-Key ile tekrar deneyin (bkz. Yazma istekleri).
Tüm şube yazma uçlarında başlık Idempotency-Keyzorunludur: 8–160 karakter, boşluksuz görünür
ASCII (0x21–0x7E). Önerilen: UUID v4.
Her kullanıcı eylemi için bir kez üretin; yeniden denemede aynı anahtarı gönderin.
Başlık yok → 400 IDEMPOTENCY_KEY_REQUIRED. Uzunluk / karakter dışı → 400 IDEMPOTENCY_KEY_INVALID
(error.minLength, error.maxLength). Sunucu anahtarı kırpmaz, yok saymaz.
X-Client-Event-Id başlığı ve gövdedeki clientEventId anahtar yerine geçmez. Sunucu
başlığı okumaz; gövde alanı varsa yalnız audit kaydına yazılır.
Tekrar davranışı
Aynı anahtar + aynı uç tekrar gelirse ilk başarılı sonuç döner: HTTP 200 (ilk istek 201/202 olsa bile) ve
data.replayed: true (ilk istekte false). Üst seviye replayed ve idempotent
aynı değerin eski web kopyasıdır.
Anahtar kapsamı: dağıtım, etiket, sayım ve kart uçlarında aynı kullanıcı; transfer, kurye dönüşü, SMS ve fatura
uçlarında aynı şube.
Hatalı ilk istek saklanmaz; aynı anahtarla yeniden denenebilir. Aynı anahtar farklı gövdeyle gelirse ilk sonuç döner (gövde
karşılaştırılmaz).
Sonucu nesne olmayan işlemlerde (counts/{id} void-scan, line-reason, close, cancel) yanıt
data: { result: null, replayed } olur.
Kontrol sırası: oturum (401) → yetenek (403) → anahtar (400) → gövde (400/422). İstisnalar:
compliance/cards yeteneği gövdedeki ownerType'a göre seçtiği için anahtar → gövde → yetenek;
counts/{id} yetenek kontrolü (action'a göre) gövde doğrulandıktan ve sayım bulunduktan sonra yapılır.
200 (data.idempotent de korunur; yanıt partinin güncel özetidir)
Anahtar gerekmeyen POST'lar (yan etkisiz; başlık gönderilirse yok sayılır): transfers/outgoing/resolve,
preparation/print-rows, sms/preview, compliance/cards/verify (audit yazar ama durum
değiştirmez). agency-auth/login ve logout da anahtar istemez.
Çevrimdışı kuyruk
Web'deki offline-queue.ts ile aynı sözleşme:
Kullanıcı eylemi geldiğinde anahtarı üretin ve isteği anahtarıyla birlikte cihazda saklayın.
İsteği gönderin. Ağ hatası ya da 5xx gelirse kuyrukta tutun ve aynıIdempotency-Key ile yeniden deneyin.
Sunucu teyidi (success: true) gelmeden "tamamlandı / içeri alındı" göstermeyin; o ana kadar "kuyrukta" gösterin.
4xx yanıt kalıcı hatadır: kaydı kuyruktan çıkarın ve kullanıcıya gösterin.
6. Ekran ekran akışlar
Her kart aynı sırayı izler: amaç, çağrı sırası, iş kuralları, hata durumunda ne yapılmalı. Yollar
/api/portal/v1/ önekiyle başlar. Tüm yazma çağrıları Idempotency-Key ister (bkz.
5. bölüm); yetki için Roller bölümüne bakın.
GirişGiriş ve kabuk
Amaç
Kullanıcıyı içeri almak, şubeyi seçtirmek ve her ekranda kullanıcı / şube adını ve yetkileri göstermek.
Çağrı sırası
POSTagency-auth/login (X-Client-Type: mobile)
409 ise şube seçtirin → POSTagency-auth/login (agencyId ile)
GETagency-auth/session — rol, şube adı, capabilities
rows: birimdeki 4010 gönderiler (AWAITING_COURIER, IN_QUEUE) + INCOMING
(merkezde hazırlanan, yalnız KUVEYT_HGS ürünü, 2010 / 2011, en fazla 300 aday).
Atama gönderiyi 4010'da bırakır (IN_QUEUE); zimmet ve 4020'ye geçiş kurye okutarak kabul edince olur
(bkz. zimmet kuralları).
options: bu birime aktif bağlı, çalışır durumdaki (AVAILABLE / ASSIGNED / WORKING) kuryeler. eligible:
kurye bölgesi gönderinin ilçesine uyuyor. ready: false ise atama DISPATCH_NOT_READY ile reddedilir;
"Değiştir" modunda web ready'yi yok sayar. Çoklu seçimde ilk gönderinin seçenekleri kullanılır.
handover/change iki ayrı adımdır (geri al + yeniden zimmetle); ikinci adım başarısız olursa gönderi birimin
zimmetinde kalır — yeniden atayın.
reassign: REASSIGN devri açar; mevcut kurye listede yoktur; zimmet ve görev yeni kurye okutana kadar eski
kuryededir. note 500 karakterde kesilir.
print-rows: 1–200 gönderi, hepsi bu birimde olmalı; geçersiz UUID'ler sessizce elenir. ZPL dönmez, alıcı
telefonu yoktur. Veri değiştirmez, anahtar istemez.
kpis.efficiency = bugün çıkan / (bugün çıkan + birimde bekleyen) yüzdesi; payda 0 ise null.
Düğmeler capabilities.operate ile açılır (canManage eski alan, aynı değer).
Hata durumunda
409 (DISPATCH_NOT_READY, HANDOVER_ALREADY_PENDING, HANDOVER_SHIPMENT_WITH_COURIER,
MAX_REDELIVERY_COUNT_REACHED, DISPATCH_COURIER_UNAVAILABLE…): error.message'ı ve
error.shipmentNumber'ı gösterin, listeyi ve kurye seçeneklerini yenileyin.
404 BRANCH_SHIPMENT_NOT_FOUND / BRANCH_COURIER_NOT_FOUND: gönderi ya da kurye artık bu birimde
değil → listeyi yenileyin.
400 DISPATCH_INVALID_INPUT: seçim boş ya da 200'den fazla → seçimi düzeltin.
403: kullanıcının operate yetkisi yok → düğmeyi pasif gösterin.
B12Bugün dağıtılacaklar
Amaç
Birimde bugün dağıtılacak (4010) ve dağıtımdaki (4020) gönderileri öncelikle göstermek; kurye atamak ya da değiştirmek.
Çağrı sırası
GETbranch/dispatch
Kurye ata / değiştir diyaloğu B01 ile aynı: dispatch/options → dispatch/handover ya da
handover/change; 4020 için dispatch/reassign (GET → POST)
İşlemden sonra GETbranch/dispatch
İş kuralları
En fazla 500 satır.
Öncelik HIGH: Devir (9116 / tekrar çıkış), SLA ihlali ya da 24 saat içinde dolacak SLA. late: SLA ihlali.
suggestions sırası: bölge uyumu (MATCH > PARTIAL > NONE), aktif iş, ETA, ad. activeJobs = 4020 +
kabul bekleyen zimmet; ETA hesabı konum bölümünde.
cancelReasons: 5110 (teslim edilemedi) neden kataloğu; ad locale'e göre gelir, "DLF-xx - " öneki atılır.
Teslim edilemedi nedenleri için ayrı bir uç yoktur.
İptal yalnız kabul bekleyen zimmette yapılır; gönderi birimde ve 4010'da kalır, neden audit'e yazılır.
recent: gönderi olayları + şube paneli audit kayıtları (en fazla 12).
Hata durumunda
409 HANDOVER_NOT_PENDING (iptal / değiştir): gönderi artık kabul beklemiyor (ör. kurye okuttu, 4020) → yenileyin.
400 CANCEL_REASON_REQUIRED / CANCEL_REASON_INVALID: katalogdan neden seçtirin.
Kuyruklar (her biri en fazla 500): handovers (kuryeye zimmet, kurye okutmadı), returns (kurye iade
başlattı, şube okutmadı), endOfDay (sonuç girilmiş, iade başlatılmamış), overdue (alarm eşiğini aşan),
approvals (2040 / 2041-2042), matching (2030). approvals / matching
öğelerinde courier ve transferNumber null'dır.
Okutma: zimmet birime geçer, otomatik yeniden dağıtım denenir (data.redelivery: applied; olmadıysa
reason = NOT_WAITING / MANUAL_DECISION_REQUIRED).
Gönderi bu birime açık bir kurye iadesinde (COURIER_RETURN) ya da bu birimin kuryesinin zimmetinde olmalı.
scanType: AUTO (varsayılan; tanınmayan değer de AUTO) | CARGO_CODE |
PARCEL_BARCODE | ITEM_BARCODE (son ikisi aynı barkod çözümleyicisi). scanCode 191,
clientEventId 100 karakterde kesilir; clientEventId yalnız audit içindir.
Hata durumunda
400 RETURN_SCAN_REQUIRED: okutma boş → tekrar okutun.
404 RETURN_SCAN_NOT_FOUND / SHIPMENT_NOT_FOUND: barkod tanınmadı ya da gönderi bu birimin kuryesinde değil.
409 RETURN_RESULT_REQUIRED: kurye önce teslim sonucunu girmeli. RETURN_NOT_WITH_COURIER,
RETURN_UNIT_REQUIRED, CUSTODY_*: error.message'ı gösterin ("<gönderiNo>: <metin>"
biçiminde olabilir; gönderi no ayrıca error.shipmentNumber).
B02/B17Transfer kabul
Amaç
Şubeye gelen transferleri okutup içeri almak ve transferi onaylayarak kapatmak.
Liste: depo → birim ve birim → birim transferleri; açık (DISPATCHED, ACCEPTANCE_PENDING) + son 7 günde kapanan (ACCEPTED,
PARTIALLY_ACCEPTED, REJECTED); en fazla 100. Kurye devir / dönüşleri burada yoktur; summary yalnız açıkları sayar.
Detay satır state: IN, SCANNED, PENDING, MISSING, EXCEPTION.
Okutma zorunludur; okutulmayan kalem içeri alınmaz. Okutma sonuçları ve merkez kaynaklı otomatik kabul
Transfer okutma bölümünde.
Onay, okutulanları içeri alır ve kalanları MISSING (NOT_SCANNED_AT_BRANCH) kapatır.
Hata durumunda
404 SCAN_NOT_IN_INCOMING_TRANSFER: kod gelen transferlerde yok → uyarı gösterin, okutmaya devam edin.
422 SCAN_VALUE_REQUIRED / VALIDATION_FAILED: okutma boş ya da alan hatalı.
Gönderimde gönderi başına bir satır; expectedQuantity = barkod sayısı (en az 1). Tüm satırlar bu birimin
zimmetinde (kuryede değil) ve aynı zimmet kaynağında olmalı.
Taslağı ve anahtarı cihazda saklayın; ağ kesintisinde aynı anahtarla tekrar gönderin.
Hata durumunda
409 TRANSFER_DISPATCH_FAILED: taslak oluştu ama sevk edilemedi → error.transferNumber'ı gösterin.
Gönderi alıcılarına ya da kuryelere şablonlu SMS göndermek ve gönderim geçmişini izlemek.
Çağrı sırası
GETbranch/sms/templates + GETbranch/sms/history
Alıcı: GETbranch/sms/targets?type=SHIPMENTS&q= ya da type=COURIERS
POSTbranch/sms/preview
POSTbranch/sms/send (aynı gövde)
GETbranch/sms/history
İş kuralları
Şablonlar: aktif, müşteri / ürün kapsamsız NOTIFICATION / SHIPMENT_WORKFLOW; kod başına kullanıcı diline en uygun ve en yüksek sürüm.
Kanal yalnız SMS. Hedef türleri: SHIPMENTS (gönderi id), COURIERS (kurye id),
MANUAL (05XXXXXXXXX / +905XXXXXXXXX). En fazla 500 alıcı.
SHIPMENTS araması: bu birimin teslim edilmemiş gönderileri, en fazla 100; q gönderi no / takip no / alıcı
adında (80 karakter). Telefonlar maskeli (+90 5** *** 12 34).
variables: en fazla 20 anahtar (^[A-Za-z_][A-Za-z0-9_]{0,59}$), değer metin / sayı (300 karakterde
kesilir); branchName ve recipientName otomatik dolar.
Önizleme ilk ulaşılabilir alıcı için metni ve segment sayısını döner; eksik değişkenler missingVariables içinde
(rendered: null).
Gönderim kuyruğa alınır (202); sağlayıcıya doğrudan istek atılmaz. Ağ geçidi yoksa kayıtlar SKIPPED
(SMS_GATEWAY_NOT_CONFIGURED); telefonu olmayan alıcı SKIPPED (RECIPIENT_PHONE_MISSING).
Parti kimliği BRANCH_MSG:<providerId>:<anahtar>; tekrar istekte partinin güncel özeti döner
(gatewayConfigured: null).
Geçmiş: son 400 kayıt; en fazla 30 parti, parti başına 50 alıcı; telefonlar maskeli.
Yalnız bu birimin tamamlanmış teslim denemeleri (en fazla 20.000); Türkiye günü (UTC+3). truncated: true ise limit aşıldı.
Teslim oranı = denenen tekil gönderilerden teslim edilenler; ilk denemede teslim; ortalama süre startedAt → attemptedAt
(>24 saat hariç); SLA = planlı teslimi olanlarda deliveredAt ≤ plannedDeliveryAt.
Yüzdeler 1 ondalık, payda 0 ise null (grafikte "—" gösterin). daily en az 7 gün.
Hata durumunda
400 RANGE_INVALID: geçerli aralığa dönün. 500 INTERNAL_ERROR: yenile düğmesi sunun.
B06Fatura mutabakatı
Amaç
Dönem faturalarını göstermek ve fatura için itiraz / talep / geri arama / canlı destek kaydı açmak.
Çağrı sırası
GETbranch/invoices?period=YYYY-MM
POSTbranch/invoices/support
GETbranch/invoices ile yenileyin
İş kuralları
schemaReady: false: invoices her zaman boş. Gerçek veri supportCases (son 30;
period filtresi uygulanmaz). period boşsa içinde bulunulan ay (UTC+3).
Talep manage yetkisi ister; INTERNAL destek kaydı açar (SupportTicket, requesterTypeCode=AGENCY).
category: DISPUTE, REQUEST, CALL_REQUEST, LIVE_CHAT.
DISPUTE için reasonKey zorunlu (büyük harfe çevrilir); DISPUTE ve REQUEST için
note en az 5 karakter (en fazla 1000). invoiceId serbest referanstır (100 karakterde kesilir).
Fatura onay (approve) ucu yoktur.
Hata durumunda
400 DISPUTE_REASON_REQUIRED / NOTE_REQUIRED / SUPPORT_CATEGORY_INVALID / PERIOD_INVALID: formu düzeltin.
403 BRANCH_MANAGE_REQUIRED: talep düğmesini operatöre pasif gösterin.
B07Sözleşme / evrak / kart
Amaç
Şube sözleşme ve evrak durumunu, kuryelerin belge özetini göstermek; şube / kurye kartı (QR) üretmek ve doğrulamak.
Çağrı sırası
GETbranch/compliance
Kart: POSTbranch/compliance/cards
QR doğrula: POSTbranch/compliance/cards/verify
İş kuralları
schemaReady: false: contracts[] (PARTNERSHIP, KVKK, SLA) ve documents[] (IDENTITY, TAX_PLATE,
AUTHORIZATION, SIGNATURE_CIRCULAR, BRANCH_PHOTO) her kalemde NOT_AVAILABLE. Gerçek veri: şubeye aktif bağlı kuryelerin
belge ve onay özeti (operationReady).
Kart: HMAC imzalı belirteç JDC1.<payload>.<imza> + QR (card.qrSvg, satır içi SVG); 365 gün
geçerli; aynı gün aynı sahip için aynı belirteç. Kalıcı kart / iptal / yenileme kaydı yoktur.
Doğrulama: imza, süre ve sahibin canlı durumu (şube ACTIVE; kurye şubeye aktif bağlı ve uygun durumda). Yalnız kendi şubesinin
kartı. token 2000 karakterde kesilir. Audit yazar, durum değiştirmez; anahtar istemez.
Hata durumunda
Doğrulamada imza geçersizse hata değil: 200 + valid: false, reason: SIGNATURE_INVALID → "geçersiz kart" gösterin.
404 CARD_NOT_FOUND: başka şube / tenant kartı. 404 CARD_OWNER_NOT_FOUND, 409 CARD_OWNER_INACTIVE: sahibi kontrol edin.
503 CARD_SIGNING_NOT_CONFIGURED: sunucuda imza anahtarı yok → JetDiji ekibine bildirin.
KuryelerŞube kuryeleri
Amaç
Şubeye bağlı kuryeleri listelemek.
Çağrı sırası
GETagency/couriers
İş kuralları
Şubeye ACTIVE ve geçerlilik aralığında bağlı kurye atamaları; birincil önce, sonra ada göre.
İptal nedeni kataloğu (courier-jobs.cancelReasons) bu durumun nedenleridir
7010 / 7030
İade bekliyor / İade edilecek
B11 returnToCenter
8010 / 8030
İptal / Operasyon kaynaklı iptal
B11 cancelledToday
Aşama (stage)
INCOMING: merkezde hazırlanıyor, bu şubeye gelecek.
AWAITING_COURIER: 4010, kurye yok.
IN_QUEUE: 4010, kuryeye zimmetlendi, kurye henüz okutmadı.
IN_DISTRIBUTION: 4020, dağıtımda.
Neden kodları
9117 Normal ilk çıkış.
9116 Devir: alıcıya ulaşılamayınca tekrar çıkış. Öncelik HIGH.
Teslim edilemedi (5110) nedenleri ayrı bir uçta değil, GET branch/courier-jobs yanıtındaki cancelReasons[] içinde gelir.
Zimmet kuralları
Okutarak kabul: kurye ataması (dispatch/handover) gönderiyi 4010'da bırakır (stage=IN_QUEUE).
Zimmet ve 4020'ye geçiş yalnız kurye kendi uygulamasında okutarak kabul ettiğinde olur.
Kurye değişimi: dağıtımdaki gönderide reassign REASSIGN devri açar; yeni kurye okutana kadar zimmet
eski kuryededir.
Gün sonu: kurye gönderiyi elinde tutabilir; gün sonu iadesi şubede okutularak alınır
(pending/courier-return-scan). Kabulde otomatik yeniden dağıtım denenir (redelivery).
Kuryede bekleme alarmı: varsayılan 24 saat; şube bazında 1–336 saat arası ayarlanabilir
(Provider.configuration.courierHoldingAlertHours). Yanıtlarda alertHours / holdingAlertHours
olarak gelir; overdue bayrakları bu eşiğe göredir.
8. Roller (operate / manage)
Şube tek bir yetki modeli kullanır (src/modules/agency-portal/branch-permissions.ts). Roller iki yeteneğe çevrilir:
Yetenek
Anlamı
Sahip olanlar
operate
Günlük operasyon: dağıtım, devir, transfer kabul, etiket, sayım okutma, SMS gönderimi…
AGENCY_ADMIN, AGENCY_OPERATOR ve sistem sahibi
manage
Yönetim / onay / mali: sayım manuel giriş, okutma iptali, onay, iptal; fatura destek; şube kartı
AGENCY_ADMIN ve sistem sahibi
okuma
GET'ler ve yan etkisiz POST'lar
Oturumlu her şube kullanıcısı (diğer roller yalnız okur)
Sistem sahibi = oturumda isSystemOwner: true ya da rol kodu SYSTEM_OWNER. Şube rolü olmadan
girişte şube seçerek bağlanabilir.
Düğmeler:GET agency-auth/session → user.capabilities: { operate, manage }. Aynı nesne
preparation, dispatch, courier-jobs, counts, counts/{id} yanıtlarında
capabilities olarak da gelir.
Eski canManage alanı korunur: preparation / dispatch / courier-jobs →
capabilities.operate; counts / counts/{id} → capabilities.manage. Mobilde
capabilities kullanın.
Yetkisiz kullanıcıya yazma düğmelerini pasif ve ipuçlu gösterin; yine de her yazma ucunda 403'ü ele alın.
Yetki hatası her uçta tektir: 403 FORBIDDEN, error.reason = BRANCH_OPERATE_REQUIRED
("Bu işlem şube operasyon yetkisi gerektirir.") ya da BRANCH_MANAGE_REQUIRED ("Bu işlem şube yöneticisi yetkisi
gerektirir."). Eski BRANCH_FORBIDDEN kodu ve eski reason değerleri (BRANCH_DISPATCH_ROLE_REQUIRED,
COUNT_PERMISSION_REQUIRED) artık dönmez.
ZPL'i Zebra yazıcıya gönderin: Bluetooth (Zebra Link-OS SDK / BLE SPP) ya da ağ üzerinden TCP 9100 portuna ham ZPL.
Birden çok etiketi \n ile birleştirip tek seferde yollayabilirsiniz (web de böyle yapar).
Baskı başarılı olunca POSTbranch/labels{ action: "printed", labelIds, printer: "<cihaz adı>" } (sayaç + audit). Web, Zebra yoksa printer: "BROWSER" gönderir.
Zebra yoksa web etiketi istemcide HTML olarak çizip tarayıcıdan yazdırır (label-html); HTML üreten bir API ucu
yoktur. Mobilde ZPL kullanamıyorsanız aynı alanlardan (barkod, tür, paket i/n, gönderi no, depo, tarih) yerel bir PDF /
görsel üretin.
B01 "Etiket yazdır" (preparation/print-rows) ZPL döndürmez; gönderi satırı verir, etiket istemcide çizilir (alıcı
telefonu bu sorguda da yoktur).
10. Sayım
Tüm işlemler POSTbranch/counts/{countId} üzerinden, gövdedeki action ile yapılır.
action
Yetki
Ne yapar
Yanıt data
scan
operate
Barkod okut (ana yöntem, adet 1). Alanlar: clientScanId, barcode, isteğe bağlı deviceTypeCode, isDamaged, containerId, sealIntact.
ScanResult
manual
manage
Manuel adet; quantity + reasonNote (3–500) zorunlu; aynı işlemde audit yazılır.
ScanResult
void-scan
manage
Okutmayı iptal (scanId, reason).
{ result: null, replayed }
line-reason
operate
Fark nedeni (yalnız kapatılmış satır): MISCOUNT, DAMAGE, LOSS, RECORD_ERROR, FOUND, RETURN_PENDING, OTHER.
{ result: null, replayed }
close
operate
"Sayımı Tamamla" (REVIEW). uncountedAsZero: false iken sayılmamış ürün varsa 409.
{ result: null, replayed }
post
manage
Onay: POSTED, stok hareketleri oluşur.
{ movementCount, replayed }
cancel
manage
Sayımı iptal (reason zorunlu).
{ result: null, replayed }
clientScanId (1–60, [A-Za-z0-9_-]) sayım servisinde ayrı bir tekrar korumasıdır: aynı id adedi
ikinci kez eklemez. Web bunu çevrimdışı kuyrukla, Idempotency-Key = clientScanId olacak şekilde gönderir;
UUID her iki kurala da uyar.
data.replayed yalnız Idempotency-Key tekrarını gösterir. clientScanId tekrarında (yeni anahtarla)
adet eklenmez ama data.replayed: false döner.
Yetki kontrolü gövde doğrulandıktan ve sayım bulunduktan sonra yapılır.
Detay (GET branch/counts/{countId}): başlık, özet, satırlar (sistem stoğu / sayılan / fark), koli durumları, seri farkları,
son okutmalar, kullanıcı adları. Alt nesneler admin sayım modülüyle aynı çıktıdır (getStockCountDetail).
11. Transfer okutma
Gelen transfer (B02/B17)
Durum
action
eventCode
Sonraki adım
Merkez kaynaklı transfer (centerSource: true: tenant zimmeti ya da işleticisi olmayan depo)
AUTO_INTAKE
intake.auto
Kalem doğrudan kabul edildi.
Diğer kaynaklar
SCANNED
transfer.scan.accepted
"İçeri Al" (accept) gerekir.
Kalem zaten içeri alınmış
ALREADY_INTAKEN
transfer.scan.duplicate
Yok (200 döner).
scanType (CARGO_CODE | PARCEL_BARCODE | ITEM_BARCODE) yalnız önceliktir: önce kalemin okutma kodu (ITEM_BARCODE'da seri no da)
aranır, sonra gönderi no / takip no / etiket / koli barkodu tüm yollarla çözülür.
transferId verilirse arama o transferle sınırlanır. clientEventId (1–80) zorunlu alandır ama yalnız audit
içindir; deviceId isteğe bağlıdır.
accept (eventCode: "transfer.accept"): okutulmuş ve bekleyen kalemleri kabul eder; kalem hataları
failed[] içinde (200). Yeni anahtarla tekrar çağrı kabul edilmiş kalemleri atlar (accepted: 0).
confirm (eventCode: "transfer.accepted"): okutulanları içeri alır, kalanları MISSING
(NOT_SCANNED_AT_BRANCH) kapatır; transfer ACCEPTED / PARTIALLY_ACCEPTED olur. İsteğe bağlı note (500).
Merkeze transfer (B03)
resolve: gönderiye bağlı olmayan, şube deposundaki koli / paket etiketi → kind: PACKAGE (transferin ambalaj
barkodu, gövdede packageBarcodes). Aksi halde gönderi çözümlenir → kind: SHIPMENT (bu birimin zimmetinde,
terminal değil, açık devirde değil).
scanType=CARGO_CODE kargo koduyla, diğerleri AUTO çözümleyiciyle aranır.
Gönderim: transferType (RETURN, EQUIPMENT, PHYSICAL_DOCUMENT, CARD_RETURN, BRANCH_TRANSFER, OTHER),
destinationWarehouseId (centers[].id), lines (1–500; her satır shipmentId +
en fazla 200 barcodes), packageBarcodes (en fazla 200), note (300).
Gönderiye bağlı olmayan ekipman / evrak satırı eklenemez (her satır bir shipmentId ister).
12. Dosya, konum ve harita
Dosya
Şube uçlarında multipart yükleme ve dosya indirme ucu yoktur. Kart QR'ı yanıtta satır içi SVG (card.qrSvg),
etiketler ZPL metni olarak gelir.
Konum ve harita
Şube uygulaması konum göndermez. Kurye konumu kurye uygulamasının görev konum ucundan gelir.
courier-map / dashboard son 24 saatteki son konumu döner. Canlı durum son konum yaşından türetilir:
ACTIVE ≤10 dk, BREAK 10–60 dk, OFFLINE >60 dk ya da konum yok (eşikler thresholds).
Harita çizimi, kümeleme ve mesafe gösterimi istemcide yapılır.
Kurye önerilerindeki etaMinutes sunucuda kuş uçuşu mesafe / 20 km/sa + 5 dk ile hesaplanır; konum 180 dakikadan eskiyse
null.
13. Boş dönen modüller
Bu modüllerin şeması henüz yok. Uçlar schemaReady: false döner ve sahte veri üretmez; uygulamada boş durum ekranı gösterin.
SMS: kanal yalnız SMS (PUSH, BOTH → 422 CHANNEL_NOT_AVAILABLE); hedef
CUSTOMER_GROUP → 422 TARGET_TYPE_NOT_SUPPORTED. Ağ geçidi yoksa kayıtlar SKIPPED
(SMS_GATEWAY_NOT_CONFIGURED).
Fatura onayı (approve) yok.
Şube kartı iptal / yenileme kaydı yok (kart imzalı belirteçtir, 365 gün geçerli).
Merkeze transferde gönderiye bağlı olmayan ekipman / evrak satırı eklenemez.
Duyuru okundu / onay ve eğitim ilerleme uçları yok.