pariette / signalbird
Signalbird SDK — Telsiz (Radio), Gönderim (Messaging), Yönetim (Management) ve Partner istemcisi (PHP / Laravel)
Package info
github.com/Pariette-Inc/signalbird.sdk
Language:TypeScript
pkg:composer/pariette/signalbird
Requires
- php: ^8.1
- ext-curl: *
Requires (Dev)
- phpunit/phpunit: ^10.0
Suggests
- monolog/monolog: Laravel log kanalını Telsiz'e bağlamak için (SignalbirdLogHandler)
- symfony/mailer: MAIL_MAILER=signalbird posta taşıyıcısı için (Laravel'de zaten vardır)
This package is not auto-updated.
Last update: 2026-08-22 13:07:34 UTC
README
Tek paket, dört yüzey, on iki giriş noktası. Panelde tıklayarak yapabildiğiniz her şey kodla da yapılabilir.
| Yüzey | Ne yapar | Anahtar | Nerede |
|---|---|---|---|
| Telsiz (Radio) | projenizden bir kanala log/olay yazar | sbr_live_… / sbr_pub_… |
sunucu / tarayıcı |
| Gönderim (Messaging) | e-posta, SMS, push gönderir; kişi, liste, kampanya yönetir; mesaj durumu okur; webhook imzası doğrular | sb_… |
yalnız sunucu |
| Yönetim (Management) | Telsiz projesi/kanalı açar, olay akışını okur, sohbet gelen kutusunu işler, uygulama ve cihaz yönetir | sb_… + scope |
yalnız sunucu |
| Uygulama (App) | müşterinizin son kullanıcısına canlı sohbet + push cihaz kaydı | sbw_pub_… |
web, iOS, Android |
| Partner | Signalbird'ü kendi ürününde satan sözleşmeli platform müşterisini sağlar ve yetkilendirir | sbp_live_… |
yalnız sunucu |
Bir seçenek daha var ve kod yazmaz: hazır sohbet widget'ı
(signalbird.js), siteye tek <script> ile gömülür.
Dil matrisi
| Dil / platform | Telsiz | Gönderim | Yönetim | Uygulama | Kurulum |
|---|---|---|---|---|---|
| Node.js / TypeScript | ✓ | ✓ | ✓ | ✓ | npm i signalbird |
| Tarayıcı (düz JS) | ✓ | — | — | ✓ | signalbird/browser · /app |
| React / Next.js | ✓ | ✓ | ✓ | ✓ | signalbird/react |
| Vue 3 | ✓ | — | — | ✓ | signalbird/vue |
| Angular | ✓ | — | — | ✓ | signalbird/angular |
| React Native / Expo | ✓ | — | — | ✓ | signalbird/react-native |
| PHP / Laravel | ✓ | ✓ | ✓ | — | composer require pariette/signalbird |
| Python | ✓ | ✓ | ✓ | — | pip install signalbird |
| Go | ✓ | ✓ | ✓ | — | go get github.com/Pariette-Inc/signalbird.sdk |
| .NET / ASP.NET Core | ✓ | ✓ | ✓ | — | dotnet add package Signalbird.Sdk |
| Swift (iOS) | ✓ | — | — | ✓ | SPM: Signalbird |
| Kotlin (Android) | ✓ | — | — | ✓ | io.signalbird:signalbird-sdk |
Metot adları diller arasında birebir aynıdır; her dil kendi yazım
geleneğini korur (createRadioProject / create_radio_project /
CreateRadioProject). node scripts/check-parity.mjs bunu her derlemede
denetler.
Uygulama yüzeyi mobil ve tarayıcı içindir: gizli anahtar oraya gömülmez. Gönderim ve Yönetim yüzeyleri yalnız sunucudadır.
Telsiz
Telsiz'in tek işi vardır: projenizden bir kanala mesaj yazmak.
Bildirimin kime gideceği, hangi kanaldan (push/e-posta), sessiz saatlerde ne olacağı ve aynı mesajın kaç kez uyarı üreteceği sunucuda, kanal ayarlarında durur. Kod tarafında bunlar yoktur ve olmamalıdır: bildirim kuralını değiştirmek için uygulamanızı yeniden yayınlamanız gerekmesin.
proje → penyu.io (anahtarın sahibi)
kanal → critical, info, deploy… (bildirim kuralı burada)
olay → tek bir kayıt
İki anahtar, iki paket
| Sunucu | Tarayıcı | |
|---|---|---|
| Anahtar | sbr_live_… gizli |
sbr_pub_… açık |
| Giriş noktası | signalbird · pariette/signalbird |
signalbird/browser |
| Yazabildiği kanal | hepsi | yalnız izin verilenler |
| Kısıt | — | yalnız izinli alan adlarından |
Gizli anahtar tarayıcıya gömülemez: sunucu, Origin başlığı taşıyan bir
istekte gizli anahtarı reddeder (SECRET_KEY_IN_BROWSER). Bu bir kolaylık
değil, kasıtlı bir duvardır — anahtar bir kez istemciye indiğinde herkesindir.
Kurulum
| Dil / çatı | Kurulum |
|---|---|
| Node.js, Next.js (sunucu), Express, NestJS, Fastify | npm install signalbird |
| React, Vue, Angular, Svelte, düz JS (tarayıcı) | npm install signalbird → /browser, /app, /react, /vue, /angular |
| React Native, Expo | npm install signalbird → /react-native |
| PHP, Laravel | composer require pariette/signalbird |
| Python (Django, FastAPI, Flask, Celery) | pip install signalbird |
| Go | go get github.com/Pariette-Inc/signalbird.sdk |
| .NET, ASP.NET Core | dotnet add package Signalbird.Sdk |
| Swift (iOS, macOS) | SPM: https://github.com/Pariette-Inc/signalbird.sdk |
| Kotlin (Android) | implementation("io.signalbird:signalbird-sdk:1.4.1") |
| Canlı sohbet widget'ı (herhangi bir site) | <script async src="https://signalbird.io/sdk/v1/signalbird.js" data-app-key="sbw_pub_…"></script> |
Hepsi bu repodan çıkar ve aynı sürümü taşır — ayrı SDK reposu ya da dil başına sürüm yoktur.
Node.js / TypeScript
import { signalbird } from 'signalbird' // SIGNALBIRD_KEY ortam değişkeninden okunur await signalbird().critical('critical', 'ödeme servisi yanıt vermiyor', { service: 'iyzico', attempt: 3, }) await signalbird().info('info', 'ahmet@x.com yeni hesap oluşturdu')
Kendi istemcinizi kurmak isterseniz:
import { SignalbirdClient } from 'signalbird' const sb = new SignalbirdClient({ apiKey: process.env.SIGNALBIRD_KEY!, source: 'api-01', // hangi sunucudan geldiği throwOnError: false, // üretimde kapalı kalmalı }) await sb.log({ channel: 'deploy', message: 'v2.4.0 yayında', level: 'info' })
Yakalanmamış hatalar:
signalbird().captureUncaught('critical')
Toplu gönderim (kısmi başarı normaldir, satır satır sonuç döner):
const result = await signalbird().batch([ { channel: 'info', message: 'iş 1 bitti' }, { channel: 'info', message: 'iş 2 bitti' }, ])
Next.js
Sunucu tarafında (route handler, server action, app/api/**) doğrudan
signalbird kullanılır. İstemci bileşenlerinde kullanmayın — anahtar
paketle birlikte tarayıcıya iner.
// app/api/webhook/route.ts import { signalbird } from 'signalbird' export async function POST(req: Request) { try { // … } catch (error) { await signalbird().error('webhook', (error as Error).message) throw error } }
Tarayıcı (React, Vue, Angular, düz JS)
Çatıya özel sarmalayıcı yoktur; gereken tek şey bir fonksiyon çağrısıdır.
// uygulama açılışında bir kez import { initSignalbird } from 'signalbird/browser' const sb = initSignalbird({ publicKey: 'sbr_pub_…', source: 'web', }) sb.captureErrors('browser') // window.onerror + unhandledrejection sb.error('browser', 'sepet güncellenemedi', { cartId })
Kayıtlar tek tek değil, toplu gider (varsayılan 3 saniyede bir) ve sekme
kapanırken sendBeacon ile boşaltılır.
React — app/providers.tsx ya da main.tsx:
useEffect(() => { const sb = initSignalbird({ publicKey: process.env.NEXT_PUBLIC_SIGNALBIRD_KEY! }) return sb.captureErrors() }, [])
Vue — main.ts:
const sb = initSignalbird({ publicKey: import.meta.env.VITE_SIGNALBIRD_KEY }) app.config.errorHandler = (err) => sb.error('browser', String(err))
Angular — ErrorHandler sağlayıcısı:
@Injectable() export class SignalbirdErrorHandler implements ErrorHandler { private sb = initSignalbird({ publicKey: environment.signalbirdKey }) handleError(error: unknown) { this.sb.error('browser', String(error)) } }
Panelde bu projenin izinli kökenlerini ve izinli kanallarını açmayı unutmayın; ikisi de boşken tarayıcı anahtarı hiçbir şey yapamaz. Kritik kanalları tarayıcıya açmayın: istemci kodu herkesin elindedir.
PHP / Laravel
use Signalbird\Sdk\Facades\Signalbird; Signalbird::critical('critical', 'ödeme servisi yanıt vermiyor', [ 'service' => 'iyzico', ]); Signalbird::info('info', 'ahmet@x.com yeni hesap oluşturdu');
.env:
SIGNALBIRD_KEY=sbr_live_…
SIGNALBIRD_SOURCE=api-01
Laravel'in kendi loglarını Telsiz'e bağlamak — config/logging.php:
'signalbird' => [ 'driver' => 'monolog', 'handler' => \Signalbird\Sdk\SignalbirdLogHandler::class, 'with' => ['channel' => 'laravel'], 'level' => 'error', ],
Sonra LOG_STACK=single,signalbird. Mevcut Log::error() satırlarınız olduğu
gibi çalışır; tek satır kod yazmadan Telsiz'e düşerler.
Laravel dışı PHP:
use Signalbird\Sdk\Signalbird; Signalbird::configure('sbr_live_…'); Signalbird::error('api', 'veritabanı bağlantısı koptu');
Davranış kuralları
- Sessiz hata varsayılandır. Telsiz erişilemezse çağrı
ok: falsedöner ve uygulamanız çalışmaya devam eder. Log göndermek, ödeme akışını çökertmek için geçerli bir sebep değildir. Geliştirme sırasındathrowOnError: true. - Tanımsız kanal düşürülmez. İlk
log('odeme-hatasi', …)çağrısında kanal kendiliğinden açılır ve panelde "otomatik açıldı" işaretiyle görünür. Yeni kanal sessizdir — kuralı ekip koyar. - Seviye kanalın varsayılanını ezer.
levelgöndermezseniz kanalın kendi seviyesi geçerlidir. - Kritik seviye sessiz saatleri deler. Gece üçte ölen servis sabahı bekleyemez.
- Tekrar bastırma kaydı değil bildirimi susturur. Aynı mesaj kanalın
dedupesüresi içinde tekrar gelirse ikinci bildirim gitmez ama kayıt tutulur.
Gönderim (Messaging)
Takım API anahtarı (sb_…, panelde Konsol → API anahtarları, scope'lu)
ile çalışır. Telsiz anahtarı burada geçmez — istemci kurulurken
WRONG_KEY_TYPE ile reddeder. Yalnız sunucuda kullanılır.
Node:
import { SignalbirdMessaging } from 'signalbird' const sb = new SignalbirdMessaging({ apiKey: process.env.SIGNALBIRD_MESSAGING_KEY! }) const r = await sb.sendEmail({ to: 'ali@example.com', class: 'transactional', // zorunlu: transactional | commercial subject: 'Siparişiniz yola çıktı', body: '<p>Merhaba {{first_name}}…</p>', }) if (!r.ok) console.error(r.code, r.message) // ok:false → code + message await sb.sendSms({ to: '+905551112233', class: 'transactional', body: 'Kodunuz: 4821' }) await sb.sendPush({ to: 'external:user-1042', class: 'transactional', subject: 'Yeni mesaj', body: '…' }) // Kişi + liste + kampanya const list = await sb.createContactList({ name: 'agustos-kampanya' }) await sb.bulkContacts({ // 1000'lik parçalara bölünür list_id: list.data.id, consent_source: 'offline', contacts: [{ email: 'a@x.com', first_name: 'Ayşe', attributes: { external_ref: 'rcp_1' } }], }) const c = await sb.createCampaign({ name: 'Ağustos', channel: 'email', list_id: list.data.id, subject: 'Merhaba {{first_name}}', body: '…', external_ref: 'cc_42', }) for await (const m of sb.iterateCampaignMessages(c.data.batch.id)) { console.log(m.external_ref, m.status) }
PHP / Laravel:
use Signalbird\Sdk\Facades\Signalbird; $r = Signalbird::messaging()->sendEmail([ 'to' => 'ali@example.com', 'class' => 'transactional', 'subject' => 'Siparişiniz yola çıktı', 'body' => '<p>…</p>', ]); if (! $r['ok']) { Log::warning($r['code'], $r); }
.env: SIGNALBIRD_MESSAGING_KEY=sb_… (isteğe bağlı SIGNALBIRD_MESSAGING_URL,
SIGNALBIRD_MESSAGING_TIMEOUT). Laravel dışı PHP:
Signalbird::configureMessaging('sb_…') ya da new MessagingClient('sb_…').
Metot kümesi iki dilde aynıdır: sendEmail sendSms previewSms sendPush ·
listContacts createContact updateContact deleteContact bulkContacts ·
listContactLists createContactList deleteContactList · listCampaigns
createCampaign getCampaign cancelCampaign listCampaignMessages
iterateCampaignMessages · listMessages getMessage. Hepsi
{ok, status, data?, code?, message?} döner; throwOnError: true ile istisna
(SignalbirdError / SignalbirdException, code + status + body taşır).
Webhook imzası (message.*, campaign.* olayları):
import { verifyWebhook } from 'signalbird' // Express: app.post('/hooks/signalbird', express.raw({ type: '*/*' }), (req, res) => { if (!verifyWebhook(req.body, req.header('X-Signalbird-Signature'), process.env.SIGNALBIRD_WEBHOOK_SECRET!)) { return res.status(401).end() }
use Signalbird\Sdk\Messaging\Webhook; abort_unless(Webhook::verify($request->getContent(), $request->header('X-Signalbird-Signature'), config('services.signalbird.webhook_secret')), 401);
Doğrulama ham gövde üzerinde yapılır; JSON'u ayrıştırıp yeniden serileştirmek imzayı bozar.
Yönetim (Management)
Panelde tıklayarak yaptığınız her şeyi kodla yapar. Ortam kurulumunuz, CI akışınız ya da kendi ajan arayüzünüz artık panel oturumu taklit etmek zorunda değil.
Bu bir admin yüzeyi değildir: anahtar tek bir takıma bağlıdır ve yalnız o takımın kayıtlarına dokunur. Kullanıcı, faturalama ve abonelik işlemleri SDK'da yoktur.
Panelden radio:*, chat:*, apps:* scope'larıyla bir sb_… anahtarı açın.
import { management } from 'signalbird' // Yeni ortam kurulumu: proje aç, kanalını tanımla, anahtarı sakla const { data } = await management().createRadioProject({ name: 'ödeme-servisi' }) // `secret` YALNIZ burada döner — sunucuda yalnız özeti saklanır await vault.write('SIGNALBIRD_KEY', data!.secret) await management().createRadioChannel(data!.project.id, { key: 'odeme', name: 'Ödeme', level: 'critical', notify_push: true, quiet_from: 0, quiet_to: 7, // kritik seviye sessiz saatleri yine de deler })
Sohbet gelen kutusunu kendi botunuzla işleyin:
const inbox = await management().listConversations({ status: 'open', per_page: 20 }) for (const conversation of inbox.data?.data ?? []) { await management().reply(conversation.id, { body: 'Merhaba! Ekibimiz birkaç dakika içinde yanıtlayacak.', }) // İç not: gelen kutusunda görünür, ziyaretçiye ASLA gitmez await management().reply(conversation.id, { body: 'Bot yanıtladı', is_internal: true }) }
Aynısı PHP, Python, Go ve .NET'te birebir aynı metot adlarıyla:
Signalbird::management()->createRadioProject(['name' => 'ödeme-servisi']);
signalbird.SignalbirdManagement(api_key=key).create_radio_project({"name": "ödeme-servisi"})
admin.CreateRadioProject(ctx, map[string]any{"name": "ödeme-servisi"})
await management.CreateRadioProjectAsync(new { name = "ödeme-servisi" });
Tam liste (40 metot): docs/CONTRACT.md § 10.
Partner — müşteri sağlama
Signalbird'ü kendi ürününüzün içinde satıyorsanız (sözleşmeli platform) bu yüzey sizindir: müşteri hesabı açar, domain ekleyip izlemeye alır, uptime okur, ödeme alındığında modül açar ve panel ekranını kendi sayfanıza gömersiniz.
import { SignalbirdPartner } from 'signalbird' const partner = new SignalbirdPartner({ apiKey: process.env.SIGNALBIRD_PARTNER_KEY! }) // Müşteri açıldı — idempotent: aynı external_id ikinci kez yeni hesap AÇMAZ const { data } = await partner.createCompany({ external_id: 'sc_9911', name: 'Acme', owner: { email: 'sahip@acme.com', name: 'Acme Sahibi', external_id: 'u_88' }, }) // Domain açıldı → anında izlemeye girsin await partner.addDomain('sc_9911', { external_id: 'd_5', domain: 'acme.com', monitoring: { enabled: true, frequency: 5 }, }) // Ödeme alındı → modül açılsın await partner.grantModule('sc_9911', { module: 'email', expires_at: '2027-08-20' }) // Kendi domain listesi ekranınızda uptime const uptime = await partner.companyUptime('sc_9911', '7d') // Sohbet ekranını kendi sayfanıza gömün (jetonu SUNUCUNUZ üretir) const embed = await partner.createEmbedToken('sc_9911', { user_external_id: 'u_88', module: 'chat', theme: 'dark', }) // → <iframe src={embed.data.url} />
PHP'de Signalbird::partner()->createCompany([...]).
İki kural: anahtar tarayıcıya inmez ve TXT'siz domain kampanya
gönderemez (izleme, sohbet ve push açıktır). Ayrıntı: docs/CONTRACT.md § 12.
Uygulama (App) — kendi sohbet arayüzünüz
Hazır widget yerine kendi arayüzünüzü yazmak, ya da sohbeti mobil
uygulamanıza koymak istiyorsanız bu yüzey içindir. Açık uygulama anahtarı
(sbw_pub_…) kullanır ve yalnız ziyaretçinin kendi verisine dokunur.
React / Next.js
import { SignalbirdProvider, useChat } from 'signalbird/react' export function App() { return ( <SignalbirdProvider appKey={process.env.NEXT_PUBLIC_SIGNALBIRD_APP_KEY!}> <Chat /> </SignalbirdProvider> ) } function Chat() { const { messages, unread, agentTyping, send } = useChat({ open: true }) return ( <> {messages.map((m) => <Bubble key={m.id} message={m} />)} {agentTyping && <Typing />} <Composer onSend={send} /> </> ) }
Vue 3
app.use(signalbirdPlugin, { appKey: import.meta.env.VITE_SIGNALBIRD_APP_KEY }) const { state, send } = useChat({ open: isOpen })
Angular
bootstrapApplication(App, { providers: [provideSignalbird({ appKey })] }) // bileşende chat$ = inject(SignalbirdService).chat$()
React Native / Expo
import AsyncStorage from '@react-native-async-storage/async-storage' import { createSignalbirdApp, asyncStorageAdapter, useNativeChat } from 'signalbird/react-native' // Depoyu vermek ZORUNLU: sır cihazda kalmazsa geçmiş her açılışta kaybolur const client = createSignalbirdApp({ appKey, storage: asyncStorageAdapter(AsyncStorage) }) const { messages, send } = useNativeChat(client, { open: true, isForeground })
Swift (iOS)
let client = try SignalbirdApp(config: .init(appKey: "sbw_pub_…")) try await client.startSession(["name": "Ayşe"]) try await client.startConversation(body: "Kargom nerede?") try await client.registerDevice(token: apnsToken)
Kotlin (Android)
val client = SignalbirdApp(SignalbirdAppConfig(appKey = "sbw_pub_…", storage = prefsStorage)) client.startSession(mapOf("name" to "Ayşe")) client.startConversation("Kargom nerede?") client.registerDevice(token = fcmToken)
Tam liste (17 metot) ve yoklama merdiveni: docs/CONTRACT.md § 11.
Widget (canlı sohbet)
Panelde Gelen Kutusu → Ayarlar → Uygulamalar'dan bir uygulama açın; verilen
sbw_pub_… anahtarını sitenize gömün:
<script async src="https://signalbird.io/sdk/v1/signalbird.js" data-app-key="sbw_pub_…"></script>
Bu kadar. Sohbet modülü açıksa balon görünür; renk, konum, karşılama, ön-form, çalışma saatleri panelden yönetilir. Programatik kullanım:
Signalbird.identify({ external_id: 'user-1042', email: 'ali@example.com', name: 'Ali Veli' }) Signalbird.chat.open() // close() · toggle() · isOpen() Signalbird.chat.on('unread', (n) => badge.textContent = n) Signalbird.push.register({ token, platform: 'web', provider: 'fcm' }) Signalbird.destroy()
data-app-key yerine Signalbird.init({ appKey, baseUrl?, locale? }) da
çağrılabilir. Widget ev sahibi sayfaya asla hata fırlatmaz; Shadow DOM içinde
çalışır, sayfanızın CSS'iyle çakışmaz; < 20 KB gzip. Ayrıntı:
docs/CONTRACT.md § 9 ve https://signalbird.io/sdk/widget.
Hata kodları
| Kod | Anlamı |
|---|---|
INVALID_KEY |
Anahtar yok, yanlış ya da proje pasif |
SECRET_KEY_IN_BROWSER |
Gizli anahtar tarayıcıdan kullanıldı |
ORIGIN_NOT_ALLOWED |
Tarayıcı anahtarı bu alan adına açık değil |
CHANNEL_NOT_ALLOWED |
Tarayıcı anahtarı bu kanala yazamaz |
MODULE_DISABLED |
Paketinizde Telsiz (logger) modülü yok |
LIMIT_REACHED |
Aylık kayıt limitiniz doldu |
CHANNEL_DISABLED |
Kanal kapalı — kayıt yazılmaz, kota da harcanmaz |
Gönderim ve Yönetim istemcilerine özgü: WRONG_KEY_TYPE (kurulumda),
API_KEY_INVALID, API_KEY_SCOPE (anahtarda gereken scope yok),
VALIDATION_ERROR (422), NO_CONSENT, SUPPRESSED, NO_SENDING_DOMAIN,
LIST_NOT_FOUND, MODULE_DISABLED, NETWORK_ERROR, TIMEOUT, HTTP_<durum>.
Uygulama yüzeyi ve widget: VISITOR_INVALID (yerel kimlik silinir, yeni
oturum açılır), CHAT_UNAVAILABLE (kota — "sohbet kullanılamıyor" bandı),
NOT_INITIALIZED.