# Hata kodları

> Endpoint'lerin döndürdüğü hata kodları ve anlamları.

Kaynak: /tr/reference/errors/

Tüm hatalar aynı biçimdeki body ile döner:

```json
{ "error": "refused", "detail": "origin_unverified: www.markaniz.com" }
```

`error` hatanın türünü, `detail` ayrıntısını belirtir; ikisi de koddur. Bazı ayrıntılar iki nokta üst üsteden sonra bir değer içerir (`field_missing: customer_email`). Kodları ziyaretçiye olduğu gibi göstermeyin; kendi çeviri dosyalarınızdaki bir metne dönüştürün.

## Genel

| Durum | Kod | Anlamı |
|---|---|---|
| 400 | `invalid / <alan>` | Alan eksik ya da geçersiz. Ayrıntı ilgili alanı belirtir: `<alan>_required`, `<alan>_too_long`, `<alan>_out_of_range`. |
| 400 | `invalid_json` | Body okunamadı ya da body'deki bir metin saklanamayan bir karakter içeriyor (NUL `\u0000` ya da eşi olmayan vekil karakter) |
| 400 | `invalid / invalid` | Sorgu parametrelerinden birinde saklanamayan bir karakter var (NUL ya da eşi olmayan vekil karakter) |
| 401 | | Admin API'de kimlik bilgisi yok ya da anahtar geçersiz; yorum yazma akışında token yok (`token_required`); Ingest API'de sunucu anahtarı geçersiz (`refused`) ya da imza geçersiz (`signature_refused`) |
| 403 | `refused / …` | İstek tanındı ancak izin verilmedi; ayrıntılar aşağıda |
| 404 | `not_found` | Kayıt bulunamadı ya da başka bir markaya ait |
| 405 | `method_not_allowed` | HTTP metodu desteklenmiyor; `Allow` header'ına bakın |
| 429 | `rate_limited` | Rate limit aşıldı; değerler için: [Limitler](/tr/reference/limits.md) |

## Kimlik doğrulama ve anahtarlar

| Kod | Anlamı |
|---|---|
| `origin_missing` | İstek bir alan adı içermiyor (`Origin` ve `Referer` header'ları yok) |
| `origin_unverified: <alan adı>` | Alan adı doğrulanmamış; değer, isteğin `Origin` (yoksa `Referer`) header'ındaki alan adıdır |
| `unknown_site_key` | Site anahtarı tanınmıyor |
| `revoked_site_key` | Site anahtarı iptal edilmiş |
| `channel_inactive` | Kanal kapalı |
| `unknown_key`, `malformed_key` | Sunucu anahtarı tanınmıyor ya da biçimi hatalı |
| `revoked_key` | Sunucu anahtarı iptal edilmiş |
| `tenant_inactive` | Anahtarın ait olduğu markanın hizmeti dondurulmuş ya da kapatılmış (dondurulmuş markada yorum okuma ve SSR istekleri çalışmaya devam eder) |
| `scope_missing` | Anahtarın bu işlem için izni yok |
| `unknown_channel` | Kanal kodu yanlış ya da kanal kapalı |
| `server_only` | Bu endpoint yalnızca sunucu anahtarıyla kullanılabilir |

## Yorum listesi ve SSR

| Kod | Anlamı |
|---|---|
| `invalid / product` | Ürün kodu yok ya da 128 karakterden uzun |
| `sort_not_allowed` | Sıralama pazarın izinli listesinde değil |
| `invalid / rating` | Puan 1–5 dışında |
| `invalid / q_too_long`, `topic_too_long`, `topic` | Arama ifadesi ya da konu kelimesi geçersiz |
| `invalid / style`, `style_too_long` | SSR isteğindeki düzen `cards` ya da `sidebar` değil |
| `invalid / theme`, `theme_too_long` | SSR isteğindeki tasarım `warm`, `trust`, `editorial`, `minimal`, `soft`, `bold`, `natural` ya da `night` değil |
| `refused / no_site_key` | Kanalın kullanımda site anahtarı yok ve kanalın yöntem beyanı için kendi sayfanız bağlı değil |

## Oturum açmış müşteri

`GET /v1/viewer` ve `GET /v1/viewer/order` isteklerinin kodları. Bu endpoint'lere tarayıcıdan istek gönderilirse `403 refused / server_only` döner.

| Kod | Anlamı |
|---|---|
| `invalid / customer` | `X-Sayproof-Customer` header'ı yok, `@` içermiyor ya da 254 karakterden uzun |
| `invalid / order`, `order_too_long` | Sipariş detayı sorgusunda sipariş numarası yok ya da 128 karakterden uzun |

## Yorum yazma akışı

Bu kodlar için ziyaretçiye gösterilecek metni script belirler; headless kullanımda da bu kodlarla karşılaşmazsınız.

| Kod | Anlamı |
|---|---|
| `token_required` | Yazma token'ı gönderilmedi |
| `token_refused / token_unknown`, `token_expired`, `token_spent`, `token_wrong_kind`, `token_foreign_tenant` | Token tanınmıyor, süresi dolmuş, daha önce kullanılmış, türü yanlış ya da başka bir markaya ait |
| `token_refused / line_already_written` | Bu sipariş satırı için daha önce yorum yazılmış |
| `token_refused / line_out_of_scope` | Sipariş satırı bu token'ın kapsamında değil |
| `token_refused / token_foreign_market` | Bağlantı, siparişin pazarından farklı bir pazarın kanalına ait sitede açıldı |
| `invalid / rating_out_of_range` | Puan geçersiz |
| `invalid / title_too_long: 200`, `body_too_long: 5000`, `author_too_long: 120` | Metin izin verilen uzunluğu aşıyor |
| `invalid / aspect_unknown`, `aspect_out_of_range`, `aspect_required` | Değerlendirme başlığı geçersiz ya da zorunlu bir başlık boş bırakılmış |
| `invalid / too_many_reviews` | Tek istekte 20'den fazla ürün gönderildi |
| `invalid / too_many_items: 6` | Yoruma 6'dan fazla fotoğraf ya da video eklendi |
| `invalid / media_not_available` | Dosya bu sipariş için yüklenmemiş |
| `invalid / review_not_revisable` | Yorum düzeltilebilir durumda değil |

## Medya

| Durum | Kod | Anlamı |
|---|---|---|
| 400 | `refused / type_not_allowed: <tür>` | Dosya türü desteklenmiyor |
| 400 | `refused / too_large: <MB>` | Dosya boyutu sınırı aşıldı |
| 400 | `refused / too_many_items: 18` | Bu sipariş için yüklenip henüz yoruma eklenmemiş dosya sayısı sınıra ulaştı (sipariş satırı başına 18) |
| 422 | `refused / video_too_long: 60` | Video 60 saniyeden uzun; dosya yükleme sırasında reddedildi |
| 413 | `refused / too_large: <MB>` | İstek body'si izin verilen boyutu aşıyor |
| 422 | `refused / quarantined` | Dosya güvenlik taramasında karantinaya alındı |
| 422 | `refused / image_unreadable` | Görsel okunamadı ya da jpeg, png, webp değil |
| 422 | `refused / image_too_large` | Görsel 40 megapikseli aşıyor |
| 422 | `refused / video_unreadable`, `video_stream_missing` | Video okunamadı ya da görüntü içermiyor |
| 422 | `refused / video_frame_too_large: 3840x2160` | Video görüntüsü 3840×2160'tan büyük (dikey videoda 2160×3840) |
| 422 | `refused / video_frame_rate_too_high: 60` | Video saniyede 60 kareden fazla |
| 422 | `refused / video_codec_not_allowed` | Video H.264, HEVC, MPEG-4, VP9 ya da AV1 ile kodlanmamış |
| 422 | `refused / scan_failed`, `processing_failed` | Dosya taranamadı ya da işlenemedi |

Video sınırları, sunucu videoyu yükleme sırasında okuyabildiğinde yüklemede denetlenir. O anda okunamayan video işlenirken aynı sınırlarla reddedilir ve sitede gösterilmez.

## Yorum bildirme ve oy

| Kod | Anlamı |
|---|---|
| `invalid_reason` | Bildirim gerekçesi listede yer almıyor |
| `invalid / vote` | Oy `up`, `down` ya da `none` değil |

## Soru-cevap

| Kod | Anlamı |
|---|---|
| `refused / questions_disabled` | Marka soru-cevabı açmamış (403) |
| `invalid / body_required`, `body_too_long`, `email_invalid`, `email_too_long`, `name_too_long`, `asker_too_long`, `product_required`, `product_too_long` | Soru ya da cevap formunda eksik ya da hatalı alan |
| `token_required`, `token_refused / token_unknown`, `token_expired`, `token_wrong_kind`, `token_foreign_tenant`, `token_foreign_market` | Cevap için gönderilen token yok ya da geçersiz |
| `token_refused / not_a_buyer` | Token'ın siparişinde sorunun ürünü yok |
| `token_refused / asker_expired`, `asker_invalid` | Oturum açmış müşterinin soru token'ının süresi dolmuş, token geçersiz ya da başka bir markaya ait; script formu oturum açmamış ziyaretçinin formuna çevirir |
| `not_found` | Soru bulunamadı, yayında değil ya da başka bir pazara ait (404) |
| `answer_refused / text_steering`, `text_health_claim`, `text_personal_data`, `text_profanity`, `question_not_published` | Admin API: marka cevabı yönlendirme, sağlık iddiası, kişisel bilgi ya da küfür içeriyor veya soru yayında değil (409) |

## Aktarım

| Durum | Kod | Anlamı |
|---|---|---|
| 401 | `refused / unknown_key`, `malformed_key`, `revoked_key` | `Authorization: Bearer` ile gönderilen sunucu anahtarı tanınmıyor, biçimi hatalı ya da iptal edilmiş |
| 403 | `refused / scope_missing` | Sunucu anahtarının sipariş gönderme (`orders`) izni yok |
| 401 | `signature_refused / signature_missing`, `timestamp_missing` | İmzalı gönderimde imza ya da zaman header'ı eksik |
| 401 | `signature_refused / timestamp_invalid` | Zaman değeri okunamadı ya da saat dilimi içermiyor |
| 401 | `signature_refused / timestamp_outside_window` | Zaman farkı ±5 dakikadan fazla |
| 401 | `signature_refused / signature_mismatch` | İmza eşleşmiyor |
| 401 | `signature_refused / secret_unknown` | Şifre kimliği tanınmıyor, şifre iptal edilmiş ya da bu işlem için kullanılamıyor |
| 429 | `rate_limited` | Aynı IP adresinden 5 dakikada 60'tan fazla istek anahtar, şifre ya da imza nedeniyle reddedildi; değerler için: [Limitler](/tr/reference/limits.md) |
| 400 | `invalid / body_invalid`, `body_empty` | Body geçerli bir JSON değil ya da boş |
| 400 | `invalid / batch_too_large: 100` | Tek istekte 100'den fazla kayıt gönderildi (e-posta olaylarında sınır 500) |
| 400 | `invalid / field_missing: <alan>`, `field_invalid: <alan>`, `field_too_long: <alan>` | Alan eksik, geçersiz ya da çok uzun; saklanamayan bir karakter (NUL `\u0000` ya da eşi olmayan vekil karakter) de alanı geçersiz yapar |
| 400 | `invalid / market_required`, `market_without_policy: <pazar>` | Pazar belirlenemedi ya da pazar için tanımlı kural yok |
| 400 | `invalid / channel_unknown` | Kanal kodu yanlış ya da kanal kapalı |
| 400 | `invalid / market_channel_mismatch: <pazar>` | Siparişin pazarı, siparişin bağlandığı kanalın pazarıyla aynı değil |
| 400 | `invalid / status_unmapped: …` | Durum değeri tanınmıyor |

## Admin API

Panelin ve Admin API'nin döndürdüğü başlıca kodlar. Panel bu kodları ekranda cümleye çevirir.

| Durum | Kod | Anlamı |
|---|---|---|
| 403 | `forbidden / scope_missing` | Kullanıcının rolü ya da anahtarın izni bu işlem için yeterli değil |
| 403 | `forbidden / brand_inactive` | Markanın hizmeti dondurulmuş ya da kapatılmış; panelde yalnızca veri dışa aktarımı hazırlanıp indirilebilir |
| 403 | `forbidden / panel_session_required`, `refused / panel_session_required` | İşlem yalnızca panelde oturum açmış bir kullanıcıyla yapılabilir; API anahtarıyla yapılamaz (sipariş bağlantısı işlemleri, davet e-postası deneme gönderimi ve davet gönderim ayarları; kullanıcı, kanal, anahtar ve kişisel veri talebi işlemlerinde anahtar `forbidden / scope_missing` alır) |
| 400 | `invalid / scope_reserved: write` | Ayarları değiştirme (`write`) iznini yalnızca Sayproof ekibi verebilir |
| 400 | `invalid / username_taken` | Kullanıcı adı başka bir markada kullanılıyor; bir kullanıcı yalnızca bir markaya üye olabilir. Hiçbir markaya üyeliği kalmamış bir hesap ancak hesapta kayıtlı e-posta adresiyle birlikte girilirse eklenir. |
| 400 | `invalid / current_password` | Parola değiştirilirken şu anki parola yanlış girildi |
| 400 | `invalid / password_guessable`, `password_names_account` | Yeni parola kolay tahmin edilir (yaygın sözcük, takım ya da kişi adı ile yıl ya da sıralı rakamlar) ya da Sayproof'un, markanın veya kullanıcı adının adını içeriyor |
| 400 | `invalid / email_required` | Kullanıcı eklerken e-posta adresi girilmedi ya da e-posta adresi olmayan kullanıcıya parola bağlantısı gönderilmek istendi |
| 400 | `invalid_passcode` | İki adımlı girişte doğrulama kodu yanlış, süresi geçmiş ya da daha önce kullanılmış |
| 400 | `second_step_expired` | Parola adımından sonra 10 dakika geçti ya da parola adımı yapılmadı; giriş baştan yapılır |
| 409 | `invalid / second_step_on` | İki adımlı giriş zaten açık |
| 400 | `invalid / address_needs_credentials` | Sipariş bağlantısının adresi başka bir sunucuyu gösteriyor; giriş bilgileri de yeniden girilmeli |
| 400 | `invalid / cta_required` | Davet e-postası şablonunda Yorum yaz düğmesi bölümü zorunludur |
| 400 | `invalid / template_scope_taken` | Bu davet türü, dil, pazar ve kanal için başka bir davet e-postası şablonu var; önce onu düzenleyin ya da kaldırın |
| 400 | `invalid / channel` | Kanal kodu bu markada yok (yöntem beyanı, davet e-postası şablonu, denetim raporu ve istatistik istekleri) |
| 400 | `invalid / verification_locked`, `sort_not_offered: <sıralama>`, `default_sort_not_allowed`, `review_window_days_out_of_range`, `valid_from_past` | Pazar kuralı sürümü açılamadı: Sayproof kuralının zorunlu tuttuğu satın alma kanıtı kapatılamaz; sıralama Sayproof kuralında yok; varsayılan sıralama sunulanlar arasında değil; yorum yazma süresi 7–365 gün dışında; başlangıç tarihi geçmişte |
| 400 | `invalid / channel_market_mismatch` | Denetim raporu, istatistik ya da pazar kuralı isteğinde gönderilen kanal, gönderilen pazara ait değil |
| 400 | `invalid / sender_domain_unverified` | Gönderen adresinin alan adı doğrulanmamış |
| 400 | `invalid / webhook_url_required`, `webhook_secret_missing` | Davetleri kendi sisteminiz gönderecekse bildirim adresi ve bildirim adresi şifresi gerekli |
| 400 | `invalid / addresses_required`, `addresses` | E-posta almak istemeyenler sorgusunda adres yok, liste geçersiz ya da 1.000 adresten uzun |
| 400 | `invalid / url_invalid` | Adres okunamadı; tam bir `https` adresi girin |
| 400 | `invalid / host_unverified` | Sayfa denetimine verilen adres doğrulanmış alan adlarınız arasında değil |
| 400 | `invalid / review_style`, `review_theme` | Kanal için gönderilen düzen (`cards`, `sidebar`) ya da tasarım (`warm`, `trust`, `editorial`, `minimal`, `soft`, `bold`, `natural`, `night`) tanınmıyor |
| 400 | `identifier_mismatch` | KVKK erişim talebinin kopyası istenirken yazılan e-posta adresi talepteki adresle eşleşmiyor |
| 400 | `invalid / base_url`, `remote_channel`, `<alan>_required`, `address_needs_credentials` | Sipariş bağlantısında adres `https` dışında bir şemayla yazılmış (şema yazılmazsa `https://` eklenir) ya da alan adı dışında kullanıcı bilgisi, sorgu dizesi veya `#` içeriyor; Omnitron kanal numarası rakamlardan oluşmuyor; zorunlu bir bağlantı alanı boş (örneğin `username_required`, `client_secret_required`, `consumer_key_required`); adres başka bir alan adına değiştirilirken giriş bilgileri yeniden gönderilmedi |
| 400 | `platform_refused / login_refused`, `credentials_missing`, `shop_address_invalid`, `api_credentials_missing`, `api_credentials_refused`, `api_scope_missing`, `host_unresolved`, `http_status: <kod>` … | Sipariş bağlantısı denenirken platforma bağlanılamadı; kodların anlamı: [Akinon](/tr/integrate/akinon.md#hata-durumlari), [Shopify](/tr/integrate/shopify.md#hata-durumlari), [WooCommerce](/tr/integrate/woocommerce.md#hata-durumlari) |
| 409 | `source_exists` | Bu kanal için bu platformda zaten bir sipariş ya da pazaryeri bağlantısı var |
| 409 | `source_inactive` | Duraklatılmış sipariş ya da pazaryeri bağlantısı için okuma başlatılamaz |
| 400 | `invalid / seller_id_locked`, `feed_url_required`, `feed_url_not_https`, `feed_url_not_applicable`, `file_required`, `column_missing: <sütun>`, `file_unreadable`, `unsupported_format`, `too_large`, `too_many_rows`, `reviews` | Pazaryeri bağlantısında eksik ya da geçersiz alan: satıcı numarası değiştirilmeye çalışılmış, adres `https` değil, dosya okunamıyor ya da zorunlu bir sütunu yok, kaldırılacak yorum bulunamadı |
| 409 | `source_has_reviews` | Yayında aktarılmış yorumu ya da kişisel veri talebiyle kaldırılmış yorum kaydı olan pazaryeri bağlantısı kaldırılamaz |
| 409 | `channel_inactive` | Kanal kapalı olduğu için sipariş bağlantısında okuma başlatılamaz |
| 409 | `channel_in_use` | Kanalda yorum, sipariş ya da sipariş bağlantısı olduğu için kanal kaldırılamaz; kanal kapatılabilir |
| 409 | `channel_quota` | Kanal hakkı dolu; yeni kanal oluşturulamaz ve kapalı kanal yeniden açılamaz. **Ek kanal iste** ile Sayproof ekibine istek gönderin |
| 409 | `channel_request_open` | Yanıt bekleyen bir ek kanal isteği zaten var |
| 409 | `refused / template_preset`, `template_default`, `template_assigned`, `template_retired` | Değerlendirme başlığı listesi değiştirilemedi: Sayproof hazır listesi kullanımdan kaldırılamaz; genel liste ve bir ürün tipine atanmış liste kullanımdan kaldırılamaz; kullanımdan kaldırılmış listeye yeni sürüm yayınlanamaz |
| 404 | `not_found / export_not_ready` | Veri dışa aktarımı henüz hazır değil ya da indirme süresi doldu |
| 409 | `domain_in_statement / <kanal kodu/dil>` | Alan adı, ayrıntıda yazan kanal ve dilin yöntem beyanı adresinde kullanıldığı için kaldırılamaz; önce **Pazar kuralları › Yöntem beyanı**'ndaki adresi değiştirin |
| 400 | `proof_refused / proof_not_found`, `token_mismatch`, `dns_value_mismatch`, `dns_unreachable` | Alan adı doğrulanamadı: ne doğrulama dosyası ne `TXT` kaydı bulundu; dosyanın içeriği doğrulama metniyle aynı değil; `TXT` kaydı bulundu ama değeri farklı; dosya yokken alan adının DNS sunucusuna ulaşılamadı (biraz sonra yeniden deneyin). Yanıt `path`, `dns_name` ve `token` alanlarını da taşır. |
| 409 | `domain_in_use / channels: <kanal kodları>` | Alan adı, ayrıntıda kodu yazan kanalların davet bağlantısının açılacağı sayfa adresinde kullanıldığı için kaldırılamaz; önce kanalın adresini değiştirin |
| 409 | `seller_response_refused / text_personal_data`, `text_profanity`, `text_steering` | Satıcı yanıtı kaydedilmedi: metinde kişisel veri (e-posta, telefon, kimlik, IBAN, kart ya da adres), hakaret sayılan bir ifade ya da müşteriyi yorumunu veya puanını değiştirmeye yönlendiren bir cümle var |
| 409 | `seller_response_refused / seller_response_open`, `parent_review_not_published` | Yorumun bekleyen, yayında ya da gizlenmiş bir satıcı yanıtı var (yeni yanıttan önce o yanıt geri çekilmeli) ya da yorum yayında değil |
| 409 | `resolution_refused / text_personal_data`, `text_profanity`, `text_steering` | Çözüm notu kaydedilmedi; nedenler satıcı yanıtıyla aynıdır |
| 409 | `resolution_refused / review_not_live` | Çözüm notu yalnız yayındaki ya da geçici gizlenmiş yoruma eklenebilir |
| 409 | `statement_changed` | Yöntem beyanı onay sırasında değişti; yeni metni sayfanıza koyup yeniden onaylayın |
| 409 | `sender_domain_refused / sender_domain_in_use` | Gönderen alan adı, **Davet gönderimi** ekranındaki ya da bir kanalın **Gönderen e-posta adresi** alanındaki adreste kullanıldığı için kaldırılamaz |
| 409 | `not_copyable` | Talep tamamlanmış bir erişim talebi olmadığı için kopyası yeniden alınamaz |
| 502 | `sender_domain_check_failed / dns_unreachable` | Alan adının DNS sunucusuna ulaşılamadı; biraz sonra yeniden deneyin |
| 502 | `page_unreadable / …` | Sayfa denetiminde sayfa okunamadı (örneğin `http_status: 404`) |

## Ürün kaynağı okumaları

Bu kodlar bir HTTP yanıtında değil, **Ürünler › Ürün kaynakları** sekmesinden açılan kaynağın **Okumalar** sekmesinde başarısız okumanın nedeni olarak gösterilir.

| Kod | Anlamı |
|---|---|
| `page_limit_reached: <sınır>` | Okuma, katalog bitmeden sayfa sınırına ulaştı; sonraki okuma kaldığı yerden devam eder |
| `cursor_repeated` | Kaynak aynı sonraki sayfa işaretini tekrar verdi; okuma durduruldu |

## Örnek: hata kodunu çeviri anahtarına dönüştürmek

`detail` değerinin iki nokta üst üsteden önceki bölümü kodun kendisidir. Bu bölümü `error` değeriyle birleştirerek kendi çeviri dosyanızda aranacak anahtarı oluşturabilirsiniz. Örneğin `{"error": "refused", "detail": "origin_unverified: www.markaniz.com"}` yanıtı `sayproof.refused.origin_unverified` anahtarına dönüşür.

```js
export function sayproofErrorKey(problem) {
  const detail = String(problem?.detail ?? "").split(":")[0].trim();
  const error = String(problem?.error ?? "unknown");
  return detail ? `sayproof.${error}.${detail}` : `sayproof.${error}`;
}

export async function sayproofProblem(answer) {
  const problem = await answer.json().catch(() => ({}));
  return { status: answer.status, key: sayproofErrorKey(problem), requestId: answer.headers.get("X-Request-Id") };
}
```
