Telegram
<!-- BEGIN:skill-intro -->
Scripts for a Telegram bot, against the
Telegram Bot API (
https://api.telegram.org/bot<token>/<method>
). Send text, media, locations, contacts, and polls; edit, delete, forward, copy, and pin messages; and resolve the chats, members, and files a bot interacts with. Every script acts
as the bot — the bot must be a member of any chat it messages, and a user must message the bot first before the bot can DM them.
<!-- legal:disclaimer -->
Independent, unofficial connector for Telegram. Not affiliated with, endorsed by, or sponsored by Telegram. "Telegram" is a trademark of its owner, used only to identify the service this connector works with.
<!-- /legal:disclaimer -->
<!-- END:skill-intro -->
When to use this
<!-- BEGIN:skill-use-cases -->
- An agent needs a Telegram bot to send a message, photo, document, video, audio, location, contact, or poll to a chat.
- An agent needs to manage messages the bot sent — edit, delete, forward, copy, pin, or unpin.
- An agent needs to resolve a chat or member — find a (via ), confirm a chat (), check a member's role (), or list admins.
<!-- END:skill-use-cases -->
Setup
This is an
agentskills.io skill.
If the connector has not been installed as a skill yet, install it first with
npx skills add zapier/connectors --skill telegram
(or your harness's own skill-install mechanism), then continue here. Installing the skill copies these files, not dependencies. Before running the CLI, a local MCP server, or
auth commands, run
here once. Importing the published package as a dependency in your own project instead? That
already resolves everything — see
.
Want the actual repo source instead — to browse
, run this connector's tests, or hack on it? See
for a scoped
.
The connector runs on Node.js 22.18+. Pick the reference that matches how you're running it, and load it before doing anything else:
| You have... | Load |
|---|
| An MCP-aware client — tools may already be loaded (e.g. ), or you can register a local server yourself (or guide the user to) | |
| Terminal / subprocess access (you can run ) | |
| Only your own code, importing this package as a dependency | |
| No tool access, no terminal, no ability to import this package — you write your own code that calls the Telegram API directly (e.g. a code-execution sandbox) | references/use-as-recipe.md
|
Scripts
<!-- BEGIN:skill-connections-note? -->
All scripts use a single
connection.
<!-- END:skill-connections-note -->
<!-- BEGIN:skill-scripts-table -->
| Script | Script name | Connections | Description |
|---|
| | Single () | Send a text message to a chat. |
| | Single () | Send a photo by URL or file_id. |
| | Single () | Send a file/document by URL or file_id. |
| | Single () | Send a video by URL or file_id. |
| | Single () | Send an audio file (music) by URL or file_id. |
| | Single () | Send a point on the map. |
| | Single () | Send a phone contact. |
| | Single () | Send a poll or quiz. |
scripts/editMessageText.ts
| | Single () | Edit the text of a message the bot sent. |
| | Single () | Delete a message from a chat. |
scripts/forwardMessage.ts
| | Single () | Forward a message, keeping attribution. |
| | Single () | Copy a message's content without attribution. |
scripts/pinChatMessage.ts
| | Single () | Pin a message in a chat. |
scripts/unpinChatMessage.ts
| | Single () | Unpin a message (or the most recent pin). |
| | Single () | Get the bot's identity and verify the token. |
| | Single () | Get info about a chat by id or @username. |
scripts/listRecentChats.ts
| | Single () | List chats the bot recently interacted with (chat_id resolver). |
| | Single () | Get a member's status and role in a chat. |
scripts/getChatAdministrators.ts
| | Single () | List a chat's administrators. |
scripts/getChatMemberCount.ts
| | Single () | Get the number of members in a chat. |
| | Single () | Get a file's metadata and download path. |
<!-- END:skill-scripts-table -->
<!-- BEGIN:disambiguation-and-refusals? -->
Disambiguation & refusals
- Resolve before sending; don't guess. A is a numeric id (supergroups/channels are -prefixed) or a public . If the user names a chat you don't have an id for, resolve it with (chats that recently messaged the bot) or (a known id/username). If returns two chats whose names tie on what the user said, stop and ask which one — list each with its and id. If exactly one matches, act on it; don't over-ask.
- The bot must be reachable. A bot can only message chats it's a member of, and cannot start a private chat — the user must message the bot first. If a send fails with "bot can't initiate conversation" or "chat not found", say so and stop; don't retry against a different chat.
- Declined operations. This connector does not create/manage chats, ban or promote members, manage invite links, upload local files (provide an HTTPS URL or a Telegram instead), or run games/payments. If asked for one of these, say it's unsupported — don't substitute another tool and report success for an action you didn't perform.
<!-- END:disambiguation-and-refusals -->
Auth
Every shape passes auth as one connection
selector, not the secret — a
string. Every connector accepts
(Zapier-managed auth — routes through Zapier's auth, retries, and governance layer); some also accept one or more direct-token resolvers (naming and count vary per connector) — check this connector's own resolvers rather than assuming. The
prefix is optional; a bare value goes to the first resolver that claims it — a UUID-shaped bare value always claims
. Each script declares the connections it needs and the resolvers each accepts. The exact syntax for passing a connection (and how to see this connector's resolver list) differs by shape — see the reference you loaded above.
Checking what's already configured first? Don't dump environment values to do it —
or
prints the value along with the name, leaking a live credential into the transcript if one is set. Check names only (
env | cut -d= -f1 | grep -i <name>
) or test a known name directly (
).
<!-- BEGIN:skill-auth-notes? operational behavior that differs by WHICH resolver is used — a safety gate only one path enforces, scopes/permissions that differ between resolvers, a billing/plan difference tied to the auth path, or a feature only available (or unavailable) on one resolver. Not for describing how to obtain or pass a credential — that's references/use-without-zapier.md's job. Leave this region empty (unfilled) if every resolver behaves identically. -->
<!-- END:skill-auth-notes -->
No connection yet? Pick one — and follow the reference's own flow to obtain it; never just ask the user for a connection id or token as if they already have one memorized:
| Load |
|---|
| Pass the credential directly | references/use-without-zapier.md
|
| Route it through a Zapier connection | references/use-with-zapier.md
|
Output format
Every script returns a
envelope:
- — the script's result (the shape its declares; see the reference you loaded above for how to inspect a script's exact schema in your shape).
meta.outputDataValidation
— what validating did:
{ skipped: false, droppedPaths: null }
— validated, nothing removed.
{ skipped: false, droppedPaths: [...], instruction }
— validated, but those paths were stripped from : fields the script returned from the API that the doesn't declare. If you need them, re-run with output validation skipped.
- — validation was bypassed; is the raw, unchecked script output.
Reading dropped fields / . To receive the raw, unvalidated result, opt out of output validation (the exact syntax differs by shape — see the reference you loaded above). Input validation is never skipped.
Trimming the result / . To shrink a large result down to the fields you need, pass a jq expression that post-processes
(again, exact syntax per shape). The jq runs against
only, NOT the
envelope, so write it rooted at
(run the script's
— or your shape's equivalent — to see its output schema). The transformed value replaces
,
is preserved, and the result is NOT re-validated against the output schema.
<!-- BEGIN:skill-references-table -->
References
Load the matching reference file before working in that area:
| Reference | Covers | Load it when |
|---|
| references/telegram-api-gotchas.md | HTML vs MarkdownV2 escaping, file URL size limits, 1-hour links, copying vs forwarding, deleting/pinning messages, building polls, /// error envelope, rate limits | Before sending formatted text, uploading/downloading files, copying vs forwarding, deleting/pinning messages, building polls, or handling API errors and rate limits. |
<!-- END:skill-references-table -->