Skip to Content
Public APIArama Başlatma

Arama Başlatma — POST /calls

Bir CRM’e yeni lead düştüğünde tek bir POST isteğiyle yapay zeka asistanın o numarayı saniyeler içinde arayabilir — kontak yoksa otomatik açılır, asistan konuşur, görüşme faturalandırılır. Bu uç, Purvisor AI Public API’nin çekirdek yazma aksiyonudur; Zapier ve Make’teki “Arama Başlat” adımı da tam olarak bunu çağırır. Bir düşün: reklamdan gelen lead’i elle aramak yerine, form gönderilir gönderilmez asistanın devreye girer.

Bu uç anında arama yapar; kadans/kampanya zamanlaması uygulamaz. Zamana yayılmış çok adımlı takip için Kadans Nedir? veya Kampanya Oluşturma tarafını kullan.

İstek

POST /api/v1/calls X-API-Key: pk_live_... Content-Type: application/json

Kimlik doğrulama tüm /api/v1/* uçlarında olduğu gibi API anahtarıyla yapılır. Anahtarı nasıl alacağın ve gönderme biçimleri için Kimlik Doğrulama sayfasına bak.

Gövde alanları

İstek gövdesi hem snake_case hem camelCase kabul eder (örn. assistant_id veya assistantId).

AlanZorunluAçıklama
phoneEvetAranacak numara. En az 10 hane içermeli (rakam dışı karakterler yok sayılır).
assistant_idEvetAramayı yapacak asistanın id’si. Bu hesaba ait ve aktif olmalı. Listeyi GET /assistants ile çek.
phone_number_idHayırArayan numara (caller-ID). Verilmezse hesaptaki ilk aktif numara kullanılır. Verilirse hesaba ait ve aktif olmalı.
first_nameHayırKontak yoksa oluşturulurken kullanılır. Boşsa "Müşteri" yazılır.
last_nameHayırKontak yoksa oluşturulurken kullanılır.

Numarayı elle vermek yerine phone_number_id alanını GET /phone-numbers çıktısındaki bir id ile besle — böylece hangi hattan çıktığını kontrol edersin.

curl örneği

curl -X POST https://app.purvisor.ai/api/v1/calls \ -H "X-API-Key: pk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "phone": "+905321234567", "assistant_id": "asst_abc123", "phone_number_id": "42", "first_name": "Ayşe", "last_name": "Yılmaz" }'

İşleyiş ve kapılar

Uç, kanıtlanmış kampanya makinesini (oda metadata + SIP + agent dispatch + faturalama) yeniden kullanır. Arama gerçekleşmeden önce sırayla şu kapılardan geçilir:

POST /calls ↓ Gövde doğrulama (phone + assistant_id, ≥10 hane) → 400 ↓ Asistan sahipliği (bu hesaba ait + aktif mi?) → 404 ↓ Arayan numara (verilen ait+aktif mi / ilk aktif) → 404 ↓ Arama izni: hesap penceresi ∩ yasal pencere → 422 ↓ Eşzamanlılık ve hacim tavanı → 429 / 503 ↓ Dakika bakiyesi ≥ 1 → 402 ↓ Kontağı bul (telefonla dedupe) — yoksa oluştur ↓ Gizli "zapier-auto" kampanyası (asistan+numara başına) ↓ Devam eden arama var mı? (çift arama koruması) → 409 ↓ makeCall → arama başlar → 502 (başarısızsa) ↓ 201 { call_id, status: "initiated", ... }

Gizli kampanya mekaniği. Arama, (asistan, numara) çifti başına oluşturulan gizli bir kampanya altında yürür — description="zapier-auto", status="completed", isActive=false. Bu bayraklar sayesinde zamanlayıcılar ve kampanya worker’ı bu kampanyaya dokunmaz; panelindeki normal kampanya raporlarını kirletmez. Sen bir şey yapmana gerek yok, otomatik yönetilir.

Kontak eşleştirmesi POST /contacts ile aynı mantıkla çalışır: tam numara veya son 10 hane eşleşmesi. Eşleşen kontak yoksa yenisi leadSource="zapier", status="new" ile açılır.

Aynı kişiye devam eden bir API araması varken ikinci istek atarsan HTTP 409 dönersin — çift arama böyle engellenir. Bir Zap’i yanlışlıkla iki kez tetiklersen ikinci çağrı sessizce yeni arama başlatmaz.

Başarılı yanıt

Arama başlatıldığında HTTP 201 ve şu gövde döner:

{ "call_id": "1287", "status": "initiated", "contact_id": "9043", "assistant_id": "asst_abc123", "from_number": "+904440000", "to": "+905321234567" }
AlanAçıklama
call_idBaşlatılan aramanın id’si. Görüşme bitince call.completed webhook’unda bu değerle eşleşir.
statusHer zaman "initiated" — arama kuyruğa alındı, henüz bağlanma sonucu değil.
contact_idAranan kontağın id’si (bulunan veya yeni oluşturulan).
assistant_idİstekte gönderdiğin asistan id’si.
from_numberAramanın çıktığı numara (caller-ID).
toKontağın kayıtlı telefon numarası.

warning: "outside_your_business_hours" alanı kaldırıldı. Eskiden çalışma saatlerin dışında başlatılan aramalar 201 + bu uyarıyla dönüyordu. Hesap arama penceresi artık bağlayıcı bir kapı olduğu için o durum 201 değil 422 üretir (aşağıya bak). Bu alana bakan bir Zap/senaryon varsa koşulu HTTP durum koduna taşı.

Arama saatleri

Arama iki katmandan geçer ve ikisi de kapıdır:

  • Hesap arama penceresi — Ayarlar → Arama penceresi’nde tanımladığın saat ve günler. API’yi çağırmış olman bu pencereyi aşmaz.
  • Aranan ülkenin yasal penceresi — numaradan çözülen ülkeye göre uygulanır.

İzin = hesap penceresi ∩ (uygulanıyorsa) yasal pencere. Biri kapalıysa arama başlatılmaz: HTTP 422.

Hangi ülkede hangi pencere?

ArananPencere (aranan yerel saatiyle)Bildirgeyle aşılabilir mi?
ABD08:00–21:00, her gün (TCPA)Hayır
Birleşik Krallık08:00–21:00, Pzt–Cmt (Ofcom)Hayır
Türkiye09:00–19:00, Pzt–CmtEvet
Paketi olmayan ülke (DE, CA, AE…)09:00–19:00, Pzt–CmtHayır
Ülkesi / saat dilimi çözülemeyen numara—Arama hiç yapılmaz

Türkiye’de yasal pencere kapı değil, eşiktir. Onaysız bir hesabın arama penceresi bu eşiğin içinde kalmak zorundadır; bildirgeyi onaylayan hesap dışına çıkabilir (Ayarlar → Arama penceresi). Sonuç: TR numarada outside_legal_call_window dönmez — pencere dışı istek outside_business_hours alır, onaylı geniş pencerede ise arama gider (201).

Ülkesi ya da saat dilimi çözülemeyen numara aranmaz. Yasal saati doğrulanamayan bir numarayı aramak yerine istek 422 callee_region_unknown ile reddedilir. Kanada ve Avustralya gibi çok saat dilimli ülkelerde kişide kayıtlı saat dilimi yoksa tahmin yapılmaz — o numara da bu kapıya takılır. Çözüm pencereyi değiştirmek değil, numarayı E.164 biçiminde (+49…) göndermek ya da kişinin ülke/saat dilimi bilgisini doldurmaktır.

422 yanıt gövdesi

{ "error": "Calling is outside your account's calling hours (Settings → Call window). Retry after next_allowed_at.", "code": "outside_business_hours", "blocked_by": ["account"], "country_code": "TR", "next_allowed_at": "2026-09-16T06:00:00.000Z" }
AlanTürAnlam
code"outside_legal_call_window" · "outside_business_hours" · "callee_region_unknown"Reddi tek sebebe indirger.
blocked_bydizi: "account" · "campaign" · "legal"Dallanmak için kullanacağın kararlı alan — reddeden bütün katmanları sayar.
country_codedizge · nullNumaradan çözülen aranan ülke.
next_allowed_atISO-8601 · nullBir sonraki izinli an. Katmanlar önümüzdeki haftalarda hiç kesişmiyorsa null.
errordizgeİnsan okuması için; dallanmada kullanma, uyarısız değişir.

Ne yapmalı?

  • next_allowed_at dolu, blocked_by içinde "legal" → yapılacak şey beklemek; Zap’i next_allowed_at’e ertele.
  • next_allowed_at dolu, yalnız "account" → ya bekle ya da Ayarlar → Arama penceresi’ni genişlet.
  • next_allowed_at null → bu numara bu hesap penceresiyle önümüzdeki haftalarda aranamaz; otomatik yeniden deneme kurma. Pencereyi değiştir. (Yaz saati geçişleri kesişimi haftalar sonra açabilir; pencere değişmeden tekrar denemek günlerce aynı 422’yi döndürür.)
  • code: "callee_region_unknown" → yeniden deneme yok, pencere değişikliği de çözmez. Numarayı düzelt.

Kesişim yok örneği (TR hesap 09:00–18:00 + Los Angeles numarası — saat 12:00’de de 20:00’de de aynı gövde döner):

{ "error": "Your account's calling hours do not overlap the legally permitted hours for the destination country in the coming weeks, so this number cannot be called with the current call window. Retrying will not help; widen the call window (Settings → Call window).", "code": "outside_legal_call_window", "blocked_by": ["account", "legal"], "country_code": "US", "next_allowed_at": null }

Bölgesi çözülemeyen numara örneği:

{ "error": "The destination number's country or time zone could not be determined, so its legal calling hours cannot be verified and this number will not be called. Retrying will not help; check the phone number (international format, e.g. +49…).", "code": "callee_region_unknown", "blocked_by": ["legal"], "country_code": "NG", "next_allowed_at": null }

Değişenler (entegrasyonunu etkileyebilir). TR numarada outside_legal_call_window artık dönmüyor; hesap penceresi kapalıyken eskiden gelen yanıltıcı 502 "Could not start the call…" yerine artık sebebiyle birlikte 422 dönüyor; next_allowed_at null olabilir; blocked_by yeni eklendi; warning: "outside_your_business_hours" kaldırıldı. Koşullarını error metnine değil, HTTP durum koduna ve blocked_by/code alanlarına bağla.

status: "initiated" “telefon çaldı/açıldı” demek değildir; sadece aramanın başarıyla kuyruğa alındığını bildirir. Görüşmenin sonucunu (süre, özet, duygu) öğrenmek için call.completed webhook’una abone ol — bkz. Webhook’lar.

Eşzamanlılık ve hacim tavanları

Aynı anda kaç aramanın açık olabileceği planına bağlıdır; ayrıca hesabına saatlik ve günlük toplam arama tavanı koyabilirsin. İstek bu kapıya takılırsa arama başlatılmaz ve bakiyenden dakika düşülmez — kapı bakiye rezervinden önce çalışır.

DurumHTTPcodeGövdedeki ek alanlar
Eşzamanlılık tavanı dolu429concurrency_limitscope: "tenant" (senin planının tavanı) veya "global" (platform tavanı), active, limit
Saatlik arama tavanı dolu429hourly_call_capscope: "hourly", active, limit
Günlük arama tavanı dolu429daily_call_capscope: "daily", active, limit
Kapı karar veremedi503 + Retry-After: 30call_gate_unavailableretry_after: 30
{ "error": "Concurrent or volume call limit reached", "code": "concurrency_limit", "scope": "tenant", "active": 10, "limit": 10 }

429 ile 503 aynı şey değil:

  • 429 gerçek bir tavandır. active ve limit ile birlikte gelir; hızını düşür, kuyruğunu yay. Eşzamanlılık tavanı planına göredir (Planlar); saatlik/günlük tavanlar senin kendi koyduğun frendir ve tanımlı değilse uygulanmaz.
  • 503 geçicidir. Tavan dolduğu için değil, kapı o an doğrulanamadığı için reddedilir (arka plandaki sayaç okunamamıştır). Retry-After kadar bekleyip aynı isteği tekrar dene — bir şeyi düzeltmen gerekmiyor. Kapı doğrulanamadan arama açılmaz; çünkü açık geçilseydi tavan hiç uygulanmamış olurdu.

Değişti — eskiden bunların hepsi tek bir 502 "Could not start the call — check your minute balance and phone number" idi. Entegratör tavanın dolduğunu anlayamıyor, boşuna bakiye ve numara kontrol ediyordu. Artık her durumun ayrı kodu var; bakiye (402) ve arama penceresi (422) zaten ayrı kodlardı. Koşullarını error metnine değil, HTTP durum koduna ve code alanına bağla.

Hata kodları

KodGövde (error)Neden
400invalid_jsonGövde geçerli JSON değil.
400phone and assistant_id are requiredZorunlu alanlardan biri eksik.
400Invalid phone — must contain at least 10 digitsTelefon 10 haneden az.
401invalid_api_keyAPI anahtarı geçersiz/eksik.
402Insufficient minute balanceDakika bakiyesi 1’in altında.
429concurrency_limit · hourly_call_cap · daily_call_capEşzamanlılık ya da hacim tavanı dolu. Gövdedeki active/limit ile ne kadar aştığını görürsün.
422outside_legal_call_windowAranan ülkenin yasal arama saatleri dışında (ya da hesap penceresiyle yasal pencere hiç kesişmiyor). next_allowed_at doluysa o ana ertele, null ise pencereyi değiştir.
422outside_business_hoursHesabının arama penceresi dışında (Ayarlar → Arama penceresi).
422callee_region_unknownNumaranın ülkesi / saat dilimi çözülemedi; yasal saat doğrulanamadığı için arama yapılmaz. Yeniden deneme çözmez — numarayı E.164 biçiminde gönder.
404assistant_id not found, not owned by this account, or inactiveAsistan yok, başka hesaba ait ya da pasif.
404phone_number_id not found or inactiveVerilen numara yok/pasif.
404No active phone number on this accountphone_number_id verilmedi ve hesapta aktif numara yok.
409A call to this contact is already in progressAynı kontağa açık bir API araması mevcut.
503call_gate_unavailableEşzamanlılık kapısı o an doğrulanamadı. Geçici — Retry-After (30 sn) kadar bekleyip tekrar dene.
502Could not start the call — check your minute balance and phone numberArama başlatılamadı. Kalan sebepler: kişi DNC listesinde ya da SIP/santral sorunu. Arama penceresi (422), eşzamanlılık/hacim tavanı (429), kapı doğrulanamaması (503) ve bakiye (402) artık bu satıra düşmez — kendi kodlarıyla döner.

Hata metinlerine göre dallanma yapma — bu dizeler uyarı yapılmadan değişir (v1 mesajları bir kez toptan Türkçe’den İngilizce’ye çevrildi). Zap/senaryo koşullarını HTTP durum koduna göre kur.

Tüm hata kodlarının ortak referansı için Limitler ve Hatalar sayfasına bak.

KVKK notu. Bu uç gerçek bir telefon araması başlatır. Aradığın numaranın açık rızası otomatik arama kapsamını da içermeli; asistanının açılışında kim olduğunu ve neden aradığını net söylediğinden emin ol. Rıza yönetimi için KVKK ve Veri Yönetimi.

Sorun giderme

BelirtiOlası neden / çözüm
402 dönüyorDakika bakiyesi bitmiş → Dakika Paketleri ile yükle.
404 (asistan)Yanlış assistant_id veya asistan pasif → GET /assistants ile doğru id’yi çek.
404 (numara)Hesapta aktif SIP numarası yok → Telefon Numarası (SIP) ile bağla.
409 dönüyorAynı kişiye zaten açık bir arama var; Zap’in çift tetiklenmediğinden emin ol.
422 outside_legal_call_window dönüyorAranan ülkenin yasal arama penceresi dışındasın (TR 09:00–19:00, Pzt–Cmt). Hemen tekrar denemek işe yaramaz: yanıttaki next_allowed_at zamanına kadar bekle ve isteği o zaman gönder.
502 dönüyorKişinin DNC listesinde olup olmadığını, numaranın aktif ve SIP trunk’lı olduğunu kontrol et. Bakiye, arama penceresi ve eşzamanlılık/hacim tavanı artık 502 değil, kendi kodlarını (402 / 422 / 429) döner.
429 alıyorum ama tavanı ben koymadımscope alanına bak: tenant planının eşzamanlılık tavanı, global platform tavanı, hourly/daily ise hesabındaki saatlik/günlük arama freni.
503 call_gate_unavailable sürekli geliyorTekrar denemeye devam et (Retry-After kadar bekleyerek); tavan dolu değil, kapı doğrulanamıyor. Sürüyorsa destekle iletişime geç.
201 aldım ama telefon çalmadıinitiated yalnızca kuyruğa alındığını gösterir; sonucu call.completed webhook’undan izle.

İlgili