npmjs.com ↗
Kurulumnpm install signalbird · composer require pariette/signalbird

Partner - müşterinizi Signalbird'de açın

Signalbird'ü kendi ürününüzün içinde satıyorsanız bu yüzey sizindir. Müşteri hesabını siz açarsınız, domainini siz eklersiniz, ödemeyi siz alırsınız ve modülü siz açarsınız; müşteri Signalbird'de ayrı bir kurulum yapmaz.

Bu yüzey sözleşmelidir. Anahtar (sb_secret_live_…) herkese verilmez; Signalbird ile anlaşan platformlara (bir CMS, bir rıza yönetim aracı, bir hosting paneli) tanımlanır. Diğer dört yüzeyden farkı: takımlar üstü çalışır.

Süper yönetici değildir. Anahtarınız yalnız sizin açtığınız hesaplara erişir. Başka bir partnerin ya da self-servis bir müşterinin kaydı 404 döner - o kaydın var olduğu bilgisi bile size verilmez.

Ne zaman işinize yarar:

  • Otomatik kurulum: müşteriniz sizde hesap açtığı anda Signalbird tarafında da hesabı doğsun ve sitesi izlemeye girsin.
  • Modül satışı: müşteri sizden e-posta pazarlama modülünü satın aldığında Signalbird tarafında o modül açılsın.
  • Kendi ekranınızda gösterim: uptime raporunu kendi domain listenizde, canlı destek ekranını kendi panelinizde göstermek.

Anahtar

Anahtarı Signalbird ekibi tanımlar ve size bir kez verir. Sunucunuzda saklayın - tarayıcıya asla inmez.

text
SIGNALBIRD_DOMAIN_KEY=sb_secret_live_…

Yanlış tür anahtar (açık anahtar sb_public_live_…, sb_public_live_…) kurulum anında WRONG_KEY_TYPE ile reddedilir.

Kurulum

ts
import { SignalbirdPartner } from 'signalbird'

const partner = new SignalbirdPartner({
  domainKey: process.env.SIGNALBIRD_DOMAIN_KEY!,
})
php
use Signalbird\Sdk\Facades\Signalbird;

$partner = Signalbird::partner();   // config/signalbird.php → partner_key

Müşteri açma

Her yazma işlemi kendi kimliğinizle (external_id) yapılır ve idempotenttir: aynı kimlikle ikinci çağrı yeni hesap açmaz, var olanı created: false ile döner. Webhook'unuz iki kez tetiklense de sorun olmaz.

ts
const res = await partner.createCompany({
  external_id: 'sc_9911',                 // sizin tarafınızdaki müşteri id'si
  name: 'Acme Web',
  owner: {
    email: 'sahip@acme.com',
    name: 'Acme Sahibi',
    external_id: 'u_88',                  // sizin tarafınızdaki kullanıcı id'si
  },
})

if (res.data.created) {
  // Bu iki anahtar YALNIZ şimdi döner - kendi tarafınızda saklayın.
  save(res.data.keys.domain_key)   // sb_…      → gönderim/yönetim
  save(res.data.keys.app_key)   // sb_public_live_… → sohbet widget'ı, push
}

Anahtarı kaybederseniz rotateKey('sc_9911', 'api' | 'app') yenisini üretir; eskisini geri veren bir yol yoktur.

Owner kullanıcı şifresiz doğar: müşteriniz Signalbird'e gömme jetonuyla girer. İsterse "şifremi unuttum" akışından kendi şifresini kurar.

Domain ekleme ve izleme

ts
const res = await partner.addDomain('sc_9911', {
  external_id: 'd_5',
  domain: 'acme.com',
  monitoring: { enabled: true, frequency: 5 },   // dakika
})

Domain eklenir eklenmez izlemeye girer. Yanıt beklenen TXT kaydını da döner:

json
{
  "domain": { "verified_via": "partner", "can_send_campaigns": false },
  "dns": [{ "host": "_signalbird.acme.com", "type": "TXT", "value": "signalbird-verify=…" }]
}

TXT kuralı

Sizin eklediğiniz domain verified_via: "partner" ile doğar. Bu:

Modül Durum
İzleme (uptime) ✅ açık
Canlı sohbet ✅ açık
Anlık bildirim (push) ✅ açık
E-posta / SMS kampanyası ❌ TXT kaydı yayınlanana kadar kapalı

Sebep: gönderim zarfı Signalbird'ün kendi alan adından çıkar, yani gönderim itibarı Signalbird'ündür. "Bu domain adına posta gönderilebilir" kararı bir beyanla verilemez.

Bu bir çıkmaz değil - müşterinizin DNS'ini çoğu zaman siz yönetiyorsunuz:

ts
// 1. Yanıttaki dns kaydını yayınlayın
// 2. Doğrulatın
const check = await partner.verifyDomain('d_5')

if (check.data.verified) {
  // domain.can_send_campaigns artık true
}

Uptime raporu

Kendi domain listesi ekranınızda göstermek için:

ts
const report = await partner.companyUptime('sc_9911', '7d')   // 24h | 7d | 30d
json
{
  "range": "7d",
  "data": [{
    "external_id": "d_5", "domain": "acme.com", "monitored": true,
    "uptime": 99.86, "avg_response_ms": 214, "checks": 2016, "status": "up",
    "incidents": [{ "started_at": "…", "ended_at": "…", "duration_s": 420, "reason": "HTTP 503" }]
  }]
}

Hiç kontrol yapılmamışsa uptime null döner, 100 değil. Eksik veri iyimserlik değildir; ekranınızda "veri yok" gösterin.

Modül açma ve kapatma

Ödeme sizde alınır; Signalbird'de ikinci bir tahsilat yoktur. Ödeme tamamlandığında modülü açarsınız:

ts
await partner.grantModule('sc_9911', {
  module: 'email',                    // email | sms | push | chat | logger | monitoring
  limits: { max_emails: 25000 },      // vermezseniz modülün varsayılanı geçerli
  expires_at: '2027-08-20',           // aboneliğin bitiş tarihi
})

expires_at geldiğinde modül kendiliğinden kapanır - yenilemede tazeleyin. Erken kapatmak için:

ts
await partner.revokeModule('sc_9911', 'email')

İki durum bilinçli olarak reddedilir:

Kod Ne demek
MODULE_IS_AUTOMATIC (422) Bu modül sizin paketinize dahil (ör. izleme); kapatılamaz.
MODULE_REVOKED_BY_ADMIN (409) Signalbird yöneticisi bu modülü kapatmış; satışla geri açılmaz.

Panel ekranını kendi sayfanıza gömme

Signalbird'deki ekranın birebir aynısı kendi panelinizde görünür - çünkü aynı ekrandır, kopyası değil. Kendi sunucunuzdan kısa ömürlü bir jeton üretip iframe'e verirsiniz.

ts
// SİZİN sunucunuzda (partner anahtarı tarayıcıya inmez)
const { data } = await partner.createEmbedToken('sc_9911', {
  user_external_id: 'u_88',
  module: 'chat',          // chat | monitoring | campaigns | contacts | radio
  theme: 'dark',
  locale: 'tr',
})

return Response.json({ url: data.url })
html
<iframe src="{{ url }}" style="width:100%;border:0" id="sb"></iframe>
<script>
  addEventListener('message', (e) => {
    if (e.data?.type === 'signalbird:height') {
      document.getElementById('sb').style.height = e.data.px + 'px'
    }
  })
</script>

Jeton 120 saniye yaşar ve tek kullanımlıktır. Sayfa yenilendiğinde yeni jeton üretin. Kısa ömür isteğe bağlı değil: jeton URL'de gider, yani sunucu loglarına ve Referer başlığına düşer.

Ekranı gömebilmek için o modülün müşteride açık olması gerekir; kapalıysa MODULE_DISABLED (403) döner - satın alınmamış ürünün boş kabuğu gösterilmez.

Kullanıcılar

Gömme jetonu bir kullanıcı adına üretilir; destek personeliniz Signalbird sohbetinde de kendi adıyla görünsün diye:

ts
await partner.createUser('sc_9911', {
  external_id: 'agent_7',
  email: 'ajan@acme.com',
  name: 'Destek Ajanı',
  team_role: 'member',
})

removeUser üyeliği kaldırır, kişinin Signalbird hesabını silmez - aynı kişi başka bir müşterinin de üyesi olabilir.

Mevcut hesabı bağlama

Müşterinizin Signalbird'de zaten kendi hesabı varsa onu otomatik devralamazsınız. createCompany çağrısına link_email verirseniz bir bağlama talebi açılır ve hesap sahibinin panelinde onaylanır (COMPANY_LINK_REQUIRES_CONSENT, 403).

Bu kısıt bilinçlidir: e-posta adresini bilen bir partner, istediği müşterinin verisine ulaşamamalı.

Hata kodları

Kod Durum Ne demek
PARTNER_KEY_MISSING / PARTNER_KEY_INVALID 401 Anahtar yok ya da iptal edilmiş
PARTNER_INACTIVE 403 Partner hesabınız pasif
COMPANY_NOT_FOUND 404 Bu müşteri sizin değil (ya da hiç yok)
PARTNER_DOMAIN_LIMIT 422 Müşteri başına domain sınırınız doldu
DOMAIN_OWNED_BY_OTHER_PARTNER 409 Bu domain başka bir partnerin yönetiminde
MODULE_IS_AUTOMATIC 422 Paketinize dahil modül kapatılamaz
MODULE_REVOKED_BY_ADMIN 409 Yönetici kapatmış; satışla açılmaz
EMBED_TOKEN_INVALID 401 Gömme jetonu kullanılmış ya da süresi dolmuş

Tam metot listesi (20 metot): docs/CONTRACT.md § 12.