# Telegram webhook trigger

> Run a workflow on Telegram Bot API updates: messages, inline button taps, and reactions, with secret-token authentication.

Source: https://cotera.co/docs/reference/webhooks/telegram

---

Run a workflow on Telegram Bot API updates — your bot gets a message, a user taps an inline button, someone reacts to a message. The update becomes the workflow's input.

For behavior shared by every provider (the delivery URL, testing), see the [webhook triggers reference](https://cotera.co/docs/reference/webhooks.md).

## Prerequisites

Telegram webhooks are **auto-registered**: Cotera calls the Telegram Bot API to set your bot's webhook. That requires a connected Telegram **bot token**. Without one, install fails with `telegram_credentials_missing`.

## Setup

A Telegram bot allows only one webhook URL, so Cotera uses a single endpoint for your bot and routes updates to the triggers that match:

1. Add a **From an app** trigger and pick **Telegram**.
2. Choose the event (see below).
3. Save. Cotera calls Telegram's `setWebhook` for your bot, pointed at the shared endpoint, subscribing to the update types your active triggers need.

Deleting your last Telegram trigger removes the bot's webhook (`deleteWebhook`); Cotera reconciles the subscribed update types as you add or remove triggers.

## Events

| Event key                | Fires when                                            |
| ------------------------ | ----------------------------------------------------- |
| `message`                | The bot receives a new message                        |
| `callback_query`         | A user taps an inline keyboard button                 |
| `message_reaction`       | A user adds or removes an emoji reaction on a message |
| `message_reaction_count` | Anonymous reaction counts change on a channel message |

## Payload

The raw Telegram Update object is passed through as the workflow input. A `message` update looks like:

```json
{
  "update_id": 10000,
  "message": {
    "message_id": 1,
    "from": {
      "id": 123456789,
      "is_bot": false,
      "first_name": "Test",
      "last_name": "User",
      "username": "testuser",
      "language_code": "en"
    },
    "chat": { "id": 123456789, "first_name": "Test", "username": "testuser", "type": "private" },
    "date": 1716111111,
    "text": "Hello from Cotera"
  }
}
```

| Field                                                                        | Description                                                            |
| ---------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| `update_id`                                                                  | The update's unique id, used to deduplicate retries.                   |
| `message` / `callback_query` / `message_reaction` / `message_reaction_count` | The update body — exactly one is present, and it determines the event. |

Cotera routes each update to the trigger for its type: an update with `callback_query` runs the `callback_query` trigger, one with `message` runs the `message` trigger, and so on.

## Authentication

Telegram doesn't sign deliveries. When Cotera registers the webhook it sets a **secret token**, and Telegram sends that token back in the `X-Telegram-Bot-Api-Secret-Token` header on every delivery. Cotera constant-time compares it against the trigger's secret and rejects anything that doesn't match.

