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

# Hata yanıtları

> Hata zarfını, doğrulama hatalarını, HTTP durum kodlarını ve hata koduna göre işlem yapmayı anlatır.

`https://app.flextell.ai/api/v1` altındaki her hata, aynı JSON biçiminde döner. Bu sayfa o biçimi, doğrulama (422) hatalarının nasıl okunacağını, HTTP durum kodlarının anlamını ve istemcinizde hatayı nasıl ele alacağınızı anlatır. Tek tek hata kodlarının listesi için [Hata kodları](/api/istekler/hata-kodlari) sayfasına bakın.

<Info>
  Bu sayfa `/api/v1` altındaki endpoint'leri kapsar. OAuth uç noktaları (`/oauth/token` gibi) farklı, OAuth biçiminde hata verir; bunlar için [Kimlik doğrulama hataları](/api/kimlik-dogrulama/hatalar) sayfasına bakın.
</Info>

## Hata zarfı

Başarısız her istek `success: false` ile başlayan bir gövde döner:

```json theme={null}
{
  "success": false,
  "error_code": "RESOURCE_NOT_FOUND",
  "message": "İstenen kaynak bulunamadı.",
  "meta": { "timezone": "Europe/Istanbul" }
}
```

| Alan | Her zaman var mı | Açıklama |
| - | - | - |
| `success` | Evet | Hatalarda her zaman `false`. |
| `error_code` | Evet | Makine tarafından okunacak sabit kod, örneğin `VALIDATION_FAILED`. İstemcinizin dallanacağı alan budur. |
| `message` | Evet | İnsan tarafından okunacak açıklama. `Accept-Language` başlığına göre Türkçe ya da İngilizce gelir. |
| `errors` | Hayır | Yalnızca alan hataları varsa gelir. Anahtar alan adı, değer hata mesajlarının dizisidir. |
| `data` | Hayır | Yalnızca hatanın makine tarafından okunabilir bir bağlamı varsa gelir. Örneğin `LEAD_NOT_ASSIGNED` hatasında `data.assigned_user`. |
| `meta.timezone` | Klinik bağlamında | Klinik bağlamındaki (`X-Tenant` ile çağrılan) yanıtlarda gelir. Klinik çözülmeden önce oluşan hatalarda (`401`, `429`, `400 TENANT_HEADER_REQUIRED`, `404 TENANT_NOT_FOUND`) `meta` yoktur. |

Değeri olmayan alanlar `null` olarak gönderilmez, yanıttan çıkarılır. `errors` ve `data` için `null` kontrolü yapmak yerine anahtarın varlığına bakın.

<Warning>
  `message` metnine göre dallanmayın. Metin dile göre değişir ve zamanla güncellenebilir. Daima `error_code` alanını kullanın. Yanıt dili ve her zaman İngilizce gelen metinler için [Başlıklar, dil ve CORS](/api/istekler/basliklar) sayfasına bakın.
</Warning>

Sunucu hatalarında (`500 SERVER_ERROR`) `message` genel bir metindir; iç hata ayrıntısı yanıta eklenmez.

## Doğrulama hataları

Gönderdiğiniz veri kurallara uymuyorsa API `422` ve `VALIDATION_FAILED` döner. Üst düzey `message` her zaman genel bir metindir (`Gönderilen veriler geçersiz.` ya da `Accept-Language: en` ile `The given data is invalid.`). Asıl bilgi `errors` alanındadır:

```json theme={null}
{
  "success": false,
  "error_code": "VALIDATION_FAILED",
  "message": "Gönderilen veriler geçersiz.",
  "errors": {
    "name": ["İsim alanı zorunludur."],
    "phone_number": ["Telefon alanı zorunludur."]
  },
  "meta": { "timezone": "Europe/Istanbul" }
}
```

Bu örnekteki alan adları yalnızca biçimi göstermek içindir; gerçek alanlar ve kurallar endpoint'e göre değişir.

* Anahtarlar istek gövdesindeki alan adlarıdır. Bir alanın birden fazla hatası olabilir; değer her zaman bir dizidir.
* İç içe alanlar nokta ile yazılır: `treatment_session_plans.0.sessions.0.scheduled_at`. Sayı, dizideki sıra numarasıdır (0'dan başlar).
* Türkçe yanıtlarda alan mesajları Türkçedir ve alan adı Türkçe karşılığıyla geçer (örneğin `name` için **İsim**, `phone_number` için **Telefon**). İngilizce yanıtlarda standart doğrulama metinleri gelir.
* Bazı iş kuralı hataları da `errors` taşır ama kendi kodunu korur. Örneğin Telegram bağlantı hataları `errors.bot_token` ile gelir ve `VALIDATION_FAILED` değildir. Bu yüzden önce `error_code` değerine bakın.

<Tip>
  Formu olan bir arayüz yapıyorsanız `errors` anahtarlarını form alanlarınızla eşleştirip mesajı alanın altında gösterin. `errors` içinde karşılığı olmayan bir anahtar gelirse mesajı form düzeyinde gösterin.
</Tip>

## HTTP durum kodları

| HTTP | Ne anlama gelir | `error_code` örnekleri |
| - | - | - |
| `400` | İstek işlenemedi: gövde geçersiz JSON ya da `X-Tenant` başlığı eksik. | `MALFORMED_JSON`, `TENANT_HEADER_REQUIRED`, `BAD_REQUEST` |
| `401` | Token eksik, geçersiz ya da süresi dolmuş. | `UNAUTHENTICATED` |
| `402` | Kliniğin aboneliği veya ödeme durumu erişimi kapatıyor. | `SUBSCRIPTION_REQUIRED`, `ACCESS_RESTRICTED_BY_OVERDUE_PAYMENT` |
| `403` | Token'ın scope'u ya da kullanıcının izni yetmiyor. | `FORBIDDEN`, `LEAD_NOT_ASSIGNED`, `CONVERSATION_NOT_ASSIGNED` |
| `404` | Kaynak yok, klinik bulunamadı ya da kaynağı görme yetkiniz yok. | `RESOURCE_NOT_FOUND`, `TENANT_NOT_FOUND` |
| `405` | Bu adres bu HTTP metodunu desteklemiyor. | `METHOD_NOT_ALLOWED` |
| `409` | İstek kaynağın mevcut durumuyla çakışıyor. | `RESTORE_CONFLICT`, `APPOINTMENT_ALREADY_CANCELLED` |
| `413` | İstek çok büyük. | `INTEGRATION_INBOUND_TOO_MANY_RECORDS` |
| `422` | Veri geçersiz ya da bir iş kuralı işlemi engelledi. | `VALIDATION_FAILED` ve alana özgü iş kuralı kodları |
| `428` | Kliniğin kurulumu tamamlanmamış. | `SETUP_REQUIRED` |
| `429` | Oran sınırı aşıldı. | `TOO_MANY_REQUESTS` |
| `500` | Beklenmeyen sunucu hatası. | `SERVER_ERROR` |

Notlar:

* **403 ve 404 farkı.** Kliniğinize ait olmayan ya da görünürlük kapsamınızın dışındaki bir kayıt için `403` değil `404 RESOURCE_NOT_FOUND` alırsınız. Bu, kaydın var olup olmadığının sızmaması içindir. Görünürlük kuralları için [İzinler ve görünürlük](/api/izinler-ve-gorunurluk) sayfasına bakın. İstisna: `LEAD_NOT_ASSIGNED` ve `CONVERSATION_NOT_ASSIGNED` `403` döner ve `data.assigned_user` (`{id, name}` ya da `null`) içerir. Böylece kaydın kime atandığını kullanıcıya gösterebilirsiniz.
* **403 ve scope.** Token'ınızda gerekli scope yoksa `403 FORBIDDEN` döner ve `message` her zaman İngilizce `Invalid scope(s) provided.` olur. Token'ın scope'u sonradan artmaz; uygulamanızın isteyeceği scope'ları [Scope'lar](/api/kimlik-dogrulama/scopelar) sayfasından kontrol edip yeniden yetkilendirme yapın.
* **402 ve 428.** `402` yanıtında `data` abonelik bilgisini (`SUBSCRIPTION_REQUIRED`) ya da `proforma_invoice_id` ve `due_date` alanlarını (`ACCESS_RESTRICTED_BY_OVERDUE_PAYMENT`) taşır. `428` yanıtında `data.next_step` kurulumun sıradaki adımını verir (örneğin `clinic_info`). Ayrıntılar için [Erişim kilitleri](/api/istekler/erisim-kilitleri) sayfasına bakın.
* **429.** Oran sınırı katmanından gelen yanıt `Retry-After` (saniye) ve `X-RateLimit-Reset` başlıklarını taşır; klinik oluşturma gibi servis düzeyindeki `429` yanıtlarında `Retry-After` yoktur. Bu başlıklar CORS ile açılmadığı için başka bir kökenden çalışan tarayıcı JavaScript'i onları okuyamaz; orada beklemeyi sabit bir süreyle ya da üstel artışla yapın. Sınırlar için [Oran sınırları](/api/istekler/oran-sinirlari) sayfasına bakın.
* **405.** Yanıtta `Allow` başlığı desteklenen metotları listeler. `404` ve `405` mesajları yönlendirme düzeyinde oluştuğu için her zaman İngilizcedir.
* **409 ve 422 ayrımı.** Çakışma durumları (örneğin zaten iptal edilmiş bir randevuyu iptal etmek) `409` döner. Çoğu iş kuralı hatası ise `422` ve kendi `error_code` değeriyle gelir; kodu belirtilmeyen iş kuralı hataları `422` varsayılır.

## Hata koduna göre işlem yapma

İstemcinizi önce `error_code`, sonra gerekirse HTTP durum koduna göre kurun. `message` yalnızca kullanıcıya gösterilecek metindir.

| Durum | Ne yapın |
| - | - |
| `401 UNAUTHENTICATED` | Access token'ı yenileyin ve isteği bir kez tekrarlayın. Yenileme de başarısızsa kullanıcıyı yeniden yetkilendirin. Bkz. [Tokenlar](/api/kimlik-dogrulama/tokenlar). |
| `403 FORBIDDEN` (scope mesajı) | Yeniden denemek işe yaramaz. Gerekli scope ile yeniden yetkilendirin. |
| `403` diğer | Kullanıcının izni yok. Hatayı gösterin; aynı isteği otomatik tekrarlamayın. |
| `LEAD_NOT_ASSIGNED`, `CONVERSATION_NOT_ASSIGNED` | `data.assigned_user` ile kaydın sahibini gösterin. `null` ise kayıt kimseye atanmamıştır. |
| `404 TENANT_NOT_FOUND`, `400 TENANT_HEADER_REQUIRED` | `X-Tenant` değerini kontrol edin. Bkz. [Klinikler ve X-Tenant](/api/klinikler-ve-x-tenant). |
| `422 VALIDATION_FAILED` | `errors` içindeki mesajları ilgili alanlarda gösterin. Aynı veriyle tekrar denemeyin. |
| `402`, `428` | Klinik yöneticisinin işlem yapması gerekir. Kullanıcıya durumu açıklayın; otomatik tekrar denemeyin. |
| `409` | Kaynağın güncel durumunu yeniden okuyun, ardından kullanıcıya seçenek sunun. |
| `429 TOO_MANY_REQUESTS` | `Retry-After` süresi kadar bekleyin, sonra isteği tekrarlayın. |
| `500 SERVER_ERROR` | Genel bir hata olarak gösterin. Sorun sürerse [Destek](/api/destek) sayfasındaki yollarla bildirin. |

Örnek bir istemci tarafı işleyici:

<CodeGroup>
  ```js JavaScript theme={null}
  async function flextell(path, options = {}) {
    const res = await fetch(`https://app.flextell.ai/api/v1${path}`, {
      ...options,
      headers: {
        Authorization: `Bearer ${accessToken}`,
        "X-Tenant": tenantId,
        Accept: "application/json",
        ...options.headers,
      },
    });

    if (res.ok) return res.json();

    const err = await res.json();

    switch (err.error_code) {
      case "UNAUTHENTICATED":
        // token'ı yenileyin, isteği bir kez tekrarlayın
        break;
      case "VALIDATION_FAILED":
        // err.errors: { alan: ["mesaj", ...] }
        throw Object.assign(new Error("Doğrulama hatası"), { fields: err.errors });
      case "TOO_MANY_REQUESTS": {
        const wait = Number(res.headers.get("Retry-After") ?? 1);
        await new Promise((r) => setTimeout(r, wait * 1000));
        return flextell(path, options);
      }
      default:
        throw Object.assign(new Error(err.message), { code: err.error_code, data: err.data });
    }
  }
  ```

  ```bash curl theme={null}
  # X-Tenant başlığı olmadan klinik bağlamındaki bir endpoint'i çağırın
  curl -i "https://app.flextell.ai/api/v1/tags" \
    -H "Authorization: Bearer <access_token>" \
    -H "Accept: application/json"
  # 400 {"success":false,"error_code":"TENANT_HEADER_REQUIRED","message":"X-Tenant başlığı zorunludur."}
  ```
</CodeGroup>

<Note>
  Bu örnek yalnızca akışı göstermek içindir; üretimde yeniden deneme sayısını sınırlayın. Yazma isteklerini güvenle tekrarlamak için [Idempotency](/api/istekler/idempotency) sayfasına bakın.
</Note>

## Hata önceliği

Bir istek birden fazla nedenle başarısız olabilir. API kontrolleri aşağıdaki sırayla yapar ve **ilk başarısız olan** yanıtı belirler. Örneğin gövdesi bozuk bir istek, token olmasa bile `400` alır; token'ı eksik ve `X-Tenant` başlığı da eksik bir istek önce `401` alır.

| Sıra | Kontrol | Başarısız olursa |
| - | - | - |
| 1 | Adres ve metot | `404 RESOURCE_NOT_FOUND`, `405 METHOD_NOT_ALLOWED`. Sayısal olması gereken `id` yer tutucusuna sayı olmayan değer vermek de `404` döner. |
| 2 | JSON gövde (içerik tipi JSON ve gövde doluysa) | `400 MALFORMED_JSON` |
| 3 | Kimlik doğrulama | `401 UNAUTHENTICATED` |
| 4 | Genel oran sınırı | `429 TOO_MANY_REQUESTS` |
| 5 | `X-Tenant` başlığı | `400 TENANT_HEADER_REQUIRED`, `404 TENANT_NOT_FOUND` |
| 6 | Abonelik ve ödeme durumu | `402 SUBSCRIPTION_REQUIRED`, `402 ACCESS_RESTRICTED_BY_OVERDUE_PAYMENT` |
| 7 | Kurulum durumu | `428 SETUP_REQUIRED` |
| 8 | Token scope'u | `403 FORBIDDEN` (`Invalid scope(s) provided.`) |
| 9 | Endpoint'e özgü oran sınırları (dışa aktarma, istatistikler, hesap işlemleri, davetler) | `429 TOO_MANY_REQUESTS` |
| 10 | İzin kontrolü ve alan doğrulaması | `403 FORBIDDEN`, `422 VALIDATION_FAILED` |
| 11 | İş kuralları ve kayıt erişimi | Kaydın klinik ya da görünürlük dışında kalması `404`, diğerleri ilgili iş kuralı kodu |

Bu sıranın pratik sonuçları:

* Geçersiz JSON gönderen bir istemci, token'ı geçerli olsa da olmasa da `400` alır. Önce gövdeyi düzeltin.
* Genel oran sınırı kimlik doğrulamadan **sonra** sayılır; geçersiz token ile yapılan istekler bu sınıra yazılmaz.
* Doğrulama hatası (`422`) görmeniz, yetki ve kilit kontrollerinin geçildiği anlamına gelir.
* Abonelik ya da kurulum kilidi, alan doğrulamasından önce uygulandığı için bu durumlarda eksik alan hatası değil `402` ya da `428` alırsınız. Faturalama ile ilgili bazı endpoint'ler `402` kilidinde de açık kalır; ayrıntı [Erişim kilitleri](/api/istekler/erisim-kilitleri) sayfasındadır.
* Hiçbir ayrıntı yanıta sızmaz: beklenmeyen bir istisna her zaman `500 SERVER_ERROR` ve genel bir mesajla döner.

## İlgili sayfalar

<CardGroup cols={2}>
  <Card title="Hata kodları" icon="list" href="/api/istekler/hata-kodlari">
    `error_code` değerlerinin tam listesi.
  </Card>

  <Card title="Yanıt yapısı" icon="braces" href="/api/istekler/yanit-yapisi">
    Başarılı yanıt zarfı ve liste yanıtları.
  </Card>

  <Card title="Oran sınırları" icon="gauge" href="/api/istekler/oran-sinirlari">
    429 yanıtları ve `Retry-After`.
  </Card>

  <Card title="Erişim kilitleri" icon="lock" href="/api/istekler/erisim-kilitleri">
    402 ve 428 yanıtları.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.