01 · GET /config — Config Çekme Sözleşmesi
Görev:
00 · AUTH'un döndürdüğütokenile cihazın tam config'ini (tema + ekranlar + gruplar + metinler) sunucudan çeker; SDK config'i parsel edip onay ekranını (banner/manager/detail) kurar.Ne zaman çalışır: AUTH'un yanıtında
decision.updateRequired === trueolduğunda. Değilse (içerik değişmedi) bu adım atlanır; cihazdaki mevcut config önbellekten kullanılır.Bu dosyadan sonra kullanıcı onay ekranında bir seçim yaptığında
02 · POST_CONSENT'e geçersiniz.
1. Genel Bakış
GET /config, açılış döngüsünün orta halkasıdır: AUTH onu besler (token verir), o da onay kaydına zemin hazırlar (UI'ı kurar, aynı token'ı taşır).
SDK sunucuya:
- Kimlik taşır → path'te
consentId+ header'daX-Consent-Token(+ gövdede opsiyonellocale/sdkVersion)
Sunucu karşılığında:
- Tam config gövdesi döndürür →
config(tema, ekranlar, gruplar, metinler; detay §5.2) - Çerçeve (envelope) döndürür →
success/code/consentId/deliveredAt/contentVersion/tokenConsumed
Tasarım felsefesi: Bu bir OKUMA (read) işlemidir — durumu değiştirmez, idempotent'tir. AUTH hafif tutulur (yalnız versiyonlar + token + decision); tam config yalnızca gerçekten gerektiğinde bu adım ile çekilir. Böylece büyük çoğunluk açılışta config hiç transfer edilmez → açılış hızlı, veri tasarruflu, gecikme düşük.
GET /config, AUTH'ın "gerekli mi?" sorusuna verdiği cevabı (
decision.updateRequired) hayata geçiren adımdır.updateRequired === falseise bu adımı atlayın, cihazdaki mevcut config'i kullanın.
2. Döngüdeki Yeri
AUTH (00) GET /config (BU) POST_CONSENT (02)
kimlik + localState ──▶ token ─▶ tam config ────▶ onay kaydı
│ token │ parse → UI kur │ consent + localState
└── decision.updateRequired ──┘ (aynı token) │
│
bir sonraki AUTH ◀─────────────── localState geri besleme
| Adım | Koşul | SDK davranışı |
|---|---|---|
| 00 — AUTH | Her açılışta | Kimlik + localState gönder; versiyon + token + decision al |
| 01 — GET /config (bu adım) | decision.updateRequired === true | Token ile tam config indir, parsel et, önbelleğe yaz, UI'ı yeniden kur |
| 02 — POST_CONSENT | Kullanıcı onay ekranında karar verirse | Aynı token ile onay eylemini post et |
Neden iki aşamalı? İçerik değişmiyorsa config hiç transfer edilmez. Değişiyorsa, AUTH'ın verdiği token ile tek istekte tam config çekilir — ayrı bir anahtar imzalama derdi yoktur (o iş AUTH'ta yapıldı).
3. Endpoint & Güvenlik
3.1 Endpoint
| Özellik | Değer |
|---|---|
| Method | POST |
| Path | /v2/consent/{consentId}/config |
| Base URL | {{SDK_BASE_URL}} |
| Gövde formatı | application/json (UTF-8) |
| Timeout | 15 sn |
| Idempotent | Evet — okuma işlemidir; aynı istek tekrarlandığında aynı config'i döndürür (retry güvenli). |
Neden
POST(RESTGETdeğil)? İki neden: (1) SDK'nın üç sözleşmesi tutarlı biçimdePOST'tur — tek transport modeli. (2)GET, ara katmanlarda (proxy/CDN/tarayıcı) önbelleğe alınabilir; token + kimlik taşıyan hassas bir istek önbelleğe alınmamalıdır.POSTbunu garanti eder. Adımdaki "GET" okuma semantiğidir, HTTP fiilini değil.
3.2 Güvenlik (token-bearer — imza/nonce YOK)
GET /config, AUTH'taki HMAC + nonce + timestamp modelini kullanmaz. Kimlik yalnızca AUTH'tan alınan imzalı, oturum bazlı token ile yapılır:
| Header | Değer / Açıklama |
|---|---|
Content-Type | application/json |
X-Consent-Token | AUTH yanıtındaki token (imzalı, oturum bazlı, tokenExpiresIn'e bağlı). Örnek: cfg_t_8a3f5c2d1e0b. |
- Doğrulama (sunucu): (1) token biçimi/doğrulaması geçerli mi? (2) süresi doldu mu? (3) daha önce tüketildi mi? (4) token'ın bağlı olduğu
consentId== path/gövdeconsentIdmi? → her ihlal ilgili401/404kodu. - Replay: Okuma işlemi zararsızdır (aynı config'in tekrar çekilmesi idempotent'tir). Bu yüzden
nonce/timestamp gerekmez; replay koruması token'ın bağlı olduğu consentId + sınırlı geçerlilik penceresi (tokenExpiresIn) + oturum bazlı tüketimi (§4) ile sağlanır.
POST_CONSENT ile fark (önemli):
02 · POST /consentbir YAZMA işlemidir → durumu değiştirir, mükerrer yazma riski taşır → bu yüzden HMAC +nonce+ timestamp zorunludur.GET /configbir OKUMA işlemidir → idempotent + retry-tolerant → bearer token yeterlidir, ek imza/nonce eklenmez. Bu ayrım, SDK'nın ağ kesintisi gibi okuma hatasında rahatça retry yapabilmesini sağlar; nonce tabanlı bir okuma ise retry'ı reddederdi.
4. İstek (request)
Gövde minimaldir: kimlik path'te, token header'dadır. Gövde yalnızca opsiyonel çözümleme/telemetri alanlarını taşır. camelCase zorunludur.
| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
consentId | string | Evet | Onay kaydı kimliği (ör. ck_mobildev_0001). Path'teki {consentId} ile birebir aynı olmalıdır; sunucu path ↔ gövde ↔ token üçlüsünü çapraz-doğrar, uyumsuzluk → 401 INVALID_TOKEN. |
locale | string (BCP-47) | Hayır | Kullanıcı tercih edilen dil (ör. tr-TR). Response'u daraltmaz (bkz. Not 1); telemetri + SDK'ın aktif dil çözümlemesine ipuç. Yoksa SDK behavior.defaultLanguage'i kullanır. |
sdkVersion | string (semver) | Hayır | SDK sürümü. AUTH çağrısıyla korelasyon + uyumluluk/telemetri. |
Not 1 —
localeresponse'u değiştirmez: Sunucu, requestlocale'i ne olursa olsun tam config'i (tümlocalizationblokları) döndürür. Dil çözümlemesi SDK tarafında yapılır (behavior.defaultLanguage+ kullanıcı tercihi +availableLanguages). Böylece response deterministik kalır ve SDK, dil değiştirdiğinde yeniden istek atmak zorunda kalmaz.Not 2 — Token yalnız header'dadır: Token gövde içine yazılmaz;
X-Consent-Tokenheader'ında taşınır (§3.2). Bu yüzden gövde küçük ve sade kalır.
4.1 Örnek İstek
{
"consentId": "ck_mobildev_0001",
"locale": "tr-TR",
"sdkVersion": "1.4.0"
}
Ayrıca header'da:
X-Consent-Token: cfg_t_8a3f5c2d1e0b. Bu örneğin aynısı ayrıca[01-config.request.json](./01-config.request.json)dosyasında yer alır.
5. Yanıt (response)
Response, diğer sözleşmelerle tutarlı bir envelope + içinde tam config taşır. HTTP 200 → başarılı; 4xx/5xx → ortak hata envelope'u.
5.1 Envelope Alanları (200)
| Alan | Tip | Açıklama |
|---|---|---|
success | boolean | true — config başarıyla getirildi. (Hatalarda false ortak envelope döner, bkz. §7.) |
code | string | Kod (başarıda OK). |
consentId | string | Çözülen consentId (eko; log + doğrulama). |
deliveredAt | string (ISO 8601 UTC) | Config'in sunucu tarafından servis edildiği an (audit/telemetri). |
contentVersion | string | Config'in içerik versiyonu. SDK bunu cihazdaki installedContentVersion'ıyla karşılaştırıp reprompt kararını hızla üretebilir. |
tokenConsumed | boolean | Bu çağrı token'ı tüketmiş midir? GET /config'de false (okuma token'ı bitirmez). SDK bu değere bakarak token'ın onay adımı için hâlâ geçerli olduğunu bilir (bkz. §6). |
config | object | TAM config gövdesi = §5.2'deki blok yapısı. |
5.2 config Gövdesi (üst düzey yapı)
config, uygulamanızın onay deneyiminin tamamını tanımlayan tek JSON'dır. Üst düzey bloklar:
| Blok | İçerik |
|---|---|
schemaVersion | "2.0" — SDK feature-gate. |
meta | consentId / organization / contentVersion / contentMode / generatedAt. |
behavior | defaultLanguage / availableLanguages / allowLanguageChange / showConsentId / promptATTdialog / displayATTStatus / retrigger{…}. |
theme | scheme + light/dark renk token'ları + typography + radius + spacing. |
banner | layout / logo / title / description / buttons.list[] (ilk onay ekranı). |
manager | title / showBack / groupRow / groups[] (her grupta consentKeys[] + items[]) / footer.actions[] (ana tercih ekranı). |
detail | showBack / sections / links[] / actions[] (öğe/grup detay ekranı). |
localization | tr-TR / en-US / de-DE — tüm metinlerin i18n anahtarları. |
Alt bloklarda öne çıkanlar:
manager.groups[]— izin kategorileri:essential/functionality/targeting/tracking. Her grupta:id,titleLangKey,descLangKey,isEssential,lockState,defaultState,consentKeys[](etiketlere karşılık gelen key listesi) veitems[](o gruptaki teknoloji/vendor satırları — bilgilendirme amaçlı, etiket key taşımaz).- Tema token'ları — Bileşenler renk hex değerini değil, token ismin referans verir (
primary,surface,onSurface…). Aynı token setilightvedarkbloklarında ayrı değerlerle tanımlanır → tek config ile açık+koyu mod. consentKeysgrup seviyesindedir —items[]yalnız teknoloji/amacı açıklar; onay durumu grubun kimliğinde taşır. Etiketlere dağıtım SDK tarafında yapılır (02 adımında, §6).
5.3 Örnek Yanıt (örnek config gövdesi — özet)
Aşağıda envelope + config'in ilk kısımları gösterilir. Üretimdeki config, gerçek markaya/müşteriye göre doldurulur; buradaki değerler örnek (placeholder) amaçlıdır.
{
"success": true,
"code": "OK",
"consentId": "ck_mobildev_0001",
"deliveredAt": "2026-09-20T11:33:30Z",
"contentVersion": "2",
"tokenConsumed": false,
"config": {
"schemaVersion": "2.0",
"meta": {
"consentId": "ck_mobildev_0001",
"organization": "Mobildev",
"contentVersion": "2",
"contentMode": "sample",
"generatedAt": "2026-09-18T10:20:00Z"
},
"behavior": {
"defaultLanguage": "tr-TR",
"availableLanguages": ["tr-TR", "en-US", "de-DE"],
"allowLanguageChange": true,
"showConsentId": false,
"promptATTdialog": true,
"displayATTStatus": false,
"retrigger": { "onConfigChange": true, "onMajorChange": true, "interval": null }
},
"theme": {
"scheme": "system",
"light": { "primary": "#1976D2", "onPrimary": "#FFFFFF", "surface": "#F6F8FB", "onSurface": "#1F2328" },
"dark": { "primary": "#8AB4F8", "onPrimary": "#0B2E5C", "surface": "#1B2027", "onSurface": "#E6E9EF" },
"typography": { "family": "system-ui, sans-serif", "title": { "size": 18, "weight": 700 }, "body": { "size": 14, "weight": 400 } },
"radius": 16,
"spacing": 20
},
"banner": {
"layout": { "type": "bottomSheet", "showDragHandle": true, "maxHeightPercent": 82 },
"logo": { "show": true, "src": "", "size": 46, "position": "center" },
"title": { "langKey": "banner_title" },
"description": { "langKey": "banner_description", "maxLines": 6, "format": "plain" },
"buttons": {
"direction": "vertical", "gap": 10, "height": 50, "stretch": true,
"list": [
{ "id": "accept_all", "style": "filled", "langKey": "banner_btn_accept_all", "colorToken": "primary" },
{ "id": "reject_all", "style": "outlined", "langKey": "banner_btn_reject_all", "colorToken": "primary" },
{ "id": "modify", "style": "text", "langKey": "banner_btn_modify", "colorToken": "primary" }
]
}
},
"manager": {
"title": { "langKey": "manager_title" },
"showBack": true,
"groupRow": { "showToggle": true, "showChevron": true, "showIcon": false },
"groups": [
{ "id": "essential", "lockState": true, "defaultState": "on",
"consentKeys": ["security_storage"],
"items": [ { "id": "session", "scope": "first_party" }, { "id": "fraud", "scope": "first_party" } ] },
{ "id": "functionality", "lockState": null, "defaultState": "off",
"consentKeys": ["personalization_storage", "functionality_storage"] },
{ "id": "targeting", "lockState": null, "defaultState": "off",
"consentKeys": ["ad_storage", "ad_user_data", "ad_personalization"] },
{ "id": "tracking", "lockState": null, "defaultState": "off",
"consentKeys": ["analytics_storage"] }
],
"footer": { "position": "sticky", "actions": [
{ "id": "accept_all", "style": "outlined", "langKey": "banner_btn_accept_all", "colorToken": "primary" },
{ "id": "save", "style": "filled", "langKey": "manager_btn_save", "colorToken": "primary" }
] }
},
"detail": { "showBack": true, "sections": { "showTechnology": true, "showPurpose": true, "showToggle": true }, "links": [], "actions": [ { "id": "save", "style": "filled", "langKey": "manager_btn_save", "colorToken": "primary" } ] },
"localization": { "tr-TR": { "…": "…" }, "en-US": { "…": "…" }, "de-DE": { "…": "…" } }
}
}
localizationbloğu, config'deki tümlangKeyalanlarına karşılık gelen metindir (banner, manager, gruplar, öğeler, runtime durum metinleri). Her dil bloğu aynı anahtar setine sahiptir;behavior.availableLanguages'indeki her dil için bir blok zorunludur. Eksik anahtar → SDKdefaultLanguage'ye fallback eder.Bu örneğin aynısı, envelope ve tam config gövdesiyle birlikte ayrıca
[01-config.response.json](./01-config.response.json)dosyasında yer alır. Not: bu.mdiçindelocalizationbloğu yer tasarrufu için özetlenmiş görünür;.jsondosyasında üç dilin tam metin setiyle geçer.
6. Token Yaşam Döngüsü (KRİTİK)
Token = imzalı, oturum bazlı bir kimlik (session credential). "Tek kullanımlık" ifadesi tek HTTP çağrısı değil, tek consent-oturumu anlamına gelir. Döngü, aynı token'ın hem bu adımda hem onay adımında kullanılmasını gerektirir.
| Özellik | Açıklama |
|---|---|
| Köken | AUTH (00), her başarılı çağrısında bir token üretir. Bir AUTH → bir token. |
| Bağlılık | Token belirli bir consentId'ye bağlıdır. Başka bir consentId ile kullanılamaz (→ INVALID_TOKEN). |
| Geçerlilik penceresi | tokenExpiresIn (sn; varsayılan 300 = 5 dk). Pencere dolunca token geçersiz olur (TOKEN_EXPIRED). |
| GET /config (bu adım, okuma) | Token'ı tüketmez. Config çekilir; token oturumda yaşamaya devam eder, tokenConsumed: false döner. Aynı pencerede yeniden denenebilir (retry güvenli). |
| POST /consent (02, yazma) | Başarılı onay kaydı, oturumu tamamlar → token'ı tüketir. Sonrası için token ölüdür. |
| Yaşam sonu | Pencere dolunca veya onay kaydı oturumu kapatınca token geçersizleşir → sonraki etkileşim yeni AUTH ile başlar. |
AUTH ──üretir──▶ TOKEN (consentId'ye bağlı, 300 sn)
│
┌───────────┴───────────┐
│ (okuma) │ (yazma)
▼ ▼
GET /config POST_CONSENT
token TÜKELENMEZ token TÜKETİLİR (oturum kapanır)
(retry serbest) ──────────────────────────▶
│ │
└──► pencere dolunca / oturum kapanınca ──► YENİ AUTH
Sonuç: AUTH'tan gelen token, bir consent oturumu boyunca hem config okuma (tüketmez) hem onay yazma (tüketir) için geçerlidir. Bu adımı başarıyla tamamladıktan sonra aynı token'la
02 · POST_CONSENT'e güvenle geçebilirsiniz. Token yalnızca gerçek durum değişikliği (onay kaydı) sonucunda veya süresi dolunca ömürden düşer.
7. Hata Kodları
Hatalarda ortak gövde döner: { success:false, code, message, retryable, requestId }. (message teşhis metnidir; UI'da gösterilmez — kullanıcıya gösterilecek metin localization bloklarından gelir, ör. error_state.)
GET /config bir token-bearer okuma olduğu için, AUTH'taki HMAC bağlı kodlar (SIGNATURE_MISMATCH, REPLAY_DETECTED…) bu sözleşmede yoktur. Yalnız token/consent kaynaklı kodlar:
code | HTTP | retryable | Açıklama / SDK müdahalesi |
|---|---|---|---|
OK | 200 | — | Config başarıyla getirildi. |
INVALID_TOKEN | 401 | Hayır | Token geçersiz/bilinmiyor, veya bağlı consentId ≠ path/gövde consentId → yeni AUTH (taze token). |
TOKEN_EXPIRED | 401 | Hayır | tokenExpiresIn dolmuş → yeni AUTH, ardından config'i yeniden çek. |
TOKEN_CONSUMED | 401 | Hayır | Token daha önce bir onay kaydı ile tüketilmiş → yeni AUTH. |
CONSENT_NOT_FOUND | 404 | Hayır | Bu consentId için yayımlanmış config yok → consentId doğrulanmalı; varsa bundled config fallback (§8). |
CONFIG_UNAVAILABLE | 503 | Evet | Config mevcut ama şu an servis edilemiyor → bundled config fallback, arka planda backoff ile dene. |
VALIDATION_ERROR | 400 | Hayır | Gövde şemayı karşılamıyor (örn. locale biçimi, zorunlu eksik alan) → detail[] alan hatalarını düzelt. |
RATE_LIMITED | 429 | Evet | Hız sınırı → Retry-After (sn) kadar bekle, yeniden dene. |
SERVER_ERROR | 500 | Evet | Sunucu iç hata → bundled config fallback, arka planda backoff ile dene. |
retryablesemantiği:false→ aynı istekle (aynı token) tekrar denemek işe yaramaz; yeni AUTH gerekir.true→ aynı istek (token hâlâ geçerliyse) daha sonra yeniden denenebilir.
8. Offline / Fallback Davranışı (KRİTİK)
Onay deneyimi sessizce bozulmamalı. Config getirilemese bile kullanıcı onay akışını yaşar.
| Senaryo | SDK davranışı |
|---|---|
INVALID_TOKEN / TOKEN_EXPIRED / TOKEN_CONSUMED | Yeni AUTH başlat → taze al → config'i yeniden çek. (Eski bir token ile retry boşuna 401 üretir.) |
SERVER_ERROR / CONFIG_UNAVAILABLE / RATE_LIMITED / timeout (15 sn) | Bundled (SDK'ya dahil) config ile devam et; arka planda exponential backoff ile sunucuyu dene. Bağlantı gelince + taze token ile config yenile. |
| Hiç önbellek yok ve çevrimdışı (ilk kurulum) | Bundled varsayılan config ile onay akışı çalışır; kullanıcı boş ekranda bırakılmaz. |
CONSENT_NOT_FOUND | consentId geçersiz/yayınlanmamış → bundled config varsa onunla devam, yoksa onay UI'ı zarifçe devre dışı (uygulama normal akışına döner). |
Kural: Hiçbir hatada onay deneyimi "boş ekran" veya "kilitlenmiş durum" üretmez. Okuma retry'ye toleranslı olduğu için backoff sınırlıdır; sonsuz döngü üretilmez.
9. Developer Notları
- GET /config = OKUMA yolu; yalnız bearer token (HMAC/nonce yok). Sunucu token'ı
X-Consent-Tokenheader'ından doğrular; replay koruması token'ın consentId-bağlılığı +tokenExpiresInpenceresi + oturum tüketimi ile sağlanır. SDK, ağ kesintisinden sonra güvenle retry yapabilir. (Yazma yolu olan POST_CONSENT ise HMAC+nonce ister.) - Token = oturum kimliği (one per AUTH), tek HTTP çağrısı DEĞİL. Bu adım tamamlanınca
tokenConsumed: falsedöner → aynı token ile POST_CONSENT'e güvenle geçilir. - Response
configalanı = tam config. SDK parse eder:behavior(dil/ATT/retrigger),theme,banner,manager.groups[](+consentKeys[]+items[]),detail,localization. Config değişikliğinde örnek de güncellenir. - Sunucu tüm dilleri döndürür; dil çözümlemesi SDK'da. Request
locale'i response'u daraltmaz; SDKbehavior.defaultLanguage+ kullanıcı tercihi +availableLanguagesile aktif dili seçer. Dil değiştirmek yeniden istek atmayı gerektirmez. - Akışı sırala: AUTH (token al) →
updateRequiredise bu adım (tam config, parse → UI kur) → kullanıcı karar verirse POST_CONSENT (aynı token ile) → responselocalState'ı önbelleğe yaz → döngü kapalı. consentKeysgrup seviyesindedir; etiket dağıtımı SDK'dadır. Config'dekigroups[].consentKeysve onay adımının döndürdüğü{[groupId]: state}haritası, SDK tarafında etiket key'lerine yayılır (02 adımında). Sunucu config'i ham olarak döndürür; çevirimi SDK sorumluluğudur.- Çapraz-doğrulama: Sunucu path
{consentId}↔ gövdeconsentId↔ token'ın bağlı consentId üçlüsünü karşılaştırır; uyumsuzluk401 INVALID_TOKENdöndürür. SDK üçünü de AUTH çıktısından/istekten doğru üretmelidir.