Documentation menu

Endpoints

Endpoint reference

Every one of the 102 routes the control plane registers: verb, path, auth level, the fields each one accepts and a real response body.

Verified against the checkout built for v2.2.4 · updated 20 Oct 2026

On this page

The table on this page is not typed by hand. api/main.go is parsed at build time, including the routes registered through middleware, so the list is exactly what the binary under test registers — 102 routes across 4 groups. Each one carries what it accepts and what it answers.

68 need a token15 need an administrator19 are public probesGET 47POST 36PUT 8PATCH 3DELETE 8

How to read a route

The four facts every route card states
RowWhat it tells youWhy it matters
GET verb chipThe HTTP verb, colour-coded consistently across this site.A PATCH is a partial update; a PUT replaces the whole resource.
/api/rules/{id}The exact path, resolved through every mount prefix.These paths are registered on a standard-library mux, so {id} matches one path segment.
Bearer / Admin / PublicThe credential the route requires.Public routes are probes and login exchanges. Admin routes are gated on the route and re-checked in the core.
ScopeWhat the query is filtered by server-side.A tenant route can only ever read rows whose owner is the identity the token proves.
StatusesThe statuses this route can actually answer with.Read the response reference for the body shape behind each code.

Filter by verb

The verb chips under the search box are toggles: press POST and PUT to see only the routes that change something.

Filter by anything else

The search box matches the path, the handler name, the summary and every accepted field — searchidempotency and only the routes that take one remain.

No JavaScript?

Every card is rendered on the server. Filtering is an enhancement, so the full table is present and linkable with scripting disabled.

What each group is scoped to

Service health & system

12 routes

The unauthenticated surface an operator, a load balancer or the upgrade gate calls: liveness, readiness, the version block, the environment contract and the live probe of every service in the chain. These routes answer without a token because they must be callable precisely when authentication is the thing that is broken.

Scope · public probe

Authentication

7 routes

Public by definition — this is where a caller stops being anonymous. Three ways in: username and password, a single-use code the bot hands to an already-verified Telegram user, or signed Mini App init data. Every route here is inside the authentication rate class, so the brute-force budget is enforced before a token is ever minted.

Scope · public, rate-limited

Authenticated control plane

71 routes

The tenant surface. Each call resolves the caller from the verified token and then queries only that identity’s rows; an owner id in the body is never read. A row that belongs to somebody else is reported as missing, so ids cannot be probed.

Scope · tenant-scoped

Administration

12 routes

Installation-wide operations. The route is wrapped in the administrator gate, and the core re-checks the role on the other side of gRPC, so a forged or stale admin claim fails twice.

Scope · administrator only

All 102 routes

Grouped by the mux that owns them, in registration order, with the mount prefixes already applied. Statuses are the ones each handler can return; the shared envelope is described in the response reference.

Showing all 102 registered routes across 4 groups.

Service health & system

12 routes · public probe

The unauthenticated surface an operator, a load balancer or the upgrade gate calls: liveness, readiness, the version block, the environment contract and the live probe of every service in the chain. These routes answer without a token because they must be callable precisely when authentication is the thing that is broken.

GET

/api/health/services

Publich.ServicesHealth

Live reachability of every service in the chain — core (gRPC channel plus pipeline loop), logger, web and this process — probed in parallel with short timeouts.

Auth
No credential — public probe or login exchange
Scope
No identity and no tenant data — deployment-level facts only.
Statuses
200
Note
The overall status is "healthy" only when every probe answers; a single failure degrades the whole stack to "degraded" with a per-service detail.
GET /api/health/services — response
{
  "status": "healthy",
  "time": "2026-10-19T00:00:00Z",
  "services": [
    { "name": "core", "online": true, "detail": "gRPC + pipeline loop", "latency_ms": 4 },
    { "name": "logger", "online": true, "detail": "log store answers", "latency_ms": 2 }
  ]
}
GET

/api/openapi.yaml

Publich.OpenAPIDoc

The control plane’s own OpenAPI 3.1 document. It ships inside the image next to the code that serves it, so the published contract cannot drift from the binary.

Auth
No credential — public probe or login exchange
Scope
No identity and no tenant data — deployment-level facts only.
Statuses
200
Note
This route is public on purpose: the schema is not tenant data, and a client needs it before it has a token.

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/system/env

Publich.EnvContractHandler

The environment contract: every recognised key with whether it is set and whether it is required, plus the hints that turn a missing key into an actionable next step. Values are never returned.

Auth
No credential — public probe or login exchange
Scope
No identity and no tenant data — deployment-level facts only.
Statuses
200
Note
A secret is reported as set:true or set:false. The value itself has no route, by design.
GET /api/system/env — response
{
  "checks": [
    { "key": "ATF_BOT_TOKEN", "set": true, "required": true, "hint": "Create the bot with @BotFather" }
  ],
  "missing_required": [],
  "missing_recommended": ["ATF_REDIS_PASSWORD"],
  "deployment": "docker-compose",
  "ok": true
}
GET

/api/system/setup

Publich.SetupReport

One answer to “is this deployment usable?”: the version block, the environment contract, a live probe of all four services, the rate-limiter summary and the next command to run.

Auth
No credential — public probe or login exchange
Scope
No identity and no tenant data — deployment-level facts only.
Statuses
200
Note
Add ?probe=0 to skip the live probes and get the same verdict from configuration alone — the form the web dashboard uses when a probe would be too slow.
GET /api/system/setup — response
{
  "ready": true,
  "ratelimit": { "mode": "redis", "enforcing": true },
  "product_version": "2.2.4",
  "api_version": "1.0.0",
  "deployment": "docker-compose",
  "checks": [{ "key": "ATF_BOT_TOKEN", "set": true, "required": true }],
  "missing_required": [],
  "missing_recommended": [],
  "services": [{ "name": "core", "online": true, "latency_ms": 4, "detail": "gRPC + pipeline" }],
  "next_steps": ["atf validate --runtime — full health re-check of the live stack"]
}
GET

/api/v1/health/services

Publich.ServicesHealth

Versioned alias of /api/health/services.

Auth
No credential — public probe or login exchange
Scope
No identity and no tenant data — deployment-level facts only.
Statuses
200

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/v1/system/env

Publich.EnvContractHandler

Versioned alias of /api/system/env.

Auth
No credential — public probe or login exchange
Scope
No identity and no tenant data — deployment-level facts only.
Statuses
200

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/v1/system/setup

Publich.SetupReport

Versioned alias of /api/system/setup — same body, same booleans-only rule.

Auth
No credential — public probe or login exchange
Scope
No identity and no tenant data — deployment-level facts only.
Statuses
200

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/version

Publich.Version

The client-negotiation block: product version, API contract version, the oldest client still supported, the commit that built the binary, and the capability keys a client may probe before using a feature.

Auth
No credential — public probe or login exchange
Scope
No identity and no tenant data — deployment-level facts only.
Statuses
200
GET /api/version — response
{
  "product_version": "2.2.4",
  "api_version": "1.0.0",
  "min_supported_client": "1.0.0",
  "commit_sha": "07f3613",
  "features": ["rules", "filters", "ai_configs", "sessions", "logs", "dlq", "backup", "system_setup", "env_contract"]
}
GET

/health

Publich.Health

Alias of /healthz, kept for gateways that were configured against it.

Auth
No credential — public probe or login exchange
Scope
No identity and no tenant data — deployment-level facts only.
Statuses
200

Request and response bodies follow the shared envelope — see the response reference below.

GET

/healthz

Publich.Health

Liveness. Answers 200 as soon as the process can serve, with nothing checked downstream.

Auth
No credential — public probe or login exchange
Scope
No identity and no tenant data — deployment-level facts only.
Statuses
200
Note
Liveness must not depend on a dependency: a core outage is not a reason to restart a healthy API process.
GET /healthz — response
{
  "status": "ok",
  "time": "2026-10-19T00:00:00Z"
}
GET

/ready

Publich.Ready

Alias of /readyz.

Auth
No credential — public probe or login exchange
Scope
No identity and no tenant data — deployment-level facts only.
Statuses
200 · 503

Request and response bodies follow the shared envelope — see the response reference below.

GET

/readyz

Publich.Ready

Readiness, and a strictly stronger signal than liveness: it pings the rate-limiter store and answers 503 when a wired limiter cannot enforce the budget it promised.

Auth
No credential — public probe or login exchange
Scope
No identity and no tenant data — deployment-level facts only.
Statuses
200 · 503
Note
A deployment with the limiter disabled is ready — the in-process fallback is then the whole limit. Only a wired limiter that cannot reach its store makes this 503.
GET /readyz — response
{
  "status": "ready",
  "ready": true,
  "time": "2026-10-19T00:00:00Z",
  "checks": [
    { "name": "ratelimit", "ready": true, "detail": "redis" }
  ]
}

Authentication

7 routes · public, rate-limited

Public by definition — this is where a caller stops being anonymous. Three ways in: username and password, a single-use code the bot hands to an already-verified Telegram user, or signed Mini App init data. Every route here is inside the authentication rate class, so the brute-force budget is enforced before a token is ever minted.

GET

/api/auth/bot-login-link

Publich.AuthBotLoginLink

Mints the caller’s own single-use dashboard login code and returns the relative link to open. Requires a valid Bearer token — the code is minted for the identity the token proves, never for an id in the request.

Auth
No credential — public probe or login exchange
Scope
Anonymous caller; the response is what establishes identity.
Statuses
200 · 401 · 429
Note
A 60-second per-user cooldown applies: while a code is live and unused the endpoint answers 429 with Retry-After instead of minting another, so a double click cannot invalidate the link that was just handed out. Codes die after 10 minutes or one use.
GET /api/auth/bot-login-link — response
{
  "code": "…",
  "expires_at": 1790000000,
  "link": "/dashboard/login?code=…"
}
PATCH

/api/auth/change-password

Publich.AuthChangePassword

Changes the caller’s own password; the old password is required and verified before the new one is hashed.

Auth
No credential — public probe or login exchange
Scope
Anonymous caller; the response is what establishes identity.
Statuses
200 · 400 · 401
FieldTypeRequiredMeaning
old_passwordstringYesVerified before any change is stored.
new_passwordstringYesRejected when weak.

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/auth/exchange-bot-token

Publich.AuthBotExchange

Exchanges a single-use login code — minted by the bot for the Telegram user it already authenticated — for the same 7-day JWT.

Auth
No credential — public probe or login exchange
Scope
Anonymous caller; the response is what establishes identity.
Statuses
200 · 400 · 401 · 429
Note
It deliberately does not accept a user id. A Telegram id is public, so minting a session for one would let any caller sign in as any account; sending user_id is accepted only so the field can be rejected.
FieldTypeRequiredMeaning
login_codestringYesSingle-use, 10-minute code from the bot’s dashboard link.
POST /api/auth/exchange-bot-token — response
{
  "success": true,
  "token": "<jwt>",
  "expires_at": 1790000000
}
POST

/api/auth/login

Publich.AuthLogin

Username and password → a 7-day HS256 JWT, its expiry and the account record.

Auth
No credential — public probe or login exchange
Scope
Anonymous caller; the response is what establishes identity.
Statuses
200 · 400 · 401 · 429
Note
A wrong password and an unknown username return the same refusal, so the endpoint is not an account oracle.
FieldTypeRequiredMeaning
usernamestringYesAccount username.
passwordstringYesAccount password.
telegram_user_idint64OptionalOptional link proof when the call is issued from the bot.
POST /api/auth/login — response
{
  "success": true,
  "token": "<jwt>",
  "expires_at": 1790000000,
  "account": { "user_id": 5094837833, "username": "operator", "is_admin": false }
}
Request body
{
  "username": "operator",
  "password": "…"
}
GET

/api/auth/me

Publich.AuthMe

The identity behind the presented token: user id, username and whether it carries the administrator flag.

Auth
No credential — public probe or login exchange
Scope
Anonymous caller; the response is what establishes identity.
Statuses
200 · 401
GET /api/auth/me — response
{
  "user_id": 5094837833,
  "username": "operator",
  "is_admin": false
}
POST

/api/auth/register

Publich.AuthRegister

Creates a web account and returns the account record. The first account on a fresh install is the administrator.

Auth
No credential — public probe or login exchange
Scope
Anonymous caller; the response is what establishes identity.
Statuses
201 · 400 · 409 · 429
FieldTypeRequiredMeaning
usernamestringYesUnique login name.
passwordstringYesRejected when weak (WEAK_PASSWORD).
telegram_user_idint64OptionalLinks the account to a Telegram identity at creation.

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/auth/tma

Publich.AuthTMA

Verifies the HMAC-SHA256 signature of a Telegram Mini App initData payload against the bot token, then issues the same JWT for the verified numeric user id.

Auth
No credential — public probe or login exchange
Scope
Anonymous caller; the response is what establishes identity.
Statuses
200 · 400 · 401 · 429
FieldTypeRequiredMeaning
init_datastringYesThe raw window.Telegram.WebApp.initData string.

Request and response bodies follow the shared envelope — see the response reference below.

Authenticated control plane

71 routes · tenant-scoped

The tenant surface. Each call resolves the caller from the verified token and then queries only that identity’s rows; an owner id in the body is never read. A row that belongs to somebody else is reported as missing, so ids cannot be probed.

GET

/api/ai-configs

Bearerh.ListAIConfigs

The caller’s AI providers. The API key is write-only: it is returned masked or omitted, never in clear text.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/ai-configs

Bearerh.CreateAIConfig

Stores a provider configuration. The base URL is validated by the endpoint guard before it is accepted.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
201 · 400 · 401

Request and response bodies follow the shared envelope — see the response reference below.

PUT

/api/ai-configs/{id}

Bearerh.UpdateAIConfig

Updates a provider configuration; sending a new key replaces the stored one.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

DELETE

/api/ai-configs/{id}

Bearerh.DeleteAIConfig

Deletes a provider configuration and its stored key.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/ai-configs/check-key

Bearerh.CheckProviderKey

Health-probes a provider with the key that was typed, before it is stored, and reports whether the model actually answered.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401
Note
The endpoint guard refuses loopback, link-local and metadata addresses unless the operator has explicitly allowed private AI peers.

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/ai-configs/providers

Bearerh.ListAIProviders

The provider catalogue: known endpoints, default models and which fields each one needs.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/audit/events

Bearerh.QueryAuditEvents

Tenant-scoped audit events: who changed what, when, and under which correlation id.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/backup/export

Bearerh.BackupExport

Starts a whole-installation export as a durable async task (kind backup.export).

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
201 · 202 · 400 · 401

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/backup/import

Bearerh.BackupImport

Imports a backup bundle into the caller’s tenant; encrypted bundles are decrypted with the operator key.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 422

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/bot-tokens

Bearerh.ListBotTokens

The bots this tenant has registered, each with the tasks that inherit from it.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/bot-tokens

Bearerh.CreateBotToken

Registers a bot token. The token is validated with Telegram before it is stored.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
201 · 400 · 401

Request and response bodies follow the shared envelope — see the response reference below.

DELETE

/api/bot-tokens/{id}

Bearerh.DeleteBotToken

Removes a bot registration; tasks attached to it must be re-pointed.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/bot-tokens/{id}/defaults

Bearerh.GetBotDefaults

The defaults every task attached to this bot inherits, with where each value comes from.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

PUT

/api/bot-tokens/{id}/defaults

Bearerh.SetBotDefaults

Sets the inherited defaults for every task attached to this bot.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/client/credentials

Bearerh.ClientSaveCredentials

Stores the caller’s personal client credentials. Write-only: they are never read back.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/client/settings

Bearerh.ClientGetSettings

The caller’s client-side preferences (theme, language, notification choices).

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/diagnostics

Bearerh.Diagnostics

Preflight findings for the caller’s own rules, sessions and AI configs — the problems that would make a task fail, reported before it runs.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/dlq

Bearerh.ListDeadLetter

The caller’s dead-letter entries with their failure reason and original target.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

DELETE

/api/dlq

Bearerh.PurgeDeadLetter

Purges the caller’s dead-letter queue. Ownership is applied before the delete, not after.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/dlq/{id}/retry

Bearerh.ReplayDeadLetter

Replays one dead-lettered delivery. A refused replay still returns its reason on the wire instead of an empty body.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/filters

Bearerh.ListFilters

Lists the caller’s saved keyword filters (blacklist, whitelist, link and media gates).

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/filters

Bearerh.CreateFilter

Creates a reusable filter that tasks can reference instead of repeating keyword lists.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
201 · 400 · 401

Request and response bodies follow the shared envelope — see the response reference below.

PUT

/api/filters/{id}

Bearerh.UpdateFilter

Replaces a filter definition.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

DELETE

/api/filters/{id}

Bearerh.DeleteFilter

Deletes a filter; tasks that referenced it keep their own inline rules.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/logs

Bearerh.QueryLogs

Bounded, filterable query over the caller’s log history (level, task, time window, limit).

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401
Note
Reads page with limit/since rather than returning unbounded history; the collection policy decides which levels are stored at all.

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/logs/diagnostics/start

Adminh.RequireAdmin(http.HandlerFunc(h.LogDiagnosticsStart))

Starts a bounded diagnostic capture for support. Administrator-only.

Auth
Bearer identity that also carries the administrator flag — gated twice, on the route and in the core
Scope
Installation-wide. Administrator flag required on the route and re-verified by the core.
Statuses
200 · 401 · 403

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/logs/diagnostics/stop

Adminh.RequireAdmin(http.HandlerFunc(h.LogDiagnosticsStop))

Stops the diagnostic capture and returns what it collected. Administrator-only.

Auth
Bearer identity that also carries the administrator flag — gated twice, on the route and in the core
Scope
Installation-wide. Administrator flag required on the route and re-verified by the core.
Statuses
200 · 401 · 403

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/logs/export

Bearerh.ExportLogs

A downloadable copy of the filtered history as JSON or CSV, so evidence can leave the box without screen-scraping.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/logs/health

Bearerh.LoggingHealth

Whether the logger answers, and whether the policy in force matches the one configured.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/logs/policy

Bearerh.LogPolicy

The collection policy this process is actually applying: levels, retention and sampling.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

PUT

/api/logs/policy

Adminh.RequireAdmin(http.HandlerFunc(h.LogPolicyUpdate))

Changes what the core collects, through the process that enforces it. Administrator-only and audited, because this is the one control that decides what the evidence trail keeps.

Auth
Bearer identity that also carries the administrator flag — gated twice, on the route and in the core
Scope
Installation-wide. Administrator flag required on the route and re-verified by the core.
Statuses
200 · 400 · 401 · 403

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/logs/purge

Bearerh.PurgeLogs

Deletes the caller’s stored log history inside the requested window. A tenant must name one of their own tasks: the archive is one shared store with no tenant column on this path, so the installation-wide purge is administrator-only and answers 403 otherwise.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 403 · 404

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/logs/stats

Bearerh.LogStats

Counts per level and per task over a window — the numbers behind the log explorer.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/prompts

Bearerh.ListPromptTemplates

The caller’s AI rewrite prompt templates.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/prompts

Bearerh.CreatePromptTemplate

Creates a prompt template; new versions are stored rather than overwriting history.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
201 · 400 · 401

Request and response bodies follow the shared envelope — see the response reference below.

PUT

/api/prompts/{id}

Bearerh.UpdatePromptTemplate

Replaces a prompt template’s body and name.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

DELETE

/api/prompts/{id}

Bearerh.DeletePromptTemplate

Deletes a prompt template. Tasks that referenced it fall back to the default prompt.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/prompts/test

Bearerh.TestPrompt

Runs a prompt against sample text through the tenant’s AI provider and returns the model output.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 502

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/pv-responder

Bearerh.GetPVResponder

The private-chat auto-responder configuration: persona, typing delay, cooldown, history depth.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/pv-responder

Bearerh.SetPVResponder

Creates or replaces the auto-responder configuration.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

PUT

/api/pv-responder

Bearerh.SetPVResponder

Same write path as POST, kept for clients that PUT.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/queue

Bearerh.DeliveryStats

Queue depth and worker state. A healthy queue reports zeroes; it never reports a backlog it does not have.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/rules

Bearerh.ListRules

Lists the caller’s forwarding tasks, newest first, including their lists of sources and targets.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/rules

Bearerh.CreateRule

Creates a forwarding task. The first source and the first target are mirrored into the legacy scalar columns by one write path.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
201 · 400 · 401 · 422
FieldTypeRequiredMeaning
namestringYesHuman label shown in every client.
source_chat_idsstring[]OptionalM sources; the first entry becomes the primary source.
target_chat_idsstring[]OptionalN targets; the first entry becomes the primary target.
modestringOptionalcopy or forward — the delivery mode applied to every target.
settingsobjectOptionalPer-task cleaner, filters, header/footer, AI and schedule settings.
Request body
{
  "name": "Desk feed → VIP + free tier",
  "source_chat_ids": ["@desk_feed", "-1001695513745"],
  "target_chat_ids": ["-1002000000001", "-1002000000002"],
  "mode": "copy",
  "settings": { "clean_links": true, "header_template": "📰 [[ORIGIN_NAME]]" }
}
GET

/api/rules/{id}

Bearerh.GetRule

One task, ownership-checked before the read.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

PUT

/api/rules/{id}

Bearerh.UpdateRule

Full update of a task. A stale version is refused rather than silently overwriting a concurrent edit.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404 · 409 · 422

Request and response bodies follow the shared envelope — see the response reference below.

PATCH

/api/rules/{id}

Bearerh.UpdateRule

Partial update: the body carries only what changes and update_mask names it — the only way to set a value to false, zero or empty.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404 · 409 · 422

Request and response bodies follow the shared envelope — see the response reference below.

DELETE

/api/rules/{id}

Bearerh.DeleteRule

Deletes a task and its policy. The delivery history stays queryable by the caller.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/rules/{id}/duplicate

Bearerh.DuplicateRule

Clones a task — same policy, same lists — as a new row owned by the caller.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
201 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/rules/{id}/logs

Bearerh.RuleLogs

One task’s complete delivery history, ownership-checked before the read.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/rules/{id}/pause

Bearerh.PauseRule

Pauses delivery for one task; in-flight jobs are deferred rather than failed.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/rules/{id}/restart

Bearerh.RestartRule

Restarts the poller after a stop, re-reading the task’s current settings.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/rules/{id}/resume

Bearerh.ResumeRule

Resumes a paused task and drains what was deferred.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/rules/{id}/route-path

Bearerh.RoutePathQuickSet

Sets the source→target path in one call, keeping the legacy mirror consistent.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/rules/{id}/settings

Bearerh.GetRuleSettings

Stored settings, the schema that describes them, and the effective values with the provenance of each one.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401 · 404
Note
Effective values are what the forwarder will actually use, so a client that echoes its own settings back cannot pin a value the task merely inherits from its bot.
GET /api/rules/{id}/settings — response
{
  "success": true,
  "settings": { "clean_links": true },
  "schema": { "type": "object" },
  "effective": { "clean_links": { "value": true, "source": "rule" } }
}
PUT

/api/rules/{id}/settings

Bearerh.UpdateRuleSettings

Replaces the task’s stored settings after schema validation.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

PATCH

/api/rules/{id}/settings

Bearerh.UpdateRuleSettings

Applies only the named settings; everything else keeps its current value.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/rules/{id}/stop

Bearerh.StopRule

Stops the task’s poller. Unlike pause, nothing is queued for later.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/rules/{id}/toggle

Bearerh.ToggleRule

Flips enabled state without touching any other field.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/rules/settings/schema

Bearerh.GetRuleSettingsSchema

The JSON schema of the per-task settings surface. It needs no task, so an editor can be built before the user owns anything.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/sessions

Bearerh.ListSessions

Lists the caller’s Telegram sessions with their account, status and last-seen time.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

DELETE

/api/sessions/{id}

Bearerh.TerminateSession

Terminates a session and drops its live client. The stored session file is removed.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/sessions/{id}/backup

Bearerh.BackupSession

Starts a session backup as a durable async task (kind session.backup) and returns the task row.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/sessions/{sessionId}/chats

Bearerh.ListChats

The chat list for the source and target pickers, scoped entirely from the token identity.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401 · 404 · 503
Note
A session that exists but has no live Telegram client answers 503 session_not_connected — a different fact from a session that is not yours, which is a 404.

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/simulate

Bearerh.TestRule

Dry-runs a task against a sample message and returns the text that would be delivered — the cleaner, filters, replacements, header and footer applied in the real order.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404
FieldTypeRequiredMeaning
rule_idstringYesThe task whose policy is applied.
textstringYesSample message body.

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/stats

Bearerh.GetStats

Aggregate counters for the caller’s tasks: delivered, failed, queued and dead-lettered.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/tasks

Bearerh.ListTasks

Lists the caller’s durable async jobs, filterable by status and kind, with a bounded page (limit 1–200, default 50).

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401
FieldTypeRequiredMeaning
statusstringOptionalPENDING · RUNNING · RETRY_WAIT · SUCCEEDED · FAILED · CANCELLED
kindstringOptionalsession.backup · dlq.replay · dlq.purge · backup.export
limitintOptional1–200, default 50.
offsetintOptionalDefault 0.
GET /api/tasks — response
{
  "tasks": [
    {
      "id": "6f1c…",
      "owner_user_id": 5094837833,
      "kind": "dlq.replay",
      "status": "RUNNING",
      "attempt": 1,
      "max_attempts": 3,
      "created_at": 1790000000
    }
  ],
  "total": 1,
  "limit": 50,
  "offset": 0
}
POST

/api/tasks

Bearerh.CreateTask

Registers a durable, tenant-owned job. Resubmitting the same (owner, kind, idempotency_key) returns the original task with already_existed:true instead of a duplicate.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
201 · 200 · 400 · 401
Note
The owner is taken from the verified token, never from the body. Payload and result are each capped at 64 KiB and must be JSON; max_attempts is clamped to 8.
FieldTypeRequiredMeaning
kindstringYesOne of session.backup, dlq.replay, dlq.purge, backup.export.
payloadobjectOptionalJSON object; ≤ 64 KiB; stored canonically.
idempotency_keystringOptionalClient-chosen; makes retries safe.
max_attemptsintOptionalDefault 3, clamped to 8.
POST /api/tasks — response
{
  "task": {
    "id": "6f1c…",
    "owner_user_id": 5094837833,
    "kind": "dlq.replay",
    "status": "PENDING",
    "idempotency_key": "replay-2026-10-19",
    "attempt": 0,
    "max_attempts": 3
  },
  "already_existed": false,
  "id": "6f1c…",
  "status": "PENDING"
}
Request body
{
  "kind": "dlq.replay",
  "payload": { "ids": ["a1"] },
  "idempotency_key": "replay-2026-10-19",
  "max_attempts": 3
}
GET

/api/tasks/{id}

Bearerh.GetTask

One job. A job that belongs to another tenant is reported as missing, exactly like a job that does not exist.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/tasks/{id}/cancel

Bearerh.CancelTask

Requests cancellation. A terminal job refuses with not_cancellable; a running one with running_not_cancellable.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/tasks/{id}/retry

Bearerh.RetryTask

Re-queues a FAILED job with a fresh attempt budget. Any other state refuses with not_retryable.

Auth
Verified identity — Bearer JWT (or TMA exchange), scoped server-side
Scope
The verified user id is the only tenant key; a caller-supplied owner id is ignored.
Statuses
200 · 400 · 401 · 404

Request and response bodies follow the shared envelope — see the response reference below.

Administration

12 routes · administrator only

Installation-wide operations. The route is wrapped in the administrator gate, and the core re-checks the role on the other side of gRPC, so a forged or stale admin claim fails twice.

GET

/api/admin/admins

Adminh.AdminListAdmins

The administrator roster.

Auth
Bearer identity that also carries the administrator flag — gated twice, on the route and in the core
Scope
Installation-wide. Administrator flag required on the route and re-verified by the core.
Statuses
200 · 401 · 403

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/admin/admins

Adminh.AdminAddAdmin

Grants the administrator flag to an existing account.

Auth
Bearer identity that also carries the administrator flag — gated twice, on the route and in the core
Scope
Installation-wide. Administrator flag required on the route and re-verified by the core.
Statuses
200 · 201 · 400 · 401 · 403

Request and response bodies follow the shared envelope — see the response reference below.

DELETE

/api/admin/admins/{id}

Adminh.AdminRemoveAdmin

Revokes the administrator flag. The last remaining administrator cannot be removed.

Auth
Bearer identity that also carries the administrator flag — gated twice, on the route and in the core
Scope
Installation-wide. Administrator flag required on the route and re-verified by the core.
Statuses
200 · 400 · 401 · 403 · 404

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/admin/broadcast

Adminh.AdminBroadcast

Sends an operator announcement to every linked user through the bot.

Auth
Bearer identity that also carries the administrator flag — gated twice, on the route and in the core
Scope
Installation-wide. Administrator flag required on the route and re-verified by the core.
Statuses
200 · 400 · 401 · 403

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/admin/extensions

Adminh.AdminListExtensions

Installed extensions and whether each one is enabled.

Auth
Bearer identity that also carries the administrator flag — gated twice, on the route and in the core
Scope
Installation-wide. Administrator flag required on the route and re-verified by the core.
Statuses
200 · 401 · 403

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/admin/extensions/{id}/toggle

Adminh.AdminToggleExtension

Enables or disables one extension.

Auth
Bearer identity that also carries the administrator flag — gated twice, on the route and in the core
Scope
Installation-wide. Administrator flag required on the route and re-verified by the core.
Statuses
200 · 401 · 403 · 404

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/admin/overview

Adminh.AdminOverview

Installation totals: accounts, tasks, deliveries, queue depth and service health in one response.

Auth
Bearer identity that also carries the administrator flag — gated twice, on the route and in the core
Scope
Installation-wide. Administrator flag required on the route and re-verified by the core.
Statuses
200 · 401 · 403

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/admin/ratelimit

Adminh.RateLimitStatus

The limiter’s own control surface: effective class policies, whether the store is reachable, and whether requests are currently served by the in-process fallback.

Auth
Bearer identity that also carries the administrator flag — gated twice, on the route and in the core
Scope
Installation-wide. Administrator flag required on the route and re-verified by the core.
Statuses
200 · 401 · 403
GET /api/admin/ratelimit — response
{
  "enabled": true,
  "backend": "redis",
  "degraded": false,
  "classes": {
    "auth":  { "limit": 30,  "window_seconds": 60, "burst": 10, "scope": "ip",  "fail": "closed" },
    "read":  { "limit": 600, "window_seconds": 60, "burst": 120, "scope": "u",  "fail": "local" },
    "write": { "limit": 120, "window_seconds": 60, "burst": 30, "scope": "u",   "fail": "local" },
    "admin": { "limit": 300, "window_seconds": 60, "burst": 60, "scope": "u",   "fail": "local" }
  }
}
GET

/api/admin/settings

Adminh.AdminGetSettings

Installation settings currently in force.

Auth
Bearer identity that also carries the administrator flag — gated twice, on the route and in the core
Scope
Installation-wide. Administrator flag required on the route and re-verified by the core.
Statuses
200 · 401 · 403

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/admin/settings

Adminh.AdminSaveSettings

Saves installation settings; secret values are write-only and never echoed.

Auth
Bearer identity that also carries the administrator flag — gated twice, on the route and in the core
Scope
Installation-wide. Administrator flag required on the route and re-verified by the core.
Statuses
200 · 400 · 401 · 403

Request and response bodies follow the shared envelope — see the response reference below.

GET

/api/admin/users

Adminh.AdminListUsers

Paginated account list with status and link state.

Auth
Bearer identity that also carries the administrator flag — gated twice, on the route and in the core
Scope
Installation-wide. Administrator flag required on the route and re-verified by the core.
Statuses
200 · 401 · 403

Request and response bodies follow the shared envelope — see the response reference below.

POST

/api/admin/users/{id}/status

Adminh.AdminSetUserStatus

Enables or disables one account. A disabled account’s tokens stop resolving on the next request.

Auth
Bearer identity that also carries the administrator flag — gated twice, on the route and in the core
Scope
Installation-wide. Administrator flag required on the route and re-verified by the core.
Statuses
200 · 400 · 401 · 403 · 404

Request and response bodies follow the shared envelope — see the response reference below.

Versioning and aliases

  • Two contract versions are exposed on purpose. The product version (2.2.4) moves with releases; the API contract version stays at 1.0.0 until a breaking change lands.
  • Probes answer on both shapes. Health and system routes exist under/api/… and /api/v1/…; the versioned form is what the mobile client pins.
  • Clients negotiate before they call. Read /api/version and check min_supported_client plus the features keys instead of probing endpoints for their presence.
  • The shipped schema is authoritative. The API serves its own OpenAPI document at /api/openapi.yaml, baked into the image next to the code that serves it.