Helios

API reference

The live OpenAPI spec is served at `/openapi.json` and a Swagger UI lives

The live OpenAPI spec is served at /openapi.json and a Swagger UI lives at /docs on every running API instance. This page is the human map above that.

Auth

Two layers, evaluated in order:

  1. Telegram initData in X-Telegram-Init-Data. HMAC-verified against the bot token; the tg_user_id from the payload becomes the identity. Required on every non-public route.
  2. TOTP in X-TOTP-Code. Only when OWNER_TOTP_ENABLED=true and the route is /v1/owner/*. See TOTP enrolment.

Public routes (no auth): /healthz, /metrics, /openapi.json, /docs, /.well-known/*.

Routes

GroupRoutesAuth
IdentityGET /v1/meinitData
TargetsGET /v1/targets · POST /v1/targets · DELETE /v1/targets/{id}initData
Target settingsPOST /v1/targets/{id}/mute · GET/PATCH /v1/targets/{id}/settings/{key}initData
AnalyticsGET /v1/targets/{id}/analytics · /heatmap · /dailyinitData
SettingsGET /v1/settings/parameters/visibleinitData
Owner — paramsGET /v1/owner/parameters · PATCH .../{key}/overrideinitData + TOTP
Owner — auditGET /v1/owner/auditinitData + TOTP
Owner — userbotsGET /v1/owner/userbots/ · POST .../importinitData + TOTP
Owner — personasGET /v1/owner/personas/ · POST .../try-pickinitData + TOTP
Owner — GDPRPOST /v1/owner/gdpr/export · POST .../eraseinitData + TOTP

Rate limits

Token-bucket via Redis, evaluated per request. Two buckets:

  • Per source IP — default 60 capacity, 1/s refill.
  • Per verified Telegram identity — default 240 capacity, 4/s refill. Activated only when initData is valid.

429 responses carry a Retry-After header. Public paths skip the limiter entirely so health probes don't get throttled.

Defaults are parameters; tune via the admin panel without a deploy:

  • api.rate_limit.ip.capacity / .refill_per_sec
  • api.rate_limit.identity.capacity / .refill_per_sec

Security headers

Every response carries:

  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY
  • Referrer-Policy: strict-origin-when-cross-origin
  • Cross-Origin-Opener-Policy: same-origin-allow-popups
  • Cross-Origin-Resource-Policy: same-site
  • Strict-Transport-Security, Content-Security-Policy, Permissions-Policy — sourced from parameters (api.security.{csp,hsts,permissions_policy}), with OWASP-style defaults.

Errors

Standard {"detail": "human-readable reason"} payloads with the right HTTP status:

StatusMeaning
400malformed body / invalid parameter value
401missing or invalid X-Telegram-Init-Data
403authenticated but unauthorised (non-owner, wrong TOTP, …)
404resource not visible to this client (often RLS-hidden)
409conflict (duplicate persona, duplicate session, …)
415unsupported session format on userbot import
422value failed validators (cadence below floor, etc.)
429rate limit exceeded — honour Retry-After

Versioning

/v1 is the only versioned prefix today. Additions (new routes, new fields) are non-breaking; renames or removals require a /v2 carve-out that runs alongside /v1 for the deprecation window. None of those are planned yet.

On this page