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

# İzinler ve kayıt görünürlüğü

> İzin, scope ve kayıt sahipliğinin birlikte nasıl değerlendirildiğini, "tümünü görüntüleme" izinlerini ve record_state bloğunu anlatır.

Bir API çağrısının başarılı olması için token'ın scope'u, kullanıcının klinikteki **İzin**'i ve kaydın kullanıcıya görünür olması birlikte gerekir. Bu sayfa üç katmanın nasıl birleştiğini, hangi izinlerin kayıtları genişlettiğini ve yanıttaki `record_state` bloğunu anlatır. Klinik seçimi için [Klinikler ve X-Tenant](/api/klinikler-ve-x-tenant) sayfasına bakın.

## Yetkilendirme katmanları

Her istek aşağıdaki sırayla denetlenir. İlk başarısız adım yanıtı belirler.

| Sıra | Katman | Başarısız olursa |
| - | - | - |
| 1 | Geçerli token | `401 UNAUTHENTICATED` |
| 2 | `X-Tenant` başlığı ve kliniğe üyelik | `400 TENANT_HEADER_REQUIRED` veya `404 TENANT_NOT_FOUND` |
| 3 | Klinik kilitleri (abonelik, kurulum) | `402` veya `428` |
| 4 | Token scope'u | `403 FORBIDDEN`, mesaj `Invalid scope(s) provided.` |
| 5 | Seçili klinikteki izin | `403 FORBIDDEN`, mesaj `Bu işlem için yetkiniz yok.` |
| 6 | Kayıt görünürlüğü | `404 RESOURCE_NOT_FOUND`; Lead'de ve sohbet başlatmada `403` |
| 7 | Kayıt durumu (`record_state`) | `409 CUSTOMER_ERASED` veya `403 LEAD_NOT_ASSIGNED` |
| 8 | İş kuralları | `409` / `422` alan koduyla |

<Note>
  Scope ve izin birbirinin yerini tutmaz. `Update:Customer` iznine sahip bir kullanıcı, `customers:write` scope'u olmayan bir token'la `403 Invalid scope(s) provided.` alır. Tam yetkili bir token da izni olmayan kullanıcıyı `403 Bu işlem için yetkiniz yok.` hatasından kurtarmaz. Scope listesi için [Scope'lar](/api/kimlik-dogrulama/scopelar) sayfasına bakın.
</Note>

İzinler yalnızca klinik rolleri üzerinden gelir. Kullanıcıya doğrudan izin verilmez. Kullanıcının bir klinikteki izinleri, o klinikteki rollerinin izinlerinin birleşimidir. Aynı kullanıcı başka bir klinikte farklı izinlere sahip olabilir; izinler her zaman `X-Tenant` ile seçtiğiniz klinikte değerlendirilir.

İzinler `Fiil:Konu` biçimindedir: `View:Lead`, `Update:Customer`, `ViewAllLeads:Lead`.

## Kullanıcının izinlerini okuma

İki endpoint izinleri okumanızı sağlar. İkisi de `X-Tenant` gerektirir.

| Metot | Endpoint | Açıklama | Scope | Gereken izin |
| - | - | - | - | - |
| GET | `/api/v1/account/roles` | Token sahibinin seçili klinikteki rollerini ve izinlerini döndürür | `account:read` | Kliniğe üyelik yeterli |
| GET | `/api/v1/permissions` | Rollere atanabilir izin kataloğunu döndürür | `roles:read` | `View:Role` |

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

  ```json Yanıt theme={null}
  {
    "success": true,
    "data": {
      "roles": ["salesperson"],
      "permissions": ["View:Lead", "Create:Lead", "View:Conversation"]
    }
  }
  ```
</CodeGroup>

`data.permissions` yalnızca izin adlarını içerir. Bir uç noktayı çağırmadan önce gereken iznin listede olup olmadığına bakarak arayüzünüzde ilgili düğmeleri gizleyebilirsiniz. Rol veya izin değişikliği bir sonraki istekte geçerli olur; uygulamanız izin listesini yeniden okumalıdır.

`GET /permissions` her izin için `id`, `name` ve `label` döndürür. İzinler modül ve grup altında gruplanır. `label` değeri `Accept-Language` başlığına göre yerelleşir. Rol oluşturma ve atama için [Kullanıcılar, roller ve davetler](/api/kaynaklar/kullanicilar-roller-davetler) sayfasına bakın.

<Info>
  Bir rolü kaydederken veya kullanıcıya rol atarken sahip olmadığınız izinleri veremezsiniz. Bu denemeler `403 FORBIDDEN` ile reddedilir ve `data.missing_permissions` eksik izinleri listeler. Kendi rollerinizi de değiştiremezsiniz.
</Info>

## Tümünü görüntüleme izinleri

`View:X` izni, kaydın listesini ve detayını **kendi payınız** ile sınırlı okumanızı sağlar. Klinikteki tüm kayıtları görmek için aynı kaynağın `ViewAll…` izni gerekir. Bu izne sahip olmayan kullanıcıda API sessizce yalnızca kendi kayıtlarını döndürür.

| İzin | Panel etiketi | Bu izin olmadan görünen kayıtlar |
| - | - | - |
| `ViewAllLeads:Lead` | Tüm leadleri görüntüleme | Yalnızca size atanmış Lead'ler (her rol için geçerli) |
| `ViewAllCustomers:Customer` | Tüm hastaları görüntüleme | Satış Temsilcisi dışındaki roller: yalnızca lead'i size atanmış hastalar. Satış Temsilcisi: lead'siz veya dönüşmüş tüm hastalar |
| `ViewAllAppointments:Appointment` | Tüm randevuları görüntüleme | Uygulayıcısı olduğunuz veya hastasının lead'i size atanmış randevular |
| `ViewAllOffers:Offer` | Tüm teklifleri görüntüleme | Oluşturduğunuz veya lead'i size atanmış teklifler |
| `ViewAllSales:Sale` | Tüm satışları görüntüleme | Satıcısı olduğunuz veya lead'i size atanmış satışlar |
| `ViewAllConversations:Conversation` | Tüm konuşmaları görüntüleme | Yalnızca kişisinin lead'i size atanmış sohbetler |
| `ViewAllChannelBlacklists:ChannelBlacklist` | Tüm kanal kara listelerini görüntüleme | Hastasının lead'i size atanmış kayıtlar |
| `ViewAllTickets:Ticket` | Tüm destek taleplerini görüntüleme | Hastasının lead'i size atanmış talepler |
| `ViewAllNotes:Note` | Tüm notları görüntüleme | Yazarı veya atanan kişisi olduğunuz notlar |
| `ViewAllAIReports:AIReport` | Tüm yapay zekâ raporlarını görüntüleme | Sizin oluşturduğunuz, tamamlanmış raporlar |

Ürün, depo, tedavi, oda, dosya, fatura, kanal ve pipeline gibi diğer kaynaklarda `View:X` izni klinik genelini kapsar; bu kaynaklarda ayrı bir `ViewAll…` izni yoktur.

<Warning>
  Sohbetlerde kural sert işler. `ViewAllConversations:Conversation` izni olmayan kullanıcı, yalnızca kişisinin lead'i kendisine atanmış sohbetleri görür. Kişisi olmayan veya kişisinin lead'i olmayan sohbetler bu kullanıcılara görünmez. Hasta sohbetleri ekip içinde paylaşılmaz. Sohbetlere bağlı medya dosyaları da aynı kurala uyar: görmediğiniz sohbetin dosyalarını `GET /files` ve indirme uç noktalarında göremezsiniz.
</Warning>

`GET /conversations` isteğinde `scope` parametresi kullanılabilir:

| Değer | Sonuç |
| - | - |
| `assigned` | Yalnızca lead'i size atanmış sohbetler |
| `all` (varsayılan) | Görmeye yetkili olduğunuz tüm sohbetler |

`ViewAllConversations` izniniz yoksa `scope` değeri ne olursa olsun sonuç atanmış sohbetlerle sınırlı kalır. Filtreler görünürlük kapsamını hiçbir zaman genişletmez.

Kliniğin geneline ait toplamlar da `ViewAll…` izni ister. Örneğin `GET /statistics/customers` için `ViewAllCustomers:Customer`, `GET /statistics/revenue` için `ViewAllSales:Sale` gerekir.

## Atanmış kayıtlar

Lead'ler, hastalar ve onlara bağlı kayıtlar Lead'in atandığı kullanıcıya göre sahiplenir. Bir kayıt kapsamınızın dışındaysa API iki farklı yanıt verir.

**Genel kural: 404.** Kapsamınız dışındaki bir kaydın `id` değeri `404 RESOURCE_NOT_FOUND` döndürür. Kaydın var olup olmadığı sızdırılmaz.

**İki istisna: 403.** Lead ve sohbet için API kaydın kime atandığını söyler:

* Var olan ama size görünmeyen bir Lead için `403 LEAD_NOT_ASSIGNED` döner. Silinmiş veya hiç olmayan bir Lead yine `404` verir.
* Size atanmamış bir kişiyle `POST /conversations` ile sohbet başlatmak `403 CONVERSATION_NOT_ASSIGNED` döndürür. İstek reddedildiğinde hiçbir kayıt oluşmaz.

Her iki hatada `data.assigned_user` alanı Lead'in sahibini `{id, name}` olarak, Lead kimseye atanmamışsa `null` olarak verir.

```json CONVERSATION_NOT_ASSIGNED yanıtı theme={null}
{
  "success": false,
  "error_code": "CONVERSATION_NOT_ASSIGNED",
  "message": "Bu kişinin sohbeti size atanmamış. Görüntülemek için yöneticinizden atama ya da yetki isteyin.",
  "data": { "assigned_user": { "id": 123, "name": "Ayşe Yılmaz" } },
  "meta": { "timezone": "Europe/Istanbul" }
}
```

<Note>
  Sohbet başlatmak `Create:Conversation` izni ister. Bu izin yeni kurulan kliniklerde varsayılan olarak yalnızca `super_admin` rolündedir. Satış Temsilcisi rolü sohbet başlatacaksa kliniğin yöneticisi izni role eklemelidir.
</Note>

### Satış Temsilcisi için Lead kilidi

`salesperson` rolüne sahip ve `ViewAllLeads:Lead` izni olmayan kullanıcı için ek bir kural çalışır. Başka bir temsilciye atanmış veya kimseye atanmamış **lead aşamasındaki** hastanın kayıtları:

* Randevu, hatırlatma, teklif, satış, destek talebi, sohbet, işlem ve fatura gibi ilişkili yanıtlarda **maskelenir**: `is_masked: true` gelir, ad ve telefon kısmen gizlenir (`Ah••• Öz•••`, `+90 5•• ••• •• 33`).
* **Salt okunur** olur: bu kayıtlara yapılan her yazma isteği `403 LEAD_NOT_ASSIGNED` ile reddedilir.

Dönüşmüş hastalar, lead'siz hastalar ve temsilcinin kendi Lead'leri kilitlenmez. Başka roller bu kilide tabi değildir. Atama için [Lead atama](/panel/leadler/atama) sayfasına bakın.

## record\_state

Bazı kaynaklar yanıtta bir `record_state` bloğu taşır. Blok, bu kaydın üzerinde yazma yapılıp yapılamayacağını **istek atmadan** anlamanızı sağlar.

```json theme={null}
"record_state": {
  "is_read_only": true,
  "reason_code": "LEAD_NOT_ASSIGNED"
}
```

| Alan | Tür | Açıklama |
| - | - | - |
| `is_read_only` | boolean | `true` ise bu kayda yapılan her yazma isteği reddedilir |
| `reason_code` | string veya `null` | `CUSTOMER_ERASED`, `LEAD_NOT_ASSIGNED` veya `null` |

`reason_code`, yazma isteğinin döneceği `error_code` ile aynıdır:

| `reason_code` | Anlamı | Yazma yanıtı |
| - | - | - |
| `LEAD_NOT_ASSIGNED` | Kayıt, size atanmamış bir lead'e ait | `403 LEAD_NOT_ASSIGNED` |
| `CUSTOMER_ERASED` | Hastanın verileri imha edilmiş, kayıt salt okunur | `409 CUSTOMER_ERASED` |

İki durum birlikte geçerliyse `CUSTOMER_ERASED` önceliklidir.

<Warning>
  `is_read_only: false`, yazabileceğiniz anlamına gelmez. Blok yalnızca kayıt durumundan doğan engeli gösterir. Scope ve izin denetimleri ayrıca uygulanır.
</Warning>

`record_state` şu kaynakların yanıtlarında bulunur: hasta, dosya, not, fatura, hesap işlemi, Lead görevi, randevu hatırlatması ve randevu tedavi seansı.  Hasta ve Lead kaynakları için [Hastalar](/api/kaynaklar/hastalar) ve [Leadler](/api/kaynaklar/leadler) sayfalarına bakın.

## Hata kodları

| Kod | HTTP | Ne zaman |
| - | - | - |
| `UNAUTHENTICATED` | 401 | Token eksik, geçersiz veya süresi dolmuş |
| `TENANT_HEADER_REQUIRED` | 400 | `X-Tenant` başlığı gönderilmemiş |
| `TENANT_NOT_FOUND` | 404 | Klinik yok veya kullanıcı o kliniğin üyesi değil |
| `FORBIDDEN` | 403 | Token'da scope yok (`Invalid scope(s) provided.`) veya kullanıcıda izin yok (`Bu işlem için yetkiniz yok.`) |
| `RESOURCE_NOT_FOUND` | 404 | Kayıt yok, başka klinikte veya görünürlük kapsamınızın dışında |
| `LEAD_NOT_ASSIGNED` | 403 | Kayıt, size atanmamış bir lead'e ait; `data.assigned_user` sahibini verir |
| `CONVERSATION_NOT_ASSIGNED` | 403 | Size atanmamış bir kişiyle sohbet başlatma; `data.assigned_user` sahibini verir |
| `CUSTOMER_ERASED` | 409 | İmha edilmiş hastaya veya onun kayıtlarına yazma denemesi |

`FORBIDDEN` iki farklı nedenle döner. Hatanın scope'tan mı izinden mi geldiğini `message` alanından ayırt edin. Kodların tam listesi için [Hata kodları](/api/istekler/hata-kodlari), zarf yapısı için [Hatalar](/api/istekler/hatalar) sayfasına bakın. 402 ve 428 kilitleri [Erişim kilitleri](/api/istekler/erisim-kilitleri) sayfasında anlatılır.


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