Connect your Telegram support bot
Receive private messages from human customers as tickets and reply through the same bot and private chat. CaseKit derives the bot identity from your token. A dedicated bot belongs to one workspace in one deployment stage; use separate bots for testing and production.
Create a bot or use one you own
-
Open the verified BotFather account in Telegram. Send
/newbot, choose a display name and a unique username ending inbot. -
For an existing bot, use
/mybots, select it and open API Token. Revoke/regenerate a compromised token in BotFather before replacing it in CaseKit. - Keep the token private in your password manager. Enter it only in the write-only Channels → Telegram token input or a secure API client. Never put it in a ticket, log, source file, screenshot or URL.
- An operator enables the stage capability, and a human Owner/Admin opts the workspace in. The defaults are capability off, sends paused, workspace Telegram off. Select an active routing team, enter the token and optional label, and connect.
- Wait for the current configuration operation and canonical connection to become ready. Ask the operator to release stage send pause for a controlled customer message and reply. Setup diagnostics alone do not prove delivery.
Publish the command menu
In the verified @BotFather chat, send /setcommands, select
your bot, and paste all three lines below. You can also use
/mybots → select your bot → Edit Bot → Edit Commands.
Repeat for each bot. Names have no leading slash.
start - Show welcome and support instructions
end - Mark the current issue as resolved
help - Show support instructions
BotFather replaces the whole list. Include help so it
appears in the menu. Typed commands work without a menu entry; CaseKit
implements their actions.
-
/startshows a welcome and support instructions without creating, reopening or changing a ticket. -
/endis optional: it marks the current issue as resolved and preserves the ticket and chat history. It does not close the ticket or end its association. Resolved or staff-closed tickets stay settled; with no ticket, it sends instructions without creating one. -
/helpsends a fixed guide without changing tickets.
Customers can simply send a message or supported attachment: the first content opens a ticket, and later messages stay in that same ticket for this customer and bot. No command is required. A different bot keeps its own ticket for the same customer.
Staff resolve handled issues from the dashboard or API and may close
them after resolution. A later ordinary customer message reopens the
same ticket, including after /end or staff closure. There
is no automatic inactivity closure; silence does not resolve unanswered
work. Edits do not reopen tickets. Commands in edited messages or
attachment captions do not execute ticket controls. Bot responses use
durable delivery and honor pauses.
If an older release ended the chat association, later content reuses its latest ticket after the retained message boundary. Older tickets remain separate history and are not merged.
For conversations started before this update, the bot may ask for one
new message before optional /end resolution is available.
Staff can still resolve those tickets normally.
Authentication and access
Select the workspace with X-Helpdesk-Tenant-Id and use
Authorization: Bearer <ACCESS_TOKEN> or
Authorization: ApiKey <API_KEY>. Current human
Owner/Admin or active full_access keys manage bots.
Workspace opt-in is human-only. Agents and agent/staff_admin
keys cannot manage bots. Those three values are the entire supported key
union; read_only is unsupported. Bot tokens and Telegram
IDs are not staff authentication.
Human Owner/Admin security recovery permits reads, diagnostics, pause/archive and paused token replacement during suspension/deletion pending. It cannot enable, repair, take over or send. Keys require active admission. Purging/deleted tenants deny all actions. Authorized historical ticket content remains readable under normal ticket access even if stage bot management is disabled.
Connect, pause, rotate and repair
Bot mutations require a UUID Idempotency-Key; tenant opt-in
uses its existing policy key convention. Existing-connection changes
also require If-Match with the current quoted connection
version. Read GET /v1/tenant/settings for the policy
version used by the human opt-in
PUT /v1/channels/telegram with
{"enabled":true,"expectedVersion":<CURRENT_POLICY_VERSION>}.
POST /v1/telegram/bots
Authorization: Bearer <ACCESS_TOKEN>
X-Helpdesk-Tenant-Id: <WORKSPACE_UUID>
Idempotency-Key: <FRESH_KEY>
Content-Type: application/json
{"token":"<BOT_TOKEN>","teamId":"<TEAM_UUID>","label":"Support"}
A successful mutation returns 202 {connection,operation},
Location: /v1/telegram/operations/<OPERATION_ID>, the
connection ETag and Cache-Control: no-store.
Poll the operation and refresh the connection; 202 means durable intent,
not readiness. Setup completion changes the connection version. On 412
refresh both its ETag and authoritative lastOperationId.
| Action | Request | Body |
|---|---|---|
| List / read | GET /v1/telegram/bots; GET /v1/telegram/bots/{id} | Optional list cursor/limit (25 default, 100 maximum); archived records included |
| Pause / enable / archive | PATCH /v1/telegram/bots/{id} | {"desiredState":"paused"}, "enabled" or "archived"; label/team updates also supported |
| Replace token | POST /v1/telegram/bots/{id}/token | {"token":"<REPLACEMENT_BOT_TOKEN>"}; must identify the same bot |
| Repair | POST /v1/telegram/bots/{id}/repair | {} |
| Inspect | GET /v1/telegram/bots/{id}/diagnostics; GET /v1/telegram/operations/{id} | No body |
Use a fresh mutation key and current If-Match for each new command. Exact uncertain-request retries reuse the original body/key/version and return a safe receipt; bot receipts have a 24-hour window. Secret fingerprints are keyed digests. Tokens, ciphertext, ingress secrets and raw provider errors never appear in responses or replays. No caller can choose webhook host, storage, key or generation.
A foreign webhook is refused or reported drifted. The exact
connect/repair field
"takeoverConfirmation":"replace-existing-telegram-webhook"
deliberately redirects future updates away from the old integration.
Confirm only when you control it. Ordinary repair never silently takes
over. Telegram has no conditional webhook change, so avoid simultaneous
external administration. Archive preserves history and attempts
owned-webhook cleanup; archived credentials can still be replaced during
eligible recovery. Ten connection records are allowed, including
archives.
Errors are safe generic codes: 400 invalid input/selector, 401 authentication, 404 missing or unauthorized, 409 management conflict, 412 stale version, 428 missing If-Match, 429 rate limit (Retry-After 60), 503 temporarily unavailable and 500 internal error. See the API schemas for exact fields. Never infer another workspace's existence from a denial.
Tickets across channels
| Capability | API | Telegram | |
|---|---|---|---|
| Status, resolve before close, reopen, assignment/team, priority/type/tags/due date | Shared ticket rules and current staff authorization | ||
| Timeline, private notes, clean attachments, saved replies/views, targets and fixed reports | Shared; private notes never contact customers | ||
| Requester | Real email optional | Email address | Stable bot + private user/chat; display name and optional username |
| New staff reply | Stored locally, delivery none | Exact originating email route | Original bot/private chat; durable send |
| Email/To/CC/audience controls | No email sending controls | Email-specific requester/reply-all | Unavailable; no fabricated email |
| Origin and history | API filter | Email filter; recorded legacy email intents preserved | Telegram and historical bot filters; immutable source snapshots visible to Agents after archive |
Limits and uncertainty
- Private human chats only; groups, channels, business messages and bot senders are unsupported. No historical import.
- Hosted inbound media: at most 20,000,000 bytes. Outbound replies: up to five clean files totaling 10 MiB. Text splits at 4,096 UTF-16 code units without breaking surrogate pairs.
- Unsupported media produces safe handling. Edits become revisions and do not reserve new attachments.
- Telegram retains upstream updates at most 24 hours. Paused bots acknowledge and discard incoming updates; enabling cannot recover them. Enabled setup-pending bots return retryable 503 subject to provider retention.
- Sent means Telegram accepted the part, not read by the customer. A timeout after submission may become unknown_outcome and is never automatically resent.
Explicit uncertain-reply retry uses
POST /v1/tickets/{ticketId}/messages/{messageId}/telegram-retry, current ticket If-Match, fresh idempotency key and
{"confirmation":"retry-possibly-sent-telegram-reply"}. It
may duplicate unconfirmed parts. Only those parts get a fresh
five-attempt/24-hour generation, appended to the current wire tail and
possibly sent after later replies. Accepted parts, original body,
logical message and report facts stay unchanged.
Diagnostics, recovery and privacy
Diagnostics report observed work from at most 100 rows per family. Show
truncated, evidenceState and checked time:
incomplete/unavailable evidence and partial zero counts do not prove
health or absence. Configuration evidence differs from retained send
attempts and customer round trips. Setup-operation detail and ticketless
system outcomes are retained for 30 days after settlement. Ticket reply
delivery and retry evidence remain with ticket history. An older
operation result may be unavailable while the current bot setup state
remains visible.
Lost wakes are recovered from durable due work. Expired leases and poison rows use bounded reconciliation and fair per-family checkpoints. Inspect queue age, DLQs, worker errors/throttles and missing heartbeat through the exact linked deployment. Replay only with operator authorization and current tenant/connection/deadline checks; never blindly redrive an unknown send.
Deletion scheduling stops ordinary work. Cancellation strictly before 30 days restores local policy while setting bots pending for fresh readiness and fencing old send generations. Revocation, drift or outage can keep a bot unready without preventing local cancellation. Permanent local erasure waits the actual recovery window and at least 35 minutes of drain. Best-effort owned-webhook cleanup precedes ciphertext erasure; revoked tokens, foreign ownership, failures and bounded timeouts do not indefinitely block local purge. Exact object versions and all owned records are erased with repeated verification and late-upload reaping. Remote chat copies and physical backup restoration are outside this guarantee; shared platform resources remain.
Validate in a nonproduction stage with two dedicated bots, real benign media and controlled injected failures. A short test cannot prove the physical 30-day deletion window; never shorten it for acceptance. Record only checks actually executed.
Provider references: BotFather and upstream update retention. CaseKit imposes the bounded product limits described above.