> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Tercih Merkezi: herkese açık opt-in/opt-out sayfası

> Barındırılmış, token-imzalı tercih merkezini yapılandırın — markalama, kanallar, sıklık seçenekleri ve GDPR-silme düğmesi — kişi başına bağlantı oluşturun ve bir opt-out'un tam olarak hangi uyum yüzeylerini yazdığını öğrenin (onay, bastırma, STOP koruması, denetim).

# Tercih Merkezi: herkese açık opt-in/opt-out sayfası

**Tercih merkezi**, bir kişinin kendi kanal opt-in'lerini, abonelik konularını, mesaj sıklığını ve (etkinleştirdiyseniz) veri silme isteğini yönettiği herkese açık bir sayfadır — hesap yok, giriş yok. Her kişi **imzalı bir bağlantı** ile ulaşır: URL, 30 gün sonra süresi dolan bir HMAC-SHA256 token'ı (`v1.<payload>.<signature>`) taşıdığından sayfa kişiye özel ve kendi kendine hizmet verir.

Özetlenmiş uç nokta yüzeyi ayrıca [Gönderi Kapıları](/compliance/send-gates#preference-center) içinde yaşar; bu rehber tam kılavuzdur: her yapılandırma alanı, bağlantının nereye konulacağı, herkese açık sayfanın API'sinin ne döndürdüğü ve bir opt-out veya opt-in'in hangi uyum yüzeylerini yazdığı.

Aşağıdaki tüm uç noktalar `https://api.orbit.devotel.io/api/v1/compliance` köklüdür.

> İngilizce asıl: [Preference center: the public opt-in/opt-out page](/guides/preference-center-opt-out-page).

<Note>
  Tercih merkezi bir **kiracıya ait kontroldür**: kanalları, konuları ve markalamayı siz seçersiniz ve onay kanıtı organizasyonunuz içinde durur. Orbit platformu işletir; onay kararı kişiye aittir. Bu rehber hukuki tavsiye değildir — yükümlülüklerinizi avukatınızla teyit edin.
</Note>

***

## 1. Bir kez yapılandırın: POST/GET /preference-center

`POST /preference-center` ile yapılandırmayı ayarlayın (sahip/yönetici API anahtarı). Uç nokta yapılandırmayı organizasyonunuzun ayarlarına upsert eder ve kaydedilmiş nesneyi döndürür — güncellemek için yeniden çalıştırın. `GET /preference-center` geçerli yapılandırmayı okur; yapılandırma öncesi `enabled: false` ile bir ipucu mesajı döndürür.

### Yapılandırma alanları

Her alan sunucu tarafında doğrulanır — reddedilen POST, hangi alanın başarısız olduğunu söylemek için alan başına sorunlarla (`field`, `message`) `422` döndürür.

| Alan                   | Tür             | Varsayılan                                   | Ne kontrol eder                                                                                       |
| ---------------------- | --------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `enabled`              | boolean         | `true`                                       | Ana anahtar. `false` olduğunda, herkese açık sayfa kişiye "mevcut değil" döndürür.                    |
| `companyName`          | string (1–200)  | **gerekli**                                  | Barındırılmış sayfada görüntülenen şirket adı.                                                        |
| `logoUrl`              | string (URL)    | —                                            | Sayfa tarafından alınan logo. URL'ler `http://` veya `https://` ile sınırlıdır.                       |
| `primaryColor`         | hex `#rrggbb`   | `#2563eb`                                    | Sayfa kullanıcı arayüzünün vurgu rengi.                                                               |
| `headerText`           | string (≤500)   | `"Communication Preferences"`                | Sayfa başlığı.                                                                                        |
| `footerText`           | string (≤1000)  | `"İletişim tercihlerinize saygı duyuyoruz."` | Sayfa altbilgi metni.                                                                                 |
| `optOutMessage`        | string (≤500)   | `"Tercihlerinizi yönetin"`                   | Bağlantı giden mesajlara otomatik eklendiğinde kullanılan altbilgi etiketi.                           |
| `channels`             | enum array (≥1) | `["sms","email"]`                            | Sayfada sunulan kanallar. İzin verilen değerler: `sms`, `whatsapp`, `email`, `rcs`, `viber`, `voice`. |
| `showFrequencyOptions` | boolean         | `true`                                       | Sıklık seçiciyi gösterir (`all`, `important_only`, `weekly_digest`, `monthly_digest`).                |
| `showGdprDelete`       | boolean         | `true`                                       | Veri silme düğmesini gösterir (bölüm 6'yı görün).                                                     |
| `customCss`            | string (≤10000) | —                                            | Barındırılmış sayfaya enjekte edilen ek CSS.                                                          |
| `redirectUrl`          | string (URL)    | —                                            | Bir opt-out tamamlandıktan sonra kişinin nereye yönlendirileceği. Yalnızca `http(s)` şemaları.        |
| `topics`               | array (≤50)     | `[]`                                         | Bir kişinin kanal anahtarından bağımsız olarak açtığı abonelik grupları (aşağıya bakın).              |

### Abonelik konuları

Bir konu bir adlandırılmış gruptur — Bülten, Ürün Güncellemeleri, Faturalandırma Uyarıları — kişi **tüm kanalı** devre dışı bırakmadan açıp kapatır. Konu `id`'leri benzersiz olmalı ve slug kalıbıyla eşleşmelidir (`[a-z0-9][a-z0-9_-]{0,63}`); her giriş şunlara sahiptir:

* `name` (1–120 karakter) — sayfada görüntülenen ad.
* `description` (isteğe bağlı, ≤500) — düğmenin yanında gösterilen bir satır bağlam.
* `defaultOptIn` (varsayılan `false`) — kaydedilmiş tercih olmayan bir kişinin nasıl değerlendirildiği.
* `archived` (isteğe bağlı) — arşivlenmiş konular denetim izinde kalır ama artık sayfada görüntülenmez.

Lint düzeyi terslikler: `http(s)`-şeması iyileştirmesinde başarısız URL'ler önden reddedilir ve yinelenen konu `id`'leri "Konu id'leri benzersiz olmalıdır" diye başarısız olur, sessiz üzerine yazma yerine.

***

## 2. Kişi başına bağlantı oluşturun

Yapılandırıldıktan sonra, `POST /preference-center/link` ile tek seferde bir kişi için bağlantı oluşturun:

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/compliance/preference-center/link" \
  -H "Authorization: Bearer $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "contactId": "cnt_01H…" }'
```

Yanıt `link` döndürür — `${DEVOTEL_WEB_URL}/preferences?token=v1…` formunda bir URL. Dikkat edilmesi gereken noktalar:

* **Bağlantı barındırılmış sayfaya, JSON uç noktasına değil.** Bunu alt bilgi/gönderici şablonlarınıza harfiyen kopyalayın; sayfa kendisi veri uç noktasını arka planda çağırır.
* **30 günlük TTL.** Sonrasında token süresi dolmuş olarak doğrulanır ve kişi yeni bir bağlantı istemek zorunda kalır (yenisini oluşturmak bir API çağrısı alır).
* **Sayfa oluşturma zamanında yerel ayar bilmez.** Web uygulaması `?token=` sorgusunu korurken bir yönlendirmeyi çözer, böylece kişinin yerel ayarını tahmin etmeniz gerekmez.

### Nereye konulacağı

* **E-posta altbilgisi (birincil).** Oluşturulan bağlantıyı (veya postacınızın kullandığı kısa izlenen varyantı) pazarlama şablonlarının abonelikten çıkma alanına ekleyin.
* **SMS / WhatsApp yedeği.** Mesajda altbilgi bloğu yoksa, bağlantıyı satır içi ekleyin: `{optOutMessage}: {link}`. Giden gövdeleri oluşturan yardımcı, önceden oluşturulmuş bir kısa bağlantıyı kabul eder, böylece abonelikten çıkma tıklamanız normal tıklama atıbarını almaya devam eder.
* **Bastırma-taraflı yeniden-opt-in.** Bir kişi başka bir akıştan yeniden-opt-in olduğunda, ona yeni bir bağlantı verebilirsiniz, böylece aynı self-servis sayfayı alır.

Kısa bağlantı oluşturma başarısız olursa ham bağlantı yine de çalışır — yedek eklemeli, uyum için hiçbir zaman yük taşıyıcı değildir.

***

## 3. Herkese açık token sayfası

Barındırılmış sayfa, imzalı token tarafından kapılanan kimliği açık olmayan iki uç nokta üzerinden okur ve yazar:

* `GET /preferences/:token` — sayfa yükünü döndürür.
* `PUT /preferences/:token` — güncellemeler uygular.

Geçersiz token biçimleri `400 INVALID_TOKEN` döndürür; süresi dolmuş veya bozuk tokenler "Lütfen yeni bir link isteyin." ile `401 TOKEN_EXPIRED` döndürür.

### GET yanıtı

Yük, kişinin geçerli durumunu ve organizasyonun yapılandırmasını birleştirir:

```json theme={null}
{
  "contactId": "cnt_01H…",
  "displayName": "…",
  "email": "m*****@example.com",
  "phone": "+15551****…",
  "channelPreferences": { "sms": "opted_in", "email": "opted_out" },
  "frequencyPreference": "all",
  "channels": ["sms", "email"],
  "topics": [ { "id": "newsletter", "name": "Newsletter", "defaultOptIn": false } ],
  "topicPreferences": { "newsletter": "opted_in" },
  "consentHistory": [
    { "channel": "all", "state": "opted_out", "topicId": "newsletter", "occurredAt": "2026-09-01T…" }
  ],
  "config": { /* organizasyonun tercih merkezi yapılandırması */ }
}
```

E-posta ve telefon, herkese açık yanıtta **maskelenmiştir** — sayfa, çağrılan ham tanımlayıcıyı asla göstermez. `consentHistory` kişinin en yeni-önce opt-in/opt-out denetim izindendir, 20 satıra kadar sınırlı, operatörlerinizin kontrol panelinde gördüğü aynı onay defterinden çekilir.

### PUT isteği gövdesi

```json theme={null}
{
  "channelPreferences": {
    "sms": "opted_in",
    "email": "opted_out"
  },
  "frequencyPreference": "important_only",
  "topicPreferences": { "newsletter": "opted_in" },
  "requestDataDeletion": false
}
```

* `channelPreferences` — kısmi haritaya izin verilir (Zod kısmi-kayıt); **en az bir kanal gerekli**.
* `frequencyPreference` — isteğe bağlı, `all`, `important_only`, `weekly_digest`, `monthly_digest` biri.
* `topicPreferences` — yapılandırılan konularınıza karşı doğrulanan `{ topicId: opted_in | opted_out }` haritası; bilinmeyen id'ler yoksayılır.
* `requestDataDeletion` — opt-out yanında bir GDPR-silme isteği ayarlar (bölüm 6'yı görün).

Bir 422 yanıtı, barındırılmış formun geçersiz seçimi işaret etmesi için alan başına sorunları taşır.

***

## 4. Güncellemeler nasıl akar

Burada yazılan bir opt-in/opt-out **yalnızca bir kullanıcı arayüzü bayrağı değildir** — bir STOP anahtar kelimesinin yazdığı dört uyum yüzeyinin aynısı güncellenir:

* **Onay defteri.** Kanal (veya konu) başına bir `consent_records` satırı `source: preference_center` ile eklenir — GDPR Madde 7 ispat yükü denetim izininiz.
* **Bastırma listesi.** Herhangi bir opt-out edilen kanalda, kişinin kanonikleştirilmiş telefon/e-postası `all` kapsamıyla eklenir — her send kapısının okuduğu kanallar arası blok.
* **STOP koruması.** Opt-out üzerinde bir Redis hızlı-yol koruması ayarlanır (ve tam yeniden-opt-in üzerinde temizlenir), böylece havada olan kampanya yığınları daha yavaş veritabanı bastırma yayılımından önce değişikliği görür.
* **Denetim günlüğü.** Yapılandırmayı değiştirdiğinizde `compliance.preference_center_updated` kaydedilir ve kişi düzeyi opt-in/out olayları onay defterine yakalanır.

Yeniden-opt-in simetriktir: tam bir opt-in (her kanal `opted_in`) kişinin telefonu için etkin bastırma satırlarını iptal eder ve STOP korumasını temizler, onay defteri ters kaydı alır.

<Note>
  **Konu vs. kanal.** Kanal düzeyi bir opt-out her zaman kazanır — bir konu düğmesi, kişinin hâlâ kabul ettiği kanallar *içinde* onayı daraltır. PUT içinde bilinmeyen konu id'leri kalıcı olmak yerine yoksayılır, bu yüzden eski bir form rasgele öznitelik anahtarları yazamaz.
</Note>

***

## 5. GDPR-silme düğmesi anlambilimi

`showGdprDelete` etkin olduğunda ve kişi PUT içinde `requestDataDeletion: true` seçtiğinde, API **eski bir GDPR silme isteği** kaydeder — veri silme süreciniz için işaretlenmiş `pending` bir satır — opt-out yanında. Bu işaret kasıtlıdır: tercih merkezi silme düğmesi kişiyi işaretler, **takip edilen DSAR hattını başlatmaz**.

<Warning>
  Tercih merkezi silme düğmesinin **SLA saati, şifrelenmiş veri dışa aktarması ve Madde 17 silme sertifikası yoktur.** DPO'nuzun takip edebileceği bir silme hakkı isteği için bunu DSAR uç noktasına kaydırın (`POST /compliance/dsar`, sahip/yönetici) — bkz. [Veri Sahibi Erişim İstekleri](/compliance/dsar) ve [DSAR + ihlal kaydı rehberi](/guides/compliance-dsar-breach-register).
</Warning>

***

## 6. Test etmek

Bir duman betiğinize yapıştırabileceğiniz işlenmiş iki curl örneği:

**Yapılandırmayı kaydet:**

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/compliance/preference-center" \
  -H "Authorization: Bearer $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "companyName": "Acme Logistics",
    "primaryColor": "#1d4ed8",
    "channels": ["sms", "email"],
    "headerText": "Manage how Acme contacts you",
    "topics": [
      { "id": "shipping-updates", "name": "Shipping updates", "defaultOptIn": true },
      { "id": "promotions", "name": "Promotions", "defaultOptIn": false }
    ]
  }'
```

Beklenen: `201` ve kaydedilen yapılandımasın yansıması.

**Bağlantı oluştur ve herkese açık uç noktaları çalıştır:**

```bash theme={null}
LINK=$(curl -s -X POST "https://api.orbit.devotel.io/api/v1/compliance/preference-center/link" \
  -H "Authorization: Bearer $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"contactId":"cnt_01H…"}' | jq -r '.link')

TOKEN="${LINK#*token=}"

curl -s "https://api.orbit.devotel.io/api/v1/compliance/preferences/$TOKEN" | jq

curl -s -X PUT "https://api.orbit.devotel.io/api/v1/compliance/preferences/$TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"channelPreferences":{"sms":"opted_out"}}' | jq
```

Beklenen: GET kişinin geçerli tercihlerini döndürür; PUT `updated: true` artı uygulanan tercihleri döndürür ve istendiğinde bir `gdprRequest` girişi.

Kontrol edilecek yaygın hatalar: `400 INVALID_TOKEN` (bozuk token), `401 TOKEN_EXPIRED` (TTL geçti veya imza uyumsuzluğu — yeni bir bağlantı oluşturun), `422 VALIDATION_ERROR` (yapılandırma veya güncelleme gövdesinde alan düzeyi sorunlar) ve `404 NOT_FOUND` tercih merkezi kapalı olduğunda veya kişi id'si mevcut olmadığında.

***

## İlgili

* [Gönderi kapıları ve gönderi öncesi koruyucular](/compliance/send-gates) — tercih merkezi özetinin sessiz saatler, acil durum durakları ve sınırlarla birlikte yaşadığı yer.
* [Opt-Out & Bastırma Listeleri](/compliance/opt-out-suppression) — `all` kapsamının ve toplu CSV içe aktarmalarının bu yüzeyle nasıl ilişkili olduğu.
* [Onay yönetimi](/compliance/consent-management) — aynı onay defterini saklayan operatör tarafı API.
* [DSAR referansı](/compliance/dsar) — `requestDataDeletion` isteklerini yönlendirmek için takip edilen silme hattı.
