# `PhoenixKit.Integrations.Telegram`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v2.13.7/lib/phoenix_kit/integrations/telegram.ex#L1)

Send messages via a stored Telegram bot integration, plus the one-shot
read primitive the notification **chat-linking** flow needs.

Telegram puts the bot token in the URL path (`/bot<token>/<method>`) rather
than an `Authorization` header, so it can't ride the header-based
`PhoenixKit.Integrations.authenticated_request/4`. This module resolves the
token via `Integrations.get_credentials/2` (owner-scoped, so a connection is
only reachable by an owner entitled to it) and calls the Bot API directly.

Scope is deliberately narrow: **sending**, plus a **one-shot `getUpdates`**
used purely to discover a user's `chat_id` when they link their chat (NOT a
streaming receiver — long-poll loops / webhooks are out of scope).

    Telegram.send_message(conn_uuid, chat_id, "Deploy finished ✅")
    Telegram.send_message(conn_uuid, chat_id, "*Alert*", parse_mode: "MarkdownV2")

`chat_id` is the numeric id of a user/group/channel, or `"@channelusername"`.
A user must have messaged the bot first (Telegram's anti-spam rule) — which is
exactly what the chat-link `/start` step arranges.

# `get_updates`

```elixir
@spec get_updates(
  String.t(),
  keyword()
) :: {:ok, [map()]} | {:error, term()}
```

Reads recent updates for the bot — the one-shot primitive the chat-linking
flow uses to discover a user's `chat_id` after they `/start` the bot.

Defaults to `offset: -1` (peek only the latest update, WITHOUT confirming it,
so a bot that also has its own update consumer isn't disturbed). Returns
`{:ok, [update]}` or `{:error, reason}`.

# `get_updates_with_token`

```elixir
@spec get_updates_with_token(
  String.t(),
  keyword()
) :: {:ok, [map()]} | {:error, term()}
```

Like `get_updates/2` but with a raw bot token.

# `send_message`

```elixir
@spec send_message(String.t(), integer() | String.t(), String.t(), keyword()) ::
  {:ok, map()} | {:error, term()}
```

Sends a text message via a stored Telegram connection.

Opts: `:parse_mode` (`"MarkdownV2"` / `"HTML"`), `:silent` (no notification
sound), `:reply_markup` (inline/keyboard map), and `:owner` for the credential
lookup (`:system` default, or `{type, id}`). Returns `{:ok, message}` (the
sent Message object) or `{:error, reason}`.

# `send_message_with_token`

```elixir
@spec send_message_with_token(
  String.t(),
  integer() | String.t(),
  String.t(),
  keyword()
) ::
  {:ok, map()} | {:error, term()}
```

Like `send_message/4` but with a raw bot token instead of a connection uuid.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
