Ana içeriğe geç

01 · GET /config — Config Çekme Sözleşmesi

Görev: 00 · AUTH'un döndürdüğü token ile 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 === true olduğ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'da X-Consent-Token (+ gövdede opsiyonel locale/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 === false ise 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ımKoşulSDK davranışı
00 — AUTHHer açılıştaKimlik + localState gönder; versiyon + token + decision al
01 — GET /config (bu adım)decision.updateRequired === trueToken ile tam config indir, parsel et, önbelleğe yaz, UI'ı yeniden kur
02 — POST_CONSENTKullanıcı onay ekranında karar verirseAynı 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​

ÖzellikDeğer
MethodPOST
Path/v2/consent/{consentId}/config
Base URL{{SDK_BASE_URL}}
Gövde formatıapplication/json (UTF-8)
Timeout15 sn
IdempotentEvet — okuma işlemidir; aynı istek tekrarlandığında aynı config'i döndürür (retry güvenli).

Neden POST (REST GET değil)? İki neden: (1) SDK'nın üç sözleşmesi tutarlı biçimde POST'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. POST bunu 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:

HeaderDeğer / Açıklama
Content-Typeapplication/json
X-Consent-TokenAUTH 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övde consentId mi? → her ihlal ilgili 401/404 kodu.
  • 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 /consent bir YAZMA işlemidir → durumu değiştirir, mükerrer yazma riski taşır → bu yüzden HMAC + nonce + timestamp zorunludur. GET /config bir 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.

AlanTipZorunluAçıklama
consentIdstringEvetOnay 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.
localestring (BCP-47)HayırKullanı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.
sdkVersionstring (semver)HayırSDK sürümü. AUTH çağrısıyla korelasyon + uyumluluk/telemetri.

Not 1 — locale response'u değiştirmez: Sunucu, request locale'i ne olursa olsun tam config'i (tüm localization blokları) 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-Token header'ı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)​

AlanTipAçıklama
successbooleantrue — config başarıyla getirildi. (Hatalarda false ortak envelope döner, bkz. §7.)
codestringKod (başarıda OK).
consentIdstringÇözülen consentId (eko; log + doğrulama).
deliveredAtstring (ISO 8601 UTC)Config'in sunucu tarafından servis edildiği an (audit/telemetri).
contentVersionstringConfig'in içerik versiyonu. SDK bunu cihazdaki installedContentVersion'ıyla karşılaştırıp reprompt kararını hızla üretebilir.
tokenConsumedbooleanBu ç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).
configobjectTAM 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.
metaconsentId / organization / contentVersion / contentMode / generatedAt.
behaviordefaultLanguage / availableLanguages / allowLanguageChange / showConsentId / promptATTdialog / displayATTStatus / retrigger{…}.
themescheme + light/dark renk token'ları + typography + radius + spacing.
bannerlayout / logo / title / description / buttons.list[] (ilk onay ekranı).
managertitle / showBack / groupRow / groups[] (her grupta consentKeys[] + items[]) / footer.actions[] (ana tercih ekranı).
detailshowBack / sections / links[] / actions[] (öğe/grup detay ekranı).
localizationtr-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) ve items[] (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 seti light ve dark bloklarında ayrı değerlerle tanımlanır → tek config ile açık+koyu mod.
  • consentKeys grup 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": { "…": "…" } }
}
}

localization bloğu, config'deki tüm langKey alanları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 → SDK defaultLanguage'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 .md içinde localization bloğu yer tasarrufu için özetlenmiş görünür; .json dosyası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.

ÖzellikAçıklama
KökenAUTH (00), her başarılı çağrısında bir token üretir. Bir AUTH → bir token.
BağlılıkToken belirli bir consentId'ye bağlıdır. Başka bir consentId ile kullanılamaz (→ INVALID_TOKEN).
Geçerlilik penceresitokenExpiresIn (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 sonuPencere 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:

codeHTTPretryableAçıklama / SDK müdahalesi
OK200—Config başarıyla getirildi.
INVALID_TOKEN401HayırToken geçersiz/bilinmiyor, veya bağlı consentId ≠ path/gövde consentId → yeni AUTH (taze token).
TOKEN_EXPIRED401HayırtokenExpiresIn dolmuş → yeni AUTH, ardından config'i yeniden çek.
TOKEN_CONSUMED401HayırToken daha önce bir onay kaydı ile tüketilmiş → yeni AUTH.
CONSENT_NOT_FOUND404HayırBu consentId için yayımlanmış config yok → consentId doğrulanmalı; varsa bundled config fallback (§8).
CONFIG_UNAVAILABLE503EvetConfig mevcut ama şu an servis edilemiyor → bundled config fallback, arka planda backoff ile dene.
VALIDATION_ERROR400HayırGövde şemayı karşılamıyor (örn. locale biçimi, zorunlu eksik alan) → detail[] alan hatalarını düzelt.
RATE_LIMITED429EvetHız sınırı → Retry-After (sn) kadar bekle, yeniden dene.
SERVER_ERROR500EvetSunucu iç hata → bundled config fallback, arka planda backoff ile dene.

retryable semantiğ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.

SenaryoSDK davranışı
INVALID_TOKEN / TOKEN_EXPIRED / TOKEN_CONSUMEDYeni 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_FOUNDconsentId 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ı​

  1. GET /config = OKUMA yolu; yalnız bearer token (HMAC/nonce yok). Sunucu token'ı X-Consent-Token header'ından doğrular; replay koruması token'ın consentId-bağlılığı + tokenExpiresIn penceresi + oturum tüketimi ile sağlanır. SDK, ağ kesintisinden sonra güvenle retry yapabilir. (Yazma yolu olan POST_CONSENT ise HMAC+nonce ister.)
  2. Token = oturum kimliği (one per AUTH), tek HTTP çağrısı DEĞİL. Bu adım tamamlanınca tokenConsumed: false döner → aynı token ile POST_CONSENT'e güvenle geçilir.
  3. Response config alanı = 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.
  4. Sunucu tüm dilleri döndürür; dil çözümlemesi SDK'da. Request locale'i response'u daraltmaz; SDK behavior.defaultLanguage + kullanıcı tercihi + availableLanguages ile aktif dili seçer. Dil değiştirmek yeniden istek atmayı gerektirmez.
  5. Akışı sırala: AUTH (token al) → updateRequired ise bu adım (tam config, parse → UI kur) → kullanıcı karar verirse POST_CONSENT (aynı token ile) → response localState'ı önbelleğe yaz → döngü kapalı.
  6. consentKeys grup seviyesindedir; etiket dağıtımı SDK'dadır. Config'deki groups[].consentKeys ve 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.
  7. Çapraz-doğrulama: Sunucu path {consentId} ↔ gövde consentId ↔ token'ın bağlı consentId üçlüsünü karşılaştırır; uyumsuzluk 401 INVALID_TOKEN döndürür. SDK üçünü de AUTH çıktısından/istekten doğru üretmelidir.

Bu doküman size yardımcı oldu mu?

Değerlendirmeniz, dokümanı geliştirmemize yardımcı olur.

Değerlendirme yapmak için giriş yapmalısınız.

Destek soruları ve yorumlar

Bu dokümanla ilgili soru sorabilir veya deneyiminizi paylaşabilirsiniz.