D

DoWaba — Geliştirici Rehberi

API Dokümantasyonu →

DoWaba — Geliştirici Entegrasyon Rehberi (Menü → API)

Kime: DoWaba panelini kendi uygulamasından (headless) kullanan geliştirici partner'lar. Özellikle Trusted Partner OAuth ile bağlanıp kullanıcı adına panel API'larını çağıranlar için.

Bu doküman neden var: API Dokümantasyonu (/api-docs/) endpoint'leri API grubuna göre dizer — eksiksiz referans ama "panelde gördüğüm şeyin API karşılığı ne?" sorusuna doğrudan cevap vermez. Bu rehber panelin sol menüsünü takip eder: her menü için → ne işe yarar · paneldeki form/alanlar · hangi endpoint · örnek istek · örnek yanıt. İkisi birbirini tamamlar:

İhtiyaç Kaynak
"Hangi menü hangi endpoint, akış nasıl?" Bu doküman
"Bu endpoint'in tam validasyon alanları neler?" API Dokümantasyonu — her endpoint'te alan listesi
Postman / OpenAPI 3 /api-docs/collection.json · /api-docs/openapi.yaml
Çalışan örnek projeler Örnek Projeler
Toplu gönderim / pazarlama uyum kuralları § 0.6 — opt-out + İYS + KVKK (ZORUNLU)
API'lerde ne değişti? (yeni endpoint / kural değişikliği) Panelde: Geliştirici → Sürüm Notları (canlı, sürümlü) — bkz. § 13

0. Nasıl çalışır — Trusted Partner OAuth

Senin uygulaman kendi users tablosunu tutmuyor; kullanıcılar DoWaba'nın user havuzunda. Uygulaman, kullanıcı adına DoWaba'nın panel API'larını (sites, conversations, contacts…) çağırıyor — sanki kullanıcı DoWaba'nın resmi mobil uygulamasındaymış gibi. Bunu sağlayan şey sanctum_token.

0.1 sanctum_token'ı nasıl alıyorsun (özet)

  1. (Tek seferlik) DoWaba ekibi senin OAuth client'ında issues_sanctum_token özelliğini açar. Bu, sözleşmeli partner için elle açılır — self-service panelden açılamaz.
  2. Kullanıcı "Login with DoWaba" ile gelir (PKCE + onay ekranı).
  3. Backend'in POST /api/oauth/token çağırır (grant_type=authorization_code).
  4. Yanıtta standart alanların yanında ekstra döner:
{
  "access_token":       "doat_...",
  "id_token":           "eyJ...",
  "refresh_token":      "dort_...",
  "expires_in":         3600,
  "scope":              "openid profile email",

  "sanctum_token":      "12|abc...",   // ← panel API'ları için BU
  "sanctum_token_type": "Bearer"
}

sanctum_token gelmiyorsa: client trusted partner değil veya kullanıcı superadmin (superadmin trusted partner app'lere giremez — onay ekranında bloklanır).

0.2 Her istekte

curl https://dowaba.com/api/sites \
  -H "Authorization: Bearer 12|abc..." \
  -H "Accept: application/json"

0.3 "Kullanıcı kim?" (kimlik / yetki kontrolü)

GET /api/auth/user        # oturum açan kullanıcı: id, name, email, role, reseller_id,
                          # allowed_modules, assigned_site_id, is_agent_only ...
GET /api/user             # profil detayları

allowed_modules alanı kritik: kullanıcı kısıtlıysa (sub-user / bayi müşterisi / agent) bu bir whitelist (["whatsapp","mail",...]). null ise tüm modüller açık. Bir menü/endpoint'i göstermeden önce buna bak.

0.4 Yanıt zarfı & hatalar

0.4.1 Kullanıcıyı panele taşı — tek-kullanımlık SSO giriş linki (2026-06-17)

API erişimin var ama kullanıcıyı tarayıcıda panele sokmak istiyorsan (örn. kendi arayüzünde "Panele Git" butonu):

POST /api/oauth/login-link
#   Bearer: sanctum_token   (yalnız 'oauth-' Trusted Partner PAT; panel/'api-token' → 403)
#   → 200 { "success": true, "url": "https://<marka-host>/admin/impersonate?token=...",
#          "expires_at": "...", "expires_in_seconds": 300 }
#   → 403 token Trusted Partner değilse  ·  422 pasif/askıdaki hesap

0.5 ⚠️ Veri kullanım kuralları (Meta uyumu — ZORUNLU)

inbox/unified, {kanal}/messages/..., inbox/media, contacts gibi endpoint'ler WhatsApp / Instagram / Messenger mesaj içeriği + telefon + isim + medya (Meta Verisi) döndürür. Bu veriyi çekmek = Meta Verisi'nin 3. tarafça işlenmesi → Meta Platform Terms + WhatsApp Business Solution Terms'e tabidir. Kurallar (DoWaba Partner Sözleşmesi ile bağlayıcı):

Özet: "İşletme kendi DoWaba verisi için senin aracını kullanıyor" = uygun. "Sen DoWaba verisiyle kendi ürününü besliyorsun" = ihlal.


0.6 ⚠️ Toplu gönderim & pazarlama uyumu (ZORUNLU)

scheduled-jobs, contacts/groups/{id}/send-template, mail-campaigns gibi toplu / kampanya gönderim endpoint'lerini çağırıyorsan Türkiye mevzuatı (ETK 6563 + İYS + KVKK) senin entegrasyonun için de geçerlidir — panelden manuel gönderim ile API üzerinden gönderim aynı hukuki yükümlülüğe tabidir. Üç kural:

1. Red (opt-out) listesi — DAİMA uygula. Alıcı "DUR / STOP / İPTAL" yazdıysa veya elle çıkarıldıysa kanal-bağımsız suppression listesine (message_opt_outs) düşer. Bu kişilere gönderim yapılamaz.

2. İYS onayı — pazarlamada ön onay zorunlu. Ticari/pazarlama içerikli toplu mesaj için alıcının önceden onayı

3. KVKK aydınlatması — botu kapatırsan SEN sorumlusun. Bir konuşmada toggle-bot ile AI'yı kapatıp kendi uygulamandan cevaplıyorsan, DoWaba'nın otomatik KVKK aydınlatması (son alıcının ilk mesajında gönderilen) devreye girmez — aydınlatma AI cevabına bağlıdır. Bu durumda son alıcıya KVKK aydınlatmasını sen sağlamak zorundasın (veri sorumlusu = DoWaba hesap sahibi; sen onun adına işleyensin → Partner Sözleşmesi).

Red (opt-out) listesi endpoint'leri:

GET    /api/message-opt-outs?site_id=12&channel=whatsapp   # red listesi — channel: whatsapp | sms | mail | call
POST   /api/message-opt-outs   { "site_id": 12, "channel": "call", "identifier": "+905551112233", "reason": "telefonla beni aramayın dedi" }
DELETE /api/message-opt-outs/{id}

identifier = telefon (whatsapp/sms/call, E.164) veya e-posta (mail) — sistem normalize eder. Yanıt sayfalıdır (data, total, current_page, last_page). channel=call sesli arama kampanyalarının (§ 5) red listesidir; kaydı silmek numarayı tekrar aranabilir yapar.


Menü → bölüm haritası

DoWaba sol menüsündeki sırayla:

Sol menü Bölüm Ana endpoint(ler)
Siteler §1 sites, sites/{site}/faqs, sites/{site}/documents, sites/{site}/functions
Mesaj Kutusu (Inbox) §2 inbox/unified, inbox/mark-read, inbox/media/...
Kanallar (WhatsApp · Telegram · Messenger · Instagram · X · TikTok · Mail · Widget · Google Yorumlar) §3 {kanal}/conversations, {kanal}/messages/..., {kanal}/send
Rehber & WP Kampanya §4 contacts/groups, contacts/..., scheduled-jobs
Şablonlar / Kampanyalar (+ Çağrı Kampanyası) §5 whatsapp/templates, mail-templates, mail-campaigns, voice-campaigns
Çağrılar (Voice) + Outbound + Santral §6 sites/{site}/voice-conversations, voice/call, sites/{site}/transfer-targets, outbound-intents, outbound-messages
Müşteri Talepleri (Callback) §7 callback-requests
Potansiyel Müşteriler (Leads / CRM) §7.5 leads, leads/scan, leads/{id}/stage, leads/{id}/assign, leads/{id}/activities
Bilgi Tabanı (site içi: SSS + Belge) §8 sites/{site}/faqs, sites/{site}/documents
Kullanım & Krediler / Abonelik §9 me/usage, credits, subscriptions/*, ai-credit/*
Geliştirici (kendi token/webhook/oauth) §10 me/tokens, webhook-endpoints, me/oauth/clients
Profil & Ayarlar §11 auth/user, user, settings
Faturalarım / Bayi §12 me/billing, reseller/*

Atlananlar / kısmi (2026-06-17 güncellendi): Reklam Yönetimi (ads/*) — beta, ads_beta_enabled flag'i arkasında (App Review + Business Verification onayına kadar yalnız superadmin pilot; GA olunca buraya §-bölüm eklenir). Paylaşım (social-posts/*, youtube/*, facebook-page/*) — kısmi/deneysel (YouTube videoları compliance audit'e kadar PRIVATE, IG publish scope App Review'da). Randevu (ayrı modül, site'ta appointment modülü gerektirir), Trendyol Q&A (trendyol/*). İhtiyaç olursa aynı şablonla eklenir.


1. Siteler

Ne işe yarar: Bir "site" = bir AI asistan yapılandırması (sistem promptu, dil, widget ayarı, bağlı kanallar). Her şeyin merkezi; çoğu endpoint sites/{site}/... altındadır.

Paneldeki form (Yeni Site): ad, açıklama, sistem promptu, dil(ler), (opsiyonel) domain.

Listeleme

GET /api/sites
{ "success": true, "data": [ { "id": 12, "name": "Örnek Mağaza", "is_active": true, "api_key": "...", ... } ] }

Tek site

GET /api/sites/{site}

Yeni site açma (hibrit slot / pay-per-site)

POST /api/sites
Content-Type: application/json

{ "name": "Örnek Mağaza", "description": "...", "settings": { "system_prompt": "Sen ...", "languages": ["tr"] } }

Bayi, müşteri adına site açar: POST /api/reseller/customers/{user}/sites (§12).

Güncelle / Sil / Geri al

PUT    /api/sites/{site}                 # ad, sistem promptu, ayarlar (settings.widget_theme dahil)
DELETE /api/sites/{site}                 # KVKK: anonymize + soft delete (30 gün geri alınabilir)
POST   /api/sites/{site}/restore         # 30 gün içinde geri al
POST   /api/sites/{site}/regenerate-key  # API anahtarını yeniden üret (widget vb.)
POST   /api/sites/{site}/widget-theme/ai # { "prompt": "koyu lacivert, altın vurgulu" } → AI widget tema ÖNERİSİ
POST   /api/sites/{site}/auto-messages/beautify # { "field": "ai_error", "text": "..." } → AI ile güzellenmiş metin ÖNERİSİ

widget-theme/ai yalnız öneri döner ({theme, summary}); kalıcı kayıt için dönen theme objesini PUT /api/sites/{site} ile settings.widget_theme alanına yaz (10 renk #RRGGBB + launcher_icon).

Otomatik mesajlar (2026-06-12): AI cevap veremediğinde müşteriye giden sistem metinleri site bazında özelleştirilebilir: PUT /api/sites/{id} ile settings.auto_messages.{unpaid_notice|ai_error}. Alan boş/yok ise sitenin birincil dilinde hazır metin gönderilir. auto-messages/beautify (field: unpaid_notice | ai_error; text opsiyonel — boşsa varsayılan baz alınır) yalnız öneri döner ({success, text}), kaydetmez.

Site domain'leri (widget origin doğrulama)

GET    /api/sites/{site}/domains
POST   /api/sites/{site}/domains          { "domain": "magaza.com" }
POST   /api/domains/{domain}/verify
DELETE /api/domains/{domain}

2. Mesaj Kutusu (Inbox)

Ne işe yarar: 8+ kanalın tek birleşik listesi. Panelin "Mesaj Kutusu"nun aynısı. Tek istekte tüm kanalların konuşmalarını + okunmamış sayaçlarını verir (yoksa kanal başına ~35 ayrı istek atman gerekir).

Birleşik konuşma listesi ← önerilen giriş noktası

GET /api/inbox/unified
GET /api/inbox/unified?filter=unread     # sadece okunmamışlar
GET /api/inbox/unified?fresh=1           # cache (15s) bypass
{
  "conversations": [
    { "channel": "whatsapp", "identifier": "+905551112233", "profile_id": 4,
      "display_name": "Örnek Müşteri", "last_message": "...", "unread": 2, "bot_active": true, "timestamp": "..." }
  ],
  "counts": { "whatsapp": 3, "telegram": 1 },
  "totals": { "unread": 4 }
}

channel + identifier (+ gerekiyorsa profile_id) ikilisi, kanal bölümlerindeki (§3) mesaj/gönder endpoint'lerine girdi olur.

Okundu işaretle (tüm kanallar tek endpoint)

POST /api/inbox/mark-read
{ "channel": "whatsapp", "identifier": "+905551112233", "profile_id": 4 }

Gönderilemeyen cevabı tekrar dene (2026-06-12)

Bot/operatör cevabı dış API'ye anlık reddedilirse (Meta 5xx/429/bağlantı hatası) mesaj failed kalır — kaybolmaz. Arka planda kademeli otomatik retry (5/15/45dk, maks 3) çalışır; ek olarak panelden "Tekrar dene" bu endpoint'i tetikler:

POST /api/inbox/messages/{channel}/{id}/retry     # channel: whatsapp | instagram | messenger | telegram
#   → 200 { "success": true, "delivery_status": "sent", "message_id": "..." }
#   → 422 mesajlaşma penceresi (24 saat) kapalıysa (TG'de pencere yok)

Mesaja ekli medya indir (foto/video/dosya)

GET /api/inbox/media/{channel}/{messageId}            # channel: whatsapp | instagram | telegram | messenger
GET /api/inbox/media/{channel}/{messageId}?download=1
GET /api/inbox/media-signed/{channel}/{messageId}     # imzalı varyant — Authorization header GEREKMEZ

İmzalı varyantın URL'ini kendin üretme: kanal mesaj listesi yanıtlarındaki media_signed_url alanı hazır imzalı gelir (24 saat geçerli, sonra 403). Medyayı kendi arayüzünde <img>/<video>/<audio> src'ına doğrudan koyacaksan bunu kullan — auth'lu /inbox/media/... tarayıcı media etiketlerinde header gönderilemediği için 401 alır. Sunucu tarafı indirme için Bearer'lı /inbox/media/... kullanmaya devam et.


3. Kanallar — mesajlaşma

Tüm mesajlaşma kanalları aynı 4 adımlı pattern'i izler:

  1. Konuşmaları listeleGET {kanal}/conversations
  2. Bir konuşmanın mesajlarıGET {kanal}/messages/{identifier}
  3. Yanıt gönderPOST {kanal}/send (Instagram/X/TikTok/Mail'de farklı isim)
  4. Botu aç/kapa (o konuşmada AI cevap versin mi) → POST {kanal}/toggle-bot

Bot mantığı: toggle-bot ile bir konuşmada AI'yı kapatırsan, o konuşmaya sen (operatör) cevap yazarsın. Açık bırakırsan gelen mesaja AI otomatik cevap verir. toggle-block ile konuşmayı engellersin.

Sayfalama (mesaj listesi) — 2026-06-07: {kanal}/messages/... varsayılanda konuşmanın tüm geçmişini döndürür (geriye dönük uyumlu). Performans için opt-in sayfalama var: ?limit=50 → en yeni 50 mesaj + { messages, has_more, oldest_id } zarfı; daha eski sayfa için ?before_id={oldest_id}&limit=50 (yukarı kaydırma cursor'ı, oldest_id'yi zincirle). limit/before_id vermezsen eski davranış (tüm mesajlar, düz dizi) aynen korunur — mevcut entegrasyonların bozulmaz. Destekleyen kanallar: WhatsApp · Telegram · Messenger · TikTok DM · X. (Instagram/Mail konuşma-gruplu yanıt verir, Widget/Voice tekil konuşmadır → bunlarda sayfalama yoktur.) limit 1–200 clamp.

3.1 WhatsApp — tam örnek

Paneldeki form (profil ekleme): bağlantı tipi (Evolution QR / Meta Cloud API / Coexistence) + ilgili kimlik bilgileri. Profil = bir WhatsApp numarası.

GET  /api/whatsapp/profiles                       # bağlı numaralar (profiller)
GET  /api/whatsapp/conversations                  # ?profile_id=X ile filtrele
GET  /api/whatsapp/messages/{phone}               # mesajlar (?limit=50&before_id=... ile sayfala — opsiyonel)
POST /api/whatsapp/send                           # yanıt gönder
GET  /api/whatsapp/conversation-state             # ?phone=...&profile_id=... → bot durumu
POST /api/whatsapp/toggle-bot
POST /api/whatsapp/toggle-block
DELETE /api/whatsapp/conversations/{phone}

Gönderme:

POST /api/whatsapp/send
{
  "phone": "+905551112233",
  "profile_id": 4,
  "message": "Merhaba, nasıl yardımcı olabilirim?",
  "media_file_id": null            // opsiyonel — önce POST /api/media/upload
}
{ "success": true, "data": { "id": 9001, "direction": "out", "status": "sent", "created_at": "2026-06-01T10:00:00Z" } }

Profil yönetimi (kurulum):

GET    /api/whatsapp-profiles
POST   /api/whatsapp-profiles            # profil oluştur
POST   /api/whatsapp-profiles/{id}/link-site      { "site_id": 12 }     # profili siteye bağla
POST   /api/whatsapp-profiles/{id}/unlink-site
GET    /api/whatsapp-profiles/{id}/linked-sites
# Evolution (QR): POST whatsapp-profiles/evolution/create → GET .../{id}/evolution/qrcode
# Meta Cloud:     GET whatsapp-profiles/platform/phones → POST whatsapp-profiles/platform/connect

3.2 Diğer kanallar — aynı pattern

Endpoint adları kanaldan kanala değişir ama akış aynıdır. Kimlik alanı (identifier) kanala göre farklı:

Kanal Konuşmalar Mesajlar Gönder Bot aç/kapa identifier
WhatsApp GET whatsapp/conversations GET whatsapp/messages/{phone} POST whatsapp/send POST whatsapp/toggle-bot phone
Telegram GET telegram/conversations GET telegram/messages/{chatId} POST telegram/send POST telegram/toggle-bot chat_id
Messenger GET messenger/conversations GET messenger/messages/{senderId} POST messenger/send POST messenger/toggle-bot sender_id
Instagram GET instagram/messages (mesajlar inline döner) POST instagram/messages/send POST instagram/toggle-conversation-bot sender_id
X (Twitter) GET x/conversations GET x/conversations/{conversationId}/messages POST x/reply POST x/conversations/toggle-bot conversation_id
TikTok (yorum) GET tiktok/conversations GET tiktok/conversations/{videoId}/{openId}/messages POST tiktok/reply POST tiktok/toggle-bot videoId+openId
TikTok (DM) GET tiktok/dm/conversations GET tiktok/dm/conversations/{openId}/messages POST tiktok/dm/toggle-bot openId
Mail GET mail/accounts/{id}/messages GET mail/messages/{id}/thread POST mail/reply POST mail/toggle-bot hesap + thread
Web Widget GET widget-chats GET sessions/{session} POST sessions/{session}/reply (yok) session
Google Yorumlar GET google-reviews GET google-reviews/{id} POST google-reviews/{id}/reply POST google-reviews/{id}/toggle-bot review id

Gönderme gövdesi kanala göre kimlik alanını değiştirir, gerisi aynı kalır:

// Telegram
POST /api/telegram/send       { "chat_id": "123456789", "profile_id": 7, "message": "..." }
// Messenger
POST /api/messenger/send      { "sender_id": "...", "profile_id": 3, "message": "..." }
// Instagram
POST /api/instagram/messages/send  { "sender_id": "...", "message": "..." }
// X
POST /api/x/reply             { "conversation_id": "...", "message": "..." }
// Mail
POST /api/mail/reply          { "message_id": 88, "body": "...", "subject": "..." }

Profil kurulumu her kanalda benzer: GET/POST {kanal}/profiles + .../link-site + OAuth (Instagram/Messenger/TikTok/X/Google → {kanal}/oauth/config|save). Bunlar genelde panel UI'ından yapılır. Tam alanlar API Dokümantasyonu'nda.

Ortak: AI ile mesaj iyileştirme & medya yükleme

POST /api/ai-improve-message          { "channel": "whatsapp", "text": "taslak metin" }   # kanal-aware
POST /api/sites/{site}/ai-improve-message  { "text": "..." }                              # site-explicit
#   → taslağı kanala uygun, kibar versiyona çevirir (20/dk)

POST /api/media/upload   (multipart)  → { "id": 555 }   # sonra send'de media_file_id olarak kullan
GET  /api/media
DELETE /api/media/{id}

4. Rehber & Toplu Gönderim

Ne işe yarar: Kişi/grup yönetimi (CRM) + WhatsApp şablonuyla toplu/zamanlı gönderim.

Gruplar & kişiler

GET    /api/contacts/groups
POST   /api/contacts/groups                       { "name": "VIP Müşteriler" }
PUT    /api/contacts/groups/{id}
DELETE /api/contacts/groups/{id}
GET    /api/contacts/groups/{id}/contacts
POST   /api/contacts/groups/{id}/contacts         { "name": "...", "phone": "+90..." }
PUT    /api/contacts/{id}                         # kişi güncelle (ai_instructions dahil — bkz. not)
POST   /api/contacts/delete                       { "ids": [1,2,3] }
DELETE /api/contacts/groups/{id}/contacts         # grubu boşalt — TÜM kişileri tek istekte siler (grup kalır, geri alınamaz)
POST   /api/contacts/groups/{id}/import           (CSV/çoklu)
POST   /api/contacts/quick-add                    # sohbet panelinden hızlı rehbere ekle
GET    /api/contacts/lookup-by-channel            # ?channel=whatsapp&identifier=+90...

Dış URL'den kişi çek (CSV/JSON) — import-url

Kendi web siteniz / CRM'inizden kişi listesini DoWaba rehberine çekin.

POST /api/contacts/groups/import-url
{
  "name": "Web sitesi lead'leri",
  "url": "https://siteniz.com/api/leads.csv",   // CSV veya JSON döndüren PUBLIC adres
  "api_key": "gizli-anahtar",                    // opsiyonel
  "auth_style": "bearer",                        // bearer | x-api-key | query
  "auto_refresh": false                          // true → her kampanyada yeniden çekilir
}

Akıllı segment (yalnız superadmin): POST /api/contacts/segments/owner_reseller/sync → tüm owner+bayi üyeleri (bayi müşterileri & sub-user hariç), kampanya başlarken canlı kullanıcı sorgusundan tazelenir. Diğer kullanıcılara kapalıdır (403); grup yalnız superadmin'in rehberinde görünür.

Müşteri-bazlı AI talimatı: Bir kişiye özel bot davranışı vermek için PUT /api/conversation-ai-overrides { site_id, channel, identifier, instructions, is_active } (9 kanalda geçerli; aynı kişi WhatsApp/IG/Mail'den yazsa da aynı talimat uygulanır).

Toplu WhatsApp gönderimi (şablonla)

POST /api/contacts/groups/{id}/send-template
{ "template_name": "kampanya_haziran", "site_id": 12, "params": { ... } }

⚠️ Uyum: Bu anlık toplu gönderim de scheduled-jobs gibi opt-out + İYS reddini otomatik filtreler (red'li alıcı atlanır; yanıtta skipped + skipped_samples döner). Yine de pazarlama içerikse alıcıların İYS onayını önceden almış olmalısın (§ 0.6).

Zamanlanmış işler

GET    /api/scheduled-jobs
POST   /api/scheduled-jobs                        # zamanlı toplu gönderim tanımı
POST   /api/scheduled-jobs/{id}/toggle
DELETE /api/scheduled-jobs/{id}
GET    /api/scheduled-jobs/whatsapp-stats/{contactGroupId}

⚠️ scheduled-jobs ile gönderim opt-out + İYS reddini otomatik filtreler (§ 0.6). Onaysız/red listesindeki alıcı atlanır (skipped, kotadan düşmez).

Tek seferlik kampanyaya tarih (2026-06-11): schedule_type=once iken opsiyonel scheduled_at ("2026-06-12 14:00", Europe/Istanbul) gönderilebilir — kampanya o anda başlar. Boş bırakılırsa (veya geçmiş tarihse) hemen başlar. hourly/daily tiplerinde yok sayılır.

İYS onay yönetimi (toplu gönderimden önce zorunlu)

İYS (İleti Yönetim Sistemi) onaylarını yükle/sorgula. Toplu pazarlama göndermeden önce gerekli — § 0.6.

Bu endpoint'ler iys modülü gerektirir (allowed_modules). İYS şu an STUB modda olabilir (summary.stub_mode=true) → gerçek İYS API'sine yazma için hesap credential'ı + production mod gerekir.

GET    /api/iys/consents?site_id=12          # kayıtlı onaylar (data, total, sayfalı)
GET    /api/iys/consents/summary             # { stub_mode, counts }
GET    /api/iys/consents/meta                # { sources, types, recipient_types } — geçerli enum değerleri
POST   /api/iys/consents                     # tekil onay kaydı
POST   /api/iys/consents/attest-group        # bir kişi grubuna toplu onay beyanı
DELETE /api/iys/consents/{id}

Tekil onay kaydı:

POST /api/iys/consents
{
  "site_id": 12,
  "recipient": "+905551112233",            // telefon (MESAJ/ARAMA) veya e-posta (EPOSTA)
  "type": "MESAJ",                         // MESAJ | EPOSTA | ARAMA
  "status": "ONAY",                        // ONAY | RET (varsayılan ONAY)
  "source": "HS_WEB",                      // izin kaynağı — geçerli değerler /iys/consents/meta'da
  "recipient_type": "BIREYSEL",            // BIREYSEL | TACIR
  "consent_date": "2026-06-01 10:00:00",   // iznin alındığı GERÇEK an (gelecek tarih reddedilir)
  "consent_confirmed": true                // ZORUNLU — onayın gerçekliğini beyan edersin
}

İYS hesabı (credential) yönetimi:

GET    /api/iys/accounts
POST   /api/iys/accounts   { "iys_code":"...", "brand_code":"...", "iys_username":"...", "iys_password":"...", "environment":"production" }
PUT    /api/iys/accounts/{id}
DELETE /api/iys/accounts/{id}

environment: sandbox | production. Credential'lar şifreli saklanır, yanıtta asla açık dönmez.


5. Şablonlar & Kampanyalar

WhatsApp şablonları (Meta onaylı)

GET    /api/whatsapp/templates
POST   /api/whatsapp/templates           # şablon oluştur (Meta'ya gider)
PUT    /api/whatsapp/templates/{id}
POST   /api/whatsapp/templates/add-optout-button  # şablona otomatik QUICK_REPLY "Durdur" ekler → Meta re-review (PENDING); alıcı butona basınca opt-out suppression
DELETE /api/whatsapp/templates/{name}
POST   /api/whatsapp/upload-header-image
GET    /api/whatsapp/db-columns          # şablon değişkenleri için sütun listesi

Mail şablonları (AI üretimli + manuel)

GET    /api/mail-templates
POST   /api/mail-templates
POST   /api/mail-templates/generate      { "prompt": "..." }   # AI ile şablon üret
POST   /api/mail-templates/{id}/preview
POST   /api/mail-templates/{id}/send-test

Mail kampanyaları (zamanlanmış toplu gönderim)

GET    /api/mail-campaigns
POST   /api/mail-campaigns
POST   /api/mail-campaigns/{id}/start | /pause | /resume | /retry-failed
GET    /api/mail-campaigns/{id}/logs
GET    /api/mail-campaigns/{id}/preview-recipients

Çağrı Kampanyası (toplu sesli AI araması — 2026-06-13)

Ne işe yarar: Rehber grubundaki (CSV import dahil — contacts/groups/{id}/import, § 4) numaraları site'ın sesli botu sırayla arar; sonuç alıcı bazında izlenir. Menü: Kampanyalar → Çağrı Kampanyası.

GET    /api/voice-campaigns?status=running        # liste — status: draft|running|paused|completed|cancelled
POST   /api/voice-campaigns                       # { site_id, contact_group_id, name, initial_message?, prompt_override?, scheduled_at?, consent_source, consent_date, consent_confirmed: true }
GET    /api/voice-campaigns/{id}                  # detay + sayaçlar (total_completed/no_answer/failed/skipped)
PUT    /api/voice-campaigns/{id}                  # yalnız status=draft
DELETE /api/voice-campaigns/{id}                  # running/paused silinemez (önce cancel)
POST   /api/voice-campaigns/{id}/start | /pause | /resume | /cancel
POST   /api/voice-campaigns/{id}/retry-failed     # no_answer + failed → tekrar kuyruğa (skipped ASLA yeniden aranmaz)
GET    /api/voice-campaigns/{id}/recipients       # alıcılar — status: pending|calling|completed|no_answer|failed|skipped

6. Voice / Çağrılar + Outbound

Çağrı geçmişi (site bazlı)

GET  /api/sites/{site}/voice-conversations
GET  /api/voice-conversations/{id}
GET  /api/voice-conversations/{id}/recording-url     # imzalı kayıt URL'i
POST /api/voice-conversations/{id}/clean             # transkripti AI ile yeniden temizle

Dışarı arama (outbound call)

POST /api/voice/call         { "site_id": 12, "phone": "+90...", ... }    # 5/dk

Bildirim aramaları & re-engagement mesajları (onay akışı)

GET  /api/sites/{site}/outbound-intents           # bekleyen sesli bildirim aramaları
POST /api/sites/{site}/outbound-intents           # manuel bildirim araması oluştur
POST /api/outbound-intents/{intent}/approve | /decline | /cancel

GET  /api/sites/{site}/outbound-messages          # 24h re-engagement mesaj önerileri (WA/TG/Msgr/IG)
POST /api/sites/{site}/outbound-messages          # manuel
POST /api/outbound-messages/{intent}/approve | /decline | /cancel
GET  /api/outbound-messages/all                   # tüm sitelerin bekleyenleri (badge)

Kapasite Paketleri (2026-06-12)

Ne işe yarar: Yüksek hacimli telefon trafiği için site başına ek kapasite (eşzamanlı + günlük + aylık çağrı limitleri). Satın alma abonelik akışında (subscriptions/initiate, plans yanıtındaki capacity_plans planlarıyla); atama buradan:

GET    /api/me/voice-capacity                 # sahip olunan kapasite paketleri + atandıkları site
GET    /api/sites/{site}/voice-capacity       # sitenin paketi + anlık eşzamanlı / bugünkü çağrı sayacı
POST   /api/sites/{site}/voice-capacity       # { "subscription_id": 41 } — paket tek siteye atanır
DELETE /api/sites/{site}/voice-capacity       # atamayı kaldır (site default 20 eşzamanlıya döner)

Santral / Çağrı Aktarımı (2026-06-12)

Ne işe yarar: Telefonu AI karşılar; arayan "teknik ekiple görüşmek istiyorum" deyince AI onay alır ve çağrıyı aktarım rehberindeki kişinin telefonuna canlı bağlar. AI serbest numara çeviremez — yalnızca rehberdeki kişiler (sunucu tarafında da doğrulanır).

GET    /api/sites/{site}/transfer-targets              # rehber + enabled (opt-in) durumu
POST   /api/sites/{site}/transfer-targets              # { "name": "Ahmet Yılmaz", "department": "Teknik Ekip", "phone": "5551112233", "is_active": true }
PUT    /api/sites/{site}/transfer-targets/{target}     # kısmi güncelleme
DELETE /api/sites/{site}/transfer-targets/{target}

7. Müşteri Talepleri (Callback)

Ne işe yarar: AI "sizi geri arayalım" dediğinde / müşteri talep bıraktığında oluşan kayıtlar.

GET /api/callback-requests
PUT /api/callback-requests/{id}/status        { "status": "done" }
PUT /api/callback-requests/{id}/note          { "note": "..." }
POST /api/callback-requests/{id}/beautify-note   # notu AI ile düzelt

Talep atama (2026-06-11)

Talepler site ekibindeki bir kullanıcıya atanabilir; istenirse yeni talepler ekipteki agent rolündeki kullanıcılara en az açık talebi olana otomatik dağıtılır.

GET  /api/callback-requests/assignment-options?site_id=12   # atanabilir ekip + açık talep sayıları + auto_assign durumu
POST /api/callback-requests/{id}/assign       { "user_id": 17 }   # null → atamayı kaldır
PUT  /api/callback-requests/auto-assign       { "site_id": 12, "enabled": true }

7.5. Potansiyel Müşteriler (Leads / CRM) — module:leads

Ne işe yarar: Konuşmalardan / talep / lead-ads kaynaklarından oluşan satış adayları (CRM pipeline: sürüklenebilir aşamalar + ekip ataması). Yalnız KENDİ sitelerinin lead'leri görünür (bayi, müşteri sitelerinin lead'lerini göremez — mesaj/rehber gizlilik kilidiyle tutarlı). module:leads gerektirir.

GET    /api/leads                  # liste (site/aşama filtreli)
POST   /api/leads                  # manuel aday ekle (kaynak: manuel/öneri/talep/lead-ads)
POST   /api/leads/inbox            # Mesaj Kutusu konuşmasından aday ekle (channel + identifier)
GET    /api/leads/inbox-status     # konuşma zaten lead mi? (yazmaz — idempotent probe)
POST   /api/leads/scan             # konuşmaları AI ile tara → aday çıkar (10/dk)
POST   /api/leads/{id}/analyze     # tek adayı AI ile analiz et (10/dk)
GET    /api/leads/{id}/activities  # değişiklik geçmişi: kim ne yaptı (created/stage_changed/assigned/updated)
PATCH  /api/leads/{id}/stage       # pipeline aşaması değiştir   { "stage": "..." }
POST   /api/leads/{id}/assign      # ekip üyesine ata   { "user_id": 17 }   (null → kaldır)
POST   /api/leads/reorder          # sütun içi sıralama (sürükle)
PATCH  /api/leads/{id}             # güncelle (ad / telefon / not ...)
DELETE /api/leads/{id}             # sil
GET    /api/lead-submissions       # Lead Ads form yanıtları (Meta/Facebook lead formları — ham gönderimler)

Lead kaynakları: manuel · konuşma taraması (scan) · Müşteri Talepleri · Lead Ads (Facebook lead formu → POST facebook-page-profiles/{id}/sync-leads, module:publishinglead-submissions + otomatik lead). Alan (body) listeleri için /api-docs (Scribe) → "Potansiyel Müşteriler (Leads)" grubuna bak.

Değişiklik geçmişi: lead yazma uçları (ekleme / düzenleme / aşama / atama) her değişiklikte otomatik geçmiş kaydı üretir; GET /api/leads/{id}/activities en yeni üstte döner. Kayıt: action, actor_name (sistem işlemlerinde null), actor_role (owner | agent | subuser | system ...), alan bazlı changes { alan: {from, to} } (atamada okuma anında çözülen from_label/to_label da eklenir). Sürükleme sırası (reorder) bilinçli olarak geçmişe yazılmaz.


8. Bilgi Tabanı (SSS + Belgeler)

Sitenin AI'ının cevap verirken kullandığı bilgi. Hepsi sites/{site}/... altında.

SSS (FAQ)

GET    /api/sites/{site}/faqs
POST   /api/sites/{site}/faqs                 { "question": "...", "answer": "..." }
PUT    /api/faqs/{faq}
DELETE /api/faqs/{faq}
POST   /api/sites/{site}/faqs/batch           # toplu EKLE (yeni SSS'ler)
POST   /api/sites/{site}/faqs/batch-update    { "updates": [{ "id": 12, "question": "...", "answer": "..." }] }   # toplu DEĞİŞTİR (var olanları)
POST   /api/faqs/{faq}/ai-rewrite             { "instruction": "5551234567 numarasını kaldır" }   # tek SSS'i AI talimatla yeniden yaz
POST   /api/sites/{site}/faqs/extract-from-text   { "text": "..." }    # metinden SSS çıkar (AI)
POST   /api/sites/{site}/faqs/extract-from-image  (görselden)
DELETE /api/sites/{site}/faqs/delete-all

Belgeler

GET    /api/sites/{site}/documents
POST   /api/sites/{site}/documents            (yükle)
POST   /api/documents/{document}/process      # parse + embedding
DELETE /api/documents/{document}

Fonksiyon Gateway (AI'ın çağırdığı dış fonksiyonlar — ileri seviye)

GET  /api/sites/{site}/functions
POST /api/sites/{site}/functions              # DB sorgusu veya HTTP API fonksiyonu tanımla
POST /api/functions/{function}/test
POST /api/functions/{function}/toggle
# Harici bağlantılar (DB/HTTP):
GET  /api/sites/{site}/connections
POST /api/sites/{site}/connections
POST /api/connections/{connection}/generate-functions        # tablodan otomatik fonksiyon üret (AI)
# Hazır modül paketi yükle — connection + TÜM fonksiyonlar tek seferde:
POST /api/sites/{site}/bundles/import   { "manifest": { ...JSON... }, "api_key": "<secret>", "replace": true }
#   veya dış URL'den:                   { "manifest_url": "https://...",  "api_key": "<secret>" }
#   → "manifest" (JSON gövde) ÖNERİLİR: dış URL fetch YOK = SSRF yüzeyi sıfır. manifest|manifest_url biri zorunlu.
#     api_key = connection bearer/api_key sırrı; replace=true mevcut paketi günceller (idempotent re-sync).
#
# Fonksiyon şablon değişkenleri  (url_template / body_template / headers içinde {{...}}):
#   {{arg.X}}                       → AI'ın doldurduğu fonksiyon argümanı (model/kullanıcı girdisi → DOĞRULANMAMIŞ)
#   {{connection.base_url}} ...     → connection'ın kayıtlı (şifreli) değerleri
#   {{user.id|phone|name|email}}    → DOĞRULANMIŞ son-kullanıcı kimliği: web widget'ta imzalı data-user-token'dan
#                                     çözülen kullanıcı, WhatsApp/voice'ta Meta-imzalı telefon. Sistem otomatik
#                                     enjekte eder → AI/kullanıcı SPOOF EDEMEZ. "Giriş yapanın KENDİ verisi"
#                                     isteyen fonksiyonlarda (siparişlerim, derslerim, şifre-sıfırlama) kimliği
#                                     {{arg.*}} parametresi YAPMA → body_template'te {{user.id}}/{{user.phone}}
#                                     kullan. Anonim kullanıcıda boş gelir (istek o alan olmadan gider).

9. Kullanım, Krediler & Abonelik

Kullanım & kredi özeti (panelin "Kullanım" sayfası)

GET /api/me/usage                 # birleşik mesaj+voice snapshot (dashboard)
GET /api/usage                    # detay
GET /api/usage/stats
GET /api/credits                  # bakiye
GET /api/credits/transactions
GET /api/me/credit-summary        # header badge için rol-aware özet

Abonelik

GET  /api/subscriptions/plans
GET  /api/subscriptions/current
GET  /api/subscriptions/usage
GET  /api/subscriptions/price-quote        # ?plan_id=&sites_count= → fiyat
POST /api/subscriptions/initiate           { "plan_id": "business", "sites_count": 5 }
POST /api/subscriptions/change-sites
# Ödeme: PayTR (TR), Stripe (USD, otomatik webhook), PayPal (USD, manuel onay)
POST /api/subscriptions/stripe/checkout
POST /api/subscriptions/paypal/initiate

AI Mesaj Paketi (Gemini kredi cüzdanı — anahtarsız kullanıcı)

GET  /api/ai-credit/catalog
GET  /api/ai-credit/summary               # bakiye
GET  /api/ai-credit/transactions
POST /api/ai-credit/stripe/checkout | /paytr/checkout | /paypal/initiate

Cüzdan neyi fonlar: Kullanıcının (veya bayisinin) kendi Gemini anahtarı yoksa AI maliyetleri bu cüzdandan düşülür — yalnız sohbet mesajları (tüm kanallar) değil, sesli çağrılar (AI'ın karşıladığı telefon, 2026-06-14'ten itibaren) ve canlı çeviri (telefon aktarımında çapraz dil) de. transactions yanıtındaki source alanı kalemi ayırır (ör. voice_conversation, voice_translate). Maliyet gerçek token kullanımından (Gemini usageMetadata) hesaplanır × kâr marjı; sesli kalem metinden pahalıdır (ses çıkışı yüksek oranlı). Bakiye biterse AI yanıt veremez → kullanıcı paket satın almalı (catalogcheckout).


10. Geliştirici paneli (self-service)

Ne işe yarar: Kullanıcının kendi API anahtarı (Sanctum PAT), outbound webhook ve OAuth client'ı. Senin trusted-partner client'ından AYRIDIR — bu, kullanıcının panelden kendi entegrasyonunu açması içindir.

⚠️ Bu endpoint'lere erişim için kullanıcının developer modülü açık olmalı (allowed_modules). Ayrıca token/webhook/oauth oluşturmadan önce geliştirici şartları kabulü zorunlu: GET /api/me/developer-termsPOST /api/me/developer-terms/accept.

Kişisel API anahtarları (Sanctum PAT)

GET    /api/me/tokens
POST   /api/me/tokens          { "name": "Entegrasyonum" }     # 10/dk — plain token bir kez döner
DELETE /api/me/tokens/{id}

Outbound webhook (DoWaba → senin sunucun)

GET    /api/webhook-endpoints
POST   /api/webhook-endpoints  { "url": "https://...", "events": ["whatsapp.message.received"] }   # 20/dk
PATCH  /api/webhook-endpoints/{id}
POST   /api/webhook-endpoints/{id}/test
GET    /api/webhook-endpoints/{id}/deliveries        # gönderim logları
DELETE /api/webhook-endpoints/{id}

İmza: gelen webhook'larda X-Dowaba-Signature (HMAC-SHA256) doğrula. ⚠️ Payload müşteri PII'si içerir (telefon/ad/mesaj metni) — maskeli değildir; bu veriyi yalnız veri sahibine hizmet için kullanabilirsin (§ 0.5).

OAuth client (kendi "Login with DoWaba" entegrasyonu)

GET    /api/me/oauth/clients
POST   /api/me/oauth/clients   # issues_sanctum_token DAİMA false (trusted partner sadece DoWaba ekibi açar)
PATCH  /api/me/oauth/clients/{id}
POST   /api/me/oauth/clients/{id}/rotate-secret
DELETE /api/me/oauth/clients/{id}

11. Profil & Ayarlar

GET /api/auth/user                 # kimlik + role + allowed_modules (§0.3)
GET /api/user                      # profil detay
PUT /api/user                      # profil güncelle
PUT /api/user/locale               { "locale": "tr" }
PUT /api/user/menu-settings        # sol menü görünürlüğü

GET /api/settings                  # kullanıcı global ayarları (key-value)
PUT /api/settings
GET/PUT /api/settings/gemini-models    # AI model tercihi
GET/PUT /api/settings/whatsapp | /sms | /sip

12. Fatura & Bayi

Müşterinin kendi cari hesabı (read-only)

GET /api/me/billing                          # bayiden gelen borç + taksit + ödeme
GET /api/customer-invoices/{invoice}/data    # fatura JSON (PDF client-side üretilir)

Bayi paneli (sadece role=reseller)

GET  /api/reseller/summary                   # KPI kartları
GET  /api/reseller/customers
POST /api/reseller/customers                 { "name": "...", "email": "...", "phone": "+90..." }
GET  /api/reseller/customers/{user}
POST /api/reseller/customers/{user}/send-password-link   # müşteriye şifre kurulum bağlantısı (3/saat)
POST /api/reseller/customers/{user}/sites    # müşteri adına site + lisans
GET  /api/reseller/invoices                  # bekleyen/ödenmiş lisans faturaları
POST /api/reseller/customers/{user}/billing/invoices    # müşteriye fatura kes (cari hesap)
GET  /api/reseller/branding                  # white-label marka

⚠️ Müşteri şifresi (2026-06-11): POST/PUT /reseller/customers* artık password parametresi kabul etmez (gönderilirse yok sayılır). Müşteri şifresini, kendisine e-posta/SMS ile giden kurulum bağlantısıyla kendisi belirler (send-password-link; yeni müşteri oluşturmada otomatik gönderilir — yanıtta password_link_sent + password_link_channel). Bayi müşterisinin konuşma/mesaj içeriğine de erişemez (§ 0.2).


Ek — pratik notlar


13. Sürüm Notları + Kararlı API Sözleşmeleri

Sürüm notları artık panelde (dinamik, sürümlü): Geliştirici → Sürüm Notları sekmesi (/admin/developer). Her deploy otomatik bir taslak üretir (eklenen/çıkan endpoint + git değişiklikleri); ekip bunu geliştirici-dostu dille düzenleyip yayınlar. Geçmiş ve yeni tüm API değişikliklerini oradan takip et — eski statik liste kaldırıldı (her sürümde elle güncellenmiyordu, geride kalıyordu).

Değişmeyen kararlı sözleşmeler (stable)

Bunlara güvenebilirsin — kırıcı değişiklik olursa burada duyurulur: