This is a cleaned-up reference implementation for running multiple Nutgram bots inside one Laravel application.
It is not a package. It is a small set of app-level files showing one approach that has worked in production for a Laravel app with several Telegram bots.
- Configure multiple bot tokens in
config/nutgram.php. - Resolve bots by name through
NutgramManager. - Share Nutgram package configuration across all bot instances.
- Use one webhook route:
/api/nutgram/{bot}. - Set or remove webhooks per bot with an Artisan command.
- Support safe-mode webhook secret validation.
- Keep test mode fake-friendly.
- Optionally register command menus for every configured bot.
This reference was extracted from an app using:
nutgram/nutgram4.xnutgram/laravel1.x- Laravel 11+ with the
Illuminate\Support\deferhelper - PHP 8.1+ for the core files
The core multi-bot manager should still be useful as a starting point for
Nutgram 5, but the optional command-menu registrar depends on Nutgram 4's
extendable SergiX44\Nutgram\Handlers\Type\Command pattern.
-
config/nutgram.phpSanitized multi-bot config. -
app/Telegram/Manager/NutgramManager.phpThe central resolver/factory for named bot instances. -
routes/api.phpA single webhook endpoint using{bot}as the bot selector. -
routes/telegram.phpCentralized handler registration loaded for each named bot. -
app/Console/Commands/NutgramWebhookCommand.phpSets or removes webhooks for one named bot. -
app/Telegram/Support/HandleNutgramWebhookFailure.phpLogs webhook bootstrap failures and can notify an admin without resolving Nutgram. -
optional-v4/RegisterBotCommandsCommand.phpOptional Nutgram 4 command-menu registrar.
NUTGRAM_DEFAULT_BOT=main
TELEGRAM_BOT_MAIN_TOKEN=123:abc
TELEGRAM_BOT_MAIN_BOTNAME=ExampleMainBot
TELEGRAM_BOT_ADMIN_TOKEN=456:def
TELEGRAM_BOT_ADMIN_BOTNAME=ExampleAdminBot
TELEGRAM_ADMIN_CHAT_ID=123456789
NUTGRAM_SAFE_MODE=true
NUTGRAM_WEBHOOK_SECRET=change-me-to-a-long-random-tokenYou can also configure per-bot webhook secrets, such as
TELEGRAM_BOT_MAIN_WEBHOOK_SECRET. If no explicit secret is configured, the
manager derives a stable bot-specific secret from APP_KEY. Rotating APP_KEY
will change derived webhook secrets, so re-run the webhook command after an app
key rotation.
app(NutgramManager::class)->bot('main')->sendMessage(
chat_id: 123456789,
text: 'Hello from the main bot',
);
app(NutgramManager::class)->bot('admin')->sendMessage(
chat_id: 123456789,
text: 'Hello from the admin bot',
);Set webhooks:
php artisan nutgram:webhook main
php artisan nutgram:webhook adminOr provide an explicit URL during local tunneling:
php artisan nutgram:webhook main --url=https://example.ngrok-free.app/api/nutgram/mainIf you include the optional Nutgram 4 command-menu registrar:
php artisan nutgram:register-bot-commands
php artisan nutgram:register-bot-commands mainIn the app this was extracted from, handler registration is centralized in
routes/telegram.php and loaded once per bot instance:
// routes/telegram.php
use SergiX44\Nutgram\Nutgram;
/** @var Nutgram $bot */
// Replace these placeholders with your own app handlers.
$bot->onCommand('start', StartCommand::class)
->description('Start the bot')
->insensitive();
$bot->onText('Cancel', CancelHandler::class);The manager injects $bot before requiring that file, so the same route file is
applied to each named bot.
The webhook route in this gist uses Laravel's throttle middleware. Tune the
limit for your traffic and hosting setup.
The namespaces are intentionally mixed: nutgram/laravel exposes
Nutgram\Laravel\..., while the core package exposes SergiX44\Nutgram\....
Nutgram 5 changes the command-registration model. If you use this with Nutgram
5, prefer registering app command classes via onCommand(...) and keep command
metadata in your own app-level structure instead of extending Nutgram's internal
command class.
The multi-bot parts of this reference are separate from that command-class change:
- named bot resolution
- config cloning
- webhook routing
- webhook management
- fake/testing behavior
Those ideas should still transfer.