JetDiji
Kurye Mobil API · Geliştirici Rehberi Kurye uygulamasını geliştiren mobil ekip için

Kurye Mobil API Rehberi

JetDiji kurye uygulamasının sunucuyla nasıl konuştuğunu ekran ekran anlatır. Uç ayrıntıları (alanlar, şemalar, yanıt örnekleri) API Referansı'nda; bu sayfa sıra, kural ve hata davranışını anlatır.

1. Hızlı başlangıç

Beş dakikada ilk isteğinizi atın. Örnekler preprod ortamını kullanır; şifre yerine kendi test şifrenizi yazın.

  1. Giriş yapın ve token alın. X-Client-Type: mobile başlığı olmadan token dönmez.
    curl -s -X POST https://api-mobile.preprod.jetdiji.com/api/public/v1/courier-auth/login \
      -H "Content-Type: application/json" \
      -H "X-Client-Type: mobile" \
      -d '{"identifier":"kurye@example.com","password":"***"}'
    Yanıttaki data.accessToken değerini saklayın:
    BASE=https://api-mobile.preprod.jetdiji.com
    TOKEN=<data.accessToken>
  2. Bir okuma isteği atın. Görev listesi; bir görevin id değerini not edin.
    curl -s "$BASE/api/public/v1/courier-tasks?page=1&pageSize=5" \
      -H "Authorization: Bearer $TOKEN"
  3. Bir yazma isteği atın. Göreve not kanıtı ekleyin. Yazma isteklerinde Idempotency-Key gönderin.
    SHIPMENT_ID=<tasks[0].id>
    curl -s -X POST "$BASE/api/public/v1/courier-tasks/$SHIPMENT_ID/evidence" \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: 7d0f4c4e-1b2a-4f7e-9c3d-5a6b7c8d9e0f" \
      -d '{"evidenceType":"NOTE","textValue":"Paket kapıcıya bırakıldı.","category":"DELIVERY"}'
    İlk çağrı 201 döner. Aynı komutu tekrar çalıştırın: aynı kayıt 200 ile döner, ikinci kayıt açılmaz.

2. Ortamlar ve hesaplar

OrtamTaban adresNe zaman
Preprod (test)https://api-mobile.preprod.jetdiji.comGeliştirme ve test
Canlıhttps://api-mobile.jetdiji.comYayındaki uygulama
  • Token'ı hangi ortamdan aldıysanız o ortamda kullanın.
  • API Referansı'ndaki "Aynı origin" (/) seçeneği, dokümanın sunulduğu sunucuya istek atar. "Try it out" yalnız test ortamlarında açıktır.
  • Test hesabı: preprod kurye hesabını JetDiji ekibinden isteyin.

Temel biçimler

  • Tüm yollar /api/public/v1/ ile başlar. Bu rehberde kısalık için önek yazılmaz (ör. courier-tasks).
  • Tarih/saat alanları ISO 8601, UTC (Z) döner.
  • Ondalık koordinat ve ağırlık alanları JSON'da string gelir (ör. "41.012345").
  • Başarılı yanıt: { "success": true, "data": {…} }. Bazı uçlarda ek message, başvuru uçlarında ek meta gelir.
  • Web karşılığı /kurye-paneli uygulamasıdır; ekran kartlarında web yolu da verilmiştir.

3. Kimlik doğrulama

  1. Açılışta saklı token varsa GET courier-auth/session çağırın. 200 → K01; 401 → giriş ekranı.
  2. Girişte POST courier-auth/login; gövde { "identifier": "<e-posta veya telefon>", "password": "…" }, başlık X-Client-Type: mobile.
  3. Yanıttan data.accessToken, data.tokenType: "Bearer", data.expiresAt alın. Başlık yoksa bu alanlar dönmez, yalnız web çerezi yazılır.
  4. Sonraki her istekte Authorization: Bearer <accessToken> gönderin.
  5. Çıkışta POST courier-auth/logout çağırın; o token'ın oturumu kapanır. Sonra token'ı cihazdan silin.
KonuKural
Token süresi8 saat. Yenileme (refresh) ucu yoktur. Süre dolunca ya da oturum iptal edilince uçlar 401 UNAUTHENTICATED döner → giriş ekranına götürün.
Hatalı şifre5 başarısız denemede hesap 15 dakika kilitlenir (423 ACCOUNT_TEMPORARILY_LOCKED, error.lockedUntil). Her hatada error.remainingAttempts gelir (hesap yoksa gelmez).
Şifre değiştirmePOST courier-auth/change-password kuryenin tüm eski oturumlarını kapatır (kullanılan token dahil) ve yeni oturum açar. X-Client-Type: mobile varsa yanıtta yeni accessToken, tokenType, expiresAt döner; hemen güvenli depoya yazıp eskisinin yerine kullanın. Eski token artık 401 alır. Başlık yoksa (web) yeni oturum yalnız çereze yazılır.
Token saklamaiOS Keychain ya da Android Keystore (EncryptedSharedPreferences). Düz metin dosyaya, loga ya da analitik olayına yazmayın.
ÇerezWeb paneli aynı oturumu dijigoo_courier_session HttpOnly çereziyle taşır. Bearer başlığı varsa çerezden önce okunur. Mobil istemci çerez kullanmamalıdır.
Hesap aktivasyonuİlk şifre, e-postadaki bağlantının token değeriyle courier-auth/activate üzerinden belirlenir (bkz. Hesap oluştur).

4. Hata yönetimi

Tüm uçlar aynı hata zarfını döner (şema ApiError):

{ "success": false,
  "error": { "code": "OTP_INVALID", "message": "…", "remainingAttempts": 3 },
  "code": "OTP_INVALID", "message": "…" }
  • Yalnız error.code alanına bakın. Dallanmayı error.code + HTTP durumuyla yapın.
  • error.message insan okunur metindir (çoğunlukla Türkçe; bazı uçlarda locale ile İngilizce). Her hatada bulunmaz; kullanıcı metnini error.code'dan kendi çevirinizle üretin.
  • Uca özgü ek bilgiler error içindedir: remainingAttempts, lockedUntil, field, fieldErrors, fieldCode, minCount, missing, retryAfterSeconds, details[]. Hangi uçta hangisinin geldiği API Referansı'ndaki yanıt açıklamasında yazar.
  • Üst seviyedeki code, message, fieldErrors, field, remainingAttempts, lockedUntil, details, meta alanları eski web ekranları için bırakılmıştır; kullanmayın.
  • Bozuk, boş ya da nesne olmayan JSON gövdesi tüm JSON uçlarında 400 INVALID_JSON döner. İstisna: POST courier-tasks/{shipmentId}/otp boş gövdeyi {} sayar.
  • geography/* uçları aynı error nesnesini döner ama üst seviyede code yoktur (yalnız meta). error.code kuralı orada da geçerlidir.

İstemci ne yapmalı

HTTPAnlamıUygulama ne yapar
400İstek biçimi hatalıHatalı alanı göster; aynı istek tekrar denenmez (kalıcı hata).
401Oturum yok, süresi dolmuş ya da iptalToken'ı sil, giriş ekranına git. Aday portalında (ACCESS_TOKEN_INVALID) bağlantıyı kontrol etmesini söyle.
403Yetki ya da hesap durumuYetki/hesap mesajı göster (ör. hesap aktive edilmemiş, pasif).
404Kayıt yok ya da bu kuryede değilListeyi yenile; görev başka kuryeye geçmiş olabilir.
409Durum çakışmasıEkranı yeniden oku (detay/özet) ve güncel duruma göre devam et. CONCURRENT_UPDATE'te aynı anahtarla tekrar dene.
410Süresi dolmuş / iptalYeni kod ya da yeni bağlantı iste (OTP, aktivasyon, aday portalı).
413 / 415Dosya çok büyük / tip izinsizDosyayı küçült ya da izinli biçime çevir.
422İş kuralı ya da alan doğrulamasıAlan hatasını ya da eksik adımı göster (fieldCode, missing[], details[]).
423KilitlilockedUntil'e kadar bekleme mesajı göster.
429Hız sınırıRetry-After (saniye) dolmadan tekrar deneme; geri sayım göster.
5xxSunucu ya da dış servis hatasıBekleyip aynı Idempotency-Key ile tekrar dene.
Tüm hata kodları sözlüğü
KodHTTPAnlam
Genel
UNAUTHENTICATED401Oturum yok, süresi dolmuş ya da iptal; yeniden giriş.
INVALID_JSON400İstek gövdesi bozuk JSON, boş ya da nesne değil (tüm JSON gövdeli uçlar).
VALIDATION_ERROR400 / 422Alan doğrulaması: giriş/aktivasyonda error.field, şifre/profilde error.fieldErrors, başvuruda error.details[] (422).
INTERNAL_ERROR500Beklenmeyen hata (oturum, giriş, aktivasyon, şifre, profil, müsaitlik, sözleşmeler, belgeler, onay metinleri, bekleyen zimmet, neden kodları).
INTERNAL_SERVER_ERROR500Beklenmeyen hata (başvuru, telefon kontrolü, Başvurum, aday belge portalı, şehir/ilçe).
CONCURRENT_UPDATE409Eşzamanlı güncelleme; aynı anahtarla tekrar deneyin.
IDEMPOTENCY_KEY_REQUIRED400Idempotency-Key zorunlu.
IDEMPOTENCY_KEY_INVALID400Anahtar uzunluğu geçersiz.
IDEMPOTENCY_KEY_CONFLICT409Anahtar başka işlemde kullanılmış.
CAPTURED_AT_INVALID / CAPTURED_AT_IN_FUTURE400Çekim zamanı geçersiz / 1 dk'dan fazla ileri.
FIELD_TOO_LONG400Metin alanı sınırı aşıldı.
Giriş ve hesap
INVALID_CREDENTIALS401E-posta, telefon ya da şifre hatalı (error.remainingAttempts, error.lockedUntil).
ACCOUNT_TEMPORARILY_LOCKED423Çok sayıda hatalı giriş; error.lockedUntil.
ACCOUNT_NOT_ACTIVATED403Hesap aktive edilmemiş (e-posta bağlantısı).
ACCOUNT_NOT_ACTIVE403Hesap pasif ya da askıda.
PASSWORD_NOT_SET403 / 409Şifre belirlenmemiş (girişte 403, şifre değiştirmede 409).
TOKEN_REQUIRED400Aktivasyon token'ı yok.
ACTIVATION_NOT_FOUND404Aktivasyon bağlantısı geçersiz.
ACTIVATION_REVOKED / ACTIVATION_ALREADY_USED / ACTIVATION_EXPIRED410Bağlantı iptal / kullanılmış / süresi dolmuş.
ACCOUNT_ALREADY_ACTIVE409Hesap zaten aktif.
ACCOUNT_NOT_ACTIVATABLE403 (GET) / 409 (POST)Hesap aktivasyona uygun değil.
ACCOUNT_NOT_FOUND404Kurye hesabı yok.
CURRENT_PASSWORD_INVALID400Mevcut şifre yanlış.
PASSWORD_REUSE_NOT_ALLOWED400Yeni şifre eskisiyle aynı.
Görev, konum ve arama
COURIER_NOT_FOUND404Kurye kaydı ya da tenant bulunamadı.
COURIER_DASHBOARD_LOAD_FAILED500Ana sayfa yüklenemedi.
COURIER_TASKS_LOAD_FAILED500Görev listesi yüklenemedi.
COURIER_TASK_NOT_FOUND404Görev bu kuryede değil ya da shipmentId geçersiz (detay, accept, start, location, finalize).
CURRENT_ASSIGNMENT_NOT_FOUND409Kuryenin güncel ataması yok.
COURIER_TASK_DETAIL_LOAD_FAILED500Görev detayı yüklenemedi.
COURIER_TASK_ACCEPT_FAILED / COURIER_TASK_START_FAILED / COURIER_LOCATION_SAVE_FAILED / COURIER_TASK_FINALIZE_FAILED500Beklenmeyen hata.
LOCATION_INVALID400 / 409 / 422Koordinat aralık dışı ya da sayı değil.
LOCATION_PAIR_REQUIRED400 / 422Enlem ve boylam birlikte gönderilmeli.
LOCATION_TIMESTAMP_INVALID400 / 409capturedAt geçersiz.
LOCATION_NOT_FRESH409Konum 5 dk'dan eski ya da 1 dk'dan fazla ileri tarihli.
LOCATION_PURPOSE_INVALID400purposeCode ACTIVE_TASK ya da ARRIVAL değil.
RUNNING_SHIPMENT_WORKFLOW_NOT_FOUND409Gönderinin çalışan iş akışı yok.
TASK_NOT_READY_FOR_DELIVERY409Görev dağıtıma hazır durumda değil.
TASK_NOT_STARTED409Görev başlatılmamış.
TASK_NOT_OUT_FOR_DELIVERY409Görev dağıtımda değil.
SHIPMENT_NOT_FOUND404Gönderi bulunamadı ya da bu kuryede değil.
RECIPIENT_PHONE_MISSING422Alıcı telefonu yok ya da 10 haneden kısa: OTP gönderilemez (istemci OTP adımını atlar) ve "Müşteriyi Ara" yapılamaz.
TASK_ALREADY_FINALIZED409Görev teslim edilmiş ya da sonuçlanmış; alıcı aranamaz.
RECIPIENT_CALL_FAILED500Arama kaydı yazılamadı; numara dönmez.
OTP
RECEIVER_TYPE_INVALID400Teslim alan tipi geçersiz.
OTP_RATE_LIMITED429reason: RESEND_TOO_SOON (60 sn) ya da HOURLY_LIMIT (saatte 5); Retry-After başlığı.
SMS_SEND_FAILED503SMS gönderilemedi.
OTP_NOT_FOUND404Doğrulama kaydı yok.
OTP_INVALID422Kod yanlış ya da 6 hane değil (remainingAttempts; biçim hatasında alan yok).
OTP_TOO_MANY_ATTEMPTS4295 hatalı deneme; yeni kod isteyin.
OTP_EXPIRED410Kod süresi (120 sn) doldu ya da yeni kod istendi.
OTP_REQUEST_FAILED / OTP_VERIFY_FAILED500Beklenmeyen hata.
Kanıt
CATEGORY_INVALID400Kanıt kategorisi geçersiz.
EVIDENCE_TYPE_INVALID400Kanıt tipi geçersiz.
TEXT_REQUIRED / TEXT_TOO_LONG400Not metni boş / 4000 karakteri aşıyor.
NOTE_TOO_LONG400Not 2000 (kanıt) / 4000 (tutanak) karakteri aşıyor.
CONTENT_TYPE_INVALID415multipart/form-data ya da application/json değil.
FILE_REQUIRED / FILE_EMPTY400Dosya yok / boş (kanıt ve aday belge yükleme).
FILE_TOO_LARGE413Kanıtta 10 MB üstü (error.maxBytes); aday belgede tanımdaki maxFileSizeMb üstü.
FILE_TYPE_NOT_ALLOWED415İzinli tip değil.
PAGE_COUNT_INVALID400Sayfa sayısı 1–500 tam sayı değil.
REQUIREMENT_CODE_INVALID400 / 422400: PHOTO dışı tipte ya da 80 karakter üstü; 422: bu gönderide tanımlı değil.
REQUIREMENT_CATEGORY_MISMATCH422Kategori gereksinimin kategorisiyle uyuşmuyor.
EVIDENCE_NOT_FOUND404 / 422Kanıt yok (finalize'da 422).
EVIDENCE_ALREADY_LINKED422Kanıt başka teslim denemesine bağlı.
EVIDENCE_IDS_INVALID400evidenceIds UUID dizisi değil ya da 50'den fazla.
EVIDENCE_NOT_DELETABLE409Bu tip kanıt silinemez.
EVIDENCE_NOT_OWNED403Kanıt bu kuryeye ait değil.
EVIDENCE_LOCKED409Tamamlanmış teslim denemesine bağlı kanıt silinemez.
EVIDENCE_FILE_NOT_FOUND404Dosya yok ya da kanıt VOID.
EVIDENCE_FILE_PATH_INVALID400Depolama yolu geçersiz.
EVIDENCE_STORAGE_NOT_SUPPORTED501Depolama sağlayıcısı desteklenmiyor.
EVIDENCE_LIST_FAILED / EVIDENCE_UPLOAD_FAILED / EVIDENCE_DELETE_FAILED / EVIDENCE_FILE_READ_FAILED500Beklenmeyen hata.
Tutanak
REPORT_TYPE_INVALID / REPORT_STATUS_INVALID400Tutanak tipi ya da durumu geçersiz.
SIGNATURE_INVALID400İmza data:image/png;base64,... değil.
SIGNATURE_TOO_LARGE413İmza PNG'si 2 MB üstü.
SIGNATURE_REQUIRED422SUBMITTED tutanakta iki imza da zorunlu.
SIGNER_NAME_REQUIRED / SIGNER_NAME_INVALID / SIGNER_ROLE_INVALID400İmzacı adı ya da rolü.
ATTACHMENTS_INVALID400 / 422Ek kanıt kimlikleri geçersiz / bu gönderiye ait değil ya da VOID.
REPORT_LIST_FAILED / REPORT_CREATE_FAILED500Beklenmeyen hata.
Anket
FORM_VERSION_MISMATCH409Anket sürümü değişti (formVersionId güncel değer; geçersiz UUID'de alan yok).
FORM_STATUS_INVALID / FORM_VALUES_INVALID400Anket durumu ya da değerler nesnesi geçersiz.
FORM_NOT_REQUIRED_FOR_SHIPMENT409Bu gönderide anket yok.
FORM_FIELD_INVALID422Alan kodu bilinmiyor ya da değer tipi/sınırı hatalı (fieldCode).
FORM_FIELD_REQUIRED422Zorunlu alan boş (fieldCode).
FORM_EVIDENCE_REQUIRED422Alan için fotoğraf eksik (fieldCode, minCount, actual).
FORM_ALREADY_SUBMITTED409Anket farklı değerlerle zaten tamamlanmış.
FORM_SAVE_FAILED500Beklenmeyen hata.
Teslim sonucu (finalize)
DELIVERY_REQUIREMENTS_LOAD_FAILED500Gereksinimler çözülemedi.
DELIVERY_REQUIREMENTS_MISSING422Teslim gereksinimleri eksik (missing[]).
FINALIZE_BODY_INVALID / FINALIZE_RESULT_INVALID / FINALIZE_RESULT_CONFLICT / FINALIZE_RESULT_REQUIRED400Sonuç alanları.
DELIVERY_REASON_REQUIRED422Teslim edilemedi için neden kodu zorunlu.
DELIVERED_REASON_NOT_ALLOWED422Teslim edildi'de reasonCode gönderilmez (yakınlık için receivedRelationCode).
DELIVERY_REASON_INVALID422Neden kodu tanımsız ya da pasif.
FINAL_V3_REASON_NOT_ALLOWED_FOR_TARGET_STATUS422Neden bu durum için izinli değil.
FINAL_V3_REASON_PATH_NOT_CONFIGURED422İş akışı yapılandırma hatası.
RECEIVED_RELATION_INVALID422Teslim alan yakınlık kodu 5010 için izinli değil.
OTP_NOT_VERIFIED422otpEvidenceId doğrulanmış OTP değil.
DELIVERY_ATTEMPT_NOT_FOUND_FOR_FINALIZE409Açık teslim denemesi yok.
DELIVERY_ATTEMPT_NOT_COMPLETABLE:<durum>409Deneme tamamlanabilir durumda değil.
FINALIZE_TRANSITION_NOT_AVAILABLE409İş akışında geçiş yok.
FINALIZE_IDEMPOTENCY_CONFLICT409Görev farklı sonuçla zaten kapatılmış.
FINAL_V3_TARGET_STATUS_NOT_FOUND409Hedef durum tanımı yok.
Zimmet
HANDOVER_SCAN_REQUIRED409Barkod boş.
HANDOVER_SCAN_NOT_FOUND409Bu gönderi size zimmetlenmemiş.
HANDOVER_ALREADY_ACCEPTED409Zaten kabul edildi (anahtarlı tekrarda 200 + replayed).
HANDOVER_CONTEXT_INVALID409Zimmet kaydı eksik.
HANDOVER_ALREADY_PENDING / CUSTODY_TRANSFER_SUBJECT_LOCKED409Gönderi başka bir kabul bekliyor.
CUSTODY_TRANSFER_*kayda göreZimmet kaydı hataları; HTTP kayıttaki duruma göre değişebilir, error.message içerir.
COURIER_RETURN_PENDING409Birime iade başlatılmış; tekrar çıkılamaz.
COURIER_REDISPATCH_MANUAL_REASON409Neden operasyon kararı gerektiriyor; birime iade edin.
COURIER_REDISPATCH_NOT_ALLOWED409Tekrar çıkış hakkı yok; birime iade edin.
MAX_REDELIVERY_COUNT_REACHED409Dağıtıma çıkış hakkı doldu.
DISPATCH_TRANSITION_FAILED / DISPATCH_COURIER_UNAVAILABLE / REASSIGN_*409Dağıtıma çıkarma başarısız.
RETURN_SCAN_REQUIRED400İade için gönderi seçilmedi.
RETURN_SCAN_NOT_FOUND404Barkodla gönderi bulunamadı (error.shipmentNumber = okutulan değer).
RETURN_UNIT_NOT_FOUND404Hedef birim bulunamadı.
RETURN_TOO_MANY400Tek seferde en fazla 200 gönderi.
RETURN_NOT_WITH_COURIER409Açık iade başka kuryeye ait.
RETURN_RESULT_REQUIRED409Gönderi hâlâ dağıtımda; önce teslim sonucu girilmeli.
RETURN_UNIT_REQUIRED409Gönderinin teslimat birimi yok.
COURIER_HANDOVER_FAILED500Zimmet işleminde beklenmeyen hata.
COURIER_CUSTODY_OVERVIEW_FAILED / COURIER_CUSTODY_HISTORY_FAILED500Beklenmeyen hata.
Hesabım ve profil
COURIER_PROFILE_SUMMARY_LOAD_FAILED500Profil özeti yüklenemedi.
BANK_ACCOUNT_ALREADY_EXISTS409IBAN zaten kayıtlı.
INVALID_CHANGE_TYPE400ADDRESS, VEHICLE ya da WORK değil.
NO_CHANGE400Talep mevcut bilgilerle aynı.
REQUEST_NOT_FOUND404Profil değişiklik talebi yok.
REQUEST_NOT_CANCELLABLE409Yalnız PENDING talep iptal edilir.
SUPPORT_CATEGORY_INVALID400Destek kategorisi geçersiz.
TICKET_SUBJECT_REQUIRED / TICKET_DESCRIPTION_REQUIRED400Destek konusu ya da açıklaması.
COURIER_SUPPORT_LOAD_FAILED / COURIER_SUPPORT_CREATE_FAILED500Beklenmeyen hata.
APPLICATION_NOT_FOUND404Kuryeye bağlı kaynak başvuru yok.
Müsaitlik
INVALID_DAYS / INVALID_DAY_COUNT / INVALID_DAY_INDEX / DUPLICATE_DAY / INVALID_RANGES / TOO_MANY_RANGES / INVALID_TIME_FORMAT / INVALID_TIME_RANGE / OVERLAPPING_TIME_RANGES / RANGE_REQUIRED422Haftalık plan doğrulaması (error.details.field).
INVALID_EXCEPTIONS / TOO_MANY_EXCEPTIONS / INVALID_EXCEPTION_DATE / DUPLICATE_EXCEPTION_DATE / INVALID_EXCEPTION_TYPE / INVALID_EXCEPTION_TIME / INVALID_EXCEPTION_TIME_RANGE422Tarih istisnası doğrulaması.
Kurye ol başvurusu
APPLICATION_ALREADY_EXISTS409Bu telefonla daha önce başvuru yapılmış (error.details[0].field = "phone"); mevcut başvuru bilgisi dönmez.
RATE_LIMITED429Çok fazla istek (telefon kontrolü, başvuru); Retry-After (saniye).
GEOGRAPHY_MISMATCH422İlçe şehre bağlı değil (error.details[0].field = "districtId").
INVALID_PHONE422Telefon geçersiz (error.details[0].field = "phone").
PHONE_REQUIRED400Telefon parametresi yok.
INVALID_CONSENT_VERSION / CONSENT_VERSION_MISMATCH / REQUIRED_CONSENT_MISSING / CONSENT_NOT_VIEWED_TO_END / REQUIRED_CONSENT_NOT_ACCEPTED422Onay metni doğrulaması.
DRAFT_LEGAL_TEXTS_NOT_ALLOWED503Canlıda taslak hukuki metin aktif (error.details[], ör. code: DRAFT_LEGAL_TEXT_COUNT).
INVALID_CITY_ID / CITY_NOT_FOUND400 / 404Şehir kimliği.
Aday belge portalı
ACCESS_LINK_INVALID400publicId ya da token eksik.
ACCESS_TOKEN_INVALID401Token hatalı (hatalı deneme sayılır).
ACCESS_NOT_FOUND404Bağlantı bulunamadı.
ACCESS_REVOKED410Bağlantı iptal edildi (yeni bağlantı gönderildi ya da aday kuryeye dönüştürüldü).
ACCESS_EXPIRED410Bağlantının süresi doldu (expiresAt). Yeni bağlantılar varsayılan 14 gün geçerlidir; revizyon e-postası yeni bağlantı üretir.
ACCESS_LOCKED423Hatalı token deneme sınırı aşıldı; bağlantı kilitli.
DOCUMENT_PACKAGE_NOT_FOUND404Açık belge paketi yok.
DOCUMENT_REQUEST_NOT_FOUND404Belge talebi bu pakette yok.
DOCUMENT_NOT_UPLOADABLE409Belge onaylı, reddedilmiş, iptal ya da süresi dolmuş; yükleme yapılamaz.
INVALID_FORM_DATA400Multipart gövde okunamadı.
INVALID_DOCUMENT_SIDE400side belge tipine uygun değil.
INVALID_EXPIRY_DATE / EXPIRY_DATE_REQUIRED400Belge son kullanma tarihi geçersiz / zorunlu.
UNSUPPORTED_FILE_TYPE415Dosya tipi belge tanımında izinli değil.
DOCUMENTS_ALREADY_SUBMITTED409Paket zaten onaya gönderilmiş.
REJECTED_DOCUMENT_PRESENT409Reddedilmiş belge var (error.rejectedDocuments).
NO_DOCUMENTS_TO_SUBMIT409Gönderilecek yeni yüklenmiş belge yok.
REQUIRED_DOCUMENTS_MISSING422Zorunlu belge ya da yüz eksik (error.missingDocuments).

5. Yazma istekleri ve çevrimdışı

Idempotency-Key

Uç grubuAnahtarTekrar gönderilince
Kanıt, tutanak, anketZorunlu, 8–160 karakterİlk oluşturma 201, tekrar 200 (aynı kayıt). Anket tekrarı değer özetiyle tespit edilir.
OTP göndermeOpsiyonel, verilirse 8–160200, mevcut kod kaydı.
Teslim sonucu (finalize)Zorunlu, 8–200İçerik tabanlı: aynı sonuç alanları → alreadyFinalized: true; farklı → 409 FINALIZE_IDEMPOTENCY_CONFLICT.
Zimmet kabulü ve iadeOpsiyonel, en çok 120 (fazlası kesilir, alt sınır yok)data.replayed: true.
Destek talebiOpsiyonel, en çok 191data.idempotent: true.
Kanıt silme (VOID)Yalnız korelasyon için saklanırVOID kayıt 200.
  • UUID önerilir. Başlık yoksa gövdedeki idempotencyKey alanı okunur.
  • Aralık dışı anahtar → 400 IDEMPOTENCY_KEY_INVALID. Aynı anahtar başka bir işlem ya da gönderi için kullanılırsa → 409 IDEMPOTENCY_KEY_CONFLICT.
  • X-Client-Event-Id: cihazdaki kuyruk kaydının kimliği (UUID, en çok 191). Sunucu bunu korelasyon kimliği olarak saklar; X-Correlation-Id de kabul edilir.

Çevrimdışı kuyruk

  1. İşlemi cihazda (ör. SQLite ya da IndexedDB) X-Client-Event-Id + Idempotency-Key ile saklayın.
  2. Bağlantı gelince kuyruğu eskiden yeniye sırayla boşaltın; her işlemi aynı anahtarla yeniden gönderin.
  3. Sunucudan 2xx gelmeden işlemi kullanıcıya "tamamlandı" göstermeyin.
  4. 4xx (408 ve 429 hariç) kalıcı hatadır; tekrar denemek sonucu değiştirmez, kullanıcıya gösterin. 408, 429, 5xx ve ağ hatalarını yeniden deneyin.
  • Web istemcisinin kuyruğa aldığı işlem türleri: CUSTODY_ACCEPT, CUSTODY_RETURN, REPORT, FORM, EVIDENCE, DOCUMENT_UPLOAD, DELIVERY_RESULT.
  • OTP gönderme/doğrulama ve "Müşteriyi Ara" çevrimdışı yapılamaz; kuyruğa almayın.
  • Teslim sonucu kuyrukta aynı gövde + aynı anahtarla gönderilir. Gereksinim eksikliğinden sonra gövde değişirse yeni anahtar kullanın.
  • Eski konumları start/location uçlarına göndermeyin (tazelik kuralı, bkz. Konum). Kanıt, tutanak ve finalize konumları geçmiş zamanlı olabilir.

6. Ekran ekran akışlar

Kartlar uygulamadaki kullanım sırasıyla dizilidir. Her kart aynı şablonu izler: amaç → çağrı sırası → iş kuralları → hata durumunda. Web sayfaları src/app/[locale]/kurye-paneli/** altındadır.

Giriş ve hesap

GirişGiriş ve uygulama kabuğu

Web: /kurye-giris; kabuk tüm sayfalarda

1. Amaç

Kurye kimliğini doğrulamak, token almak ve her açılışta oturumun hâlâ geçerli olduğunu kontrol etmek.

2. Çağrı sırası

  1. GET courier-auth/session — açılışta; oturum varsa doğrudan K01.
  2. POST courier-auth/login — X-Client-Type: mobile ile; token saklanır.
  3. POST courier-auth/logout — çıkışta (K09'dan da).

3. İş kuralları

  • E-posta küçük harfe çevrilir; telefon rakamlarıyla, + önekiyle ve girildiği hâliyle denenir.
  • Token 8 saat geçerli; refresh yok. Logout oturum olmasa da 200 döner.

4. Hata durumunda

  • INVALID_CREDENTIALS → "Bilgiler hatalı" ve kalan deneme (remainingAttempts).
  • ACCOUNT_TEMPORARILY_LOCKED → lockedUntil'e kadar bekleme mesajı.
  • ACCOUNT_NOT_ACTIVATED / PASSWORD_NOT_SET → e-postadaki aktivasyon bağlantısına yönlendir; ACCOUNT_NOT_ACTIVE → hesabın pasif olduğunu söyle.
  • VALIDATION_ERROR → error.field alanını işaretle.
HesapHesap oluştur (aktivasyon)

Web: /kurye-paneli/hesap-olustur?token=

1. Amaç

Onaylanan kuryenin e-postadaki bağlantıyla ilk şifresini belirlemesi.

2. Çağrı sırası

  1. GET courier-auth/activate?token= — bağlantıyı doğrula, hesap özetini göster.
  2. POST courier-auth/activate — token, password, passwordConfirmation.
  3. POST courier-auth/login — aktivasyon oturum açmaz.

3. İş kuralları

  • Şifre: 8–72 karakter, en az bir küçük harf, bir büyük harf ve bir rakam.
  • Başarıda hesabın diğer aktivasyon bağlantıları iptal edilir.

4. Hata durumunda

  • ACTIVATION_REVOKED / ACTIVATION_ALREADY_USED / ACTIVATION_EXPIRED (410), ACTIVATION_NOT_FOUND (404) → "Bağlantı geçersiz, yenisini isteyin".
  • ACCOUNT_ALREADY_ACTIVE → giriş ekranına yönlendir.
  • ACCOUNT_NOT_ACTIVATABLE (GET'te 403, POST'ta 409) → destekle iletişim mesajı.
  • VALIDATION_ERROR → error.field (token, password, passwordConfirmation) alanını işaretle.

Güne başlarken

K01Ana sayfa

Web: /kurye-paneli

1. Amaç

Günün sayaçlarını ve sıradaki görevi göstermek; diğer ekranlara kısayol vermek.

2. Çağrı sırası

  1. GET courier-dashboard — sayaçlar ve nextTask.

3. İş kuralları

  • Açık görev = kuryedeki ve durumu 40xx olan gönderi. "Bugün" sınırı sunucunun yerel saat dilimine göredir.
  • Sayaç kartları K02'ye filtreyle (gorevlerim?filtre=), toReturnToBranch K08 iade filtresine gider.
  • Bekleyen çevrimdışı kuyruk sayısı cihazdan gösterilir. Destek/SOS kısayolu POST courier-support/cases kullanır.
  • Alıcı telefonu dönmez.

4. Hata durumunda

  • 401 → giriş ekranı. COURIER_NOT_FOUND → hesabın kuryeye bağlı olmadığını söyle, destek.
  • COURIER_DASHBOARD_LOAD_FAILED (500) → "Yenile" butonu, tekrar dene.
K10Depodan alım

Web: /kurye-paneli/depodan-alim

1. Amaç

Depodan, birimden ya da başka kuryeden gelen gönderileri okutarak teslim almak ve dağıtıma çıkarmak.

2. Çağrı sırası

  1. GET courier-custody/overview (pendingTransfers) + GET courier-dashboard (counts.awaitingDelivery durak sayısı).
  2. POST courier-custody/accept — okutulan her kalem için bir çağrı.
  3. GET courier-custody/overview — listeyi tazele.

3. İş kuralları

  • Zimmet yalnız teslim alan taraf okutarak kabul edince değişir. Kabul aynı işlemde gönderiyi dağıtıma (4020, neden 9117) çıkarır.
  • Okutulan değer gönderi no, takip no, etiket barkodu ya da koli barkodu/no/takip no olabilir; scanType (AUTO, SHIPMENT_NUMBER, BARCODE, CARGO_CODE) ile daraltılır.
  • Sonuç mode: HANDOVER (kabul + çıkış), REASSIGN (başka kuryeden devir, 4020 kalır), REDISPATCH (elde tutulan 6010 tekrar çıkış, 9116 Devir).
  • Okutmalar kuyruğa alınabilir (CUSTODY_ACCEPT); anahtarla tekrar → replayed: true.

4. Hata durumunda

  • HANDOVER_SCAN_NOT_FOUND → "Bu gönderi size zimmetlenmemiş"; error.message doğrudan gösterilebilir (Türkçe).
  • HANDOVER_ALREADY_ACCEPTED → kalemi "kabul edildi" işaretle (anahtarlı tekrarda zaten 200 döner).
  • HANDOVER_ALREADY_PENDING / CUSTODY_TRANSFER_* → mesajı göster, listeyi yenile.
  • COURIER_RETURN_PENDING, COURIER_REDISPATCH_MANUAL_REASON, COURIER_REDISPATCH_NOT_ALLOWED, MAX_REDELIVERY_COUNT_REACHED → tekrar çıkılamaz; gönderiyi K08'den birime iade et.
  • COURIER_HANDOVER_FAILED (500) → aynı anahtarla tekrar dene.

Görevler ve teslim

K02Görevlerim

Web: /kurye-paneli/gorevlerim

1. Amaç

Kuryedeki tüm görevleri listelemek, filtrelemek ve haritada göstermek.

2. Çağrı sırası

  1. GET courier-tasks?page=1&pageSize=500 — tek sayfada hepsi.
  2. Göreve dokununca → K03.

3. İş kuralları

  • Kapsam: şu an bu kuryeye atanmış (currentCourierId) tüm gönderiler. Sıralama plannedDeliveryAt artan, sonra createdAt azalan.
  • Filtre, sıralama ve harita istemcide yapılır. status parametresi ALL ya da birebir durum kodu (ör. 4020) alır; search gönderi no, harici referans, alıcı adı ya da telefonunda arar (telefonla eşleşse de numara dönmez).
  • statuses filtre seçenekleridir; summary.total/planned/today/filtered sayaçlardır.
  • Alıcı telefonu yalnız maskeli: 10 haneli numarada +90 5** *** 34 27, diğerlerinde son 4 hane (*****1234).

4. Hata durumunda

  • COURIER_TASKS_LOAD_FAILED (500) → son önbellekteki listeyi göster, tekrar dene.
  • COURIER_NOT_FOUND → destek mesajı.
K03Görev detayı

Web: /kurye-paneli/gorevlerim/{id}

1. Amaç

Görevi incelemek, alıcıyı aramak, görevi kabul edip dağıtıma başlamak ve canlı konum göndermek.

2. Çağrı sırası

  1. GET courier-tasks/{shipmentId} — ekranda recipientPhoneMasked gösterilir.
  2. POST courier-tasks/{shipmentId}/call — "Müşteriyi Ara"; dönen telUri ile çevirici açılır. Detay yeniden okununca lastRecipientCallAt dolu gelir, adım tamam sayılır.
  3. POST courier-tasks/{shipmentId}/accept — kabul.
  4. POST courier-tasks/{shipmentId}/start — taze konumla dağıtıma çık.
  5. POST courier-tasks/{shipmentId}/location — dağıtımdayken ACTIVE_TASK (en az 30 sn ve 50 m arayla).
  6. POST courier-tasks/{shipmentId}/location — ARRIVAL ("Adrese vardım"), sonra K05/K07.

3. İş kuralları

  • Gerçek numara yalnız call ucundan gelir. Koşul: gönderi bu kuryede, güncel atama var, görev sonuçlanmamış. Her çağrı denetim kaydı yazar (audit_logs, COURIER_RECIPIENT_CALL; X-Client-Event-Id verilirse metadata.clientEventId'e yazılır). Gövde okunmaz, idempotency yok. Yanıt Cache-Control: no-store: numarayı saklamayın, loglamayın.
  • accept idempotenttir (alreadyAccepted: true), gövde okunmaz.
  • start: iş akışı READY_FOR_DELIVERY olmalı; DELIVERY_STARTED olayı uygulanır, kurye WORKING, atama startedAt alır. Zaten başlamışsa alreadyStarted: true.
  • location: görev başlatılmış ve OUT_FOR_DELIVERY olmalı. ARRIVAL ayrıca COURIER_ARRIVED_AT_DESTINATION olayı yazar.
  • deliveryRequirements çözülemezse null gelir; varsayılan akışa düşün (1 teslim fotoğrafı, imza, OTP).
  • Etiket dili: locale → NEXT_LOCALE çerezi → Accept-Language.

4. Hata durumunda

  • COURIER_TASK_NOT_FOUND / SHIPMENT_NOT_FOUND (404) → görev artık bu kuryede değil; K02'ye dön ve listeyi yenile.
  • CURRENT_ASSIGNMENT_NOT_FOUND (409) → atama kalkmış; listeyi yenile.
  • RECIPIENT_PHONE_MISSING (422) → arama butonunu gizle. TASK_ALREADY_FINALIZED → görev kapanmış, detayı yenile. RECIPIENT_CALL_FAILED → tekrar dene.
  • LOCATION_NOT_FRESH / LOCATION_* (start'ta 409, location'da 400) → yeni konum al, tekrar gönder.
  • TASK_NOT_READY_FOR_DELIVERY, TASK_NOT_STARTED, TASK_NOT_OUT_FOR_DELIVERY, RUNNING_SHIPMENT_WORKFLOW_NOT_FOUND → detayı yeniden oku, doğru adıma dön.
K04Rota

Web: /kurye-paneli/rota

1. Amaç

Görevleri haritada sıralı rota olarak göstermek.

2. Çağrı sırası

  1. GET courier-tasks?page=1&pageSize=500

3. İş kuralları

  • Rota sırası, mesafe (haversine), varış yarıçapı ve harita yönlendirmesi istemcide hesaplanır.
  • destination.usableForProximity=false ise koordinat yaklaşıktır; mesafe hesabında uyarı gösterin.

4. Hata durumunda

  • COURIER_TASKS_LOAD_FAILED → önbellekteki rotayı göster, tekrar dene.
K05/K07Teslim

Web: /kurye-paneli/gorevlerim/{id}/teslim

1. Amaç

Teslimi kurala uygun adımlarla tamamlamak: konum → teslim alan → OTP → kanıt → anket → sonuç.

2. Çağrı sırası

  1. GET courier-tasks/{shipmentId} (deliveryRequirements) + GET courier-tasks/delivery-reasons?locale=
  2. Konum: POST …/location (ARRIVAL).
  3. Teslim alan: istemcide seçilir (SELF, RELATIVE, AUTHORIZED, SECRETARY).
  4. OTP (otpRequired ise): POST …/otp → POST …/otp/verify.
  5. Kanıt: POST …/evidence (fotoğraf gereksinimi başına requirementCode; imza, belge, not); gerekirse DELETE …/evidence/{evidenceId}; ilerleme için GET …/requirements.
  6. Anket (form varsa): PUT …/form ile DRAFT otomatik kayıt, sonra SUBMITTED.
  7. Sonuç: POST …/finalize.
  8. Sonraki görev: GET courier-tasks?status=4020&pageSize=20.

3. İş kuralları

  • Adımlar sabit değildir; teslim gereksinimlerinden gelir. "Teslim edilemedi" seçilirse doğrudan Sonuç adımına geçilir.
  • OTP: 6 hane, "JetDiji" başlıklı SMS, 120 sn geçerli; 60 sn'den önce yeniden istenemez; gönderi başına saatte en fazla 5. Yeni kod öncekini geçersiz kılar. Doğrulamada en fazla 5 deneme; zaten doğrulanmış kod tekrar 200. Dönen evidenceId finalize'da otpEvidenceId olur.
  • OTP gövdesi opsiyonel: boş gövde {} (receiverType = SELF). Geliştirme/simülasyonda SMS gitmez, channel: DEV_LOG ve devCode döner; canlıda devCode yok.
  • Finalize DELIVERED: reasonCode gönderilmez; receivedRelationCode (5010) opsiyonel; zimmet kuryeden alıcıya geçer. DELIVERY_FAILED: reasonCode (5110) zorunlu, yeniden dağıtım kararı (reason.redistribute=true) iş akışına yazılır; web açıklama notunu zorunlu tutar (sunucu tutmaz).
  • Finalize: görev başlatılmış ve açık deneme (PLANNED/STARTED) olmalı. evidenceIds (en çok 50) bu ekranda yüklenenlerdir; gereksinimle sayılanlar ayrıca otomatik bağlanır. Dağıtımda başka görevi kalmayan kurye AVAILABLE olur.
  • Finalize tekrarı içerikle tespit edilir (resultCode, reasonCode, receivedByName, note); bkz. Yazma istekleri.

4. Hata durumunda

  • RECIPIENT_PHONE_MISSING (OTP) → OTP adımını atla; kural OTP istiyorsa finalize engellenir, operasyona bildir.
  • OTP_RATE_LIMITED → Retry-After / resendAvailableAt geri sayımı. OTP_INVALID → kalan deneme. OTP_EXPIRED / OTP_TOO_MANY_ATTEMPTS → "Yeni kod gönder". SMS_SEND_FAILED (503) → tekrar dene.
  • DELIVERY_REQUIREMENTS_MISSING → error.missing[] içindeki adıma dön (fotoğraf, imza, OTP, anket), sonra yeni anahtarla tekrar gönder.
  • FORM_FIELD_REQUIRED / FORM_FIELD_INVALID / FORM_EVIDENCE_REQUIRED → fieldCode alanını işaretle. FORM_VERSION_MISMATCH → detayı yeniden oku, anketi güncel sürümle doldur.
  • DELIVERY_REASON_REQUIRED, DELIVERED_REASON_NOT_ALLOWED, DELIVERY_REASON_INVALID, RECEIVED_RELATION_INVALID → seçenekleri delivery-reasons'tan yeniden yükle.
  • FINALIZE_IDEMPOTENCY_CONFLICT → görev zaten farklı sonuçla kapanmış; detayı yenile. DELIVERY_ATTEMPT_NOT_FOUND_FOR_FINALIZE, FINALIZE_TRANSITION_NOT_AVAILABLE, FINAL_V3_* → operasyona bildir.
K12Fotoğraf

Web: /kurye-paneli/gorevlerim/{id}/fotograf

1. Amaç

Göreve fotoğraf kanıtı çekip yüklemek, yanlışları geçersiz kılmak.

2. Çağrı sırası

  1. GET courier-tasks/{shipmentId} + GET …/evidence
  2. POST …/evidence — PHOTO, multipart.
  3. DELETE …/evidence/{evidenceId} — gerekirse.
  4. GET …/evidence/{evidenceId}/file — önizleme.

3. İş kuralları

  • Yükleme kuralları: Dosya yükleme. Web yüklemeden önce en uzun kenarı 1600 px, JPEG kalite 0.82'ye küçültür (önerilir).
  • Silme fiziksel değildir (VOID). Yalnız kendi yüklediğiniz ve tamamlanmış teslim denemesine bağlanmamış kanıt silinir.

4. Hata durumunda

  • FILE_TOO_LARGE (413) → küçültüp tekrar yükle. FILE_TYPE_NOT_ALLOWED / CONTENT_TYPE_INVALID (415) → biçimi çevir.
  • IDEMPOTENCY_KEY_CONFLICT → her yeni fotoğraf için yeni anahtar üret.
  • EVIDENCE_LOCKED / EVIDENCE_NOT_DELETABLE / EVIDENCE_NOT_OWNED → sil butonunu gizle.
K13Belge yükleme

Web: /kurye-paneli/gorevlerim/{id}/belge-yukle

1. Amaç

Göreve sayfa sayılı belge (ör. irsaliye, PDF) yüklemek.

2. Çağrı sırası

  1. GET courier-tasks/{shipmentId} + GET …/evidence
  2. POST …/evidence — DOCUMENT, pageCount (1–500).
  3. DELETE …/evidence/{evidenceId}; görüntüleme GET …/file.

3. İş kuralları

  • Dosya kuralları K12 ile aynıdır (10 MB, jpeg/png/webp/heic/heif/pdf).

4. Hata durumunda

  • PAGE_COUNT_INVALID → sayfa sayısını 1–500 arası iste. Diğerleri K12 ile aynı.
K11Tutanak

Web: /kurye-paneli/gorevlerim/{id}/tutanak

1. Amaç

Kurye ve karşı tarafın imzaladığı dijital tutanak (teslim alma, teslim, hasar, diğer) oluşturmak.

2. Çağrı sırası

  1. GET courier-tasks/{shipmentId} + GET …/evidence (ek seçimi) + GET …/reports
  2. POST …/reports

3. İş kuralları

  • İmzalar JSON içinde data:image/png;base64,..., her biri en çok 2 MB. SUBMITTED (varsayılan) için iki imza da zorunlu; signerRole yalnız karşı taraf imzasında.
  • attachmentEvidenceIds: aynı gönderinin VOID olmayan kanıtları (en çok 50). Not en çok 4000 karakter.
  • Tutanak imzaları teslim imzası sayılmaz. Liste yeni → eski, en çok 100.

4. Hata durumunda

  • SIGNATURE_REQUIRED → eksik imzayı iste. SIGNATURE_TOO_LARGE → imza tuvalini küçült. SIGNATURE_INVALID → PNG data URL üret.
  • ATTACHMENTS_INVALID → ek listesini GET …/evidence ile yenile.
KanıtKanıt merkezi

Web: /kurye-paneli/kanit-merkezi

1. Amaç

Tüm görevlerin kanıt ve tutanaklarını tek yerden görmek.

2. Çağrı sırası

  1. GET courier-tasks?page=1&pageSize=500
  2. Seçilen görev için GET courier-tasks/{shipmentId}, GET …/evidence, GET …/reports; dosyalar GET …/file.

3. İş kuralları

  • Kanıt listesi VOID hariç, yeni → eski, en çok 200. OTP ve tutanak (FORM) kayıtları kanıt listesinde yoktur.

4. Hata durumunda

  • EVIDENCE_FILE_NOT_FOUND → "Dosya bulunamadı" yer tutucusu. EVIDENCE_STORAGE_NOT_SUPPORTED (501) → önizleme kapalı.

Gün sonu

K08Zimmet

Web: /kurye-paneli/zimmet

1. Amaç

Kuryedeki gönderileri görmek, bekleyen devirleri okutarak kabul etmek, elde tutulanları tekrar çıkarmak ve gün sonu birime iade başlatmak.

2. Çağrı sırası

  1. GET courier-custody/overview + GET courier-custody/pending
  2. POST courier-custody/accept — okutma (kabul ya da tekrar çıkış).
  3. POST courier-custody/return — gün sonu iade.
  4. GET courier-custody/history?limit=50 — geçmiş sekmesi.

3. İş kuralları

  • pending.items: okutarak kabul bekleyen kalemler. pending.held: teslim edilemeyip (6010) kuryede duran, okutarak tekrar çıkabilecek gönderiler.
  • İade başlatılır; zimmet birim okutana kadar kuryede kalır, birim okutunca kabul + otomatik yeniden dağıtım olur. shipmentIds ve/veya scannedValues (her biri en çok 200). targetUnitId yoksa gönderinin teslimat birimi kullanılır; birden çok birim → birden çok devir. Açık iadesi olan gönderi alreadyPending: true.
  • overview.onCourier[].overdue: kuryede 24 saatten uzun → alarm. "Bugün teslim" İstanbul saatine göre. redispatchable: okutarak tekrar çıkabilir.
  • Geçmiş: gelen (IN) ve çıkan (OUT) kalemler, son güncellenen önce; limit 1–200.

4. Hata durumunda

  • RETURN_RESULT_REQUIRED → önce teslim sonucunu gir (K05/K07).
  • RETURN_SCAN_NOT_FOUND → error.shipmentNumber ile okutulan değeri göster. RETURN_TOO_MANY → 200'lük parçalara böl.
  • RETURN_NOT_WITH_COURIER, RETURN_UNIT_REQUIRED, RETURN_UNIT_NOT_FOUND → operasyona bildir.
  • Okutma hataları K10 ile aynıdır.
K14Çevrimdışı senkron

Web: /kurye-paneli/senkron

1. Amaç

Çevrimdışıyken kuyruğa alınan işlemleri göstermek ve sunucuya göndermek.

2. Çağrı sırası

  1. Sunucu ucu yok: kuyruktaki her işlem kendi ucuna aynı Idempotency-Key ile, eskiden yeniye gönderilir.

3. İş kuralları

4. Hata durumunda

  • Kalıcı hata (4xx, 408/429 hariç) → kaydı "başarısız" işaretle ve kullanıcıya göster. Geçici hata → kuyrukta bırak, sonra tekrar dene.

Hesap

K09Hesabım

Web: /kurye-paneli/hesabim

1. Amaç

Kuryenin seviyesini, istatistiklerini ve rozetlerini göstermek; destek talebi açmak; çıkış yapmak.

2. Çağrı sırası

  1. GET courier-profile/summary
  2. Destek sekmesi: GET courier-support/cases → POST courier-support/cases
  3. POST courier-auth/logout

3. İş kuralları

  • Seviye: GOLD (≥ 500 teslim ve ≥ %95), SILVER (≥ 150, ≥ %90), BRONZE (≥ 30, ≥ %80), aksi NEW. Rozetler son 30 gün: ON_TIME (hedef 50), DOCUMENT_ACCURACY (50), TRAINING_LEADER (5; eğitim modeli yok, ilerleme 0). rating şimdilik null, trainings.available şimdilik false.
  • Destek kategorileri: CALL_REQUEST (HIGH), TICKET (NORMAL), LIVE_CHAT (HIGH), SOS (CRITICAL, ilk yanıt SLA 15 dk). Talep iç görünürlükte açılır (müşteri görmez). shipmentId verilirse gönderi bu kuryede olmalı. Konu boşsa kategori varsayılanı (+ gönderi no) kullanılır. Liste son 20 talep.

4. Hata durumunda

  • SUPPORT_CATEGORY_INVALID, TICKET_SUBJECT_REQUIRED, TICKET_DESCRIPTION_REQUIRED, LOCATION_INVALID → form alanını işaretle.
  • COURIER_SUPPORT_CREATE_FAILED → aynı anahtarla tekrar dene.
HesapProfilim

Web: /kurye-paneli/profilim

1. Amaç

Profil ve ödeme bilgisini göstermek; IBAN, adres, araç, çalışma bilgisini ve şifreyi değiştirmek.

2. Çağrı sırası

  1. GET courier-profile
  2. Ödeme: PUT courier-profile
  3. Değişiklik: GET geography/cities → GET geography/cities/{cityId}/districts → GET / POST courier-profile/change-requests → gerekirse POST …/{requestId}/cancel
  4. Şifre: POST courier-auth/change-password

3. İş kuralları

  • bankAccount: bekleyen/reddedilen varsa o, yoksa doğrulanmış hesap; IBAN yalnız maskeli. Yeni IBAN PENDING_VERIFICATION eklenir, önceki taslak/bekleyen/reddedilen kayıtlar pasifleşir. Ad tam eşleşirse NAME_MATCH, değilse FORMAT_CHECK (manuel inceleme).
  • Profil değişikliği otomatik uygulanır: talep APPROVED kaydedilir, aynı tipteki eski PENDING talepler CANCELLED olur. Bu yüzden pratikte yalnız eski bekleyen talepler iptal edilebilir.
  • ADDRESS: cityId, districtId (ilçe şehre ait), addressLine1 (5–500), countryCode (TR); diğer adres alanları opsiyonel, şehir/ilçe adlarını sunucu yazar. VEHICLE: vehicleType. WORK: workModel, companyStatus, companyName (AFFILIATED_WITH_ANOTHER_COMPANY ise zorunlu).
  • Şifre kuralları ve token yenileme: Kimlik doğrulama.

4. Hata durumunda

  • VALIDATION_ERROR → error.fieldErrors alanlarını işaretle. BANK_ACCOUNT_ALREADY_EXISTS → "Bu IBAN zaten kayıtlı".
  • NO_CHANGE → "Değişiklik yok". REQUEST_NOT_CANCELLABLE → talep listesini yenile.
  • CURRENT_PASSWORD_INVALID, PASSWORD_REUSE_NOT_ALLOWED → şifre alanında göster.
HesapMüsaitlik

Web: /kurye-paneli/musaitlik

1. Amaç

Haftalık çalışma planını ve tarih istisnalarını (izin, tatil, özel saat) yönetmek.

2. Çağrı sırası

  1. GET courier-availability
  2. PUT courier-availability — planın tamamı.

3. İş kuralları

  • dayIndex: 0 = Pazar, 1 = Pazartesi … 6 = Cumartesi. Kayıt yoksa days boş, saat dilimi Europe/Istanbul.
  • PUT tam değiştirir (gönderilmeyen istisna silinir). Tam 7 gün; gün başına en çok 4 aralık, HH:mm, bitiş > başlangıç, çakışma yok; enabled: true günde en az 1 aralık. İstisnalar en çok 500, tarih başına 1; CUSTOM_HOURS için startTime/endTime zorunlu.

4. Hata durumunda

  • 422 → error.details.field (ör. days.2.ranges.0) ile ilgili gün/aralığı işaretle.
HesapBaşvurum, Belgelerim, Sözleşmelerim

Web: /kurye-paneli/basvurum, /kurye-paneli/belgelerim, /kurye-paneli/sozlesmelerim

1. Amaç

Kurye olmuş kullanıcının kaynak başvurusunu, belgelerini ve verdiği onayları salt okunur göstermek.

2. Çağrı sırası

  1. GET courier-application — başvuru, durum geçmişi, belge özeti, güncel kurye kaydı.
  2. GET courier-my-documents — belge talepleri, güncel dosyalar, son inceleme kararı.
  3. GET courier-my-contracts — onaylar (TR ve EN metin birlikte).

3. İş kuralları

  • Üçü de Bearer ister (başvuru formundaki uçlardan farklı).
  • Belgelerim dosya indirme/yükleme sağlamaz; yükleme aday belge portalıyla yapılır.
  • requestedContracts şimdilik her zaman boş.

4. Hata durumunda

  • APPLICATION_NOT_FOUND → "Bu hesaba bağlı başvuru yok" boş durumu.
BilgiBildirimler ve Çalışma konumu

Web: /kurye-paneli/bildirimler, /kurye-paneli/calisma-konumu

1. Amaç

Bildirimler bekleyen kuyruk uyarısını gösterir; Çalışma konumu statik bilgi ekranıdır.

2. Çağrı sırası

  1. Sunucu ucu yok. Bildirim ucu henüz tanımlı değil.

3. İş kuralları

  • İçerik cihazdan (kuyruk) ya da statik metinden gelir.

4. Hata durumunda

  • Sunucu çağrısı olmadığı için yok.

Hesabı olmayanlar için

BaşvuruKurye ol

Web: /courier-application · Bearer gerekmez

1. Amaç

Aday kuryenin başvuru formunu doldurup göndermesi.

2. Çağrı sırası

  1. GET courier-consents?locale= + GET geography/cities
  2. GET geography/cities/{cityId}/districts
  3. GET courier-applications/check-phone?phone=
  4. POST courier-applications

3. İş kuralları

  • Onay metinleri: her kalem için definitionId, versionId, code, version, contentHash başvuruda aynen geri gönderilir; ayrıca decision, viewedToEnd, openedAt, scrollCompletedAt, decidedAt (offset'li ISO), locale. versionId ve code tekil; scrollCompletedAt ve decidedAt ≥ openedAt.
  • Telefon kontrolü yalnız UX içindir: yanıt yalnız { canApply }; asıl engel POST courier-applications. Hız sınırı: IP başına 30 / 10 dk, IP + numara başına 10 / 10 dk (sayaç süreç içi, çok sunucuda yaklaşık).
  • Başvuru varsayılan tenant'a kaydedilir. Hız sınırı IP başına 10 / 10 dk. X-Request-Id verilirse meta.requestId olarak döner.
  • Ad soyad en az iki kelime, yalnız harf. companyName SOLE_PROPRIETORSHIP ve AFFILIATED_WITH_ANOTHER_COMPANY için zorunlu. Şehir listesi 5 dk önbelleklenebilir.

4. Hata durumunda

  • APPLICATION_ALREADY_EXISTS → "Bu numarayla başvuru var" (başvuru bilgisi dönmez).
  • 422 (VALIDATION_ERROR, INVALID_PHONE, GEOGRAPHY_MISMATCH, onay kodları) → error.details[].field alanlarını işaretle.
  • RATE_LIMITED → Retry-After geri sayımı. DRAFT_LEGAL_TEXTS_NOT_ALLOWED (503) → "Başvuru geçici olarak kapalı".
BaşvuruAday belge portalı

Web: /courier-documents/{publicId}?token= (ve /kurye-paneli/{publicId}) · Bearer gerekmez

1. Amaç

Adayın e-postayla gelen bağlantıdan istenen belgeleri yükleyip onaya göndermesi.

2. Çağrı sırası

  1. GET courier-documents/{publicId}?token=
  2. POST …/requests/{documentRequestId}/upload?token=&side= — her belge ya da yüz için.
  3. POST …/submit?token=&locale=

3. İş kuralları

  • Erişim her uçta aynı sırayla kontrol edilir: bağlantı eksik → 400 ACCESS_LINK_INVALID; kayıt yok → 404 ACCESS_NOT_FOUND; iptal → 410 ACCESS_REVOKED; süresi dolmuş (expiresAt <= şimdi) → 410 ACCESS_EXPIRED; deneme sınırı → 423 ACCESS_LOCKED; token hatalı → 401 ACCESS_TOKEN_INVALID (deneme sayacı artar).
  • Yeni bağlantılar varsayılan 14 gün geçerlidir (sunucu ayarıyla 1–90 gün); eski, süresiz (expiresAt: null) bağlantılar geçerli kalır. Yeni bağlantı gönderilince ya da aday kuryeye dönüşünce eski bağlantı ACCESS_REVOKED olur.
  • Kapalı (COMPLETED/CANCELLED/EXPIRED) olmayan son paket döner; FRONT_BACK belgelerde ön/arka ayrı (parts).
  • Yükleme: side = SINGLE (tek dosyalı belge, varsayılan) ya da FRONT/BACK (zorunlu). Tip ve boyut belge tanımından (allowedMimeTypes, maxFileSizeMb); requiresExpiryDate ise expiresAt zorunlu. Yeni dosya öncekinin yerini alır, belge UPLOADED_DRAFT olur.
  • Gönderim: gövde yok. Başarıda başvuru DOCUMENT_REVIEW olur. Yükleme mesajları locale'e göre; submit locale=en ile İngilizce; diğerleri yalnız Türkçe.

4. Hata durumunda

  • ACCESS_REVOKED / ACCESS_EXPIRED → "Bağlantının süresi doldu; yeni bağlantı isteyin". ACCESS_LOCKED → destekle iletişim.
  • ACCESS_TOKEN_INVALID → bağlantıyı e-postadan yeniden açmasını söyle (her hatalı deneme sayılır).
  • DOCUMENT_NOT_UPLOADABLE → belgeyi kilitli göster. UNSUPPORTED_FILE_TYPE / FILE_TOO_LARGE → tanımdaki sınırları göster.
  • REQUIRED_DOCUMENTS_MISSING → error.missingDocuments; REJECTED_DOCUMENT_PRESENT → error.rejectedDocuments listesini göster. NO_DOCUMENTS_TO_SUBMIT / DOCUMENTS_ALREADY_SUBMITTED → gönder butonunu kapat.

7. Kavramlar

Gönderi durum kodları

statusCode (Shipment.currentStatusCode) sayısal stringtir.

KodAnlam
4010Teslimat şubesinde / kuryeye planlı, henüz çıkmadı
4020Dağıtımda — neden 4021 Dağıtıma çıktı, 4022 Teslim işleminde
5010Teslim edildi (alt varyantlar 5020 grubuna eşlenebilir)
5110Teslim edilemedi
6010Yeniden dağıtım bekliyor (kurye elinde tutabilir)
7010 / 7020 / 7030İade süreçleri
8010 / 8030İptal / imha süreçleri

courier-tasks listesi statusCode değerini filtre olarak birebir kabul eder. 7xxx/8xxx gönderiler kuryede kalmadığı için listede nadiren görünür. Eski metin kodları (OUT_FOR_DELIVERY, DELIVERED) yedek olarak gelebilir.

Neden kodları

GrupAlanKodlar
Teslim edildi (5010) — teslim alan yakınlığıreceivedRelationCode9201 Kendisi, 9202 Birinci Derece Akraba, 9203 Kardeşi, 9204 Sekreter, 9205 Güvenlik / Muhaberat, 9206 Banka Şubesi, 9207 Vekili
Teslim edilemedi (5110)reasonCode9301 Alıcıya Ulaşılamadı, 9302 Alıcı Adreste Yok, 9303 Alıcı Teslimatı Reddetti, 9304 Hatalı/Eksik Adres, 9305 Alıcı Adresten Ayrılmış, 9306 Alıcı Vefat Etmiş, …
Teslimat birimi çıkışıstatusReasonCode9117 Normal ilk çıkış, 9116 Devir (alıcıya ulaşılamayınca tekrar çıkış)
  • Teslim alan tipi → yakınlık eşlemesi (web): SELF → 9201, RELATIVE → 9202/9203, AUTHORIZED → 9207/9205/9206, SECRETARY → 9204.
  • Güncel ve dile göre adlandırılmış liste için her zaman GET courier-tasks/delivery-reasons kullanın; kodları sabit yazmayın.

Zimmet kuralları

  1. Zimmet yalnız teslim alan taraf okutarak kabul edince değişir. Kurye depodan, birimden ya da başka kuryeden gelen gönderiyi courier-custody/accept ile okutur; kabul aynı işlemde gönderiyi dağıtıma (4020) çıkarır.
  2. Teslim edilemeyen gönderi (6010) kuryede kalabilir; kurye aynı barkodu okutarak tekrar çıkış yapar (mode: REDISPATCH, neden 9116). Manuel karar gerektiren nedenlerde ya da çıkış hakkı dolduysa reddedilir.
  3. Teslim edildiğinde zimmet kuryeden alıcıya geçer (finalize içinde otomatik).
  4. Gün sonu: kurye courier-custody/return ile birime iade başlatır; zimmet birim okutana kadar kuryede kalır.
  5. Kuryede 24 saatten uzun duran gönderi alarmlıdır (overview.onCourier[].overdue, alertHours: 24).

8. Konum gönderimi

KonuKural
Alanlarlatitude (-90..90), longitude (-180..180), accuracy (m), heading, speed (m/s), altitude, capturedAt (ISO). Sayısal string de kabul edilir.
Tazelik (start, location)capturedAt son 5 dk içinde ve en fazla 1 dk ileri olmalı; aksi 409 LOCATION_NOT_FRESH. capturedAt yoksa sunucu zamanı kullanılır. Çevrimdışı biriktirilmiş eski konumları bu uçlara göndermeyin.
ACTIVE_TASKGörev dağıtımdayken ön planda en fazla 30 sn'de bir ve yaklaşık 50 m hareketten sonra (web davranışı).
ARRIVALAdrese varış; ayrıca gönderi olayı (COURIER_ARRIVED_AT_DESTINATION) yazar.
Kanıt, tutanak, finalizeKonum opsiyoneldir ve geçmiş zamanlı (capturedAt) olabilir; en fazla 1 dk ileri.
İstemci hesaplarıMesafe, varış yarıçapı (web: 200 m), rota sırası ve harita yönlendirmesi istemcide. destination.usableForProximity=false ise koordinat yaklaşıktır.
KaynakSunucu sourceCode değerini her istemci için BROWSER_GEOLOCATION yazar.

9. Teslim gereksinimleri ve anket

Teslim akışının adımları sabit değildir; ürün ya da operasyon kuralından gelir. GET courier-tasks/{shipmentId} (alan deliveryRequirements) ya da GET courier-tasks/{shipmentId}/requirements ile okunur (?locale=tr|en etiket dili).

Gereksinim nereden gelir (source.type)

İlk "teslim gereksinimi tanımlayan" kural kazanır:

  1. RULE_INSTANCE: gönderinin iş akışına bağlanmış yayınlanmış operasyon kuralı.
  2. RULE_POLICY: canlı operasyon kuralı ataması (müşteri/ürün/hizmet kapsamına göre).
  3. DEFAULT: 1 teslim fotoğrafı (DELIVERY) + imza + OTP. Sunucuda zorlanmaz (geriye uyum).

Gereksinim alanları

AlanAnlamı ve kural
photos[]Her kalem: code (ör. DELIVERY, DEVICE_FRONT), categoryCode (PACKAGE|WAYBILL|REPORT|DELIVERY|DEVICE|OTHER), minCount (1–10), label, hint.
signatureRequiredTeslim imzası gerekir (evidenceType=SIGNATURE; tutanak imzaları sayılmaz).
otpRequiredDoğrulanmış OTP gerekir (progress.otpVerified). Alıcı telefonu yoksa OTP 422 RECIPIENT_PHONE_MISSING döner; kural OTP istiyorsa finalize DELIVERY_REQUIREMENTS_MISSING (type OTP) ile engellenir.
appliesToDELIVERED: yalnız teslim edildi'de kontrol. BOTH: teslim edilemedi'de de yalnız fotoğraflar istenir.
form / submissionAnket tanımı (formVersionId, formCode, title, description, instructions, required, fields[]) ve mevcut kayıt.
progressphotos[code], photos["form:<ALAN>"], signature, otpVerified, formSubmitted.

Fotoğrafları gereksinime bağlama

  • Yüklerken requirementCode=<code> gönderin (yalnız evidenceType=PHOTO). Kategori boş bırakılırsa gereksinimin kategorisi atanır; farklı kategori → 422 REQUIREMENT_CATEGORY_MISMATCH; tanımsız kod → 422 REQUIREMENT_CODE_INVALID.
  • Anket alanına bağlı fotoğraf: requirementCode=form:<ALAN_KODU> (alanın evidenceRule.evidenceTypeCode değeri PHOTO olmalı).
  • Kodsuz fotoğraflar kategori eşleşmesiyle sayılır (aynı kategoride sırayla eksik olana).
  • Sayım kapsamı: henüz teslim denemesine bağlanmamış kanıtlar + açık deneme. Teslim edilemeyen denemeye bağlanan kanıtlar sonraki denemeye taşınmaz; yeniden çekilmelidir.

Anket

Kayıt PUT courier-tasks/{shipmentId}/form ile yapılır: DRAFT taslak, SUBMITTED tamamlama. Değerler alan kodu (büyük/küçük harf duyarsız) → değer nesnesidir.

Tip (dataTypeCode)DeğerDoğrulama (validationRule)
STRINGstring (trim)minLength, maxLength (varsayılan en çok 4000)
NUMBERnumber (ya da "12,5" gibi string)min/minValue, max/maxValue
BOOLEANtrue/false—
DATE"YYYY-MM-DD"Geçerli takvim günü
TIMESTAMPISO tarih-saatSunucu ISO'ya çevirir
CODEoptions[].code değerlerinden biriSeçenek listesi (ACTIVE)
  • isMultiValue: true alanlarda değer dizidir (en çok 50, tekrarlar atılır). Boş string, boş dizi ve null "boş" sayılır ve kaydedilmez.
  • Web ayrıca pattern dener; sunucu pattern uygulamaz. Bilinmeyen alan kodu → 422 FORM_FIELD_INVALID.

Koşullar (visibilityRule, requiredRule, evidenceRule.requiredWhen) şu biçimdedir: { schemaVersion: "COMPLETION_FORM_CONDITION_V1", fieldCode, operatorCode, value }

operatorCodeDoğru olduğu durum
EQAlan dolu ve değer eşit (çoklu alanda herhangi bir eleman eşit)
CONTAINSEQ ile aynı
NEQAlan boş ya da değer eşit değil → boş değerde true
NOT_CONTAINSNEQ ile aynı (boşta true)
IS_EMPTYAlan boş
NOT_EMPTYAlan dolu
  • Karşılaştırma katıdır: string'ler trim edilip eşitlenir, diğer tipler === (ör. NUMBER 5 ile kural değeri "5" eşit değildir). Bilinmeyen operatör/şema: görünürlükte "görünür", zorunlulukta "zorunlu değil" sayılır.
  • visibilityRule yanlışsa alan gizlidir; gizli alanın değeri sunucuda atılır, zorunluluk ve kanıt kontrolü yapılmaz. Sunucu alanları sortOrder sırasıyla işler; koşul yalnız önceki alanların değerlerine bakar.
  • requiredRule doğruysa (ya da isRequired) alan SUBMITTED'da zorunludur → FORM_FIELD_REQUIRED.
  • evidenceRule = { schemaVersion: "COMPLETION_FORM_EVIDENCE_RULE_V1", evidenceTypeCode: "PHOTO", minCount, requiredWhen }: requiredWhen boş ya da doğruysa form:<ALAN> fotoğraf sayısı minCount'tan az olamaz → FORM_EVIDENCE_REQUIRED (fieldCode, minCount, actual). Sunucu yalnız PHOTO değerini zorlar. Önce fotoğrafları yükleyin, sonra anketi SUBMITTED gönderin.
  • DRAFT'ta yalnız değer tipleri doğrulanır. Aynı teslim bağlamında (atama + açık deneme) tek kayıt güncellenir. Tamamlanmış anket aynı değerlerle tekrar gönderilirse aynı kayıt döner; farklı değerlerle 409 FORM_ALREADY_SUBMITTED.

Örnek gereksinim

{
  "source": { "type": "RULE_POLICY", "ruleSetCode": "KART_TESLIM", "ruleVersion": 3 },
  "photos": [
    { "code": "DELIVERY", "categoryCode": "DELIVERY", "minCount": 1, "label": "Teslim fotoğrafı" },
    { "code": "DEVICE_FRONT", "categoryCode": "DEVICE", "minCount": 2, "label": "Cihaz ön yüz" }
  ],
  "signatureRequired": true,
  "otpRequired": true,
  "appliesTo": "DELIVERED",
  "form": { "formCode": "KART_TESLIM_ANKETI", "required": true, "fields": [ "…" ] },
  "progress": { "photos": { "DELIVERY": 1, "DEVICE_FRONT": 0, "form:HASAR_FOTO": 0 },
                "signature": false, "otpVerified": false, "formSubmitted": false }
}

Finalize öncesi sunucu kontrolü

POST …/finalize işlem içinde gereksinimleri yeniden hesaplar (kaynak DEFAULT değilse). Kontrol sırası: fotoğraflar (minCount) → (yalnız DELIVERED) imza → OTP → anket (form.required ise SUBMITTED). Eksik varsa hiçbir şey yazılmaz:

{ "success": false, "error": { "code": "DELIVERY_REQUIREMENTS_MISSING",
  "missing": [ { "type": "PHOTO", "code": "DEVICE_FRONT", "required": 2, "actual": 1 },
               { "type": "SIGNATURE" }, { "type": "OTP" },
               { "type": "FORM", "code": "KART_TESLIM_ANKETI" } ] } }

Eksik giderildikten sonra gövde değişeceği için yeni Idempotency-Key ile tekrar gönderin (web davranışı). Başarılı finalize'da sayılan kanıtlar ve anket kaydı teslim denemesine bağlanır.

Finalize: eski alanlar

Eski mobil sürümlerle uyumluluk için kabul edilir; yeni istemcide kullanmayın.

Eski alanDavranışYerine
outcome (DELIVERED | FAILED)resultCode ile çelişirse 400 FINALIZE_RESULT_CONFLICT.resultCode
receivedByDELIVERED'da teslim alan adı, DELIVERY_FAILED'da not olarak okunur.receivedByName / note
reasonCode: REFUSEDRECIPIENT_REFUSED olarak çevrilir.delivery-reasons listesindeki kod

10. Dosya yükleme ve indirme

NeNasılSınırlar
Kanıt (fotoğraf, belge, teslim imzası)POST courier-tasks/{shipmentId}/evidence, multipart/form-data, alan adı fileEn çok 10 MB; image/jpeg, image/png, image/webp, image/heic, image/heif, application/pdf (image/jpg → jpeg). Tip boş ya da application/octet-stream ise uzantıdan çözülür.
Not kanıtıAynı uç, application/json, evidenceType: NOTE, textValueEn çok 4000 karakter.
Teslim imzasıevidenceType=SIGNATURE, PNG dosyası multipart ileKanıt sınırları.
Tutanak imzalarıJSON içinde data:image/png;base64,...Her biri en çok 2 MB.
Aday belgePOST courier-documents/{publicId}/requests/{documentRequestId}/upload?token=&side=, multipartBelge tanımından: definition.maxFileSizeMb, definition.allowedMimeTypes.
  • Kanıt ek alanları: category (varsayılan OTHER), requirementCode (yalnız PHOTO, en çok 80), note (en çok 2000), pageCount (1–500), konum alanları, capturedAt.
  • Web istemcisi fotoğrafı yüklemeden önce en uzun kenarı 1600 px, JPEG kalite 0.82'ye küçültür (önerilir).

İndirme

  • GET courier-tasks/{shipmentId}/evidence/{evidenceId}/file — Bearer zorunlu. EvidenceDto.fileUrl bu yolu origin'siz verir.
  • Görseli Authorization başlıklı istekle indirin; düz <img src> ya da URL ile çalışan görüntüleyici token taşımaz.
  • ?download=1 → Content-Disposition: attachment (varsayılan inline). Yanıt Cache-Control: private, no-store. Hata durumunda JSON (ApiError) döner.