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

  1. Open the verified BotFather account in Telegram. Send /newbot, choose a display name and a unique username ending in bot.
  2. For an existing bot, use /mybots, select it and open API Token. Revoke/regenerate a compromised token in BotFather before replacing it in CaseKit.
  3. 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.
  4. 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.
  5. 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.

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 Email 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

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.