> ## 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.

# İstatistikler

> Pano istatistiklerini, dönem parametrelerini, özet bölümlerini ve gösterge tanımlarını anlatır.

İstatistik endpoint'leri, kliniğin hasta, lead, randevu, satış, tedavi ve sohbet verilerinden hesaplanmış toplamları salt okunur olarak verir. Panelin **Ana Sayfa** ekranı ve mobil uygulamanın ana ekranı aynı verileri kullanır (bkz. [Panel metrikleri](/panel/ana-sayfa/metrikler)).

Tüm istekler `GET` ile yapılır, gövde almaz ve şunları ister:

* `Authorization: Bearer <access_token>` başlığı ve `statistics:read` [scope](/api/kimlik-dogrulama/scopelar)'u. Scope eksikse yanıt `403 FORBIDDEN` olur.
* `X-Tenant: <tenant_id>` başlığı ([Klinikler ve X-Tenant](/api/klinikler-ve-x-tenant)).

## Endpoint özeti

Taban adres: `https://app.flextell.ai/api/v1`.

| Metot | Endpoint | Açıklama | İzin (yoksa 403) |
| - | - | - | - |
| GET | `/statistics/summary` | Pano özeti: bugün ve son 30 gün | İzin kapısı yok; bölümler izne göre süzülür |
| GET | `/statistics/customers` | Hasta listesi istatistikleri | `ViewAllCustomers:Customer` |
| GET | `/statistics/leads` | Lead hunisi istatistikleri | `ViewAllLeads:Lead` |
| GET | `/statistics/appointments` | Randevu istatistikleri | `ViewAllAppointments:Appointment` |
| GET | `/statistics/revenue` | Ciro ve tahsilat istatistikleri | `ViewAllSales:Sale` |
| GET | `/statistics/treatments` | Uygulanan tedavi istatistikleri | `ViewAllAppointments:Appointment` |
| GET | `/statistics/chat` | Sohbet hacmi istatistikleri | `View:Conversation` |
| GET | `/statistics/low-stock-products` | Kritik stoğa inen ürünler (liste) | `View:StockOverview` veya `View:Product` |
| GET | `/statistics/birthdays` | Doğum günü olan hastalar (liste) | `ViewAllCustomers:Customer` |

Hepsi `statistics:read` scope'unu ister. Her toplam kliniğin tamamını kapsadığı için `ViewAll...` izinleri aranır. Yalnızca kendi kayıtlarını gören `View:Customer`, `View:Appointment` ve `View:Sale` izinleri bu endpoint'lerde yetmez. `treatments` bir tedavi izni değil, `ViewAllAppointments:Appointment` ister.

`summary` ve grup endpoint'leri `{"success": true, "data": {...}, "meta": {"timezone": "..."}}` zarfıyla döner. İki liste endpoint'i standart sayfalı liste yapısını kullanır ([Sayfalama](/api/istekler/sayfalama)).

## Dönem parametreleri

`summary` ve liste endpoint'leri dönem almaz. `summary` her zaman bugünü ve son 30 günü kullanır. Altı grup endpoint'i (`customers`, `leads`, `appointments`, `revenue`, `treatments`, `chat`) şu parametreleri alır:

| Parametre | Tür | Açıklama |
| - | - | - |
| `period` | metin, isteğe bağlı | `today`, `yesterday`, `this_week`, `this_month`, `last_month`, `this_year`, `last_7_days`, `last_30_days`, `custom`. Varsayılan `this_month`. |
| `from` | `Y-m-d` | Başlangıç günü (dahil). `period=custom` ise zorunlu. |
| `to` | `Y-m-d` | Bitiş günü (dahil). `period=custom` ise zorunlu, `from` tarihinden önce olamaz. |

`custom` dönemin uzunluğu en çok 731 gün olabilir. Kural ihlali `422 VALIDATION_FAILED` döner; 731 gün hatası `to` alanında İngilizce `The custom period may not span more than 731 days.` metniyle gelir. `period` `custom` değilse `from` ve `to` yok sayılır, ama biçimleri yine doğrulanır.

Günler klinik saat dilimine göre hesaplanır (varsayılan `Europe/Istanbul`, **Ayarlar → Genel Ayarlar** içindeki **Varsayılan Saat Dilimi**). Yanıttaki `period.timezone` kullanılan dilimi gösterir.

Her dönemin bir de karşılaştırma dönemi vardır. Önceki değer ve `change_percent` bu dönemden hesaplanır.

| `period` | Karşılaştırma dönemi |
| - | - |
| `today` | dün |
| `yesterday` | bir önceki gün |
| `this_week` | önceki hafta (Pazartesi–Pazar) |
| `this_month` | önceki ayın tamamı |
| `last_month` | ondan önceki ay |
| `this_year` | önceki yılın tamamı |
| `last_7_days`, `last_30_days` | hemen öncesindeki aynı uzunlukta dönem |
| `custom` | `from` tarihinden hemen önceki, aynı uzunlukta dönem |

<Warning>
  Süren bir dönem, önceki dönemin tamamıyla karşılaştırılır. Ayın 10'unda `this_month` istediğinizde toplamlar (örneğin yeni hasta sayısı) doğal olarak negatif `change_percent` gösterir.
</Warning>

## Özet bölümleri ve izinler

`GET /statistics/summary` hiçbir zaman izin nedeniyle `403` dönmez. Çağıran kullanıcının izni olan bölümleri `metrics` içine koyar; izni olmayan bölüm yanıtta yer almaz (sıfırlanmış değil, eksik). Hiçbir izin yoksa `200` döner ve `metrics` boş dizi `[]` olur. `currency` her durumda gelir.

| `metrics.` bölümü | Gereken izin | Kapsadığı zaman |
| - | - | - |
| `customers` | `ViewAllCustomers:Customer` | Şu anki hasta dağılımı ve son 30 günde yeni hasta |
| `appointments_today` | `ViewAllAppointments:Appointment` | Bugün |
| `revenue_today` | `ViewAllSales:Sale` | Bugün |
| `revenue_last_30` | `ViewAllSales:Sale` | Son 30 gün, önceki 30 günle karşılaştırmalı |
| `balance` | `View:CustomerTransaction` | Şu an (tüm zamanlar, vadesi gelmiş) |
| `chat_today` | `View:Conversation` | Bugün |

<CodeGroup>
  ```bash curl theme={null}
  curl "https://app.flextell.ai/api/v1/statistics/summary" \
    -H "Authorization: Bearer <access_token>" \
    -H "X-Tenant: <tenant_id>"
  ```

  ```json Yanıt theme={null}
  {
    "success": true,
    "data": {
      "period": {
        "timezone": "Europe/Istanbul",
        "today": {"from": "2026-07-15", "to": "2026-07-15"},
        "last_30_days": {"from": "2026-06-16", "to": "2026-07-15"}
      },
      "metrics": {
        "customers": {"active_customers": 4, "passive_customers": 1, "potential_customers": 1, "new_customers_last_30": 3},
        "appointments_today": {"total": 4, "pending": 1, "completed": 2},
        "revenue_today": {"collections_total": 445.0, "revenue_total": 4449.0},
        "revenue_last_30": {"total_revenue": {"current": 5449.0, "previous": 500.0, "change_percent": 989.8}},
        "balance": {"overdue_balance": 1400.0},
        "chat_today": {"conversations": 1, "ai_replies": 2}
      },
      "currency": {"id": 1, "code": "TRY", "symbol": "₺", "name": "Turkish Lira"},
      "computed_at": "2026-07-15T15:00:00+03:00"
    }
  }
  ```
</CodeGroup>

## Gruplar

Grup endpoint'leri `data.period` (çözümlenmiş dönem), `data.metrics` ve `data.computed_at` döner. Tek değerli göstergeler `{current, previous, change_percent}` biçimindedir. Para tutarları kliniğin ana para biriminde verilir; `revenue` yanıtı `data.currency` alanını da taşır.

```bash theme={null}
curl "https://app.flextell.ai/api/v1/statistics/revenue?period=custom&from=2026-07-01&to=2026-07-31" \
  -H "Authorization: Bearer <access_token>" \
  -H "X-Tenant: <tenant_id>"
```

### Hastalar, lead'ler ve randevular

| Endpoint | `metrics` alanı | Anlamı |
| - | - | - |
| `customers` | `total_customers` | Dönem sonuna kadar edinilmiş hasta sayısı (birikimli) |
| | `new_customers` | Dönemde edinilen hasta |
| | `active_customers`, `passive_customers`, `potential_customers` | Şu anki aktif, pasif ve potansiyel hasta sayısı |
| | `type_distribution` | Aynı üç sayı: `{active, passive, potential}` |
| | `new_customers_trend` | Dönemin her günü için `{date, count}` |
| `leads` | `new_leads` | Dönemde oluşan lead |
| | `converted_leads` | Dönemde hastaya dönüşen lead (oluşma tarihinden bağımsız) |
| | `conversion_rate` | `converted_leads / new_leads * 100`, tek ondalık. `new_leads` 0 ise `current` değeri `null`. |
| | `active_leads` | Şu an dönüşmemiş ve kazanıldı/kaybedildi aşamasında olmayan lead |
| | `new_leads_trend` | Günlük `{date, count}` |
| `appointments` | `total_appointments` | Dönemdeki tüm randevular (gelecektekiler dahil) |
| | `completed_appointments` | Durumu `completed` olanlar |
| | `no_show_rate` | `no_show / toplam`; yalnızca dönemin geçmiş kısmı hesaba girer |
| | `status_distribution` | `pending`, `approved`, `cancelled`, `rejected`, `completed`, `no_show` anahtarlarının her biri için `{current, previous, change_percent}` |
| | `daily_distribution` | Günlük `{date, count}` (`scheduled_at` tarihine göre) |
| | `hourly_distribution` | 24 adet `{hour, count}` |

Aktif, pasif, potansiyel ve `active_leads` değerleri "şu an" durumunu anlatır. `period` ile değişmez, `previous` ve `change_percent` alanları `null` olur. Günlük seriler dönemin her gününü içerir, kayıt olmayan günler `0` ile gelir.

### Ciro, tedavi ve sohbet

| Endpoint | `metrics` alanı | Anlamı |
| - | - | - |
| `revenue` | `total_revenue` | Ciro (iki ondalık); tanım için aşağıdaki "Gösterge tanımları" bölümüne bakın |
| | `sales_count` | Satış sayısı (kalem sayısı değil) |
| | `avg_sale_amount` | `total_revenue / sales_count`; satış yoksa `0.0` |
| | `collections_total` | Tahsilat toplamı |
| | `daily_revenue_trend`, `daily_collections_trend` | Günlük `{date, amount}` |
| `treatments` | `top_treatments` | En çok uygulanan 10 tedavi: `{treatment_id, name, count}` |
| | `top_treatment_groups` | En çok uygulanan 10 tedavi grubu: `{treatment_group_id, name, count}`. Grubu olmayanlar `Diğer` adıyla toplanır. |
| `chat` | `total_conversations` | Dönemde açılan sohbet |
| | `total_messages` | Dönemde oluşan tüm mesajlar (iki yön) |
| | `avg_messages_per_conversation` | Dönemde açılan sohbetlerin dönemdeki mesajları / bu sohbetlerin sayısı (tek ondalık) |
| | `hourly_activity` | 24 adet `{hour, count}`; yalnızca hastadan gelen mesajlar |

`top_*` listelerinde `count` da `{current, previous, change_percent}` biçimindedir. Sıralama `count.current` azalan, eşitlikte kimliğe göre artandır.

### Liste endpoint'leri

Bu iki endpoint dönem almaz ve sayfalı kayıt listesi döner.

| Endpoint | Parametre | Kural |
| - | - | - |
| `low-stock-products` | `threshold` | Sayı, `0` veya büyük. Varsayılan `10`. Ürünün kendi kritik seviyesine ek sabit tavandır (VEYA). `0` ise yalnızca ürünün kendi seviyesi geçerli olur. |
| | `per_page`, `page` | `per_page` 1–100 (varsayılan 15), `page` en az 1 |
| `birthdays` | `month`, `day` | `month` 1–12, `day` 1–31. İkisi de yoksa klinik saat diliminde bugün kullanılır; biri eksikse eksik kısım bugünden alınır. |
| | `per_page`, `page` | `low-stock-products` ile aynı |

`low-stock-products` satırları: `product_id`, `product_name`, `stock_balance`, `critical_stock_level`, `base_unit_code_id`, `base_unit_name`. Liste stoğu en az olandan başlar. **Kritik Stok Seviyesi** tanımlanmamış ürünler hiç listelenmez.

`birthdays` satırları: `customer_id`, `first_name`, `last_name`, `date_of_birth`, `phone_number`, `email`. Liste ada göre sıralıdır. Doğum tarihi olmayan hastalar listeye girmez.

## Gösterge tanımları

| Gösterge | Tanım |
| - | - |
| Hasta | Lead aşamasında kalmış kayıtlar hasta sayılmaz. Bunlar yalnızca `potential_customers` içinde görünür. |
| Yeni hasta | Hastaya dönüşme tarihi (yoksa oluşma tarihi) dönemin içinde olan hasta. Aylar önce açılıp bugün dönüşen lead, bugünün yeni hastasıdır. |
| Aktif hasta | Son 180 günde randevusu (`cancelled` ve `rejected` hariç; ileri tarihli randevu da sayılır) veya satışı (`completed`, `invoiced`, `pending`) olan hasta |
| Pasif hasta | Hastaya dönüşmüş ama aktif olmayan hasta |
| Potansiyel hasta | Lead aşamasındaki kayıt. `active_leads` ile aynı küme değildir. |
| Ciro (`total_revenue`) | Satış tarihi (`sale_date`) dönemde olan satışların kalem tutarları toplamı. Silinmemiş **tüm durumlar** sayılır: taslak ve iptal edilmiş satışlar dahildir. |
| Tahsilat (`collections_total`) | Dönemde ve şu andan geç olmayan tarihli tahsilat kayıtlarının toplamı. İleri tarihli tahsilat tarihi gelene kadar sayılmaz. |
| Açık bakiye (`overdue_balance`) | Vadesi gelmiş ve tahsil edilmemiş alacak toplamı. Dönemden bağımsızdır; fazla ödenmiş bir satış başka bir satışın borcunu azaltmaz. |
| Bekleyen randevu (`appointments_today.pending`) | Bugünkü `pending` ve `approved` randevular |
| Uygulanan tedavi | Randevusu `cancelled`, `rejected`, `no_show` veya `pending` olmayan ve zamanı dönem içinde, şu andan önce olan tedavi. `approved` randevular uygulanmış sayılır. Sayı, tedavi satırı sayısıdır: 3 tedavili bir randevu burada 3 sayılır. |
| Yapay zekâ yanıtı (`ai_replies`) | `send_source` değeri `auto` olan giden mesajlar. İnsanın onayladığı veya düzenlediği AI önerileri sayılmaz. |
| `change_percent` | `(current - previous) / previous * 100`, tek ondalık. Karşılaştırılacak değer yoksa veya önceki değer 0 iken şimdiki değer 0'dan büyükse `null` olur. `null` değerini %0 diye göstermeyin. |

Tutarlar, her satışın veya hareketin kendi `exchange_rate` değeriyle kliniğin ana para birimine çevrilir (**Ayarlar → Genel Ayarlar → Para Birimi**, varsayılan `TRY`). Kur boşsa 1 alınır. Tutarlar iki, yüzdeler tek ondalıkla yuvarlanır.

<Note>
  Ciro tanımı bu endpoint'lere özgüdür. Başka ekran ve raporlardaki ciro rakamları farklı bir tanıma dayanabilir; iki sayıyı birebir karşılaştırmayın.
</Note>

## Önbellek ve sınırlar

### Önbellek

Grup yanıtları klinik bazında önbelleğe alınır. `data.computed_at`, yanıtın **hesaplandığı** andır; isteği yaptığınız an değildir ve birkaç dakika eski olabilir. İlgili hasta, lead, randevu, tedavi, satış, tahsilat veya sohbet kaydı değiştiğinde önbellek hemen geçersiz olur. Yalnızca zamanın akmasından doğan değişiklikler (örneğin bir randevunun geçmişe düşmesi) süre dolunca görünür.

| `period` | Önbellek süresi |
| - | - |
| `today`, `last_7_days`, `last_30_days` | 5 dakika |
| `this_week` | 15 dakika |
| `yesterday`, `this_month`, `last_month`, `custom` | 30 dakika |
| `this_year` | 1 saat |

`summary` 5 dakika, liste endpoint'leri ise önbelleğe alınmaz. Sık yenileme gerekmiyorsa `computed_at` değerine bakıp gereksiz istekten kaçının.

### İstek sınırı

İstatistik endpoint'lerinde sınır, varsayılan olarak klinik ve kullanıcı başına dakikada 60 istektir. Genel API sınırı ayrıca geçerlidir ([Oran sınırları](/api/istekler/oran-sinirlari)). Sınır aşılınca `429 TOO_MANY_REQUESTS` döner; mesaj İngilizcedir (`Too many requests.`). `Retry-After`, `X-RateLimit-Limit` ve `X-RateLimit-Remaining` başlıklarını okuyun.

### Hatalar

| Kod | HTTP | Ne zaman |
| - | - | - |
| `UNAUTHENTICATED` | 401 | Token eksik veya geçersiz |
| `TENANT_HEADER_REQUIRED` | 400 | `X-Tenant` başlığı yok |
| `TENANT_NOT_FOUND` | 404 | Klinik yok veya kullanıcı bu kliniğe erişemiyor |
| `FORBIDDEN` | 403 | Token'da `statistics:read` yok veya grup izni eksik (`summary` için asla izin nedeniyle dönmez) |
| `VALIDATION_FAILED` | 422 | Geçersiz `period`, `from`, `to`, `threshold`, `month`, `day`, `per_page` veya `page` |
| `SUBSCRIPTION_REQUIRED`, `ACCESS_RESTRICTED_BY_OVERDUE_PAYMENT` | 402 | Abonelik bitmiş veya gecikmiş ödeme erişimi kısıtlıyor |
| `SETUP_REQUIRED` | 428 | Klinik kurulumu tamamlanmamış |
| `TOO_MANY_REQUESTS` | 429 | İstek sınırı aşıldı |

402 ve 428 kilitleri için [Erişim kilitleri](/api/istekler/erisim-kilitleri), diğer kodlar için [Hata kodları](/api/istekler/hata-kodlari) sayfasına bakın. İzinlerin görünürlüğü nasıl etkilediği [İzinler ve görünürlük](/api/izinler-ve-gorunurluk) sayfasında anlatılır.


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