Public APILimitler ve Hatalar

Limitler ve Hata Kodları

Entegrasyonunu yazarken en çok zamanı beklenmedik hata yanıtları yer. Purvisor Public API bu konuda öngörülebilir: her hata aynı JSON zarfıyla döner — kök alanı her zaman error — ve iki gerçek kaynak kapısı vardır: arama başlatmada dakika bakiyesi (402) ve yeni kayıt açarken plan bazlı adet kotası (403 + code: "quota_exceeded"). Bu sayfa, hangi durumda hangi HTTP kodunun geldiğini ve entegrasyonunun bunları nasıl ele alması gerektiğini net biçimde açıklar.

Hız limiti (rate limit) var mı?

Evet — API anahtarı başına dakikada 60 istek. Limit IP’ye değil anahtara bağlıdır: paylaşımlı bir IP’den çalışan entegrasyonlar birbirini etkilemez, tek bir anahtar da tüm Public API’yi boğamaz.

Limit aşılırsa 429 döner ve yanıtta Retry-After başlığı bulunur — kaç saniye sonra tekrar deneyebileceğini bu başlıktan oku.

⚠️

Public API, Pro ve üzeri planlarda kullanılabilir. Anahtarın geçerli olsa bile planın kapsamıyorsa her çağrı 403 ile {"error":"premium_required","feature":"api_access"} (+ açıklayıcı bir message) döner. Bu kapı anahtar üretiminde değil her istekte uygulanır; yani Pro’yken anahtar üretip sonra plan düşerse erişim de durur.

Plan kapısının dışında iki kaynak kapısı vardır: dakika bakiyesi — yalnızca arama başlatmada devreye girer (402, aşağıda) — ve plan adet kotası — yeni kayıt açan uçlarda (POST /contacts, POST /leads) devreye girer ve 403 + code: "quota_exceeded" döner.

İyi bir entegrasyon limitlere kibar davranır — gereksiz döngüsel çağrılardan kaçın, 429 aldığında Retry-After kadar bekle, hataları geri-çekilmeli (backoff) tekrar dene. Aşağıdaki “İyi uygulamalar” bölümüne bak.

Dakika bakiyesi kısıtı — POST /calls

Arama başlatmadaki kaynak kapısı dakika bakiyesidir. POST /api/v1/calls çağrısı, hesabının dakika bakiyesi en az 1 olmadıkça aramayı başlatmaz:

POST /api/v1/calls

API anahtarı geçerli mi?           → hayır: 401 invalid_api_key
        ↓ evet
assistant_id bu hesaba ait+aktif?  → hayır: 404
        ↓ evet
arayan numara ait+aktif?           → hayır: 404
        ↓ evet
dakika bakiyesi ≥ 1 mi?            → hayır: 402 "Insufficient minute balance"
        ↓ evet
aynı kişiye devam eden arama var mı? → evet: 409
        ↓ hayır
santral araması başlatılır          → başarısız: 502 / başarılı: 201

Bakiye yetersizse yanıt:

HTTP/1.1 402 Payment Required
Content-Type: application/json
 
{"error":"Insufficient minute balance"}
⚠️

402, entegrasyonun “duracağı” ana durumdur. Bir Zap/senaryo yüksek hacimde arama tetikliyorsa ve bakiye biterse, her yeni çağrı 402 döner ve arama yapılmaz. Otomasyonuna düşük-bakiye uyarısı ekle; dakika satın alma için bkz. Dakika Paketleri.

Not: Arama başlatmak dakika bakiyesinin yanı sıra hesaba ait aktif bir asistan ve hesaba ait aktif bir telefon numarası da gerektirir. İkisi de yoksa POST /calls 404 döner (aşağıdaki tabloya bak).

Hata biçimi

Tüm hatalar aynı zarfla gelir — kök alanı her zaman error olan bir JSON nesnesi:

{ "error": "invalid_api_key" }

Doğrulama hatalarında (400 validation_error, zod ile denetlenen uçlar — ör. POST /hooks) ek bir details dizisi bulunur; her eleman insan-okur bir mesaj dizesidir:

{
  "error": "validation_error",
  "details": [
    "targetUrl must start with https://",
    "event must be one of the supported events"
  ]
}

Bazı hatalar error dışında da alan taşır:

HataEk alanlar
400 validation_errordetails[] — insan-okur doğrulama mesajları
400 invalid_eventvalidEvents[] — kabul edilen olay adları
403 premium_requiredmessage, feature ("api_access")
403 kota aşımıcode: "quota_exceeded", quota: { key, limit, current, plan }

error alanının değeri iki türdendir: bazıları makine-kodudur (invalid_api_key, validation_error, invalid_json, invalid_event, not_found, internal_error), bazıları ise doğrudan insan mesajıdır — bugün İngilizce (Insufficient minute balance, assistant_id not found, not owned by this account, or inactive), kota hatalarında ise Türkçe (kişi limitine ulaştınız (…)). Bu metinler uyarı yapılmadan değişir; entegrasyonunda dallanma yaparken HTTP durum koduna (403 için ayrıca code alanına) göre karar ver, mesaj metnine değil.

Hata kodu tablosu

HTTPerror değeri (örnek)Ne zaman olurNe yapmalı
400invalid_jsonİstek gövdesi geçerli JSON değilGövdeyi düzelt; Content-Type: application/json gönder
400(alan mesajı) örn. phone and assistant_id are required, Invalid phone — must contain at least 10 digitsZorunlu alan eksik/geçersiz (POST /calls, POST /contacts, POST /leads)Eksik alanı ekle; telefon en az 10 hane
400validation_error (+ details[])Zod doğrulaması başarısız (POST /hooks: event, targetUrl vb.)details dizisini oku, ilgili alanı düzelt
400invalid_event (+ validEvents[])GET /samples?event=... geçersiz olay adıvalidEvents listesinden geçerli bir olay seç
401invalid_api_keyAnahtar yok, biçimi bozuk (pk_live_ ile başlamıyor) veya eşleşmiyorAnahtarı kontrol et; bkz. Kimlik Doğrulama
402Insufficient minute balancePOST /calls — dakika bakiyesi 1’in altındaDakika yükle; bkz. Dakika Paketleri
403premium_required (+ message, feature: "api_access")Anahtar geçerli ama plan Public API’yi kapsamıyor — her /api/v1/* çağrısında kontrol edilirPro veya üzeri bir plana geç
403(kota mesajı) + code: "quota_exceeded" ve quota nesnesiPOST /contacts / POST /leads — planının kişi adedi kotası dolu. Kota yalnızca yeni kayıt açılırken bakılır; mevcut kişi döndürülüyorsa tüketilmezKullanılmayan kişileri sil ya da planını yükselt; yanıttaki quota.current / quota.limit alanlarına bak
429Too many requestsAnahtar başına dakikada 60 istek aşıldıYanıttaki Retry-After saniyesi kadar bekle, sonra tekrar dene
404assistant_id not found, not owned by this account, or inactivePOST /calls — asistan yok / başka hesaba ait / pasifassistant_id doğru mu? GET /assistants ile doğrula
404No active phone number on this account / phone_number_id not found or inactivePOST /calls — arayan numara yok/pasifAktif SIP numarası bağla; GET /phone-numbers
404assistant_id / campaign_id / cadence_id not found or not owned by this accountPOST /leads — gönderilen kimlik yok veya başka hesaba aitKimlikleri lookup uçlarından doğrula
404not_foundDELETE /hooks/{id} — abonelik yok veya başkasına aitVar olan bir abonelik id’si kullan (varlık sızıntısı yapılmaz)
409A call to this contact is already in progressPOST /calls — aynı kişiye zaten “calling” durumunda arama varBekle; çift arama gönderme (idempotency — aşağı bak)
502Could not start the call — check your minute balance and phone numberPOST /calls — santral/makeCall katmanı aramayı başlatamadıGeri-çekilmeli tekrar dene; sürerse durum/santralı kontrol et
500internal_errorBeklenmeyen sunucu hatası (örn. /hooks ya da /leads işlenirken)Geri-çekilmeli tekrar dene; sürerse destek

404 iki farklı anlama gelir. Kaynak arama uçlarında (GET /contacts) “bulunamadı” 404 değildir — Zapier/Make uyumu için boş dizi [] döner. 404 yalnızca sahiplik/varlık kapılarında (POST /calls asistan/numara, POST /leads asistan/kampanya/kadans, DELETE /hooks/{id}) görülür.

İyi uygulamalar — retry ve idempotency

Hız limitinin bol olması (anahtar başına dakikada 60 istek) “istediğin kadar dene” demek değildir. Sağlam bir entegrasyon şu kurallara uyar:

  • Duruma göre yeniden dene, geri-çekilerek. 502 ve 500 geçici olabilir → üstel geri-çekilme (ör. 15s taban) ile birkaç kez dene. 429 için yanıttaki Retry-After kadar bekle. 400, 401, 402, 403, 404, 409 için tekrar deneme anlamsızdır — istek/hesap durumunu düzeltmeden aynı sonucu alırsın.
  • POST /contacts ve POST /calls telefon-bazlı idempotenttir. Kişi oluşturma, telefonun tam ya da son-10-hane eşleşmesine bakar: aynı numarayı iki kez gönderirsen yeni kayıt oluşmaz, var olan kişi döner (POST /contactsexisting:true, HTTP 200). Yani ağ hatasında güvenle tekrar edebilirsin.
  • Çift aramayı 409 ile ele al. POST /calls, aynı kişiye devam eden bir arama varken ikinci isteği 409 ile reddeder. Bunu bir hata değil, “zaten sırada” olarak yorumla; tekrar tetikleme.
  • 402’yi bir dur-noktası olarak modelle. Bakiye biterse tüm aramalar durur. Otomasyonuna düşük-bakiye eşiği ekle ve bittiğinde tetiklemeyi durdur.
  • HTTP koduna göre dallan, mesaja göre değil. error metinleri uyarı yapılmadan değişir — v1 mesajları bir kez toptan Türkçe’den İngilizce’ye çevrildi ve mesaja göre dallanan entegrasyonlar sessizce kırıldı. Durum kodları (403’te ayrıca code alanı) sözleşmedir; metin değildir.
⚠️

KVKK. API üzerinden başlattığın her arama, aradığın kişinin gerçek telefonuna çıkar. Otomasyonun yalnızca açık rıza/aydınlatma kapsamındaki numaraları aramalı; asistanın açılışında kim olduğunu ve neden aradığını net söylemeli. Rıza dışı toplu arama tetiklemek yasal risktir. Bkz. KVKK ve Veri Yönetimi.

İlgili