curl -X DELETE "https://{slug}.crm.blesyum.app/api/crm/v1/lc/ai-agent-preview/conversations/<id>" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}92 uç · /api/crm/v1/lc
İstek örnekleri ucun GERÇEK metodu ve yolundan üretilir. 92 ucun elle doğrulanmış gövde örneği henüz yok; o uçlarda iskelet gövdesizdir — uydurma bir alan yazmıyoruz.
curl -X DELETE "https://{slug}.crm.blesyum.app/api/crm/v1/lc/ai-agent-preview/conversations/<id>" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}Tek uç: panel açılışında dört ayrı istek yapmasın (bakiye sayfası her AI ekranının üstünde bir bant olarak da kullanılır).
curl -X GET "https://{slug}.crm.blesyum.app/api/crm/v1/lc/ai-agent/credits" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}Neden ayrı bir PUBLIC uç: banka çağrısı kullanıcı oturumu taşımaz ve `payment_id` yalnız bu POST'ta gelir. Tarayıcı tarafında "pencere kapandı → tamamla" varsayımıyla `conversation_id`'yi `payment_id` sanmak iyzico'da HER ZAMAN başarısız olurdu. Dönüş bir **HTML sayfasıdır**: banka bunu iframe/pencere içinde açar; sayfa `postMessage` ile ana pencereye sonucu bildirir ve kendini kapatır. # Panics Yok — tüm hata yolları HTML sayfasıyla kapatılır (bankaya 500 dönmek yeniden deneme fırtınası başlatır).
curl -X POST "https://{slug}.crm.blesyum.app/api/crm/v1/lc/ai-agent/credits/3ds-return" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}bu durumda ödeme alınmış ama kredi yüklenmemiş bırakırdı.
curl -X GET "https://{slug}.crm.blesyum.app/api/crm/v1/lc/ai-agent/credits/3ds-return" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}Kredi burada YÜKLENMEZ; yalnız ödeme başlatılır (bkz. modül başlığı).
curl -X POST "https://{slug}.crm.blesyum.app/api/crm/v1/lc/ai-agent/credits/checkout" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}⚠ Normal akışta bu uç ÇAĞRILMAZ: bankanın POST'u doğrudan [`threeds_return_h`]'e gider ve tamamlamayı orası yapar (`payment_id` yalnız o POST'ta bulunur). Bu uç **elle kurtarma** yoludur: callback kaybolduysa (ağ/edge kesintisi) operatör iyzico panelindeki `paymentId` ile ödemeyi tamamlatabilir. Aynı çift-yükleme koruması burada da işler. Sıra: iyzico onayı → fatura → yükleme. Fatura üretimi patlarsa kredi yine yüklenir (müşteri parayı ödedi; belgesizlik onu cezalandırmamalı) ve hata loglanır.
curl -X POST "https://{slug}.crm.blesyum.app/api/crm/v1/lc/ai-agent/credits/checkout/complete" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}curl -X GET "https://{slug}.crm.blesyum.app/api/crm/v1/lc/ai-agent/credits/invoices/<id>/pdf" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}Bu uca kadar "Belgeler" ekranı içeriği kullanıcının **elle yapıştırmasını** istiyordu. ⚠ Dosya bu uca GÖNDERİLMEZ, mevcut `files` hattıyla yüklenir (S3'e presigned PUT, yerel kurulumda `/files/{id}/content`). Sebep: global gövde tavanı **1 MiB** (`MAX_BODY_BYTES`) ve rota-düzeyi bir tavan onu AŞAMAZ — multipart bir uç 1 MiB'ın üstündeki her PDF'i 413 ile reddederdi. Dosya hattının kendi tavanı 25 MiB'dir ve byte'lar uygulamadan hiç geçmez. Metin çıkarımı `ai::extract`tedir; taranmış PDF açıkça reddedilir (sessiz boş belge, kullanıcıyı "AI bunu bilmiyor" diye yanıltırdı).
curl -X POST "https://{slug}.crm.blesyum.app/api/crm/v1/lc/ai-agent/documents/from-file" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}yüzden yeni bir şablon eklemek frontend'e hiç dokunmadan yayına girer.
curl -X GET "https://{slug}.crm.blesyum.app/api/crm/v1/lc/ai-agent/flow-templates" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}idcurl -X GET "https://{slug}.crm.blesyum.app/api/crm/v1/lc/ai-agent/flows/<id>/attachments" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}içeriği değişenleri yeniden gömülecek işaretler. Değişmeyeni yeniden gömmek para yakmaktır: karşılaştırma içerik üzerinden yapılır (`content_hash` ingest hattında zaten var), bu uç yalnız TAZE içeriği getirip farklıysa yazar.
curl -X POST "https://{slug}.crm.blesyum.app/api/crm/v1/lc/ai-agent/knowledge/refresh" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}websiteIdcurl -X DELETE "https://{slug}.crm.blesyum.app/api/crm/v1/lc/ai-agent/websites/<websiteId>" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}websiteIdSitemap yoksa 0 döner — hata değil: sitemap'i olmayan siteler de elle sayfa eklenerek kullanılabilir olmalı.
curl -X POST "https://{slug}.crm.blesyum.app/api/crm/v1/lc/ai-agent/websites/<websiteId>/discover" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}curl -X POST "https://{slug}.crm.blesyum.app/api/crm/v1/lc/ai-agent/websites/<websiteId>/sync" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}websiteIdcurl -X GET "https://{slug}.crm.blesyum.app/api/crm/v1/lc/ai-agent/websites/<websiteId>/webpages" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}websiteIdwebpageIdcurl -X GET "https://{slug}.crm.blesyum.app/api/crm/v1/lc/ai-agent/websites/<websiteId>/webpages/<webpageId>" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}websiteIdwebpageIdcurl -X DELETE "https://{slug}.crm.blesyum.app/api/crm/v1/lc/ai-agent/websites/<websiteId>/webpages/<webpageId>" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}idcurl -X GET "https://{slug}.crm.blesyum.app/api/crm/v1/lc/campaigns/<id>" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}idcurl -X PUT "https://{slug}.crm.blesyum.app/api/crm/v1/lc/campaigns/<id>" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}idcurl -X DELETE "https://{slug}.crm.blesyum.app/api/crm/v1/lc/campaigns/<id>" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}id⚠ Yanıt `{report, campaign}`tır. Kampanyanın kendisi 2026-08-20'ye kadar DÖNMÜYORDU: uç onu yalnız sahiplik kontrolü için okuyup ATIYOR, panel ise `r.data.campaign`ı okuyup başlığa basıyordu. Sonuç: rapor sayfasının `h1`i KALICI bir iskelet çubuğu olarak kalıyor ve sayfa "yüklenmiyor" gibi görünüyordu (kullanıcı raporu, 2026-08-20). Aynı sorgu iki işi görür.
curl -X GET "https://{slug}.crm.blesyum.app/api/crm/v1/lc/campaigns/<id>/report" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}idcurl -X GET "https://{slug}.crm.blesyum.app/api/crm/v1/lc/dashboard/chats/<id>/download-transcript" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}curl -X GET "https://{slug}.crm.blesyum.app/api/crm/v1/lc/reports/campaigns" \
-H "Authorization: Bearer <oturum-token>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}gerekirse widget token'ı `lc_widget` cookie + body (`widgetToken`) ile ver, bootstrap döndür. Anonim (token yok) → yeni ziyaretçi; HMAC-identified (eşleşen token yok) → yeni oturum; dönen ziyaretçi (geçerli token) → reuse + taze per-load sessionId.
curl -X GET "https://{slug}.crm.blesyum.app/api/crm/v1/lc/widget/bootstrap" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}idAnonim de loglayabilir (user_id opsiyonel); sessionId yoksa no-op (campaigns::log_impression).
curl -X POST "https://{slug}.crm.blesyum.app/api/crm/v1/lc/widget/campaigns/<id>/imp" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}Ajanlara ConversationCreated broadcast + Created trigger; bot yanıtı = CF10 seam.
curl -X POST "https://{slug}.crm.blesyum.app/api/crm/v1/lc/widget/chats" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}idcurl -X GET "https://{slug}.crm.blesyum.app/api/crm/v1/lc/widget/chats/<id>/download-transcript" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}idsayfalama; ilk sayfa konuşma detayından pre-fill edilir, bu uç yukarı-kaydırma içindir). Ownership (widget_load_owned) → cross-visitor IDOR 404. `{data:[item]}`; FE cursor'a sarar.
curl -X GET "https://{slug}.crm.blesyum.app/api/crm/v1/lc/widget/chats/<id>/messages" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}idendStream). Kilitli→400, reopen=submit_as_customer. Ajanlara newMessage broadcast. HandleLatestUserMessage = no-op (AI kurulu değil → bot yanıtı CF10 seam).
curl -X POST "https://{slug}.crm.blesyum.app/api/crm/v1/lc/widget/chats/<id>/messages" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}iditemId(bedesk müşteri close). Ownership → IDOR 404. Kilitli (abuse terminal) kapatılamaz. actor=None → closed_by müşteriye sızmaz (portal_mark_solved deseni). Kapatma durumu yoksa "Solved" üret. CF15 Paket 9 — müşteri bot cevabını değerlendirir (👍/👎 + isteğe bağlı yorum).
curl -X POST "https://{slug}.crm.blesyum.app/api/crm/v1/lc/widget/chats/<id>/messages/<itemId>/feedback" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}iditemIdcurl -X GET "https://{slug}.crm.blesyum.app/api/crm/v1/lc/widget/chats/<id>/messages/<itemId>/sources" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}idSınıflandırıcıya bir cümle yazdırmaktan farkı: **niyet açıktır**, LLM çağrısı ve kredi harcanmaz. Bot'a atanmamış (zaten insanda olan) konuşmada no-op.
curl -X POST "https://{slug}.crm.blesyum.app/api/crm/v1/lc/widget/chats/<id>/request-human" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}idcurl -X POST "https://{slug}.crm.blesyum.app/api/crm/v1/lc/widget/chats/<id>/submit-form-data" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}idcurl -X GET "https://{slug}.crm.blesyum.app/api/crm/v1/lc/widget/conversations/<id>" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}curl -X POST "https://{slug}.crm.blesyum.app/api/crm/v1/lc/widget/customers/sync-external-data" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}Ajan ucuyla aynı gövdeyi (`store_upload_response`) paylaşır; ayrılan tek şey KAPI ve KOTA. Ayrı bir uç olmasının sebebi: panelin ucu oturum ister, widget ziyaretçisinin çekirdek oturumu YOKTUR (kimliği widget token'ıdır) — 2026-08-18'e kadar widget de panelin ucuna gidiyor ve 401 alıyordu. 🔴 **Anonim kapıya kotasız yükleme AÇILMAZ.** Buraya ulaşmak için hesap gerekmiyor; sınırsız bırakmak, herhangi birinin kiracının deposunu doldurabilmesi demektir. Üç sınır birden uygulanır: 1. **kimlik**: `require_visitor` — bootstrap'tan geçmiş bir ziyaretçi oturumu şart 2. **hız**: ziyaretçi başına `WIDGET_UPLOAD_LIMIT` / `WIDGET_UPLOAD_WINDOW` 3. **boyut**: `WIDGET_MAX_UPLOAD_BYTES` (panelin tavanından KÜÇÜK — bilinçli)
curl -X POST "https://{slug}.crm.blesyum.app/api/crm/v1/lc/widget/file-entries" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}curl -X GET "https://{slug}.crm.blesyum.app/api/crm/v1/lc/widget/help-center-data" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}L2: landing verisinden beslenir (öne çıkan makale seçimi L7'de inceltilir).
curl -X GET "https://{slug}.crm.blesyum.app/api/crm/v1/lc/widget/home-article-list" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}broadcast = L5. session_id touch widget gate'inde (resolve_visitor_by_token) yapılır.
curl -X POST "https://{slug}.crm.blesyum.app/api/crm/v1/lc/widget/visits" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}idcurl -X POST "https://{slug}.crm.blesyum.app/api/crm/v1/lc/widget/visits/<id>/change-status" \
-H "Accept: application/json"{
"data": "…",
"trace_id": "01JC…"
}