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
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.
issues_sanctum_token özelliğini açar.
Bu, sözleşmeli partner için elle açılır — self-service panelden açılamaz.POST /api/oauth/token çağırır (grant_type=authorization_code).{
"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_tokengelmiyorsa: client trusted partner değil veya kullanıcı superadmin (superadmin trusted partner app'lere giremez — onay ekranında bloklanır).
curl https://dowaba.com/api/sites \
-H "Authorization: Bearer 12|abc..." \
-H "Accept: application/json"
https://dowaba.com/apiAccept: application/json ŞART — yoksa auth hatası HTML/redirect dönebilir (302/500 görürsün). Her zaman gönder.reseller_id dolu), sanctum_token ile konuşma/mesaj endpoint'leri
çalışmaz — inbox/unified, {kanal}/conversations, {kanal}/messages/..., inbox/media,
voice transkriptleri, widget sohbetleri boş liste veya 403 döner. Fallback YOKTUR. Gerekçe:
bu token senin (partner'ın) elindedir; bayi müşterisinin konuşmaları yalnız kendi panel
oturumuna açıktır. Site/profil yönetim endpoint'leri (entegrasyon, ayarlar, kişiler,
kampanya) çalışmaya devam eder. Bağımsız (bayiye bağlı olmayan) kullanıcılar için kısıt yok.sanctum_token'ın süresi dolmaz; yalnızca OAuth revoke veya refresh rotation ile silinir
(mobil "logout" = POST /api/oauth/revoke).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.
{ "success": true, "data": ... } döner; bazı liste endpoint'leri data / profiles
anahtarı altında, bazı konuşma listeleri kök array döner. Her endpoint'in şeklini ilk çağrıda doğrula.401 (token yok/geçersiz), 403 (yetki/scope dışı), 402 (slot/abonelik gerekiyor — site açma),
422 (validasyon), 429 (rate limit).10/dk, outbound çağrı 5/dk,
AI iyileştir 20/dk). Her bölümde belirtildi.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
url'i kullanıcının tarayıcısında aç. Tek-kullanımlık + 5 dk TTL; POST /api/auth/impersonate-redeem
ile redeem edilir (değişmedi). Reseller paneldeki customers/{user}/login-link'in OAuth karşılığıdır.url host'u markaya göre döner (msg724.com / bayi özel domain / dowaba.com). Mimari: OAUTH_PROVIDER.md § 6.1.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ı):
me/developer-terms), (2) son kullanıcının açık onayı (OAuth consent). Onaylanmayan veri kategorisine erişme.Özet: "İşletme kendi DoWaba verisi için senin aracını kullanıyor" = uygun. "Sen DoWaba verisiyle kendi ürününü besliyorsun" = ihlal.
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.
scheduled-jobs (zamanlı) hem send-template (anlık toplu) yolları opt-out + İYS reddini otomatik filtreler
(red'li alıcı gönderilmez, kotadan düşmez; yanıtta skipped sayısı + skipped_samples döner).call): alıcı kampanya araması sırasında "beni bir daha aramayın" derse
sesli bot bunu otomatik kaydeder (channel=call opt-out) ve çağrıyı kibarca kapatır; voice-campaigns o numarayı
sonraki aramalarda arama anında atlar (alıcı skipped, skip_reason: opt_out — § 5).GET /api/message-opt-outs?site_id=12&channel=whatsapp
ile listeyi çekebilirsin.2. İYS onayı — pazarlamada ön onay zorunlu. Ticari/pazarlama içerikli toplu mesaj için alıcının önceden onayı
iys/consents ile yükle/sorgula (§ 4). Onaysız liste =
hukuka aykırı + Meta ban riski. (Mevcut müşteriye onaysız kampanya da yasaktır — istisna yalnız değişiklik/bakım bildirimidir.)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=callsesli arama kampanyalarının (§ 5) red listesidir; kaydı silmek numarayı tekrar aranabilir yapar.
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_enabledflag'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'taappointmentmodülü gerektirir), Trendyol Q&A (trendyol/*). İhtiyaç olursa aynı şablonla eklenir.
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.
GET /api/sites
{ "success": true, "data": [ { "id": 12, "name": "Örnek Mağaza", "is_active": true, "api_key": "...", ... } ] }
GET /api/sites/{site}
POST /api/sites
Content-Type: application/json
{ "name": "Örnek Mağaza", "description": "...", "settings": { "system_prompt": "Sen ...", "languages": ["tr"] } }
402 + onay gerekir → onaylanınca yıllık lisanslı site açılır.403 requires_upgrade.settings.system_prompt max 50.000 karakter.Bayi, müşteri adına site açar:
POST /api/reseller/customers/{user}/sites(§12).
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/aiyalnız öneri döner ({theme, summary}); kalıcı kayıt için dönenthemeobjesiniPUT /api/sites/{site}ilesettings.widget_themealanı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.
GET /api/sites/{site}/domains
POST /api/sites/{site}/domains { "domain": "magaza.com" }
POST /api/domains/{domain}/verify
DELETE /api/domains/{domain}
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).
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.
POST /api/inbox/mark-read
{ "channel": "whatsapp", "identifier": "+905551112233", "profile_id": 4 }
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)
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.
Tüm mesajlaşma kanalları aynı 4 adımlı pattern'i izler:
GET {kanal}/conversationsGET {kanal}/messages/{identifier}POST {kanal}/send (Instagram/X/TikTok/Mail'de farklı isim)POST {kanal}/toggle-botBot mantığı:
toggle-botile 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-blockile 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_idvermezsen 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.)limit1–200 clamp.
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
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 |
|---|---|---|---|---|---|
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 |
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 |
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.
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}
Ne işe yarar: Kişi/grup yönetimi (CRM) + WhatsApp şablonuyla toplu/zamanlı gönderim.
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...
import-urlKendi 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
}
email (e-posta/eposta/mail…), ad (name/isim/ad_soyad…), phone (telefon/gsm/cep…). email VEYA telefon en az biri zorunlu.auto_refresh=false (varsayılan): tek-seferlik — bir kez çekilir, statik grup oluşur, API anahtarı saklanmaz.auto_refresh=true: kaynak URL + auth + API anahtarı (şifreli) gruba kaydedilir; kampanya her başladığında liste bu adresten yeniden çekilir (hep güncel).group.id'yi mail/WhatsApp kampanyasında contact_group_id olarak kullanın.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).
POST /api/contacts/groups/{id}/send-template
{ "template_name": "kampanya_haziran", "site_id": 12, "params": { ... } }
⚠️ Uyum: Bu anlık toplu gönderim de
scheduled-jobsgibi opt-out + İYS reddini otomatik filtreler (red'li alıcı atlanır; yanıttaskipped+skipped_samplesdöner). Yine de pazarlama içerikse alıcıların İYS onayını önceden almış olmalısın (§ 0.6).
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-jobsile 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 (İleti Yönetim Sistemi) onaylarını yükle/sorgula. Toplu pazarlama göndermeden önce gerekli — § 0.6.
Bu endpoint'ler
iysmodü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.
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
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
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
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
422 {"error":"consent_required"} dönerse eksik sözleşmeleri
POST /api/consent/channel/voice_campaign/accept ile kabul et (panel modalının muadili); kabul AuditLog + mail
kopyasıyla damgalanır.consent_source + consent_date + consent_confirmed: true zorunlu — listenin İYS
ARAMA onayına sahip olduğunu beyan edersin (alıcı bazında marketing_consents ARAMA delili otomatik yazılır).channel=call opt-out'lu (§ 0.6) veya İYS RET'li numara otomatik
atlanır — alıcı skipped + skip_reason: opt_out | iys_denied, kota harcanmaz.message_opt_outs channel=call) ve kibarca kapatır; numara sonraki tüm kampanyalarda atlanır.outbound_call_hours_* + outbound_blocked_weekdays)
dışında arama yapılmaz — kampanya bekler, pencere açılınca devam eder.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
POST /api/voice/call { "site_id": 12, "phone": "+90...", ... } # 5/dk
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)
approve artık declined / cancelled / failed durumundaki
önerileri de kabul eder (tekrar kuyruğa alır, failure_reason temizlenir).
completed/queued/in_progress onaylanamaz → 422 (çift gönderim koruması). 24 saatlik
mesajlaşma penceresi gönderim anında kontrol edilir — pencere kapandıysa öneri anlamlı bir
failure_reason ile failed'e düşer.profile_name eklendi —
mesajın hangi kanal profilinden (bağlı numara/hesap) gideceğini gösterir. Eski kayıtlarda
ve manuel oluşturulan önerilerde null olabilir.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)
voice-conversations üretilmez. (İç gate:
concurrency_limit / daily_limit — operatör loglarında görünür.)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}
PUT /api/sites/{site} body { "settings": { "voice_transfer_enabled": true } }.
Kapalıyken AI'ya telefonu_aktar aracı hiç tanımlanmaz, davranış değişmez.90 öneki eklenir
(5551112233 → 905551112233). Site başına en fazla 20 hedef; user_id verilirse
site sahibı veya site ekibinden olmalı (aksi 422).language, BCP-47:
tr/en/ru/de/ar/fr/it) müşterinin konuştuğu dilden farklıysa ve
settings.voice_translate_enabled açıksa, çağrı düz bağlama yerine canlı çift-yönlü
çeviriyle aktarılır: müşteri ve temsilci kendi dilinde konuşur, Gemini sesi anlık çevirir.
transfer-targets yanıtındaki translate_enabled ile durum görünür; hedef oluştururken
language ver (boş = düz aktarım, çeviri yok). Çeviri ek AI kredisi tüketir
(§9, source: voice_translate).voice-conversations yanıtlarında başarılı aktarımlar
status: "transferred" + transferred_to_name / transferred_to_phone /
transferred_at alanlarıyla gelir; kayıt (recording) hem AI fazını hem insan
görüşmesini içerir.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
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 }
{id} = liste yanıtındaki talep kimliği (kanal bazlı konuşma id'si). Site ekibi dışındaki
kullanıcıya atama 422 döner.GET /api/callback-requests) yanıtındaki her kayda assigned_user_id +
assigned_user_name alanları eklendi (atanmamışsa null).module:leadsNe 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:publishing→lead-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}/activitiesen 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ülenfrom_label/to_labelda eklenir). Sürükleme sırası (reorder) bilinçli olarak geçmişe yazılmaz.
Sitenin AI'ının cevap verirken kullandığı bilgi. Hepsi sites/{site}/... altında.
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
GET /api/sites/{site}/documents
POST /api/sites/{site}/documents (yükle)
POST /api/documents/{document}/process # parse + embedding
DELETE /api/documents/{document}
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).
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
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
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.
transactionsyanıtındakisourcealanı kalemi ayırır (ör.voice_conversation,voice_translate). Maliyet gerçek token kullanımından (GeminiusageMetadata) 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ı (catalog→checkout).
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
developermodülü açık olmalı (allowed_modules). Ayrıca token/webhook/oauth oluşturmadan önce geliştirici şartları kabulü zorunlu:GET /api/me/developer-terms→POST /api/me/developer-terms/accept.
GET /api/me/tokens
POST /api/me/tokens { "name": "Entegrasyonum" } # 10/dk — plain token bir kez döner
DELETE /api/me/tokens/{id}
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).
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}
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
GET /api/me/billing # bayiden gelen borç + taksit + ödeme
GET /api/customer-invoices/{invoice}/data # fatura JSON (PDF client-side üretilir)
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ıkpasswordparametresi 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ıttapassword_link_sent+password_link_channel). Bayi müşterisinin konuşma/mesaj içeriğine de erişemez (§ 0.2).
*/send, mail/reply) idempotent değildir —
aynı isteği iki kez atarsan iki mesaj gider. Kendi tarafında dedup uygula.toggle-bot ile o konuşmada botu kapat.profile_id (hangi bağlı numara/hesap) bekler.
inbox/unified ve {kanal}/conversations yanıtlarında gelir; mesaj/gönder isteğinde geri ver.issues_sanctum_token için aydin@dowaba.com.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).
Bunlara güvenebilirsin — kırıcı değişiklik olursa burada duyurulur:
sanctum_token TTL'siz — yalnız oauth/revoke veya refresh rotation ile silinir (§ 0.2).*/send, mail/reply, send-template) idempotent değildir — kendi tarafında dedup uygula.{success,data} / kök array / {data,total}) — ilk çağrıda şekli doğrula (§ 0.4).