Proje: Okul B2B App · Hub: Okul B2B App — Conventions

ApiClient Header Yönetimi

utils/ApiClient.ts singleton’da default header’lar.

Header Yaşam Döngüsü

OlayMethodHeader
Login başarılıapiClient.setAuthToken(token)Authorization: Bearer {token}
Firma seçildiapiClient.setCustomerId(id)x-cid: {customerId}
LogoutapiClient.removeAuthToken()Authorization kaldır
LogoutapiClient.removeCustomerId()x-cid kaldır

Sabit Header’lar

Her istekte gönderilir:

Content-Type: application/json
Accept: application/json
Accept-Language: tr
x-consumer-key: CueoknUqTMbqtT99jNoutfs1  (production) / customer (__DEV__)
X-App-Version: {app version}

x-consumer-key

API’nin istemci tipini tanımlaması için. Production’da CueoknUqTMbqtT99jNoutfs1, development’ta customer.

okulcom-api tarafında routes/api/customer.php route grubu platform (VerifyConsumerToken) middleware’ine bağlı — bu header eksikse 403 döner. routes/api/auth.php grubunda yoktur.

postPublic vs post — Gotcha

postPublic() / getPublic() tüm defaultHeaders’ı siler (Authorization, x-cid, x-consumer-key, Accept-Language, X-App-Version hepsi gitmez). Sadece çağıranın verdiği headers gider.

Endpoint tipiMethod
Tamamen public, hiçbir header gerekmez (/auth/otp, /auth/login)postPublic
Auth gerekmez ama platform/locale/version header’ı gerekir (/customer/otp/users)post (auth token yoksa Authorization eklenmez)
Auth gerekir (/customer/leads)post

Bkz. 2026-05-06-customer-otp-users-403-consumer-keycustomer/otp/users’ı postPublic ile çağırdığımızda 403 aldık.

401 Unauthorized Handling

private async handleUnauthorized(): Promise<void> {
  // isHandlingUnauthorized flag — cascade engellemek için
  // Token + kullanıcı verisi temizlenir
  // AuthService.onLogout event'i tetiklenir
}

Bir 401 alındığında otomatik olarak tüm auth data temizlenir ve logout event’i yayılır.

Pending Requests Deduplication

Aynı URL + header’a aynı anda iki istek giderse, ikincisi bekler ve birincinin sonucunu alır:

private pendingRequests: Map<string, Promise<any>> = new Map();