DEF STUDIO srl

Need help with Laravel and web development?

Hire one of our experts for your projects.

We build tailored products, websites and platforms — with care for UX, performance and maintainability.

Booking open for Q2 — limited slots

Register Webhooks

To receive Telegram updates through a webhook, register a public https URL for a specific bot. For the fast onboarding path, see the quickstart webhook step; this page covers registration parameters and diagnostics in more detail. For symptom-based first-bot diagnostics, see Troubleshooting Telegraph onboarding.

Public URL and local tunnel

Telegram must be able to reach your application from the public internet. In production this is usually your application domain; in local development it is a temporary https tunnel:

ngrok http 8000

Copy the public tunnel URL and configure one of these values:

APP_URL=https://example.ngrok-free.app
TELEGRAM_WEBHOOK_DOMAIN=https://example.ngrok-free.app

TELEGRAM_WEBHOOK_DOMAIN sets telegraph.webhook.domain and is used when registering the webhook instead of the domain from APP_URL. This is useful when the rest of the application still uses a local APP_URL, but Telegram needs a public route.

If you use php artisan config:cache, clear cached config after changing .env:

php artisan config:clear

Route URL

Telegraph registers a Laravel route named telegraph.webhook. The default path is:

/telegraph/{token}/webhook

With the default config, the full URL looks like this:

https://example.ngrok-free.app/telegraph/{token}/webhook

You can change the path through TELEGRAPH_WEBHOOK_URL (telegraph.webhook.url) or disable the route by setting the config value to null:

TELEGRAPH_WEBHOOK_URL=/telegram/{token}/webhook

If the route changes, verify that middleware and the reverse proxy allow POST requests to the new URL.

Secret token

The Telegram Bot API lets you pass a secret_token when registering a webhook. Telegram sends that value in the X-Telegram-Bot-Api-Secret-Token header on later webhook requests.

Store the value in .env and do not publish it in issues, logs, or screenshots:

TELEGRAPH_WEBHOOK_SECRET=your-secret-token

For CLI registration, pass the secret explicitly:

php artisan telegraph:set-webhook {bot_id} --secret="${TELEGRAPH_WEBHOOK_SECRET}"

For programmatic registration, pass secretToken:

/** @var DefStudio\Telegraph\Models\TelegraphBot $telegraphBot */

$telegraphBot->registerWebhook(
    secretToken: config('telegraph.webhook.secret'),
)->send();
Note

Telegraph sends secret_token to Telegram during registration. If your application must enforce inbound validation of the X-Telegram-Bot-Api-Secret-Token header, add that check to middleware from telegraph.webhook.middleware or to your own request handling layer.

Artisan command

Register a webhook with:

php artisan telegraph:set-webhook {bot_id}

can be omitted when the system has only one bot. Available options:

php artisan telegraph:set-webhook {bot_id} \
    --drop-pending-updates \
    --max-connections=100 \
    --secret=your-secret-token
  • --drop-pending-updates removes pending updates on Telegram when changing the webhook.
  • --max-connections sets the maximum allowed simultaneous connections. The default comes from telegraph.webhook.max_connections.
  • --secret passes Telegram the secret_token.

Allowed updates

telegraph.webhook.allowed_updates can be set in config when the bot should receive only some update types. A null value keeps Telegram's default behavior: all update types except some opt-in events such as chat_member, message_reaction, and message_reaction_count.

Example config:

'webhook' => [
    'allowed_updates' => ['message', 'callback_query'],
],

Programmatic registration

If the application has its own bot management logic, register the webhook through TelegraphBot:

/** @var DefStudio\Telegraph\Models\TelegraphBot $telegraphBot */

$telegraphBot->registerWebhook(
    dropPendingUpdates: true,
    maxConnections: 100,
    secretToken: 'your-secret-token',
)->send();

For the method signature, see the TelegraphBot documentation.

Warning

Manual updates polling is not available while a bot has a configured webhook. First remove the webhook through the unregisterWebhook method.

Check with the debug command

After registration, check the webhook state on Telegram:

php artisan telegraph:debug-webhook {bot_id}

The command shows Telegram webhook diagnostics such as url, pending_update_count, last_error_date, last_error_message, max_connections, and allowed_updates when Telegram returns those fields. This is Telegram delivery diagnostics, not a dump of the incoming Laravel request.

For runtime diagnostics, use:

  • php artisan telegraph:debug-webhook {bot_id} for the webhook state in Telegram.
  • storage/logs/laravel.log for handler, middleware, and application code errors.
  • The tunnel inspector (ngrok web UI or similar) to check incoming POST requests.

Do not paste real bot tokens, webhook secrets, Telegram headers, or full user payloads into public issues or shared logs.

Troubleshooting local development

The full onboarding troubleshooting guide is available in Troubleshooting Telegraph onboarding. This section keeps the webhook-specific checks short.

Telegram rejects the URL

Make sure the webhook URL starts with https://. If the route does not use TELEGRAM_WEBHOOK_DOMAIN, Laravel must generate a secure URL from APP_URL.

Tunnel URL changed after restart

Free tunnel URLs often change after restart. Update APP_URL or TELEGRAM_WEBHOOK_DOMAIN, run php artisan config:clear, then run telegraph:set-webhook again.

debug-webhook shows an old URL

The config cache probably still contains old env values, or the webhook was not registered again after changing the tunnel. Run:

php artisan config:clear
php artisan telegraph:set-webhook {bot_id} --secret=your-secret-token
php artisan telegraph:debug-webhook {bot_id}

Route returns 404

Check TELEGRAPH_WEBHOOK_URL and the published config. By default the route should be /telegraph/{token}/webhook; if you override the path, the same path must be registered in Telegram. Also check php artisan route:list in the host application.

Route returns 401 or 403

Check middleware from telegraph.webhook.middleware, CSRF/external access rules, the reverse proxy, and any custom X-Telegram-Bot-Api-Secret-Token validation. The secret in Telegram registration and the expected middleware value must match.

/chatid does not answer in a new chat

By default the webhook handler accepts requests only from known TelegraphChat models and can reject unknown chats. To obtain the first chat_id, use the default handler flow from the overview or configure the unknown-chat security options deliberately.

Pending updates arrive after changing the webhook

If old updates are no longer useful, register the webhook again with --drop-pending-updates:

php artisan telegraph:set-webhook {bot_id} --drop-pending-updates --secret=your-secret-token

If you need to remove the webhook entirely, use telegraph:unset-webhook.

Suggest a change
Last updated 15 June 2026