laravel-telegram maintained by ozkanozcan
Laravel Telegram Notifier
A clean, zero-dependency Telegram Bot notification channel for Laravel 10, 11, 12, and 13.
Send messages, photos, and documents directly from your Laravel application via the Telegram Bot API.
Table of Contents
- Requirements
- Installation
- Step 1 — Create a Telegram Bot
- Step 2 — Get Your Chat ID
- Step 3 — Configure the Package
- Basic Usage
- Laravel Notifications
- Facade Usage
- TelegramMessage Reference
- Inline Keyboard Buttons
- Message Formatting
- Artisan Command
- Language Files
- Configuration Reference
- Error Handling
- Testing
- Changelog
- Contributing
- License
Requirements
| Dependency | Version |
|---|---|
| PHP | ^8.2 |
| Laravel | 10.x / 11.x / 12.x / 13.x |
Installation
Install the package via Composer:
composer require ozkanozcan/laravel-telegram
Laravel's auto-discovery will register the service provider and Telegram facade automatically.
Publish the configuration file:
php artisan vendor:publish --tag=telegram-config
Publish language files (optional — required only to customise messages):
php artisan vendor:publish --tag=telegram-lang
Step 1 — Create a Telegram Bot
- Open Telegram and search for @BotFather.
- Start a conversation and send the command:
/newbot - Follow the prompts:
- Choose a display name for your bot (e.g.
My Laravel App). - Choose a username — must end with
bot(e.g.mylaravelapp_bot).
- Choose a display name for your bot (e.g.
- BotFather will respond with your Bot Token:
Done! Congratulations on your new bot. Use this token to access the HTTP API: 1234567890:AAFxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - Copy the token and add it to your
.envfile:TELEGRAM_BOT_TOKEN=1234567890:AAFxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Keep your token secret. Anyone with this token can control your bot.
Step 2 — Get Your Chat ID
The chat ID is the unique identifier of the conversation your bot should send messages to.
It can be a personal chat, a group, or a channel.
Personal Chat ID
- Search for @userinfobot on Telegram.
- Start a conversation and send
/start. - The bot will reply with your user information including your Id field — that is your
chat_id.
Alternatively:
- Send any message to your own bot (
@yourbotname). - Open this URL in your browser (replace
YOUR_TOKEN):https://api.telegram.org/botYOUR_TOKEN/getUpdates - Find the
"chat"object in the JSON response:"chat": { "id": 123456789, "first_name": "John", "type": "private" } - The
"id"value is yourchat_id.
Group Chat ID
- Add your bot to the group.
- Send a message in the group (mention the bot or just type anything).
- Open
https://api.telegram.org/botYOUR_TOKEN/getUpdates. - Look for
"chat": {"id": -100xxxxxxxxxx}— group IDs start with-100.
Channel ID
For public channels use the channel username: @yourchannel
For private channels:
- Forward any message from your channel to @userinfobot.
- It will show the channel ID (e.g.
-1001234567890).
Add the chat ID to your .env:
TELEGRAM_CHAT_ID=123456789
Step 3 — Configure the Package
Add these variables to your .env file:
TELEGRAM_BOT_TOKEN=1234567890:AAFxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TELEGRAM_CHAT_ID=123456789
TELEGRAM_PARSE_MODE=HTML
Verify your setup with the built-in Artisan command:
php artisan telegram:test
Basic Usage
Send a simple message
use OzkanOzcan\LaravelTelegram\TelegramBot;
use OzkanOzcan\LaravelTelegram\TelegramMessage;
$bot = app(TelegramBot::class);
$bot->sendMessage(
config('telegram.chat_id'),
TelegramMessage::create('Hello from Laravel! 🚀')->html()
);
Send a plain string
$bot->sendMessage(config('telegram.chat_id'), 'Hello World!');
Laravel Notifications
This is the recommended way to use the package in Laravel applications.
1. Add routing to your notifiable model
// app/Models/User.php
use OzkanOzcan\LaravelTelegram\TelegramChannel;
use OzkanOzcan\LaravelTelegram\TelegramMessage;
class User extends Authenticatable
{
public function routeNotificationForTelegram(): string|int|null
{
// Return the user's personal Telegram chat_id stored in the database,
// or fall back to the application-wide default.
return $this->telegram_chat_id ?? config('telegram.chat_id');
}
}
2. Create a notification class
php artisan make:notification OrderShipped
// app/Notifications/OrderShipped.php
namespace App\Notifications;
use Illuminate\Notifications\Notification;
use OzkanOzcan\LaravelTelegram\TelegramChannel;
use OzkanOzcan\LaravelTelegram\TelegramMessage;
class OrderShipped extends Notification
{
public function __construct(private readonly Order $order) {}
public function via(object $notifiable): array
{
return [TelegramChannel::class];
}
public function toTelegram(object $notifiable): TelegramMessage
{
return TelegramMessage::create()
->html()
->content(
"📦 <b>Order Shipped!</b>\n\n" .
"Order: <code>#{$this->order->id}</code>\n" .
"Customer: {$this->order->customer_name}\n" .
"Total: <b>\${$this->order->total}</b>"
)
->button('Track Order', route('orders.track', $this->order))
->disablePreview();
}
}
3. Dispatch the notification
// Send to a specific user
$user->notify(new OrderShipped($order));
// Send to multiple users
Notification::send(User::all(), new OrderShipped($order));
Facade Usage
The Telegram facade is available after auto-discovery:
use OzkanOzcan\LaravelTelegram\TelegramFacade as Telegram;
use OzkanOzcan\LaravelTelegram\TelegramMessage;
// Send a message
Telegram::sendMessage(
config('telegram.chat_id'),
TelegramMessage::create('🔔 New user registered!')->html()
);
// Send a photo
Telegram::sendPhoto(
config('telegram.chat_id'),
'https://example.com/photo.jpg',
['caption' => 'Check out this photo!']
);
// Send a document
Telegram::sendDocument(
config('telegram.chat_id'),
'https://example.com/report.pdf',
['caption' => 'Monthly Report']
);
// Raw API call
Telegram::request('sendMessage', [
'chat_id' => config('telegram.chat_id'),
'text' => 'Hello!',
]);
// Check bot info
$me = Telegram::getMe();
echo $me['username']; // yourbot
TelegramMessage Reference
use OzkanOzcan\LaravelTelegram\TelegramMessage;
$message = TelegramMessage::create('Your text here')
// ── Content ─────────────────────────────────────
->text('Override text') // Set message text
->content('Alias for text()') // Alias
// ── Parse mode ──────────────────────────────────
->html() // HTML parse mode
->markdown() // Markdown parse mode
->markdownV2() // MarkdownV2 parse mode
->parseMode('HTML') // Custom parse mode string
// ── Behaviour ───────────────────────────────────
->disablePreview() // Disable link preview
->silent() // Send without notification sound
// ── Recipient override ───────────────────────────
->to(123456789) // Override chat_id for this message
// ── Inline keyboard ──────────────────────────────
->button('Label', 'https://...') // URL button (new row)
->callbackButton('Label', 'data') // Callback data button (new row)
->buttonRow([ // Multiple buttons in one row
['text' => 'A', 'url' => 'https://a.com'],
['text' => 'B', 'url' => 'https://b.com'],
]);
Inline Keyboard Buttons
TelegramMessage::create('Choose an option:')
->html()
->button('📖 Documentation', 'https://laravel.com/docs')
->button('🐙 GitHub', 'https://github.com')
->buttonRow([
['text' => '✅ Accept', 'callback_data' => 'accept'],
['text' => '❌ Decline', 'callback_data' => 'decline'],
]);
Message Formatting
HTML (recommended)
TelegramMessage::create(
"<b>Bold</b>, <i>Italic</i>, <u>Underline</u>\n" .
"<code>Inline code</code>\n" .
"<pre>Block code</pre>\n" .
'<a href="https://example.com">Link text</a>'
)->html();
Supported HTML tags: <b>, <i>, <u>, <s>, <code>, <pre>, <a href>, <tg-spoiler>
Markdown
TelegramMessage::create(
"*Bold*, _Italic_\n`Inline code`\n```Block code```"
)->markdown();
Artisan Command
Test your bot configuration without writing any code:
# Basic test — uses token from config and sends to default chat_id
php artisan telegram:test
# Override chat_id
php artisan telegram:test --chat_id=123456789
# Send a custom message
php artisan telegram:test --message="Hello from artisan!"
Language Files
The package ships with en and tr language files.
Publish them to customise or add new locales:
php artisan vendor:publish --tag=telegram-lang
Files will be placed at lang/vendor/telegram/{locale}/telegram.php.
To use translations in your own code:
trans('telegram::telegram.missing_token');
trans('telegram::telegram.api_error', ['code' => 429, 'description' => 'Too Many Requests']);
To add a new locale (e.g. German), create:
lang/vendor/telegram/de/telegram.php
and add the same keys as the en file.
Configuration Reference
After publishing the config (php artisan vendor:publish --tag=telegram-config), you can fine-tune config/telegram.php:
| Key | Default | Description |
|---|---|---|
token |
'' |
Bot token from BotFather |
chat_id |
'' |
Default recipient chat ID |
parse_mode |
HTML |
HTML, Markdown, or MarkdownV2 |
disable_web_page_preview |
false |
Disable link previews |
disable_notification |
false |
Silent notifications |
api_url |
Telegram API | Override for proxies |
timeout |
30 |
HTTP read timeout (seconds) |
connect_timeout |
10 |
HTTP connect timeout (seconds) |
retry.times |
3 |
Retry count on HTTP 429 |
retry.sleep_ms |
1000 |
Delay between retries (ms) |
proxy |
null |
HTTP proxy URL |
logging |
false |
Log every sent message |
Error Handling
use OzkanOzcan\LaravelTelegram\Exceptions\TelegramApiException;
use OzkanOzcan\LaravelTelegram\Exceptions\TelegramChannelException;
use OzkanOzcan\LaravelTelegram\TelegramFacade as Telegram;
use OzkanOzcan\LaravelTelegram\TelegramMessage;
try {
Telegram::sendMessage(
config('telegram.chat_id'),
TelegramMessage::create('Hello!')->html()
);
} catch (TelegramChannelException $e) {
// Configuration error (missing token, missing chat_id)
logger()->error('Telegram config error: ' . $e->getMessage());
} catch (TelegramApiException $e) {
if ($e->isRateLimit()) {
// HTTP 429 — bot is sending too many messages
logger()->warning('Telegram rate limit hit.');
} elseif ($e->isBotBlocked()) {
// HTTP 403 — user blocked the bot
logger()->warning('Bot was blocked by user.');
} elseif ($e->isBadRequest()) {
// HTTP 400 — invalid parameters
logger()->error('Bad Telegram API request: ' . $e->getTelegramDescription());
} else {
logger()->error("Telegram API [{$e->getTelegramErrorCode()}]: {$e->getTelegramDescription()}");
}
}
Testing
composer install
vendor/bin/phpunit
In your own application tests, you can mock TelegramBot to avoid real API calls:
use OzkanOzcan\LaravelTelegram\TelegramBot;
use OzkanOzcan\LaravelTelegram\TelegramMessage;
$this->mock(TelegramBot::class)
->shouldReceive('sendMessage')
->once()
->with(123456789, Mockery::type(TelegramMessage::class))
->andReturn(['message_id' => 42]);
$user->notify(new OrderShipped($order));
Changelog
See CHANGELOG.md for a history of changes.
Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Commit your changes following Conventional Commits
- Push and open a Pull Request against
development
Please make sure all tests pass before submitting a PR.
License
MIT © Özkan Özcan — Özcan Teknoloji
See LICENSE for full details.