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
| Twilio | SIP Trunk (LiveKit) | |
|---|---|---|
| Ne bağlarsın | Kendi Twilio hesabın (Account SID + Auth Token) + arama yapacaksan Elastic SIP Termination bilgileri | Bir SIP sağlayıcısının (Netgsm, santral, uluslararası operatör) trunk bilgileri |
| Doğrulama | Backend, girdiğin bilgiyi gerçek Twilio API’sine karşı anında test eder; Termination bilgisi verdiysen ayrıca LiveKit’te outbound trunk oluşturur | LiveKit’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 YAPAMAZ | Var |
| SMS | Var | Yok |
| Kayıt sayısı | 1 numara → 1 kayıt | Virgülle ayırdığın her numara için ayrı kayıt (tek trunk’a bağlı) |
| Kime uygun | Uluslararası numara, Twilio zaten kullanılıyorsa | Tü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 SID —
ACile 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:
| Alan | Zorunlu mu | Açıklama |
|---|---|---|
| Bölge | Evet — Twilio seçince varsayılan US | Numaranın hizmet ettiği bölge (TR / US / GB); aranan kişinin ülkesine göre doğru numara/trunk seçilir |
| Account SID | Evet | AC ile başlayan hesap kimliği |
| Auth Token | Evet | Twilio API’sine karşı anında doğrulanır |
| Telefon Numarası | Evet | E.164 formatında (+ ve ülke kodu ile); boşluk, tire ve parantez temizlenir, format yine tutmuyorsa 400 döner |
| Görünen Ad | Evet | İç kullanım için — örn. US Ana Hat |
| Termination SIP URI | Arama için evet | Twilio 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 evet | Credential List kullanıcısı |
| SIP Şifre | Arama için evet | Credential List şifresi |
| Transport | Hayır — varsayılan tls | Twilio 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:
| Hata | Neden |
|---|---|
| ”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_idyazılır, yanıtcanMakeCalls: truedöner — numara arama için hazırdır. - Girmediysen: numara yine kaydedilir ama yanıt
canMakeCalls: falseve ş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 birVoicerozeti 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 - Transport —
UDP,TCPveyaTLS - 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 mu | Açıklama |
|---|---|---|
Bölge (regionCode) | Evet — SIP seçince varsayılan TR | Numaranın hizmet ettiği bölge (TR / US / GB); aranan kişinin ülkesine göre doğru numara/trunk seçilir |
Trunk Adı (trunkName) | Evet | LiveKit’te trunk’ı tanımlayan isim, örn. netgsm-trunk |
SIP Address (address) | Evet | Sağlayıcının SIP sunucu adresi, örn. sip.netgsm.com.tr |
Transport (transport) | Hayır — varsayılan udp | udp / tcp / tls |
Telefon Numaraları (numbers) | Evet | Virgülle ayrılmış, her biri ayrı bir kayıt olur |
Username (username) | Evet | SIP kimlik doğrulama kullanıcı adı |
Password (password) | Evet | SIP kimlik doğrulama şifresi |
Görünen Ad (friendlyName) | Hayır | Boş 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:
- Backend, LiveKit SDK’sının
SipClient.createSipOutboundTrunk(trunkName, address, numbers[], { transport, auth_username, auth_password })fonksiyonunu çağırır. - LiveKit trunk’ı oluşturur ve bir
sipTrunkIddö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. - Başarılıysa,
numbersalanına virgülle yazdığın her numara için ayrı birPhoneNumberkaydı oluşur — hepsi aynısipTrunkId’yi paylaşır.provider: "livekit_sip",provider_type: "sip". - Trunk bilgileri (
sipTrunkId, adres, transport) ve şifrelenmiş kullanıcı adılivekit_configalanı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/Pasifrozetini 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
| Belirti | Olası 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ıyor | Termination 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ıyor | Transport 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ım | Numara başka bir kullanıcının/hesabın asistanına bağlanamaz — backend sahiplik kontrolü yapar, kendi asistanını seç. |