Appels automatiques

Fait passer une annonce, un IVR ou un appel de sondage à une liste de numéros ; renvoie le résultat et la saisie des touches. Clé d'intégration (bt_…, portée autocall).

Point d'accès : https://api.buluthat.com/api/autocall.php?action=<işlem>

Parcours type :

1. media          -> anons id'sini al (ya da tts_template kullan)
2. trunks         -> çıkış hattının slug'ını al
3. create_campaign -> status "draft", digit_labels ile anket seçenekleri
4. add_leads      -> numaraları partiler hâlinde gönder
5. start          -> kampanyayı kuyruğa al
6. webhook        -> sonuçlar size gelsin (ya da results ile çekin)
7. summary        -> tuş dağılımı

GETping · media · trunks · caller_ids

GET https://api.buluthat.com/api/autocall.php?action=ping
GET https://api.buluthat.com/api/autocall.php?action=media       → [{ "id": 12, "name": "Hatırlatma anonsu" }]
GET https://api.buluthat.com/api/autocall.php?action=trunks      → çıkış hatları (slug)
GET https://api.buluthat.com/api/autocall.php?action=caller_ids  → kullanılabilir arayan numaralar

POSTcreate_campaign

curl -X POST "https://api.buluthat.com/api/autocall.php?action=create_campaign" \
  -H "Authorization: Bearer bt_xxx" -H "Content-Type: application/json" \
  -d '{
    "name": "Randevu hatırlatma",
    "campaign_type": "survey",
    "trunk_slug": "hat-1",
    "caller_id": "02124119610",
    "tts_enabled": true,
    "tts_template": "Merhaba {sayin}, {randevu} randevunuzu hatırlatmak için aradık. Geliyorsanız 1, iptal için 2.",
    "digit_labels": { "1": "Geliyorum", "2": "İptal" },
    "digit_destinations": { "9": "queue:4" },
    "start_time": "09:00", "end_time": "18:00",
    "weekdays": ["mon","tue","wed","thu","fri"],
    "max_channels": 3, "ring_timeout_seconds": 30,
    "retry_count": 1, "retry_delay_minutes": 30,
    "amd_enabled": true, "amd_action": "hangup",
    "webhook_url": "https://ornek.com/buluthat/sonuc",
    "webhook_secret": "gizli",
    "webhook_events": "call_finished,dtmf",
    "status": "draft",
    "leads": [ { "phone": "05551112233", "name": "Ahmet Yılmaz", "external_id": "CRM-1", "fields": { "randevu": "12 Eylül 14:00" } } ]
  }'

Obligatoire : name, trunk_slug et media_file_id ou tts_template. Si les deux sont fournis, le son personnalisé est lu d'abord, puis l'annonce prête à l'emploi.

ChampValeursNote
campaign_typeannouncement, ivr, surveyannouncement diffuse l'annonce et raccroche, n'attend aucune touche
digit_labels{"1":"Evet"}À remplir pour le sondage. Une touche dotée d'un libellé est enregistrée même sans destination
digit_destinations{"9":"queue:4"}Transfère celui qui appuie sur la touche : ext:1001, queue:4, ivr:2, flow:3, repeat, hangup
amd_actionhangup, play, continueQue faire quand l'appel tombe sur un répondeur
tts_template"Sayın {ad}, …"Variables : {sayin}, {unvan}, {adi}, {ad}, {telefon} et fields les champs
statusdraft, queuedqueued si vous le fournissez, la campagne entre aussitôt en file
retry_count / retry_delay_minutesnombreRappel en cas de non-réponse/occupé
thanks_tts_texttextePhrase de remerciement après la saisie du sondage

Réponse : { "ok": true, "data": { "id": 7, "status": "draft", … } }

POSTupdate_campaign

Mise à jour partielle ; seuls les champs envoyés changent. status n'envoyez pas (cela interrompt la campagne en cours) ; pour le statut start/pause/cancel utilisez.

{ "campaign_id": 7, "max_channels": 5, "retry_count": 2 }

POSTadd_leads

Au maximum 5.000 enregistrements par requête. Dans une même campagne, un même numéro n'est pas ajouté deux fois (duplicate).

{ "campaign_id": 7, "leads": [ { "phone": "05551112233", "name": "Ahmet Yılmaz", "external_id": "CRM-1", "fields": { "borc": "1.240 TL" } } ] }

Format court : { "campaign_id": 7, "phones": ["05551112233", "05551112234"] }

Réponse : { "inserted": 2, "duplicate": 0, "invalid": 0 }

POSTrequeue_leads

Remet en file les numéros déjà appelés (calls est remis à zéro, la saisie des touches effacée). Le numéro déjà en attente n'est pas touché (skipped). Pour un rappel de paiement, plutôt que de vous fier à la touche « j'ai payé », utilisez-le pour rappeler selon vos propres enregistrements.

{ "campaign_id": 7, "phones": ["05551112233"] }

POSTstart · pause · cancel

{ "campaign_id": 7 }

start met la campagne en file ; l'appel démarre dans la plage jour/heure. Si vous ajoutez des numéros à une campagne terminée, elle est automatiquement rouverte.

GETresults

Résultat par numéro. limit (par défaut 200, maximum 1000), offset; filtres status, dtmf, phone.

GET https://api.buluthat.com/api/autocall.php?action=results&campaign_id=7&dtmf=1
{
  "ok": true, "total": 512, "limit": 200, "offset": 0,
  "data": [ {
    "campaign_id": 7, "lead_id": 91, "external_id": "CRM-1",
    "phone": "05551112233", "name": "Ahmet Yılmaz",
    "status": "answered", "attempts": 1,
    "dtmf": "1", "dtmf_label": "Geliyorum", "dtmf_all": ["1"],
    "amd_result": "HUMAN", "duration_seconds": 34, "talk_seconds": 22,
    "hangup_cause": "ANSWERED",
    "started_at": "2026-09-04 10:12:03", "answered_at": "2026-09-04 10:12:11", "ended_at": "2026-09-04 10:12:33",
    "custom_fields": { "randevu": "12 Eylül 14:00" }
  } ]
}

Statuts : pending, calling, answered, machine, no_answer, busy, failed, cancelled.

GETsummary

{ "ok": true, "data": {
  "total": 512, "answered": 388, "pressed": 301, "machine": 44,
  "answer_rate": 75.8, "press_rate": 77.6, "talk_seconds": 8624, "avg_talk_seconds": 22,
  "digits": [ { "digit": "1", "label": "Geliyorum", "total": 214, "percent": 55.2 }, { "digit": "2", "label": "İptal", "total": 87, "percent": 22.4 } ]
} }

GETevents

Journal des événements de campagne (originate, answered, amd, dtmf, cdr, error) — pour le diagnostic.

Webhook

webhook_url s'il est défini, Buluthat vous envoie le résultat en POST. Événements : call_finished (une seule fois par numéro), dtmf (au moment de l'appui sur la touche), campaign_finished. En-têtes X-Buluthat-Event, X-Buluthat-Delivery, X-Buluthat-Signature: sha256=… (webhook_secret s'il est fourni). Corps results porte les mêmes champs que. Pour la vérification de la signature et la politique de nouvelle tentative, voir Webhooks.

Annonce personnalisée et coût

Le modèle est découpé en parties fixes et variables ; la phrase fixe est synthétisée une seule fois pour une liste de mille personnes, la même {tutar} la valeur n'est pas générée une seconde fois (économie mesurée : 97,9 %). Envoyez les valeurs des variables sous forme standard ("1.000 TL" toujours écrit de la même façon). La distinction Monsieur/Madame se fait automatiquement d'après le prénom ; pour les prénoms mixtes, le titre est laissé vide.

Client PHP

Téléchargé depuis Panneau > Appels automatiques > onglet API buluthat-autocall-client.php:

require_once 'buluthat-autocall-client.php';
$bt = new BuluthatAutoCall('https://api.buluthat.com', 'bt_xxx');
$k = $bt->createCampaign(['name' => 'Ödeme hatırlatma', 'campaign_type' => 'survey', 'trunk_slug' => 'hat-1',
    'tts_enabled' => true, 'tts_template' => 'Merhaba {sayin}, {tutar} tutarındaki ödemenizi hatırlatmak için aradık. Ödediyseniz 1, ödemediyseniz 2.',
    'digit_labels' => ['1' => 'Ödedim', '2' => 'Ödemedim'], 'webhook_url' => 'https://crm.example.com/buluthat-sonuc.php']);
$bt->addLeads($k['id'], [['phone' => '05551112233', 'name' => 'Burak Yılmaz', 'external_id' => 'CARI-451', 'fields' => ['tutar' => '1.000 TL']]]);
$bt->start($k['id']);

// webhook tarafı
$olay = BuluthatAutoCall::readWebhook($secret);   // imzayı doğrular
if ($olay['event'] === 'call_finished' && $olay['data']['dtmf'] === '1') { /* ödedim dedi */ }