Documentation menu
Getting started
New in v2.0
Feature deep dives
Reference
REST API
Telegram Forwarding REST API Reference
All 102 routes the AutoTelegramForward control plane registers, grouped by subsystem, each with its verb, auth rule and a cURL example.
Verified against the checkout built for v2.2.4 · updated 20 Oct 2026
On this page
The control plane is a Go service that fronts the Python core. It owns authentication, tenancy, task CRUD, log history, dead-letter control and administration. Every route below is parsed out of api/main.go at build time, so this page cannot drift from the shipped binary.
102 endpoints68 require a token4 route groupsJSON in, JSON out
Where to go deeper
This page is the map. The four pages below are the territory: the full endpoint table with accepted fields, the response contract, the quota model and the durable-job lifecycle — each one grounded in the code that implements it rather than in a description of intent.
Endpoint reference
Every one of the 102 registered routes, searchable, with its accepted fields, its auth level and a real response body.
Response envelope
The three body shapes, the status codes that carry them, and the guard chain that decides whether a request ever reaches a handler.
Rate limits & quotas
Six classes with their real budgets, how each key is derived, and which classes refuse when the shared store is gone.
Durable task lifecycle
Six states with their full transition table, idempotent submission, retry backoff and every bound a caller can hit.
Authentication
Two schemes exist and they do different jobs. Clients (the web dashboard and the mobile app) obtain a session token from the public authentication routes and send it as a bearer token. Machines that call the API server-to-server can present a shared key instead.
| Scheme | Header | Used by | Behaviour |
|---|---|---|---|
Bearer token | Authorization: Bearer <token> | Web dashboard, mobile app, atf auth token --save | Resolves to an identity; every query is scoped to that numeric user id. |
ATF_API_KEY | X-API-Key: <key> | Service-to-service automation | Only enforced when the key is configured on the server. |
Init data | POST /api/auth/tma | Telegram Mini App | The signed WebApp init data is verified before a token is issued. |
# 1. Exchange credentials for a token
TOKEN=$(curl -s -X POST https://your-host/api/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"you@example.com","password":"…"}' \
| grep -o '"token":"[^"]*"' | cut -d'"' -f4)
# 2. Read your own tasks
curl -s https://your-host/api/rules \
-H "Authorization: Bearer $TOKEN"
# 3. Or use the CLI, which stores the token for you
atf auth token --save
atf auth whoamicurl -s https://your-host/api/system/setup | jq
# {
# "ready": true,
# "version": "2.0.0",
# "env": { "ATF_BOT_TOKEN": { "set": true } },
# "services": { "core": true, "logger": true, "api": true, "web": true }
# }
# Ready verdict without probing the services:
curl -s 'https://your-host/api/system/setup?probe=0'Conventions
- Versioned aliases. Health and system routes answer on both
/api/…and/api/v1/…; the dashboard uses the mirrored forms. - Partial updates are explicit.
PATCHcarries only what changes plusupdate_mask, which is the only way to set a field to false, zero or empty. - Optimistic concurrency. Updating a task bumps its version, so a stale writer is rejected instead of silently overwriting.
- Correlation ids. Every response carries a correlation id that also appears in the log history, so an API call and its delivery can be joined.
- Bounded reads. Log and queue queries page with
limit/sincerather than returning unbounded history. - Generated schema. The per-task settings surface publishes its own JSON schema at
/api/rules/settings/schema, so editors can be built before any task exists.
Worked examples
curl -s -X POST https://your-host/api/rules \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"name": "Market news → three channels",
"source_chats": ["-1001111111111", "-1002222222222"],
"target_chats": ["-1003333333333", "-1004444444444"],
"settings": {
"clean_links": true,
"clean_mentions": true,
"header_template": "📰 [[ORIGIN_NAME]]",
"footer_template": "🔗 [[ORIGIN_LINK]]"
}
}'curl -s -X POST https://your-host/api/simulate \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"rule_id":"<id>","text":"BUY NOW t.me/spam @channel #deal"}' | jqcurl -s "https://your-host/api/logs?level=ERROR&limit=50" \
-H "Authorization: Bearer $TOKEN" | jq '.items[0]'
curl -s https://your-host/api/logs/stats -H "Authorization: Bearer $TOKEN" | jq
curl -s https://your-host/api/dlq -H "Authorization: Bearer $TOKEN" | jq '.items[].id'
curl -s -X POST https://your-host/api/dlq/<id>/retry \
-H "Authorization: Bearer $TOKEN" | jqGroup highlights
System & readiness
GET/api/system/setupReady verdict, version, env contract and live service probes (booleans only)GET/api/system/setup?probe=0The same verdict without probing the servicesGET/api/system/envConfiguration contract: every key with set:true/false and a fix hintGET/api/health/servicesPer-service reachability, latency and detail (core / logger / api / web)GET/healthzLiveness probe used by the gateway and the upgrade gate
Tasks & rules
GET/api/rulesList the caller's tasks (tenant-scoped)POST/api/rulesCreate a task with a source list, a target list and a content policyGET/api/rules/{id}Read one task including its resolved settingsPUT/api/rules/{id}Update a task (optimistic concurrency, version bumped)DELETE/api/rules/{id}Delete a task and its schedulesPOST/api/rules/{id}/pausePause a task: queued jobs defer instead of failingPOST/api/rules/{id}/resumeResume a task and unblock retry-wait jobsPOST/api/rules/{id}/toggleEnable or disable a taskPOST/api/simulateDry-run a message through a task and see the decision
Task lifecycle (async jobs)
GET/api/tasksList the caller's async jobs (state machine, tenant-scoped)POST/api/tasksSubmit an async job (session backup, DLQ replay/purge, backup export); idempotent via idempotency_keyGET/api/tasks/{id}Poll one job: state, attempt, timestamps, structured error detailsPOST/api/tasks/{id}/cancelCancel a queued job before a worker claims itPOST/api/tasks/{id}/retryRe-queue a failed job (attempt budget reset)
Sessions
GET/api/sessionsList the caller's Telegram sessionsGET/api/sessions/{id}/chatsList the chats a session can see (sources and targets)POST/api/sessions/{id}/backupExport an encrypted session backupPOST/api/backup/exportExport an encrypted backup of sessions and settingsPOST/api/backup/importRestore from an encrypted backupDELETE/api/sessions/{id}Terminate a session and purge its credentials
Filters & AI
GET/api/filtersList filter rulesPOST/api/filtersCreate a filter rulePUT/api/filters/{id}Update a filter ruleDELETE/api/filters/{id}Delete a filter ruleGET/api/ai-configsList AI rewrite configurationsPOST/api/ai-configsCreate an AI configuration (provider, model, prompts)PUT/api/ai-configs/{id}Update an AI configurationPOST/api/prompts/testSend sample text through a rewrite prompt
Observability
GET/api/logs?service=&level=&search=&limit=&since=Query attributable log history with bounded pagingGET/api/logs/statsAggregate counts by service and levelGET/api/logs/policyWhich levels and services the engine admitsPOST/api/logs/purgePurge log history for one of the caller's own tasks (the installation-wide purge is administrator-only)GET/api/statsDelivery throughput and outcome countersGET/api/queueQueue depth and in-flight jobsGET/api/dlqDead-lettered jobsPOST/api/dlq/{id}/retryReplay a dead-lettered jobDELETE/api/dlqPurge dead-lettered jobs for the caller scope (answers with the number removed)
Complete route table
All 102 registered routes, grouped by the mux that owns them and resolved through their mount prefixes. Host and scheme are yours; the paths are exact.
Service health & system · 12 routes
| Endpoint | Handler | Auth |
|---|---|---|
GET /api/health/services | h.ServicesHealth | Public |
GET /api/openapi.yaml | h.OpenAPIDoc | Public |
GET /api/system/env | h.EnvContractHandler | Public |
GET /api/system/setup | h.SetupReport | Public |
GET /api/v1/health/services | h.ServicesHealth | Public |
GET /api/v1/system/env | h.EnvContractHandler | Public |
GET /api/v1/system/setup | h.SetupReport | Public |
GET /api/version | h.Version | Public |
GET /health | h.Health | Public |
GET /healthz | h.Health | Public |
GET /ready | h.Ready | Public |
GET /readyz | h.Ready | Public |
Authentication · 7 routes
| Endpoint | Handler | Auth |
|---|---|---|
GET /api/auth/bot-login-link | h.AuthBotLoginLink | Public |
PATCH /api/auth/change-password | h.AuthChangePassword | Public |
POST /api/auth/exchange-bot-token | h.AuthBotExchange | Public |
POST /api/auth/login | h.AuthLogin | Public |
GET /api/auth/me | h.AuthMe | Public |
POST /api/auth/register | h.AuthRegister | Public |
POST /api/auth/tma | h.AuthTMA | Public |
Authenticated control plane · 71 routes
| Endpoint | Handler | Auth |
|---|---|---|
GET /api/ai-configs | h.ListAIConfigs | Bearer |
POST /api/ai-configs | h.CreateAIConfig | Bearer |
PUT /api/ai-configs/{id} | h.UpdateAIConfig | Bearer |
DELETE /api/ai-configs/{id} | h.DeleteAIConfig | Bearer |
POST /api/ai-configs/check-key | h.CheckProviderKey | Bearer |
GET /api/ai-configs/providers | h.ListAIProviders | Bearer |
GET /api/audit/events | h.QueryAuditEvents | Bearer |
POST /api/backup/export | h.BackupExport | Bearer |
POST /api/backup/import | h.BackupImport | Bearer |
GET /api/bot-tokens | h.ListBotTokens | Bearer |
POST /api/bot-tokens | h.CreateBotToken | Bearer |
DELETE /api/bot-tokens/{id} | h.DeleteBotToken | Bearer |
GET /api/bot-tokens/{id}/defaults | h.GetBotDefaults | Bearer |
PUT /api/bot-tokens/{id}/defaults | h.SetBotDefaults | Bearer |
POST /api/client/credentials | h.ClientSaveCredentials | Bearer |
GET /api/client/settings | h.ClientGetSettings | Bearer |
GET /api/diagnostics | h.Diagnostics | Bearer |
GET /api/dlq | h.ListDeadLetter | Bearer |
DELETE /api/dlq | h.PurgeDeadLetter | Bearer |
POST /api/dlq/{id}/retry | h.ReplayDeadLetter | Bearer |
GET /api/filters | h.ListFilters | Bearer |
POST /api/filters | h.CreateFilter | Bearer |
PUT /api/filters/{id} | h.UpdateFilter | Bearer |
DELETE /api/filters/{id} | h.DeleteFilter | Bearer |
GET /api/logs | h.QueryLogs | Bearer |
POST /api/logs/diagnostics/start | h.RequireAdmin(http.HandlerFunc(h.LogDiagnosticsStart)) | Public |
POST /api/logs/diagnostics/stop | h.RequireAdmin(http.HandlerFunc(h.LogDiagnosticsStop)) | Public |
GET /api/logs/export | h.ExportLogs | Bearer |
GET /api/logs/health | h.LoggingHealth | Bearer |
GET /api/logs/policy | h.LogPolicy | Bearer |
PUT /api/logs/policy | h.RequireAdmin(http.HandlerFunc(h.LogPolicyUpdate)) | Public |
POST /api/logs/purge | h.PurgeLogs | Bearer |
GET /api/logs/stats | h.LogStats | Bearer |
GET /api/prompts | h.ListPromptTemplates | Bearer |
POST /api/prompts | h.CreatePromptTemplate | Bearer |
PUT /api/prompts/{id} | h.UpdatePromptTemplate | Bearer |
DELETE /api/prompts/{id} | h.DeletePromptTemplate | Bearer |
POST /api/prompts/test | h.TestPrompt | Bearer |
GET /api/pv-responder | h.GetPVResponder | Bearer |
POST /api/pv-responder | h.SetPVResponder | Bearer |
PUT /api/pv-responder | h.SetPVResponder | Bearer |
GET /api/queue | h.DeliveryStats | Bearer |
GET /api/rules | h.ListRules | Bearer |
POST /api/rules | h.CreateRule | Bearer |
GET /api/rules/{id} | h.GetRule | Bearer |
PUT /api/rules/{id} | h.UpdateRule | Bearer |
PATCH /api/rules/{id} | h.UpdateRule | Bearer |
DELETE /api/rules/{id} | h.DeleteRule | Bearer |
POST /api/rules/{id}/duplicate | h.DuplicateRule | Bearer |
GET /api/rules/{id}/logs | h.RuleLogs | Bearer |
POST /api/rules/{id}/pause | h.PauseRule | Bearer |
POST /api/rules/{id}/restart | h.RestartRule | Bearer |
POST /api/rules/{id}/resume | h.ResumeRule | Bearer |
POST /api/rules/{id}/route-path | h.RoutePathQuickSet | Bearer |
GET /api/rules/{id}/settings | h.GetRuleSettings | Bearer |
PUT /api/rules/{id}/settings | h.UpdateRuleSettings | Bearer |
PATCH /api/rules/{id}/settings | h.UpdateRuleSettings | Bearer |
POST /api/rules/{id}/stop | h.StopRule | Bearer |
POST /api/rules/{id}/toggle | h.ToggleRule | Bearer |
GET /api/rules/settings/schema | h.GetRuleSettingsSchema | Bearer |
GET /api/sessions | h.ListSessions | Bearer |
DELETE /api/sessions/{id} | h.TerminateSession | Bearer |
POST /api/sessions/{id}/backup | h.BackupSession | Bearer |
GET /api/sessions/{sessionId}/chats | h.ListChats | Bearer |
POST /api/simulate | h.TestRule | Bearer |
GET /api/stats | h.GetStats | Bearer |
GET /api/tasks | h.ListTasks | Bearer |
POST /api/tasks | h.CreateTask | Bearer |
GET /api/tasks/{id} | h.GetTask | Bearer |
POST /api/tasks/{id}/cancel | h.CancelTask | Bearer |
POST /api/tasks/{id}/retry | h.RetryTask | Bearer |
Administration · 12 routes
| Endpoint | Handler | Auth |
|---|---|---|
GET /api/admin/admins | h.AdminListAdmins | Public |
POST /api/admin/admins | h.AdminAddAdmin | Public |
DELETE /api/admin/admins/{id} | h.AdminRemoveAdmin | Public |
POST /api/admin/broadcast | h.AdminBroadcast | Public |
GET /api/admin/extensions | h.AdminListExtensions | Public |
POST /api/admin/extensions/{id}/toggle | h.AdminToggleExtension | Public |
GET /api/admin/overview | h.AdminOverview | Public |
GET /api/admin/ratelimit | h.RateLimitStatus | Public |
GET /api/admin/settings | h.AdminGetSettings | Public |
POST /api/admin/settings | h.AdminSaveSettings | Public |
GET /api/admin/users | h.AdminListUsers | Public |
POST /api/admin/users/{id}/status | h.AdminSetUserStatus | Public |
Delivery lifecycle
Every delivery moves through these states, and the same vocabulary is used by the queue API, the log history and the dashboard. Jobs in RETRY_WAIT are the ones a pause defers rather than fails.
- RECEIVED
- VALIDATING
- AUTHORIZED
- ACCEPTED
- IN_PROGRESS
- RETRY_WAIT
- SUCCEEDED
- FAILED
- CANCELLED
- OUTCOME_UNCONFIRMED
Errors & status codes
| Code | When | What to do |
|---|---|---|
200 | Success. | Read the JSON body. |
400 | The body or query is malformed. | Check the settings schema and the environment contract. |
401 | Missing, expired or unverifiable token. | Log in again, or run atf auth whoami. |
403 | Administration route called without admin rights. | Use an administrator account. |
404 | The resource does not exist — or does not belong to you. | Ownership failures deliberately look identical to missing rows. |
409 | A concurrent update moved the version first. | Re-read the task, re-apply your change. |
422 | A setting was rejected by validation. | Read the field error in the response body. |
502 | The logger or core service is unreachable. | Check /api/health/services and atf doctor. |