laravel-notification-channels/telegram
Send Telegram notifications from Laravel using the Telegram Bot API. Supports text messages, inline keyboards, dice, polls, media groups, photos, documents, locations, contacts, stickers and more, plus message routing, response handling and direct client access.
Architecture fit. This is a first-party-style channel for Laravel's Illuminate\Notifications subsystem, which is the strongest possible fit for any Laravel application already using the notifier. It conforms to the standard contract: return 'telegram' from via() and implement toTelegram(). That means Telegram becomes one more line in an existing multi-channel fan-out (mail, SMS, Slack) with no new abstraction layer, no bespoke queue worker, and no separate delivery service. For teams already invested in Laravel's notification model, this is close to zero architectural impedance.
Capability surface. Broader than a typical "send a message" shim. Outbound coverage spans plain text, inline keyboards (including callback buttons and Web App buttons), dice, polls, contacts, audio/photo/document/location/venue/video/GIF/sticker, media groups, and — notably — rich messages against Bot API 10.1 with block builders, tables, and sendRichMessageDraft streaming. The draft-streaming primitive is the most strategically interesting item: it enables LLM token-streaming UX directly from a Laravel queue/controller without standing up a websocket layer. A TPM should treat this as a differentiator worth prototyping, not a checkbox.
Integration feasibility. Low. composer require, a BotFather token, a config/services.php entry, and a stored telegram_user_id on the notifiable model. The package ships a TelegramUpdates helper to bootstrap chat IDs, plus proxy/base_uri support for self-hosted Bot API servers or region-blocked networks — the latter is a real procurement and compliance lever in restricted markets.
Technical risk.
callback_query from inline buttons), commands, and conversation state must be built separately. Any design that assumes a two-way bot will under-scope.laravel-notification-channels org, not Laravel core. MIT licensed, good changelog and release hygiene, ~1.1k stars — but bus factor and long-term stewardship are unverified.Key questions for the maintainers/vendor review.
Http::fake / Guzzle mock handler), and is there a documented testing recipe?429 retry_after and surface it to Laravel's queue retry semantics, or does it fail opaquely?Stack fit. Laravel 10/11/12 on PHP 8.1+, Composer, standard queue infrastructure. The package rides on Guzzle and Laravel's HTTP client conventions; there is no new runtime, daemon, or datastore. It composes with ShouldQueue notifications, so delivery inherits our existing queue topology, retry policy, and dead-letter handling for free.
Configuration and secrets. Prefer services.telegram.* as documented; the legacy services.telegram-bot-api.* keys exist for backward compatibility and should be avoided in new code to prevent split-brain config. Token in the secret manager, injected via TELEGRAM_BOT_TOKEN; HTTP timeout/proxy under services.telegram.http rather than ad-hoc Guzzle environment variables, so behavior is reviewable in version control.
Migration path. Three common entry states:
'telegram' to via() conditionally, gated by user preference and verified chat ID.base_uri to a self-hosted Bot API server or configure proxy in services.telegram.http; this is a config change, not a code change, which materially de-risks the rollout.Sequencing (recommended).
TelegramUpdates (or a small webhook) → persist telegram_user_id on the user record. This is the real project cost, not the package. Note the documented conflict: getUpdates does not work while an outgoing webhook is configured — decide the receipt mechanism before building.NotificationFailed events and the onError callback into our error tracker; distinguish permanent failures (403 blocked, 400 chat not found) from transient (429, network).Compatibility watch-items. Lock the package major version; pin Guzzle per Laravel's constraint; verify the target Telegram client population supports Bot API 10.x rich messages before making them the primary invoice/receipt format.
Maintenance. Low ongoing code maintenance — it is a thin adapter and we own almost no surface area. The real maintenance burden is external: Bot API evolution, Telegram client fragmentation, and our own chat-ID/preference data hygiene. Budget a recurring line item for dependency review at each Laravel major bump; the community release cadence appears healthy but is not contractual.
Support. Upstream support is GitHub issues plus a Telegram chat group — community-grade, not SLA-grade. Escalation for production incidents lands on our on-call. Mitigation: keep the token/config and payload construction in our own code where feasible, so a package regression or abandonment can be patched locally or forked (MIT permits it) without a rewrite.
Scaling. Telegram imposes per-chat (roughly 1 msg/sec) and global bot rate limits, and the package does not manage them for us. Design implications:
429s.Failure modes to instrument explicitly.
| Failure | Signal | Handling |
|---|---|---|
| User blocked bot | 403 | Mark chat ID invalid, suppress future sends, prompt re-opt-in elsewhere |
| Chat not found / migrated | 400 | Null out stale ID, alert growth/CRM owner |
| Rate limited | 429 + retry_after |
Honor the hint; verify package behavior, else wrap with backoff |
| Region/network block | Timeout / connection error | Failover to proxy or self-hosted base_uri |
| Bot API feature unsupported by client | Silent render degradation | Feature-flag rich messages; A/B against plain text |
| Token leak or rotation | Auth errors / audit finding | Secret-manager rotation runbook; token is a full bot takeover vector |
| Webhook/getUpdates misconfiguration | Updates silently dropped | Runbook check before enabling interactive buttons |
Ramp-up. Genuinely low for any Laravel developer: the README is unusually complete — installation, chat-ID retrieval, per-message-type recipes, routing, response handling, exception handling, on-demand and multi-recipient sends, and direct client usage. A mid-level engineer ships a working transactional notification in under a day. The non-obvious learning curve is not the package but the Telegram domain: bot lifecycle, chat-ID acquisition, group vs. channel vs. private-chat semantics, and the inbound/outbound split. Plan onboarding around the Telegram model, not the PHP code.
TPM recommendation. Proceed. The package is a low-cost, low-lock-in, high-leverage adapter with a differentiated rich-message/streaming capability. Gate the decision on three pre-commitments: (1) we build and own the chat-ID capture and consent flow, (2) we build per-chat throttling and explicit failure classification on top, and (3) we accept community-grade upstream support and retain the option to fork under MIT. Treat the advanced rich-message surface as an experiment, not a committed dependency, until Telegram client coverage is confirmed against our user base.
How can I help you explore Laravel packages today?