
# Özel CSS'i yaz

`PUT /v1/branding/css` · izin `branding:write`

Ortam taslağının özel CSS'ini yazar (Startup ya da üstü plan, `branding_custom_css` özelliği). CSS beyaz liste arındırıcısından geçer: yalnız `ui_catalog` sınıfları (`idp-*`), izinli özellikler ve değerler; korumalı katman (yasal metin, onay ve erişilebilirlik öğeleri) gizlenemez ya da örtülemez. Hepsi ya da hiç: tek bir ihlal varsa hiçbir şey yazılmaz. Taslağa gönderdiğiniz metin değil, arındırıcının kanonik çıktısı yazılır; yanıttaki `css` bu çıktıdır. Boş dize temizler ve plan kapısına takılmaz.

## İstek

| Alan | Tür | Zorunlu | Açıklama |
|---|---|---|---|
| `If-Match` | başlık | evet | Taslağın son okunan `ETag` değeri (hiç yazılmadıysa `"0"`). Yoksa `428`, eskiyse `412`. |
| `css` | dize | evet | En çok 51200 bayt, geçerli UTF-8; `""` temizler. |

## Yanıt

`200 OK`; ortam taslağı ve `ETag` başlığı. `theme` yalnız ayarlı jetonları taşır; ayarsız jetonlar platform varsayılanından gelir.

```json
{
  "theme": {"mode": "light", "light": {"color": {"primary": "#0a3d91"}}, "logo_height": 40},
  "css": ".idp-c .idp-title{color:#0a3d91}\n",
  "page_template": null,
  "updated_at": "2026-10-05T09:30:00.123456Z"
}
```

## Hatalar

| HTTP | code | Ne zaman |
|---|---|---|
| 400 | `unknown_field` | Gövdede bilinmeyen alan var ya da gövde JSON nesnesi değil. |
| 403 | `plan_feature_unavailable` | Plan bu özelliği içermiyor (`plan_feature_unavailable`, `feature` ve `required_plan` uzantıları). Geliştirme ortamları kapıya takılmaz. |
| 412 | `precondition_failed` | `If-Match` taslağın güncel sürümüyle eşleşmiyor. |
| 422 | `validation_failed` | `css` yok ya da `null` (`required`), çok uzun (`too_long`) ya da geçersiz UTF-8 (`invalid_utf8`). |
| 422 | `branding_validation_failed` | CSS arındırıcıdan geçmedi. `violations` uzantısı bütün ihlalleri listeler: `line`, `column` (1 tabanlı), `rule` (ör. `class_not_in_catalog`, `protected_property`, `property_not_allowed`, `syntax_error`) ve varsa `name` (özellik, sınıf ya da fonksiyon adı). CSS değeri yanıtta yer almaz. 100 ihlalden sonra arındırıcı durur; son öğe `too_many_issues` kuralıdır. Kanonik çıktı girdiden uzundur (her kurala kapsam öneki eklenir); 51200 baytı aşarsa tek ihlal satır 1, sütun 1'de `too_large` kuralıdır. |
| 428 | `precondition_required` | `If-Match` başlığı yok. |
| 401 | `unauthenticated` | Kimlik bilgisi yok, geçersiz ya da iptal edilmiş. |
| 403 | `insufficient_permissions` | Kimlik bilgisinde gerekli izin yok. |
| 429 | `rate_limited` | Hız sınırı aşıldı; `Retry-After` süresinden sonra yeniden deneyin. |
| 503 | `service_unavailable` | Bir bağımlılık geçici olarak kullanılamıyor; `Retry-After` süresinden sonra yeniden deneyin. |

Arındırıcı reddi örneği:

```css
.idp-button{position:fixed}
.my-banner{color:red}
```

```json
{
  "type": "https://docs.keenauth.com/errors/branding_validation_failed",
  "title": "Branding validation failed",
  "status": 422,
  "code": "branding_validation_failed",
  "violations": [
    {"line": 1, "column": 13, "rule": "property_not_allowed", "name": "position"},
    {"line": 2, "column": 1, "rule": "class_not_in_catalog", "name": "my-banner"}
  ],
  "request_id": "req_01J9Z3N5W8Q2F6V4K7T1M0XB3C"
}
```

## Örnek

```bash
curl -X PUT https://api.eu.keenauth.com/v1/branding/css \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H 'If-Match: "3"' \
  -d '{"css":".idp-title { color: #0a3d91 }"}'
```
