Telefoni & AramalarTwilio ve SIP Outbound Trunk

Twilio ve SIP Trunk Bağlama (Gelişmiş)

Panelde Telefon Numaraları → Numara Ekle dediğinde önüne iki kart çıkar: Twilio ve SIP Trunk. İkisi de aynı hedefe gider — asistanının arayabileceği/cevaplayabileceği bir numara — ama arka planda tamamen farklı iki şey olur: biri bir üçüncü parti hesabı doğrular, diğeri LiveKit üzerinde gerçek zamanlı bir outbound SIP trunk kurar. Bu sayfa o iki yolu alan alan, hata hata anlatır. Genel kavramlar ve gelen/giden ayrımı için önce Telefon Numarası (SIP) sayfasına bak — burası onun ileri seviye devamı.

Bu sayfadaki alan adları ve hata mesajları doğrudan Purvisor’ın backend kodundan alınmıştır (/api/phone-numbers/twilio ve /api/phone-numbers/sip). Panelde gördüğün formla birebir eşleşir.

İki yol, tek karar

TwilioSIP Trunk (LiveKit)
Ne bağlarsınKendi Twilio hesabın (Account SID + Auth Token) + arama yapacaksan Elastic SIP Termination bilgileriBir SIP sağlayıcısının (Netgsm, santral, uluslararası operatör) trunk bilgileri
DoğrulamaBackend, girdiğin bilgiyi gerçek Twilio API’sine karşı anında test eder; Termination bilgisi verdiysen ayrıca LiveKit’te outbound trunk oluştururLiveKit’te gerçek bir SIP outbound trunk oluşturulur; hata anında döner
Ses (voice)Yalnızca Termination bilgileri girildiyse — sadece Account SID + Auth Token girersen numara arama YAPAMAZVar
SMSVarYok
Kayıt sayısı1 numara → 1 kayıtVirgülle ayırdığın her numara için ayrı kayıt (tek trunk’a bağlı)
Kime uygunUluslararası numara, Twilio zaten kullanılıyorsaTürkiye’de yerel/toplu hat (örn. Netgsm), maliyet avantajı arayanlar

Nasıl çalışır (mimari)

Panel → Telefon Numaraları → Numara Ekle → Sağlayıcı seç

                  ┌───────────────┴───────────────┐
                  │                                │
              Twilio                          SIP Trunk
                  │                                │
   POST /api/phone-numbers/twilio      POST /api/phone-numbers/sip
                  │                                │
   Twilio API'ye Account SID/Auth       LiveKit SipClient
   Token doğrulanır (gerçek zamanlı)    .createSipOutboundTrunk()
                  │                                │
   Termination bilgisi verildiyse       LiveKit'te trunk oluşur
   LiveKit'te outbound trunk kurulur    → sipTrunkId döner
                  │                                │
   PhoneNumber kaydı (provider:                    │
   twilio; trunk kurulduysa                        │
   sip_trunk_id dolu, yoksa boş)                   │
                  │                                │
                  │                    PhoneNumber kaydı (her numara
                  │                    için ayrı satır, provider:
                  │                    livekit_sip, aynı sipTrunkId)

Yol 1: Twilio hesabı bağlama

Twilio bilgilerini hazırla

Twilio konsolundan şunları al:

  • Account SIDAC ile başlayan hesap kimliği.
  • Auth Token — panelde şifre alanı olarak girilir, ekranda gösterilmez.
  • Telefon numarası — Twilio’dan satın aldığın, E.164 formatındaki numara (örn. +15551234567).
  • Elastic SIP Trunking → Termination bilgileri — arama yapacaksan zorunlu: Termination SIP URI (örn. ornek.pstn.twilio.com), Credential List’ten bir SIP kullanıcı adı ve SIP şifresi.

Panelde bağla

Telefon Numaraları → Numara Ekle → Twilio kartı → açılan formu doldur:

AlanZorunlu muAçıklama
BölgeEvet — Twilio seçince varsayılan USNumaranın hizmet ettiği bölge (TR / US / GB); aranan kişinin ülkesine göre doğru numara/trunk seçilir
Account SIDEvetAC ile başlayan hesap kimliği
Auth TokenEvetTwilio API’sine karşı anında doğrulanır
Telefon NumarasıEvetE.164 formatında (+ ve ülke kodu ile); boşluk, tire ve parantez temizlenir, format yine tutmuyorsa 400 döner
Görünen AdEvetİç kullanım için — örn. US Ana Hat
Termination SIP URIArama için evetTwilio konsolu → Elastic SIP Trunking → Termination, örn. ornek.pstn.twilio.com (başına sip:// yapıştırırsan temizlenir)
SIP Kullanıcı AdıArama için evetCredential List kullanıcısı
SIP ŞifreArama için evetCredential List şifresi
TransportHayır — varsayılan tlsTwilio Termination TLS önerir; udp / tcp de seçilebilir
⚠️

Termination SIP URI + SIP Kullanıcı Adı + SIP Şifre üçlüsü ya hep ya hiç: birini doldurup diğerini boş bırakırsan kayıt hiç oluşmaz ve şu hata döner — “Arama yapabilmek için Termination SIP URI, SIP kullanıcı adı ve şifresinin üçü de gereklidir. Yalnızca SMS kullanacaksanız bu alanları tamamen boş bırakın.”

📸 [Ekran görüntüsü: Numara Ekle modalı — Twilio formu (Account SID, Auth Token, Telefon Numarası, Görünen Ad)]

Doğrulama otomatik çalışır

“Twilio Bağla” butonuna bastığında backend, girdiğin Account SID + Auth Token ile gerçek Twilio API’sine bir istek atar (GET /2010-04-01/Accounts/{sid}.json, Basic Auth ile); ardından Termination bilgisi verdiysen LiveKit trunk’ını kurar. Bu adımların herhangi biri takılırsa kayıt hiç oluşmaz ve şu hatalardan biri döner:

HataNeden
”Twilio kimlik bilgileri geçersiz. Account SID ve Auth Token’ı kontrol edin.”Twilio hesabı bulunamadı / SID-Token eşleşmiyor (400)
“Twilio doğrulaması yapılamadı. Bağlantıyı kontrol edip tekrar deneyin.”Twilio API’sine ağ isteği başarısız oldu (502)
“Bu telefon numarası zaten ekli”Aynı numara hesabında zaten kayıtlı (409)
“Bu numara başka bir hesapta kayıtlı. Size aitse destek ile iletişime geçin.”Aynı numara başka bir Purvisor hesabında kayıtlı (409) — gelen aramada kiracı numaradan türetildiği için mükerrer kayda izin verilmez
”Twilio SIP trunk oluşturulamadı: …”Termination bilgileri verildi ama LiveKit trunk’ı kurulamadı (502) — numara kaydı hiç oluşmaz, yarım kalmış kayıt bırakılmaz

Bu kontrol, yanlış bilgiyle eklenen bir numaranın panelde “Aktif” görünüp ilk arama denemesinde sessizce patlamasını engellemek için var.

Kayıt oluşur

Doğrulama geçerse bir PhoneNumber kaydı oluşur: provider: "twilio", provider_type: "twilio". Ses özelliği (capabilities.voice) sabit değildir — kayıtta bir sip_trunk_id varsa açık, yoksa kapalıdır; SMS her durumda açıktır.

  • Termination bilgilerini girdiysen: LiveKit’te outbound trunk oluşur, kayda sip_trunk_id yazılır, yanıt canMakeCalls: true döner — numara arama için hazırdır.
  • Girmediysen: numara yine kaydedilir ama yanıt canMakeCalls: false ve şu uyarıyı döner: “Bu numara kaydedildi ancak ARAMA YAPAMAZ. Arama için Twilio Elastic SIP Termination bilgilerini (SIP URI + kullanıcı adı + şifre) girmeniz gerekir. Numarayı silip Termination bilgileriyle tekrar ekleyebilirsiniz.” Panel bunu ekleme biter bitmez “Numara eklendi — ama arama yapamaz” ekranında gösterir; Telefon Numaraları listesinde de o numaranın kartında kalıcı bir “Bu numarayla arama yapılamaz” bandı ve sönük bir Voice rozeti görürsün.

Account SID ve Auth Token, veritabanında şifrelenmiş olarak (encrypt()) saklanır — düz metin tutulmaz. Trunk kurulduysa SIP kullanıcı adı da şifrelenerek livekit_config içine yazılır; SIP şifresi hiç saklanmaz.

Panelin arka planda gönderdiği istek, teknik referans için:

POST /api/phone-numbers/twilio
{
  "accountSid": "ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "authToken": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "phoneNumber": "+15551234567",
  "friendlyName": "US Ana Hat",
  "terminationUri": "ornek.pstn.twilio.com",
  "sipUsername": "credential-list-kullanicisi",
  "sipPassword": "xxxxxxxxxxxx",
  "transport": "tls",
  "regionCode": "US"
}

terminationUri / sipUsername / sipPassword üçlüsünü hiç göndermezsen istek yine başarılı olur — ama dönen numara yalnızca SMS içindir.

Yol 2: SIP Trunk oluşturma (LiveKit outbound trunk)

SIP trunk yolu, üçüncü bir servisi (Twilio gibi) doğrulamaz — doğrudan Purvisor’ın gerçek zamanlı ses altyapısı olan LiveKit üzerinde bir outbound SIP trunk yaratır. Bu, “Purvisor buradan çıkış yapıp arama başlatabilir” demenin teknik karşılığıdır; gelen aramaları kapsamaz (bkz. Gelen Aramalar).

SIP sağlayıcından bilgileri al

Operatöründen (örn. Netgsm) şunları al:

  • SIP sunucu adresi (host) — örn. sip.netgsm.com.tr
  • TransportUDP, TCP veya TLS
  • Kullanıcı adı / şifre — SIP kimlik doğrulama bilgileri
  • Numara(lar) — bu trunk üzerinden aranacak numaralar

Panelde formu doldur

Telefon Numaraları → Numara Ekle → SIP Trunk kartı:

Alan (kod adı)Zorunlu muAçıklama
Bölge (regionCode)Evet — SIP seçince varsayılan TRNumaranın hizmet ettiği bölge (TR / US / GB); aranan kişinin ülkesine göre doğru numara/trunk seçilir
Trunk Adı (trunkName)EvetLiveKit’te trunk’ı tanımlayan isim, örn. netgsm-trunk
SIP Address (address)EvetSağlayıcının SIP sunucu adresi, örn. sip.netgsm.com.tr
Transport (transport)Hayır — varsayılan udpudp / tcp / tls
Telefon Numaraları (numbers)EvetVirgülle ayrılmış, her biri ayrı bir kayıt olur
Username (username)EvetSIP kimlik doğrulama kullanıcı adı
Password (password)EvetSIP kimlik doğrulama şifresi
Görünen Ad (friendlyName)HayırBoş bırakılırsa Trunk Adı kullanılır

📸 [Ekran görüntüsü: Numara Ekle modalı — SIP Trunk formu (Trunk Adı, SIP Address, Transport, Numaralar, Username/Password)]

Backend ne yapar

“SIP Trunk Oluştur” butonuna basınca:

  1. Backend, LiveKit SDK’sının SipClient.createSipOutboundTrunk(trunkName, address, numbers[], { transport, auth_username, auth_password }) fonksiyonunu çağırır.
  2. LiveKit trunk’ı oluşturur ve bir sipTrunkId döner. Bu adımda hata olursa (yanlış adres, sağlayıcı IP’yi reddediyor, kimlik bilgisi hatalı vb.) kayıt hiç oluşturulmaz"LiveKit SIP Trunk creation failed: ..." hatası döner.
  3. Başarılıysa, numbers alanına virgülle yazdığın her numara için ayrı bir PhoneNumber kaydı oluşur — hepsi aynı sipTrunkId’yi paylaşır. provider: "livekit_sip", provider_type: "sip".
  4. Trunk bilgileri (sipTrunkId, adres, transport) ve şifrelenmiş kullanıcı adı livekit_config alanında saklanır. Şifre veritabanında tutulmaz — sadece LiveKit’e iletilir.

Panelin gönderdiği istek:

POST /api/phone-numbers/sip
{
  "trunkName": "netgsm-trunk",
  "address": "sip.netgsm.com.tr",
  "transport": "udp",
  "numbers": "+905XXXXXXXXX, +905YYYYYYYYY",
  "username": "8503XXXXXX",
  "password": "xxxxxxxxxxxx",
  "friendlyName": "NetGSM Ana Hat",
  "regionCode": "TR"
}

Transport seçimi: UDP / TCP / TLS

Transport, SIP sinyalinin ağ üzerinde nasıl taşınacağını belirler — LiveKit’in SIPTransport enum’una şöyle eşlenir: UDP = 0, TCP = 1, TLS = 2.

  • UDP (varsayılan) — en yaygın, çoğu operatörün beklediği seçenek. Bilmiyorsan buradan başla.
  • TCP — bağlantı temelli, UDP ile sorun yaşarsan dene.
  • TLS — şifreli sinyalleşme; sağlayıcın özellikle istiyorsa veya güvenlik gereksinimin varsa seç.

Sağlayıcın hangisini istediğini belirtmiyorsa UDP ile başla; arama kurulamıyorsa sağlayıcı desteğine transport’u sor.

Birden çok numara, tek trunk

numbers alanına yazdığın numaralar (virgülle ayrılmış) tek bir SIP trunk’ı paylaşır — aynı kullanıcı adı/şifre ile aynı sağlayıcıya çıkarlar ama panelde ayrı ayrı numaralar olarak görünür, her birine ayrı asistan/kampanya atayabilirsin. Operatörden birden fazla DID (numara) aldıysan tek seferde ekleyebilirsin.

Numarayı yönetme: aktif/pasif, silme, asistana bağlama

  • Aktif/pasif — numara kartında Aktif/Pasif rozetini görürsün ve pasif numaralar aramada kullanılmaz; ancak panelde şu an bunu değiştiren bir düğme yok, durum yalnızca API’den (PATCH /api/phone-numbers/{id}isActive) değiştirilebiliyor.
  • Düzenleme — panelde “Düzenle” ile değiştirebildiğin iki alan var: Görünen Ad ve Asistana Bağla (gelen çağrı). Numaranın kendisi, sağlayıcı ve trunk bilgileri düzenlenemez.
  • Silme — panelden “Sil” dediğinde numara kalıcı silinmez, soft-delete uygulanır (kayıt gizlenir, iz kaybolmaz).
  • Asistana bağlama (inbound) — bir numarayı belirli bir asistana bağlayabilirsin; bu numaraya gelen çağrılar o asistana düşer. Sadece kendi asistanına bağlayabilirsin, backend sahiplik kontrolü yapar. Detay: Gelen Aramalar.
⚠️

Twilio Auth Token ve SIP şifresi kimlik bilgisidir — KVKK kapsamında hassas veri sayılır. Purvisor bunları şifreli saklar (Twilio Auth Token ve SIP kullanıcı adı veritabanında encrypt() ile şifrelenir; SIP şifresi hiç saklanmaz, sadece LiveKit’e iletilir). Yine de bu bilgileri ekip içi paylaşırken parola yöneticisi gibi güvenli bir kanal kullan, düz metin mesajla göndermekten kaçın.

Hangisini seçmeliyim?

  • “SIP trunk kurulumu karmaşık görünüyor” — haklı endişe, ama tek seferlik bir işlem. Kurulduktan sonra numara yönetimi (asistana bağlama, aktif/pasif) Twilio numarasından farksız; panelde aynı listede görünür.
  • Türkiye’de yerel/toplu hat istiyorsan (çağrı merkezi, çok numaralı kampanya) SIP trunk genelde maliyet ve esneklik açısından daha uygun.
  • Zaten Twilio kullanıyorsan veya uluslararası bir numaraya ihtiyacın varsa Twilio yolu daha az adımda biter — kredi kartı/kota yönetimi Twilio tarafında kalır. Ama unutma: Twilio yolunda da arama yapmak için Elastic SIP Termination kurulumu gerekir; “daha az adım” demek “SIP’siz” demek değil.
  • Sadece SMS gönderecekseniz Twilio yolunu Termination bilgisi vermeden kullanabilirsin — numara kaydedilir, arama yapamaz.

Sorun giderme

BelirtiOlası neden / çözüm
”Twilio kimlik bilgileri geçersiz”Account SID veya Auth Token yanlış kopyalanmış; Twilio hesabı askıya alınmış olabilir.
”Twilio doğrulaması yapılamadı” (502)Anlık ağ sorunu — tekrar dene; sürerse Twilio durum sayfasını kontrol et.
”LiveKit SIP Trunk creation failed”SIP Address, Username veya Password hatalı; sağlayıcı ACL’i Purvisor’ın çıkış IP’sini engelliyor olabilir — sağlayıcıya sor.
Twilio numarası eklendi ama kartında “Bu numarayla arama yapılamaz” yazıyorTermination bilgileri girilmemiş, numaranın sip_trunk_id’si yok. Numarayı sil, Termination SIP URI + SIP kullanıcı adı + şifre ile tekrar ekle.
”Arama yapabilmek için Termination SIP URI, SIP kullanıcı adı ve şifresinin üçü de gereklidir” (400)Üç Termination alanından bazıları boş — ya üçünü de doldur ya da üçünü de boş bırak (yalnızca SMS).
”Twilio SIP trunk oluşturulamadı: …” (502)Termination adresi/kimlik bilgileri Twilio tarafındaki Credential List ile eşleşmiyor olabilir. Bu durumda numara kaydı hiç oluşmaz — düzeltip tekrar dene.
”Bu telefon numarası zaten ekli” (409)Aynı numara bu hesapta zaten kayıtlı (silinmemiş).
”Bu numara başka bir hesapta kayıtlı” (409)Numara başka bir Purvisor hesabında kayıtlı — sana aitse destekle iletişime geç.
Trunk oluştu ama arama çıkmıyorTransport uyumsuzluğu (udp/tcp/tls) veya sağlayıcı tarafında numara/kimlik eşleşmiyor — sağlayıcıyla trunk yapılandırmasını doğrula.
Birden fazla numara girdim, biri eksik göründünumbers alanını virgülle ayır; her numara E.164 formatında olmalı (+90...).
Asistana bağlayamadımNumara başka bir kullanıcının/hesabın asistanına bağlanamaz — backend sahiplik kontrolü yapar, kendi asistanını seç.

İlgili