Lower the username floor to 3 characters on the admin-only write path (account/channel set-username), separate from the 5-character self-service minimum, since a deliberately short operator handle isn't the squatting the higher floor guards against. Channel admin username assignment previously had no length/format validation at all; this adds it. Also adds three reference docs: the client's deep-link (tg://, owpg://) surface, an OpenAPI 3.1 spec for both admin HTTP APIs (built from source, not the stale docs/admin-panel-api.en.md), and a starter reserved-username blocklist.
3628 lines
165 KiB
YAML
3628 lines
165 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: owpengram-server Admin APIs
|
|
version: "1.1.0"
|
|
description: |
|
|
Two independently authenticated HTTP admin surfaces, run as **separate
|
|
listeners in the same process** (`cmd/telesrv-admin`):
|
|
|
|
1. **Admin API** (`internal/adminapi`) — a bearer-token JSON API under
|
|
`/v1/*`, listening on `TELESRV_ADMIN_API_ADDR`
|
|
(default `127.0.0.1:2599`). Closed unless configured
|
|
(`TELESRV_ADMIN_API_ADDR` empty ⇒ off). This is the raw write surface.
|
|
2. **Panel API** (`cmd/telesrv-admin`) — the cookie/CSRF-session JSON API
|
|
under `/api/*` behind the built admin SPA, listening on
|
|
`TELESRV_ADMIN_UI_ADDR` (default `127.0.0.1:2600`). Most reads go
|
|
straight to Postgres; every `/api/actions/*` mutation (plus
|
|
moderation and verification/bot-verification decisions) is relayed
|
|
through to the Admin API on your behalf, bearer-authenticated with
|
|
`TELESRV_ADMIN_API_TOKEN` — the panel itself only writes local state
|
|
directly for admin-operator accounts and server settings/identity.
|
|
|
|
Both APIs' `POST` routes return a **command result**
|
|
(`CommandResult` — shared by both surfaces, same Go type). Panel API
|
|
action routes wrap a relayed Admin API call, so most of them can also
|
|
surface a `502` if that upstream call itself fails — except the
|
|
verification/bot-verification decision routes, which preserve the
|
|
upstream's real status (404/409/429/400) instead of flattening to 502.
|
|
|
|
Panel API permissions are granular (`accounts.manage`,
|
|
`channels.read`, `content.manage`, …) — see each operation's
|
|
description for the exact permission it requires; `*` (only ever held
|
|
by the master/break-glass "owpengram" account or a token explicitly
|
|
granted it) satisfies every check.
|
|
|
|
Built entirely from reading source directly (no prose doc was used or
|
|
trusted for either surface — an earlier version of this spec was
|
|
generated from `docs/admin-panel-api.en.md` and found to document
|
|
several routes, like `grant-stars`, that don't exist, while missing
|
|
~40 real ones and understating the permission model; that doc should
|
|
be considered unreliable going forward):
|
|
`internal/adminapi/{server,rbac,verification,botverification}.go` and
|
|
`cmd/telesrv-admin/{server,security,session,adminauth,adminusers_api,
|
|
verification,botverification,serversettings}.go`.
|
|
contact:
|
|
name: owpengram-server
|
|
url: https://git.zio.sh/astra/owpengram
|
|
|
|
servers:
|
|
- url: http://127.0.0.1:2599
|
|
description: Admin API (internal/adminapi) — bearer token, TELESRV_ADMIN_API_ADDR
|
|
- url: http://127.0.0.1:2600
|
|
description: Panel API (cmd/telesrv-admin) — cookie session + CSRF, TELESRV_ADMIN_UI_ADDR
|
|
|
|
security: []
|
|
|
|
tags:
|
|
- { name: "Panel: Auth", description: "Panel API — login/logout/session/public branding" }
|
|
- { name: "Panel: Admin Operators", description: "Panel API — named admin_console_users accounts (requires admins.manage)" }
|
|
- { name: "Panel: Dashboard", description: "Panel API — dashboard summary (requires dashboard.read)" }
|
|
- { name: "Panel: Accounts", description: "Panel API — account browsing + actions (requires accounts.read / accounts.manage)" }
|
|
- { name: "Panel: Broadcasts", description: "Panel API — broadcast browsing + actions (requires broadcasts.read / broadcasts.send)" }
|
|
- { name: "Panel: Channels", description: "Panel API — channel/supergroup browsing + actions (requires channels.read / channels.manage)" }
|
|
- { name: "Panel: Bots", description: "Panel API — bot browsing + actions (requires bots.read / bots.manage / bots.token.read)" }
|
|
- { name: "Panel: Messages", description: "Panel API — message audit + deletion actions (requires messages.read / messages.manage)" }
|
|
- { name: "Panel: Content", description: "Panel API — custom emoji, sticker sets, GIF catalog (requires content.read / content.manage)" }
|
|
- { name: "Panel: Storage", description: "Panel API — storage stats + manual purge (requires storage.read / storage.manage)" }
|
|
- { name: "Panel: Moderation", description: "Panel API — moderation case queue, proxied to the Admin API (requires moderation.review)" }
|
|
- { name: "Panel: Usernames", description: "Panel API — reserved + collectible username lifecycle (requires usernames.read / usernames.manage)" }
|
|
- { name: "Panel: Official Verification", description: "Panel API — official verification queue (requires verification.review, revoke also needs verification.revoke)" }
|
|
- { name: "Panel: Bot Verification", description: "Panel API — third-party bot verification queue, hidden by default (requires botverification.review / botverification.manage)" }
|
|
- { name: "Panel: Server Settings", description: "Panel API — server identity, env, updates, restart (requires server.manage)" }
|
|
- { name: "AdminAPI: Accounts", description: "Admin API — account write actions" }
|
|
- { name: "AdminAPI: Channels", description: "Admin API — channel write actions" }
|
|
- { name: "AdminAPI: Bots & Broadcasts", description: "Admin API — bot/broadcast write actions" }
|
|
- { name: "AdminAPI: Messages", description: "Admin API — message deletion actions" }
|
|
- { name: "AdminAPI: Stickers", description: "Admin API — sticker set write actions" }
|
|
- { name: "AdminAPI: GIF Catalog", description: "Admin API — GIF catalog write actions" }
|
|
- { name: "AdminAPI: Storage", description: "Admin API — storage purge" }
|
|
- { name: "AdminAPI: Moderation", description: "Admin API — moderation case queue (raw)" }
|
|
- { name: "AdminAPI: Collectible Usernames", description: "Admin API — collectible username lifecycle" }
|
|
- { name: "AdminAPI: Reserved Usernames", description: "Admin API — operator username blocklist" }
|
|
- { name: "AdminAPI: Official Verification", description: "Admin API — official verification queue (raw)" }
|
|
- { name: "AdminAPI: Bot Verification", description: "Admin API — third-party bot verification queue (raw)" }
|
|
- { name: "AdminAPI: Health", description: "Admin API — unauthenticated health check" }
|
|
|
|
paths:
|
|
# ============================================================
|
|
# PANEL API (cmd/telesrv-admin) — cookie session + CSRF
|
|
# ============================================================
|
|
|
|
# --- Auth / session ---
|
|
|
|
/api/login:
|
|
post:
|
|
tags: ["Panel: Auth"]
|
|
summary: Log in
|
|
security: []
|
|
description: >-
|
|
Issues the signed telesrv_admin_session cookie and the
|
|
telesrv_admin_csrf cookie. The only mutating panel route without
|
|
CSRF (no session exists yet) — only the Origin header is checked.
|
|
`username` is always required: either the literal break-glass
|
|
username `"owpengram"` (checked against TELESRV_ADMIN_UI_PASSWORD/
|
|
_TOKEN — reserved, no DB account may take it), or a named account
|
|
in `admin_console_users`. Every failure mode (unknown user, wrong
|
|
password, disabled account) returns the same 401 with the same
|
|
generic message, and an unknown-user attempt still burns a dummy
|
|
bcrypt compare, so failure modes cost the same time.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [username, secret]
|
|
properties:
|
|
username: { type: string, description: "Break-glass username (\"owpengram\"), or a named admin_console_users account." }
|
|
secret: { type: string }
|
|
example: { username: "owpengram", secret: "letmein" }
|
|
responses:
|
|
"200": { description: OK, headers: { Set-Cookie: { schema: { type: string } } } }
|
|
"401": { $ref: "#/components/responses/PanelUnauthorized" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/logout:
|
|
post:
|
|
tags: ["Panel: Auth"]
|
|
summary: Log out
|
|
description: Requires an authenticated session; no specific permission.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
responses:
|
|
"200": { description: OK }
|
|
|
|
/api/session:
|
|
get:
|
|
tags: ["Panel: Auth"]
|
|
summary: Current session info
|
|
description: Requires an authenticated session; no specific permission.
|
|
security: [{ panelSession: [] }]
|
|
responses:
|
|
"200":
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
actor: { type: string }
|
|
permissions: { type: array, items: { type: string } }
|
|
csrf_token: { type: string }
|
|
"401": { $ref: "#/components/responses/PanelUnauthorized" }
|
|
|
|
/api/public/branding:
|
|
get:
|
|
tags: ["Panel: Auth"]
|
|
summary: Public server branding (name/description), unauthenticated
|
|
description: Public route — shown on the login screen before signing in.
|
|
security: []
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
|
|
/api/public/icon:
|
|
get:
|
|
tags: ["Panel: Auth"]
|
|
summary: Public server icon, unauthenticated
|
|
security: []
|
|
responses:
|
|
"200": { description: Image bytes, content: { image/*: { schema: { type: string, format: binary } } } }
|
|
"404": { description: No icon set }
|
|
|
|
# --- Admin operator accounts (admins.manage) ---
|
|
|
|
/api/admin-users:
|
|
get:
|
|
tags: ["Panel: Admin Operators"]
|
|
summary: List admin operator accounts
|
|
description: Requires `admins.manage`.
|
|
security: [{ panelSession: [] }]
|
|
responses:
|
|
"200":
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
system: { type: object, description: "the break-glass account", properties: { username: { type: string, const: owpengram }, permissions: { type: array, items: { type: string } }, enabled: { type: boolean, const: true }, system: { type: boolean, const: true } } }
|
|
rows: { type: array, items: { type: object, additionalProperties: true } }
|
|
available_permissions: { type: array, items: { type: string } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/actions/create-admin-operator:
|
|
post:
|
|
tags: ["Panel: Admin Operators"]
|
|
summary: Create a named admin operator account
|
|
description: Requires `admins.manage`. `reason` is mandatory (stricter than the generic action envelope).
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody: { $ref: "#/components/requestBodies/PanelAdminUserAction" }
|
|
responses:
|
|
"200": { $ref: "#/components/responses/PanelActionOK" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/actions/set-admin-operator-access:
|
|
post:
|
|
tags: ["Panel: Admin Operators"]
|
|
summary: Edit a named admin operator's permissions/enabled state
|
|
description: Requires `admins.manage`. `reason` is mandatory.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody: { $ref: "#/components/requestBodies/PanelAdminUserAction" }
|
|
responses:
|
|
"200": { $ref: "#/components/responses/PanelActionOK" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/actions/set-admin-operator-password:
|
|
post:
|
|
tags: ["Panel: Admin Operators"]
|
|
summary: Set a named admin operator's password
|
|
description: Requires `admins.manage`. `reason` is mandatory.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody: { $ref: "#/components/requestBodies/PanelAdminUserAction" }
|
|
responses:
|
|
"200": { $ref: "#/components/responses/PanelActionOK" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
# --- Dashboard ---
|
|
|
|
/api/dashboard:
|
|
get:
|
|
tags: ["Panel: Dashboard"]
|
|
summary: Dashboard summary
|
|
description: Requires `dashboard.read`.
|
|
security: [{ panelSession: [] }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
# --- Accounts ---
|
|
|
|
/api/accounts:
|
|
get:
|
|
tags: ["Panel: Accounts"]
|
|
summary: List/search accounts
|
|
description: Requires `accounts.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters:
|
|
- { name: q, in: query, schema: { type: string } }
|
|
- { name: before_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { name: before_active_us, in: query, description: microseconds, schema: { type: integer, format: int64 } }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
responses:
|
|
"200":
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
query: { type: string }
|
|
limit: { type: integer }
|
|
rows: { type: array, items: { $ref: "#/components/schemas/AccountRow" } }
|
|
has_more: { type: boolean }
|
|
next_before_id: { type: integer, format: int64 }
|
|
next_before_active_us: { type: integer, format: int64 }
|
|
listing: { type: boolean }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/accounts/stats:
|
|
get:
|
|
tags: ["Panel: Accounts"]
|
|
summary: Account statistics
|
|
description: Requires `accounts.read`.
|
|
security: [{ panelSession: [] }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/accounts/shared-devices:
|
|
get:
|
|
tags: ["Panel: Accounts"]
|
|
summary: Accounts grouped by shared device fingerprint
|
|
description: Requires `accounts.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters:
|
|
- { name: offset, in: query, schema: { type: integer } }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
responses:
|
|
"200":
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
limit: { type: integer }
|
|
offset: { type: integer }
|
|
rows: { type: array, items: { type: object, additionalProperties: true } }
|
|
has_more: { type: boolean }
|
|
next_offset: { type: integer }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/accounts/{id}:
|
|
get:
|
|
tags: ["Panel: Accounts"]
|
|
summary: Account card (profile, flags, statistics)
|
|
description: Requires `accounts.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
"404": { $ref: "#/components/responses/PanelNotFound" }
|
|
|
|
/api/accounts/{id}/avatar:
|
|
get:
|
|
tags: ["Panel: Accounts"]
|
|
summary: Account avatar (binary, proxied from the Admin API)
|
|
description: Requires `accounts.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses:
|
|
"200": { description: Image bytes, content: { image/*: { schema: { type: string, format: binary } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
"404": { description: Not found }
|
|
|
|
/api/actions/set-frozen:
|
|
post:
|
|
tags: ["Panel: Accounts"]
|
|
summary: Freeze/unfreeze an account
|
|
description: Requires `accounts.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody: { $ref: "#/components/requestBodies/PanelSetFrozen" }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/grant-premium:
|
|
post:
|
|
tags: ["Panel: Accounts"]
|
|
summary: Grant Premium months
|
|
description: Requires `premium.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [user_id, months], properties: { user_id: { type: integer, format: int64 }, months: { type: integer } } }]
|
|
example: { command_id: "grant-premium-001", reason: "Incident compensation", confirm: true, user_id: 123456789, months: 12 }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-verified:
|
|
post:
|
|
tags: ["Panel: Accounts"]
|
|
summary: Set/clear the legacy verified badge on a user
|
|
description: >-
|
|
Requires `verification.review` (not `accounts.manage`) — this sets
|
|
the boolean verified flag directly, separate from the official
|
|
verification-applications workflow, but shares its permission.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [user_id, verified], properties: { user_id: { type: integer, format: int64 }, verified: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-account-flags:
|
|
post:
|
|
tags: ["Panel: Accounts"]
|
|
summary: Set scam/fake flags on a user
|
|
description: Requires `accounts.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [user_id], properties: { user_id: { type: integer, format: int64 }, scam: { type: boolean }, fake: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-support:
|
|
post:
|
|
tags: ["Panel: Accounts"]
|
|
summary: Set/clear the support flag on a user
|
|
description: Requires `accounts.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [user_id, support], properties: { user_id: { type: integer, format: int64 }, support: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-account-username:
|
|
post:
|
|
tags: ["Panel: Accounts"]
|
|
summary: Set a user's username
|
|
description: Requires `accounts.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [user_id, username], properties: { user_id: { type: integer, format: int64 }, username: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-account-profile:
|
|
post:
|
|
tags: ["Panel: Accounts"]
|
|
summary: Set a user's first/last name
|
|
description: Requires `accounts.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [user_id], properties: { user_id: { type: integer, format: int64 }, first_name: { type: string }, last_name: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-account-phone:
|
|
post:
|
|
tags: ["Panel: Accounts"]
|
|
summary: Set a user's phone number
|
|
description: Requires `accounts.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [user_id, phone], properties: { user_id: { type: integer, format: int64 }, phone: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-account-login-email:
|
|
post:
|
|
tags: ["Panel: Accounts"]
|
|
summary: Set/clear a user's login email
|
|
description: Requires `accounts.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [user_id], properties: { user_id: { type: integer, format: int64 }, email: { type: string, description: "empty clears it" } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-account-avatar:
|
|
post:
|
|
tags: ["Panel: Accounts"]
|
|
summary: Set a user's avatar (static image)
|
|
description: Requires `accounts.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody: { $ref: "#/components/requestBodies/PanelUserAvatarUpload" }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-account-avatar-video:
|
|
post:
|
|
tags: ["Panel: Accounts"]
|
|
summary: Set a user's avatar (animated video)
|
|
description: Requires `accounts.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required: [metadata, file]
|
|
properties:
|
|
metadata: { description: "JSON — common fields + user_id (int64), video_start_ts (float64)", type: string }
|
|
file: { type: string, format: binary }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-account-color:
|
|
post:
|
|
tags: ["Panel: Accounts"]
|
|
summary: Set a user's profile/name color
|
|
description: Requires `accounts.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [user_id], properties: { user_id: { type: integer, format: int64 } } }, { $ref: "#/components/schemas/PeerColorInput" }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-account-emoji-status:
|
|
post:
|
|
tags: ["Panel: Accounts"]
|
|
summary: Set a user's emoji status
|
|
description: Requires `accounts.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [user_id], properties: { user_id: { type: integer, format: int64 } } }, { $ref: "#/components/schemas/EmojiStatusInput" }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/revoke-sessions:
|
|
post:
|
|
tags: ["Panel: Accounts"]
|
|
summary: Revoke a user's authorized sessions
|
|
description: Requires `accounts.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [user_id], properties: { user_id: { type: integer, format: int64 }, hash: { type: integer, format: int64 }, keep_hash: { type: integer, format: int64 }, revoke_all: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
# --- Broadcasts ---
|
|
|
|
/api/broadcasts:
|
|
get:
|
|
tags: ["Panel: Broadcasts"]
|
|
summary: List broadcasts
|
|
description: Requires `broadcasts.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters:
|
|
- { name: before_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
responses:
|
|
"200":
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties: { limit: { type: integer }, rows: { type: array, items: { type: object, additionalProperties: true } }, has_more: { type: boolean }, next_before_id: { type: integer, format: int64 } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/actions/create-broadcast:
|
|
post:
|
|
tags: ["Panel: Broadcasts"]
|
|
summary: Create a broadcast
|
|
description: Requires `broadcasts.send`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [message, target_mode], properties: { message: { type: string }, target_mode: { type: string }, user_ids: { type: array, items: { type: integer, format: int64 }, description: "only for target_mode=selected" } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
# --- Channels ---
|
|
|
|
/api/channels:
|
|
get:
|
|
tags: ["Panel: Channels"]
|
|
summary: List/search channels
|
|
description: Requires `channels.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters:
|
|
- { name: q, in: query, schema: { type: string } }
|
|
- { name: before_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { name: before_updated_us, in: query, description: microseconds, schema: { type: integer, format: int64 } }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
responses:
|
|
"200": { $ref: "#/components/responses/PanelCursorList" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/channels/{id}:
|
|
get:
|
|
tags: ["Panel: Channels"]
|
|
summary: Channel card
|
|
description: Requires `channels.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/channels/{id}/avatar:
|
|
get:
|
|
tags: ["Panel: Channels"]
|
|
summary: Channel avatar (binary, proxied from the Admin API)
|
|
description: Requires `channels.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses:
|
|
"200": { description: Image bytes, content: { image/*: { schema: { type: string, format: binary } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/actions/set-channel-flags:
|
|
post:
|
|
tags: ["Panel: Channels"]
|
|
summary: Set scam/fake flags on a channel
|
|
description: Requires `channels.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [channel_id], properties: { channel_id: { type: integer, format: int64 }, scam: { type: boolean }, fake: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-channel-avatar:
|
|
post:
|
|
tags: ["Panel: Channels"]
|
|
summary: Set a channel's avatar
|
|
description: Requires `channels.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required: [metadata, file]
|
|
properties:
|
|
metadata: { description: "JSON — common fields + channel_id (int64)", type: string }
|
|
file: { type: string, format: binary }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-channel-settings:
|
|
post:
|
|
tags: ["Panel: Channels"]
|
|
summary: Partially update channel settings
|
|
description: >-
|
|
Requires `channels.manage`. Every field besides `channel_id` is an
|
|
optional pointer — a partial PATCH: only fields present in the JSON
|
|
body are changed.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/PanelCommandFields"
|
|
- type: object
|
|
required: [channel_id]
|
|
properties:
|
|
channel_id: { type: integer, format: int64 }
|
|
gigagroup: { type: [boolean, "null"] }
|
|
antispam: { type: [boolean, "null"] }
|
|
participants_hidden: { type: [boolean, "null"] }
|
|
noforwards: { type: [boolean, "null"] }
|
|
join_to_send: { type: [boolean, "null"] }
|
|
join_request: { type: [boolean, "null"] }
|
|
slowmode_seconds: { type: [integer, "null"] }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-channel-username:
|
|
post:
|
|
tags: ["Panel: Channels"]
|
|
summary: Set a channel's username
|
|
description: Requires `channels.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [channel_id, username], properties: { channel_id: { type: integer, format: int64 }, username: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-channel-color:
|
|
post:
|
|
tags: ["Panel: Channels"]
|
|
summary: Set a channel's profile/name color
|
|
description: Requires `channels.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [channel_id], properties: { channel_id: { type: integer, format: int64 } } }, { $ref: "#/components/schemas/PeerColorInput" }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-channel-emoji-status:
|
|
post:
|
|
tags: ["Panel: Channels"]
|
|
summary: Set a channel's emoji status
|
|
description: Requires `channels.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [channel_id], properties: { channel_id: { type: integer, format: int64 } } }, { $ref: "#/components/schemas/EmojiStatusInput" }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-channel-verified:
|
|
post:
|
|
tags: ["Panel: Channels"]
|
|
summary: Set/clear the verified badge on a channel
|
|
description: Requires `verification.review` (not `channels.manage`).
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [channel_id, verified], properties: { channel_id: { type: integer, format: int64 }, verified: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
# --- Bots ---
|
|
|
|
/api/bots:
|
|
get:
|
|
tags: ["Panel: Bots"]
|
|
summary: List/search bots
|
|
description: Requires `bots.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters:
|
|
- { name: q, in: query, schema: { type: string } }
|
|
- { name: before_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
responses:
|
|
"200": { $ref: "#/components/responses/PanelCursorList" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/bots/{id}:
|
|
get:
|
|
tags: ["Panel: Bots"]
|
|
summary: Bot card
|
|
description: Requires `bots.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/actions/create-bot:
|
|
post:
|
|
tags: ["Panel: Bots"]
|
|
summary: Create a bot account
|
|
description: Requires `bots.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [owner_user_id, name, username], properties: { owner_user_id: { type: integer, format: int64 }, name: { type: string }, username: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/delete-bot:
|
|
post:
|
|
tags: ["Panel: Bots"]
|
|
summary: Delete a bot account
|
|
description: Requires `bots.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [bot_user_id], properties: { bot_user_id: { type: integer, format: int64 } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/export-bot-token:
|
|
post:
|
|
tags: ["Panel: Bots"]
|
|
summary: Export a bot's auth token
|
|
description: Requires `bots.token.read`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [bot_user_id], properties: { bot_user_id: { type: integer, format: int64 } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
# --- Messages ---
|
|
|
|
/api/messages:
|
|
get:
|
|
tags: ["Panel: Messages"]
|
|
summary: Private message audit
|
|
description: Requires `messages.read`. Only queries when both `owner_user_id` and `peer_id` are > 0.
|
|
security: [{ panelSession: [] }]
|
|
parameters:
|
|
- { name: owner_user_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { name: peer_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { name: before_date, in: query, schema: { type: integer, format: int64 } }
|
|
- { name: before_id, in: query, schema: { type: integer } }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
responses:
|
|
"200":
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties: { owner_user_id: { type: integer, format: int64 }, peer_id: { type: integer, format: int64 }, before_date: { type: integer, format: int64 }, before_id: { type: integer }, limit: { type: integer }, rows: { type: array, items: { type: object, additionalProperties: true } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/messages/detail:
|
|
get:
|
|
tags: ["Panel: Messages"]
|
|
summary: Private message detail
|
|
description: Requires `messages.read`. Both query params required.
|
|
security: [{ panelSession: [] }]
|
|
parameters:
|
|
- { name: owner_user_id, in: query, required: true, schema: { type: integer, format: int64 } }
|
|
- { name: msg_id, in: query, required: true, schema: { type: integer } }
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/messages/groups:
|
|
get:
|
|
tags: ["Panel: Messages"]
|
|
summary: Channel/group message audit
|
|
description: Requires `messages.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters:
|
|
- { name: channel_id, in: query, required: true, schema: { type: integer, format: int64 } }
|
|
- { name: before_date, in: query, schema: { type: integer, format: int64 } }
|
|
- { name: before_id, in: query, schema: { type: integer } }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
responses:
|
|
"200":
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties: { channel_id: { type: integer, format: int64 }, before_date: { type: integer, format: int64 }, before_id: { type: integer }, limit: { type: integer }, rows: { type: array, items: { type: object, additionalProperties: true } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/messages/groups/detail:
|
|
get:
|
|
tags: ["Panel: Messages"]
|
|
summary: Channel/group message detail
|
|
description: Requires `messages.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters:
|
|
- { name: channel_id, in: query, required: true, schema: { type: integer, format: int64 } }
|
|
- { name: msg_id, in: query, required: true, schema: { type: integer } }
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/actions/delete-messages:
|
|
post:
|
|
tags: ["Panel: Messages"]
|
|
summary: Delete specific private messages
|
|
description: Requires `messages.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [owner_user_id, peer_id, ids], properties: { owner_user_id: { type: integer, format: int64 }, peer_id: { type: integer, format: int64 }, ids: { type: array, items: { type: integer } }, revoke: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/delete-history:
|
|
post:
|
|
tags: ["Panel: Messages"]
|
|
summary: Delete a private chat's history
|
|
description: Requires `messages.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/PanelCommandFields"
|
|
- type: object
|
|
required: [owner_user_id, peer_id]
|
|
properties:
|
|
owner_user_id: { type: integer, format: int64 }
|
|
peer_id: { type: integer, format: int64 }
|
|
max_id: { type: integer }
|
|
min_date: { type: integer }
|
|
max_date: { type: integer }
|
|
max_batches: { type: integer }
|
|
just_clear: { type: boolean }
|
|
revoke: { type: boolean }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
# --- Content: emoji ---
|
|
|
|
/api/emoji:
|
|
get:
|
|
tags: ["Panel: Content"]
|
|
summary: List/search custom emoji
|
|
description: Requires `content.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters:
|
|
- { name: q, in: query, schema: { type: string } }
|
|
- { name: before_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
responses:
|
|
"200": { $ref: "#/components/responses/PanelCursorList" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/emoji/{id}/animation:
|
|
get:
|
|
tags: ["Panel: Content"]
|
|
summary: Emoji Lottie animation
|
|
description: Requires `content.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses:
|
|
"200": { description: Animation JSON bytes }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
# --- Content: stickers ---
|
|
|
|
/api/stickers:
|
|
get:
|
|
tags: ["Panel: Content"]
|
|
summary: List sticker sets
|
|
description: Requires `content.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters:
|
|
- { name: kind, in: query, schema: { type: string } }
|
|
responses:
|
|
"200":
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema: { type: object, properties: { rows: { type: array, items: { type: object, additionalProperties: true } }, max_items: { type: integer } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/stickers/{id}/documents:
|
|
get:
|
|
tags: ["Panel: Content"]
|
|
summary: Document ids in a sticker set
|
|
description: Requires `content.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, properties: { document_ids: { type: array, items: { type: integer, format: int64 } } } } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/stickers/documents/{id}/animation:
|
|
get:
|
|
tags: ["Panel: Content"]
|
|
summary: Sticker animation
|
|
description: Requires `content.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses:
|
|
"200": { description: Animation bytes }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/actions/set-sticker-set-archived:
|
|
post:
|
|
tags: ["Panel: Content"]
|
|
summary: Archive/unarchive a sticker set
|
|
description: Requires `content.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [set_id, archived], properties: { set_id: { type: string, description: "int64, json:\",string\"" }, archived: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-sticker-set-sort-order:
|
|
post:
|
|
tags: ["Panel: Content"]
|
|
summary: Reorder a sticker set
|
|
description: Requires `content.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [set_id, sort_order], properties: { set_id: { type: string, description: "int64, json:\",string\"" }, sort_order: { type: integer } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/rename-sticker-set:
|
|
post:
|
|
tags: ["Panel: Content"]
|
|
summary: Rename a sticker set
|
|
description: Requires `content.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [set_id, title], properties: { set_id: { type: string, description: "int64, json:\",string\"" }, title: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/delete-sticker-set:
|
|
post:
|
|
tags: ["Panel: Content"]
|
|
summary: Delete a sticker set
|
|
description: Requires `content.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [set_id], properties: { set_id: { type: string, description: "int64, json:\",string\"" } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/create-sticker-set:
|
|
post:
|
|
tags: ["Panel: Content"]
|
|
summary: Create a sticker set
|
|
description: Requires `content.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required: [metadata, file]
|
|
properties:
|
|
metadata: { description: "JSON — common fields + title, short_name, kind, emoji, keywords (opt.)", type: string }
|
|
file: { type: string, format: binary }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/add-sticker-to-set:
|
|
post:
|
|
tags: ["Panel: Content"]
|
|
summary: Add a sticker to a set
|
|
description: Requires `content.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required: [metadata, file]
|
|
properties:
|
|
metadata: { description: "JSON — common fields + set_id (int64, json:\",string\"), emoji, keywords (opt.)", type: string }
|
|
file: { type: string, format: binary }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/remove-sticker-from-set:
|
|
post:
|
|
tags: ["Panel: Content"]
|
|
summary: Remove a sticker from a set
|
|
description: Requires `content.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [set_id, document_id], properties: { set_id: { type: string, description: "int64, json:\",string\"" }, document_id: { type: string, description: "int64, json:\",string\"" } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
# --- Content: GIF catalog ---
|
|
|
|
/api/gif-catalog:
|
|
get:
|
|
tags: ["Panel: Content"]
|
|
summary: GIF catalog
|
|
description: Requires `content.read`.
|
|
security: [{ panelSession: [] }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/gif-catalog/documents/{id}/preview:
|
|
get:
|
|
tags: ["Panel: Content"]
|
|
summary: GIF preview
|
|
description: Requires `content.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses:
|
|
"200": { description: Preview bytes }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/actions/create-gif-catalog-entry:
|
|
post:
|
|
tags: ["Panel: Content"]
|
|
summary: Add a GIF catalog entry
|
|
description: Requires `content.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required: [metadata, file]
|
|
properties:
|
|
metadata: { description: "JSON — common fields + title", type: string }
|
|
file: { type: string, format: binary }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-gif-catalog-enabled:
|
|
post:
|
|
tags: ["Panel: Content"]
|
|
summary: Enable/disable a GIF catalog entry
|
|
description: Requires `content.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [id, enabled], properties: { id: { type: string, description: "int64, json:\",string\"" }, enabled: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-gif-catalog-sort-order:
|
|
post:
|
|
tags: ["Panel: Content"]
|
|
summary: Reorder a GIF catalog entry
|
|
description: Requires `content.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [id, sort_order], properties: { id: { type: string, description: "int64, json:\",string\"" }, sort_order: { type: integer } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-gif-catalog-category:
|
|
post:
|
|
tags: ["Panel: Content"]
|
|
summary: Set a GIF catalog entry's category
|
|
description: Requires `content.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [id, category], properties: { id: { type: string, description: "int64, json:\",string\"" }, category: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/auto-categorize-gif-catalog:
|
|
post:
|
|
tags: ["Panel: Content"]
|
|
summary: Auto-categorize uncategorized GIFs
|
|
description: Requires `content.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/PanelCommandFields" }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/delete-uncategorized-gifs:
|
|
post:
|
|
tags: ["Panel: Content"]
|
|
summary: Delete every uncategorized GIF catalog entry
|
|
description: Requires `content.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/PanelCommandFields" }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/delete-gif-catalog-entry:
|
|
post:
|
|
tags: ["Panel: Content"]
|
|
summary: Delete a GIF catalog entry
|
|
description: Requires `content.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [id], properties: { id: { type: string, description: "int64, json:\",string\"" } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
# --- Storage ---
|
|
|
|
/api/storage/stats:
|
|
get:
|
|
tags: ["Panel: Storage"]
|
|
summary: Object storage statistics
|
|
description: Requires `storage.read`.
|
|
security: [{ panelSession: [] }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/storage/accounts:
|
|
get:
|
|
tags: ["Panel: Storage"]
|
|
summary: Storage usage broken down by account
|
|
description: Requires `storage.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters:
|
|
- { name: offset, in: query, schema: { type: integer } }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
- { name: order, in: query, schema: { type: string, enum: [asc, desc] } }
|
|
- { name: q, in: query, schema: { type: string } }
|
|
- { name: sort, in: query, schema: { type: string } }
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/actions/storage-manual-purge:
|
|
post:
|
|
tags: ["Panel: Storage"]
|
|
summary: Manually purge storage by category
|
|
description: Requires `storage.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/PanelCommandFields"
|
|
- type: object
|
|
required: [categories]
|
|
properties:
|
|
categories: { type: array, items: { type: string, enum: [photo, video, round_video, gif, music, voice, file] } }
|
|
include_avatars: { type: boolean }
|
|
created_before: { type: [string, "null"], format: date-time, description: "RFC3339; null = no age filter" }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
# --- Moderation (proxied to the Admin API) ---
|
|
|
|
/api/moderation/cases:
|
|
get:
|
|
tags: ["Panel: Moderation"]
|
|
summary: List moderation cases
|
|
description: Requires `moderation.review`. Entire query string forwarded to the Admin API's `GET /v1/moderation/cases` unchanged.
|
|
security: [{ panelSession: [] }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/moderation/cases/{id}:
|
|
get:
|
|
tags: ["Panel: Moderation"]
|
|
summary: Moderation case detail
|
|
description: Requires `moderation.review`.
|
|
security: [{ panelSession: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/moderation/reports/{id}:
|
|
get:
|
|
tags: ["Panel: Moderation"]
|
|
summary: Moderation report detail
|
|
description: Requires `moderation.review`.
|
|
security: [{ panelSession: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/moderation/cases/{id}/claim:
|
|
post:
|
|
tags: ["Panel: Moderation"]
|
|
summary: Claim a moderation case
|
|
description: Requires `moderation.review`. Relayed to the Admin API — `actor` is injected from the session, `command_id` minted if absent.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
requestBody: { $ref: "#/components/requestBodies/PanelVersionedDecision" }
|
|
responses:
|
|
"200": { $ref: "#/components/responses/PanelActionOK" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
"409": { $ref: "#/components/responses/PanelConflict" }
|
|
|
|
/api/moderation/cases/{id}/decide:
|
|
post:
|
|
tags: ["Panel: Moderation"]
|
|
summary: Decide a moderation case
|
|
description: Requires `moderation.review`. Relayed to the Admin API's `POST /v1/moderation/cases/{id}/decide`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
requestBody: { $ref: "#/components/requestBodies/PanelVersionedDecision" }
|
|
responses:
|
|
"200": { $ref: "#/components/responses/PanelActionOK" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
"409": { $ref: "#/components/responses/PanelConflict" }
|
|
|
|
/api/moderation/cases/{id}/appeals/{appeal_id}/review:
|
|
post:
|
|
tags: ["Panel: Moderation"]
|
|
summary: Review an appeal on a moderation case
|
|
description: Requires `moderation.review`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
parameters:
|
|
- { $ref: "#/components/parameters/PathId" }
|
|
- { name: appeal_id, in: path, required: true, schema: { type: integer, format: int64 } }
|
|
requestBody: { $ref: "#/components/requestBodies/PanelVersionedDecision" }
|
|
responses:
|
|
"200": { $ref: "#/components/responses/PanelActionOK" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
"409": { $ref: "#/components/responses/PanelConflict" }
|
|
|
|
# --- Usernames: reserved + collectible ---
|
|
|
|
/api/collectible-usernames:
|
|
get:
|
|
tags: ["Panel: Usernames"]
|
|
summary: List collectible usernames
|
|
description: Requires `usernames.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters:
|
|
- { name: status, in: query, schema: { type: string, enum: ["", vault, owned, burned] } }
|
|
- { name: owner_user_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { name: before_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
- { name: q, in: query, schema: { type: string } }
|
|
responses:
|
|
"200":
|
|
description: "OK — `next_before_id` is a string (int64 precision)."
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
rows: { type: array, items: { type: object, additionalProperties: true } }
|
|
has_more: { type: boolean }
|
|
next_before_id: { type: string }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/collectible-usernames/{id}:
|
|
get:
|
|
tags: ["Panel: Usernames"]
|
|
summary: Collectible username detail + transfer log
|
|
description: Requires `usernames.read`.
|
|
security: [{ panelSession: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses:
|
|
"200":
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
asset: { type: object, additionalProperties: true }
|
|
transfers: { type: array, items: { type: object, additionalProperties: true } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/reserved-usernames:
|
|
get:
|
|
tags: ["Panel: Usernames"]
|
|
summary: List reserved usernames
|
|
description: Requires `usernames.read`. Proxied to the Admin API's `GET /v1/reserved-usernames`.
|
|
security: [{ panelSession: [] }]
|
|
parameters:
|
|
- { name: q, in: query, schema: { type: string } }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
- { name: offset, in: query, schema: { type: integer } }
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/actions/reserve-username:
|
|
post:
|
|
tags: ["Panel: Usernames"]
|
|
summary: Add a username to the operator reserved-username blocklist
|
|
description: Requires `usernames.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [username], properties: { username: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/unreserve-username:
|
|
post:
|
|
tags: ["Panel: Usernames"]
|
|
summary: Remove a username from the operator reserved-username blocklist
|
|
description: Requires `usernames.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [username], properties: { username: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/mint-collectible-username:
|
|
post:
|
|
tags: ["Panel: Usernames"]
|
|
summary: Mint a collectible username
|
|
description: Requires `usernames.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/PanelCommandFields"
|
|
- type: object
|
|
required: [username, currency, amount]
|
|
properties:
|
|
username: { type: string }
|
|
owner_user_id: { $ref: "#/components/schemas/FlexInt64" }
|
|
owner_channel_id: { $ref: "#/components/schemas/FlexInt64" }
|
|
currency: { type: string }
|
|
amount: { $ref: "#/components/schemas/FlexInt64" }
|
|
crypto_currency: { type: string }
|
|
crypto_amount: { $ref: "#/components/schemas/FlexInt64" }
|
|
url: { type: string }
|
|
purchase_date: { $ref: "#/components/schemas/FlexUnix" }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/transfer-collectible-username:
|
|
post:
|
|
tags: ["Panel: Usernames"]
|
|
summary: Transfer a collectible username
|
|
description: Requires `usernames.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/PanelCommandFields"
|
|
- type: object
|
|
required: [username]
|
|
properties:
|
|
username: { type: string }
|
|
to_user_id: { $ref: "#/components/schemas/FlexInt64" }
|
|
to_channel_id: { $ref: "#/components/schemas/FlexInt64" }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/revoke-collectible-username:
|
|
post:
|
|
tags: ["Panel: Usernames"]
|
|
summary: Revoke (or burn) a collectible username
|
|
description: >-
|
|
Requires `usernames.manage`. When `burn: true`, the effective
|
|
action name in the command envelope flips to
|
|
`burn-collectible-username` (same route/struct).
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [username], properties: { username: { type: string }, burn: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/delete-collectible-username:
|
|
post:
|
|
tags: ["Panel: Usernames"]
|
|
summary: Delete a collectible username
|
|
description: Requires `usernames.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [username], properties: { username: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
# --- Official verification ---
|
|
|
|
/api/verification/applications:
|
|
get:
|
|
tags: ["Panel: Official Verification"]
|
|
summary: List official-verification applications
|
|
description: Requires `verification.review`.
|
|
security: [{ panelSession: [] }]
|
|
parameters:
|
|
- { name: status, in: query, schema: { type: string } }
|
|
- { name: target_type, in: query, schema: { type: string } }
|
|
- { name: before_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
- { name: reviewer, in: query, schema: { type: string } }
|
|
- { name: q, in: query, schema: { type: string } }
|
|
responses:
|
|
"200": { $ref: "#/components/responses/PanelCursorList" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/verification/applications/{id}:
|
|
get:
|
|
tags: ["Panel: Official Verification"]
|
|
summary: Application detail
|
|
description: Requires `verification.review`.
|
|
security: [{ panelSession: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/verification/counts:
|
|
get:
|
|
tags: ["Panel: Official Verification"]
|
|
summary: Application counts by status
|
|
description: Requires `verification.review`.
|
|
security: [{ panelSession: [] }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/verification/applications/{id}/claim:
|
|
post:
|
|
tags: ["Panel: Official Verification"]
|
|
summary: Claim an application
|
|
description: Requires `verification.review`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
requestBody: { $ref: "#/components/requestBodies/PanelVersionedDecision" }
|
|
responses:
|
|
"200": { $ref: "#/components/responses/PanelActionOK" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
"409": { $ref: "#/components/responses/PanelConflict" }
|
|
|
|
/api/verification/applications/{id}/approve:
|
|
post:
|
|
tags: ["Panel: Official Verification"]
|
|
summary: Approve an application (grants the badge)
|
|
description: Requires `verification.review`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
requestBody: { $ref: "#/components/requestBodies/PanelVersionedDecision" }
|
|
responses:
|
|
"200": { $ref: "#/components/responses/PanelActionOK" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
"409": { $ref: "#/components/responses/PanelConflict" }
|
|
|
|
/api/verification/applications/{id}/reject:
|
|
post:
|
|
tags: ["Panel: Official Verification"]
|
|
summary: Reject an application
|
|
description: Requires `verification.review`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
requestBody: { $ref: "#/components/requestBodies/PanelVersionedDecision" }
|
|
responses:
|
|
"200": { $ref: "#/components/responses/PanelActionOK" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
"409": { $ref: "#/components/responses/PanelConflict" }
|
|
|
|
/api/actions/revoke-verification:
|
|
post:
|
|
tags: ["Panel: Official Verification"]
|
|
summary: Strip an official-verification badge
|
|
description: Requires BOTH `verification.review` and `verification.revoke`. Addresses the target directly, not an application id.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/PanelCommandFields"
|
|
- type: object
|
|
required: [target_type, target_id]
|
|
properties:
|
|
target_type: { type: string, description: "domain.VerificationTargetType, validated" }
|
|
target_id: { $ref: "#/components/schemas/FlexInt64" }
|
|
internal_note: { type: string }
|
|
responses:
|
|
"200": { $ref: "#/components/responses/PanelActionOK" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
# --- Bot verification (feature-flagged: 404s while TELESRV_HIDE_THIRD_PARTY_VERIFICATION=true, the default) ---
|
|
|
|
/api/botverification/verifiers:
|
|
get:
|
|
tags: ["Panel: Bot Verification"]
|
|
summary: List third-party verifier bots
|
|
description: Requires `botverification.review`.
|
|
security: [{ panelSession: [] }]
|
|
parameters:
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
- { name: enabled_only, in: query, schema: { type: string, description: "1/true/yes/on" } }
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, properties: { rows: { type: array, items: { type: object, additionalProperties: true } } } } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
"404": { description: "Third-party verification is disabled (TELESRV_HIDE_THIRD_PARTY_VERIFICATION)" }
|
|
|
|
/api/botverification/icons:
|
|
get:
|
|
tags: ["Panel: Bot Verification"]
|
|
summary: List verification icon catalog
|
|
description: Requires `botverification.review`.
|
|
security: [{ panelSession: [] }]
|
|
parameters:
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
- { name: active_only, in: query, schema: { type: string } }
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, properties: { rows: { type: array, items: { type: object, additionalProperties: true } } } } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/botverification/marks:
|
|
get:
|
|
tags: ["Panel: Bot Verification"]
|
|
summary: List active third-party marks
|
|
description: Requires `botverification.review`.
|
|
security: [{ panelSession: [] }]
|
|
parameters:
|
|
- { name: peer_type, in: query, schema: { type: string, enum: ["", user, channel] } }
|
|
- { name: verifier_bot_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { name: before_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
- { name: q, in: query, schema: { type: string } }
|
|
responses:
|
|
"200": { $ref: "#/components/responses/PanelCursorList" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/botverification/requests:
|
|
get:
|
|
tags: ["Panel: Bot Verification"]
|
|
summary: List third-party verification requests
|
|
description: Requires `botverification.review`.
|
|
security: [{ panelSession: [] }]
|
|
parameters:
|
|
- { name: status, in: query, schema: { type: string } }
|
|
- { name: peer_type, in: query, schema: { type: string } }
|
|
- { name: verifier_bot_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { name: before_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
- { name: q, in: query, schema: { type: string } }
|
|
responses:
|
|
"200": { $ref: "#/components/responses/PanelCursorList" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/botverification/requests/{id}:
|
|
get:
|
|
tags: ["Panel: Bot Verification"]
|
|
summary: Request detail
|
|
description: Requires `botverification.review`.
|
|
security: [{ panelSession: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses:
|
|
"200":
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
request: { type: object, additionalProperties: true }
|
|
verifier: { type: object, additionalProperties: true }
|
|
mark_active: { type: boolean }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/botverification/counts:
|
|
get:
|
|
tags: ["Panel: Bot Verification"]
|
|
summary: Request counts by status
|
|
description: Requires `botverification.review`.
|
|
security: [{ panelSession: [] }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/botverification/requests/{id}/approve:
|
|
post:
|
|
tags: ["Panel: Bot Verification"]
|
|
summary: Approve a third-party verification request
|
|
description: Requires `botverification.review`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
requestBody: { $ref: "#/components/requestBodies/PanelVersionedDecision" }
|
|
responses:
|
|
"200": { $ref: "#/components/responses/PanelActionOK" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
"409": { $ref: "#/components/responses/PanelConflict" }
|
|
|
|
/api/botverification/requests/{id}/reject:
|
|
post:
|
|
tags: ["Panel: Bot Verification"]
|
|
summary: Reject a third-party verification request
|
|
description: Requires `botverification.review`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
requestBody: { $ref: "#/components/requestBodies/PanelVersionedDecision" }
|
|
responses:
|
|
"200": { $ref: "#/components/responses/PanelActionOK" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
"409": { $ref: "#/components/responses/PanelConflict" }
|
|
|
|
/api/botverification/requests/{id}/revoke:
|
|
post:
|
|
tags: ["Panel: Bot Verification"]
|
|
summary: Revoke a granted third-party verification
|
|
description: Requires `botverification.review`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
requestBody: { $ref: "#/components/requestBodies/PanelVersionedDecision" }
|
|
responses:
|
|
"200": { $ref: "#/components/responses/PanelActionOK" }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
"409": { $ref: "#/components/responses/PanelConflict" }
|
|
|
|
/api/actions/grant-bot-verifier:
|
|
post:
|
|
tags: ["Panel: Bot Verification"]
|
|
summary: Appoint a bot as a third-party verifier
|
|
description: Requires `botverification.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/PanelCommandFields"
|
|
- type: object
|
|
required: [bot_id, company_name]
|
|
properties:
|
|
bot_id: { $ref: "#/components/schemas/FlexInt64" }
|
|
icon_document_id: { $ref: "#/components/schemas/FlexInt64" }
|
|
company_name: { type: string }
|
|
default_description: { type: string }
|
|
can_modify_custom_description: { type: boolean }
|
|
version: { $ref: "#/components/schemas/FlexInt64" }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-bot-verifier-enabled:
|
|
post:
|
|
tags: ["Panel: Bot Verification"]
|
|
summary: Enable/disable a verifier bot
|
|
description: Requires `botverification.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [bot_id, enabled], properties: { bot_id: { $ref: "#/components/schemas/FlexInt64" }, enabled: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/revoke-bot-verifier:
|
|
post:
|
|
tags: ["Panel: Bot Verification"]
|
|
summary: Strip a bot's verifier status
|
|
description: Requires `botverification.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [bot_id], properties: { bot_id: { $ref: "#/components/schemas/FlexInt64" } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/upsert-verification-icon:
|
|
post:
|
|
tags: ["Panel: Bot Verification"]
|
|
summary: Add/edit a verification-icon catalog entry
|
|
description: Requires `botverification.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [document_id, name], properties: { document_id: { $ref: "#/components/schemas/FlexInt64" }, name: { type: string }, owner_bot_id: { $ref: "#/components/schemas/FlexInt64" } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/set-verification-icon-active:
|
|
post:
|
|
tags: ["Panel: Bot Verification"]
|
|
summary: Enable/disable a verification icon
|
|
description: Requires `botverification.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [icon_id, active], properties: { icon_id: { $ref: "#/components/schemas/FlexInt64" }, active: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
/api/actions/revoke-custom-verification:
|
|
post:
|
|
tags: ["Panel: Bot Verification"]
|
|
summary: Strip a third-party mark from a peer
|
|
description: Requires `botverification.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [verifier_bot_id, peer_type, peer_id], properties: { verifier_bot_id: { $ref: "#/components/schemas/FlexInt64" }, peer_type: { type: string, enum: [user, channel] }, peer_id: { $ref: "#/components/schemas/FlexInt64" } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "502": { $ref: "#/components/responses/PanelActionUpstreamError" } }
|
|
|
|
# --- Server settings ---
|
|
|
|
/api/server/identity:
|
|
get:
|
|
tags: ["Panel: Server Settings"]
|
|
summary: Server identity (name/description/icon presence)
|
|
description: Requires `server.manage`.
|
|
security: [{ panelSession: [] }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/server/add-server-link:
|
|
get:
|
|
tags: ["Panel: Server Settings"]
|
|
summary: The ready-made owpg://addserver link for this server
|
|
description: Requires `server.manage`.
|
|
security: [{ panelSession: [] }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/server/icon:
|
|
get:
|
|
tags: ["Panel: Server Settings"]
|
|
summary: Current server icon (binary)
|
|
description: Requires `server.manage`.
|
|
security: [{ panelSession: [] }]
|
|
responses:
|
|
"200": { description: Image bytes, content: { image/*: { schema: { type: string, format: binary } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
"404": { description: No icon set }
|
|
|
|
/api/actions/set-server-identity:
|
|
post:
|
|
tags: ["Panel: Server Settings"]
|
|
summary: Set the server's name/description
|
|
description: Requires `server.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, properties: { name: { type: string }, description: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" } }
|
|
|
|
/api/actions/set-welcome-message-templates:
|
|
post:
|
|
tags: ["Panel: Server Settings"]
|
|
summary: Set the welcome (phone/email) message templates
|
|
description: Requires `server.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, properties: { phone_template: { type: string }, email_template: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" } }
|
|
|
|
/api/actions/set-login-code-message-template:
|
|
post:
|
|
tags: ["Panel: Server Settings"]
|
|
summary: Set the login-code SMS/message template
|
|
description: >-
|
|
Requires `server.manage`. The template must contain exactly one
|
|
`{{code}}` placeholder if non-empty, else 422
|
|
(`domain.ValidateLoginCodeMessageTemplate`).
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, properties: { template: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" }, "422": { description: "template must contain exactly one {{code}}", content: { application/json: { schema: { $ref: "#/components/schemas/ErrorEnvelope" } } } } }
|
|
|
|
/api/actions/upload-server-icon:
|
|
post:
|
|
tags: ["Panel: Server Settings"]
|
|
summary: Upload a new server icon
|
|
description: "Requires `server.manage`. File ≤ 2MiB, extension in {.png,.jpg,.jpeg,.webp,.gif}."
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required: [metadata, file]
|
|
properties:
|
|
metadata: { description: "JSON — common fields only", type: string }
|
|
file: { type: string, format: binary }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" } }
|
|
|
|
/api/actions/remove-server-icon:
|
|
post:
|
|
tags: ["Panel: Server Settings"]
|
|
summary: Remove the server icon
|
|
description: Requires `server.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/PanelCommandFields" }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" } }
|
|
|
|
/api/actions/complete-setup:
|
|
post:
|
|
tags: ["Panel: Server Settings"]
|
|
summary: Mark first-run setup as complete
|
|
description: Requires `server.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/PanelCommandFields" }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" } }
|
|
|
|
/api/server/env:
|
|
get:
|
|
tags: ["Panel: Server Settings"]
|
|
summary: Current .env values
|
|
description: Requires `server.manage`.
|
|
security: [{ panelSession: [] }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/actions/update-server-env:
|
|
post:
|
|
tags: ["Panel: Server Settings"]
|
|
summary: Update .env values
|
|
description: Requires `server.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/PanelCommandFields" }, { type: object, required: [values], properties: { values: { type: object, additionalProperties: { type: string } } } }]
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" } }
|
|
|
|
/api/server/status:
|
|
get:
|
|
tags: ["Panel: Server Settings"]
|
|
summary: Server process status
|
|
description: Requires `server.manage`.
|
|
security: [{ panelSession: [] }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/server/docker-status:
|
|
get:
|
|
tags: ["Panel: Server Settings"]
|
|
summary: Live container/process status (Services tab)
|
|
description: >-
|
|
Requires `server.manage`. Backed by `procctl.Manager.DockerStatus`,
|
|
which shells out to `docker compose ps`. If the deployment actually
|
|
runs under podman (or `docker` isn't installed/running), this exec
|
|
fails and the tab renders as "nothing running" rather than a clear
|
|
error — the handler doesn't currently distinguish "no services
|
|
configured" from "couldn't ask Docker".
|
|
security: [{ panelSession: [] }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/server/check-updates:
|
|
get:
|
|
tags: ["Panel: Server Settings"]
|
|
summary: Check for available server updates
|
|
description: Requires `server.manage`.
|
|
security: [{ panelSession: [] }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"403": { $ref: "#/components/responses/PanelForbidden" }
|
|
|
|
/api/actions/restart-server:
|
|
post:
|
|
tags: ["Panel: Server Settings"]
|
|
summary: Restart the server process
|
|
description: Requires `server.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/PanelCommandFields" }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" } }
|
|
|
|
/api/actions/update-server:
|
|
post:
|
|
tags: ["Panel: Server Settings"]
|
|
summary: Update the server to the latest build
|
|
description: Requires `server.manage`.
|
|
security: [{ panelSession: [], panelCsrf: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/PanelCommandFields" }
|
|
responses: { "200": { $ref: "#/components/responses/PanelActionOK" }, "403": { $ref: "#/components/responses/PanelForbidden" } }
|
|
|
|
# ============================================================
|
|
# ADMIN API (internal/adminapi) — bearer token
|
|
# ============================================================
|
|
|
|
/healthz:
|
|
get:
|
|
tags: ["AdminAPI: Health"]
|
|
summary: Health check
|
|
security: []
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, properties: { status: { type: string, const: ok } } } } } }
|
|
|
|
/v1/accounts/set-frozen:
|
|
post:
|
|
tags: ["AdminAPI: Accounts"]
|
|
summary: Freeze/unfreeze an account
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/CommandMeta"
|
|
- type: object
|
|
required: [user_id, frozen]
|
|
properties:
|
|
user_id: { type: integer, format: int64 }
|
|
frozen: { type: boolean }
|
|
freeze_until: { type: string, format: date-time }
|
|
freeze_appeal_url: { type: string }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" }, "400": { $ref: "#/components/responses/AdminApiCommandError" } }
|
|
|
|
/v1/accounts/set-restricted:
|
|
post:
|
|
tags: ["AdminAPI: Accounts"]
|
|
summary: Restrict/unrestrict an account (spam sanction — join/message gate)
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/CommandMeta"
|
|
- type: object
|
|
required: [user_id, restricted]
|
|
properties:
|
|
user_id: { type: integer, format: int64 }
|
|
restricted: { type: boolean }
|
|
restricted_until: { type: string, format: date-time }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" }, "400": { $ref: "#/components/responses/AdminApiCommandError" } }
|
|
|
|
/v1/accounts/{id}/avatar:
|
|
get:
|
|
tags: ["AdminAPI: Accounts"]
|
|
summary: Account avatar (binary)
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses:
|
|
"200": { description: Image bytes, content: { image/*: { schema: { type: string, format: binary } } } }
|
|
"404": { description: Not found }
|
|
|
|
/v1/accounts/grant-premium:
|
|
post:
|
|
tags: ["AdminAPI: Accounts"]
|
|
summary: Grant Premium months
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [user_id, months], properties: { user_id: { type: integer, format: int64 }, months: { type: integer } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/accounts/set-verified:
|
|
post:
|
|
tags: ["AdminAPI: Accounts"]
|
|
summary: Set/clear verified badge
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [user_id, verified], properties: { user_id: { type: integer, format: int64 }, verified: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/accounts/set-flags:
|
|
post:
|
|
tags: ["AdminAPI: Accounts"]
|
|
summary: Set scam/fake flags
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [user_id], properties: { user_id: { type: integer, format: int64 }, scam: { type: boolean }, fake: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/accounts/set-support:
|
|
post:
|
|
tags: ["AdminAPI: Accounts"]
|
|
summary: Set/clear support flag
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [user_id, support], properties: { user_id: { type: integer, format: int64 }, support: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/accounts/set-username:
|
|
post:
|
|
tags: ["AdminAPI: Accounts"]
|
|
summary: Set a user's username
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [user_id, username], properties: { user_id: { type: integer, format: int64 }, username: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/accounts/set-profile:
|
|
post:
|
|
tags: ["AdminAPI: Accounts"]
|
|
summary: Set a user's first/last name
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [user_id], properties: { user_id: { type: integer, format: int64 }, first_name: { type: string }, last_name: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/accounts/set-phone:
|
|
post:
|
|
tags: ["AdminAPI: Accounts"]
|
|
summary: Set a user's phone
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [user_id, phone], properties: { user_id: { type: integer, format: int64 }, phone: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/accounts/set-login-email:
|
|
post:
|
|
tags: ["AdminAPI: Accounts"]
|
|
summary: Set/clear a user's login email
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [user_id], properties: { user_id: { type: integer, format: int64 }, email: { type: string, description: "empty clears it" } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/accounts/set-avatar:
|
|
post:
|
|
tags: ["AdminAPI: Accounts"]
|
|
summary: Set a user's avatar (static image)
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required: [file, metadata]
|
|
properties:
|
|
file: { type: string, format: binary }
|
|
metadata: { description: "JSON — CommandMeta + user_id (int64)", type: string }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/accounts/set-avatar-video:
|
|
post:
|
|
tags: ["AdminAPI: Accounts"]
|
|
summary: Set a user's avatar (animated video)
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required: [file, metadata]
|
|
properties:
|
|
file: { type: string, format: binary }
|
|
metadata: { description: "JSON — CommandMeta + user_id (int64), video_start_ts (float64)", type: string }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/accounts/set-color:
|
|
post:
|
|
tags: ["AdminAPI: Accounts"]
|
|
summary: Set a user's profile/name color
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [user_id], properties: { user_id: { type: integer, format: int64 } } }, { $ref: "#/components/schemas/PeerColorInput" }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/accounts/set-emoji-status:
|
|
post:
|
|
tags: ["AdminAPI: Accounts"]
|
|
summary: Set a user's emoji status
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [user_id], properties: { user_id: { type: integer, format: int64 } } }, { $ref: "#/components/schemas/EmojiStatusInput" }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/accounts/revoke-sessions:
|
|
post:
|
|
tags: ["AdminAPI: Accounts"]
|
|
summary: Revoke a user's authorized sessions
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [user_id], properties: { user_id: { type: integer, format: int64 }, hash: { type: integer, format: int64 }, keep_hash: { type: integer, format: int64 }, revoke_all: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/channels/{id}/avatar:
|
|
get:
|
|
tags: ["AdminAPI: Channels"]
|
|
summary: Channel avatar (binary)
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses: { "200": { description: Image bytes, content: { image/*: { schema: { type: string, format: binary } } } }, "404": { description: Not found } }
|
|
|
|
/v1/channels/set-avatar:
|
|
post:
|
|
tags: ["AdminAPI: Channels"]
|
|
summary: Set a channel's avatar
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required: [file, metadata]
|
|
properties:
|
|
file: { type: string, format: binary }
|
|
metadata: { description: "JSON — CommandMeta + channel_id (int64)", type: string }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/channels/set-verified:
|
|
post:
|
|
tags: ["AdminAPI: Channels"]
|
|
summary: Set/clear verified badge
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [channel_id, verified], properties: { channel_id: { type: integer, format: int64 }, verified: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/channels/set-flags:
|
|
post:
|
|
tags: ["AdminAPI: Channels"]
|
|
summary: Set scam/fake flags
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [channel_id], properties: { channel_id: { type: integer, format: int64 }, scam: { type: boolean }, fake: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/channels/set-settings:
|
|
post:
|
|
tags: ["AdminAPI: Channels"]
|
|
summary: Partially update channel settings
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/CommandMeta"
|
|
- type: object
|
|
required: [channel_id]
|
|
properties:
|
|
channel_id: { type: integer, format: int64 }
|
|
gigagroup: { type: [boolean, "null"] }
|
|
antispam: { type: [boolean, "null"] }
|
|
participants_hidden: { type: [boolean, "null"] }
|
|
noforwards: { type: [boolean, "null"] }
|
|
join_to_send: { type: [boolean, "null"] }
|
|
join_request: { type: [boolean, "null"] }
|
|
slowmode_seconds: { type: [integer, "null"] }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/channels/set-username:
|
|
post:
|
|
tags: ["AdminAPI: Channels"]
|
|
summary: Set a channel's username
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [channel_id, username], properties: { channel_id: { type: integer, format: int64 }, username: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/channels/set-color:
|
|
post:
|
|
tags: ["AdminAPI: Channels"]
|
|
summary: Set a channel's profile/name color
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [channel_id], properties: { channel_id: { type: integer, format: int64 } } }, { $ref: "#/components/schemas/PeerColorInput" }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/channels/set-emoji-status:
|
|
post:
|
|
tags: ["AdminAPI: Channels"]
|
|
summary: Set a channel's emoji status
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [channel_id], properties: { channel_id: { type: integer, format: int64 } } }, { $ref: "#/components/schemas/EmojiStatusInput" }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/bots/create:
|
|
post:
|
|
tags: ["AdminAPI: Bots & Broadcasts"]
|
|
summary: Create a bot account
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [owner_user_id, name, username], properties: { owner_user_id: { type: integer, format: int64 }, name: { type: string }, username: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/broadcasts/create:
|
|
post:
|
|
tags: ["AdminAPI: Bots & Broadcasts"]
|
|
summary: Create a broadcast
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [message, target_mode], properties: { message: { type: string }, target_mode: { type: string }, user_ids: { type: array, items: { type: integer, format: int64 } } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/bots/delete:
|
|
post:
|
|
tags: ["AdminAPI: Bots & Broadcasts"]
|
|
summary: Delete a bot account
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [bot_user_id], properties: { bot_user_id: { type: integer, format: int64 } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/bots/export-token:
|
|
post:
|
|
tags: ["AdminAPI: Bots & Broadcasts"]
|
|
summary: Export a bot's auth token
|
|
description: Requires scoped permission `bots.token.read` (or master token).
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [bot_user_id], properties: { bot_user_id: { type: integer, format: int64 } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" }, "403": { $ref: "#/components/responses/AdminApiForbidden" } }
|
|
|
|
/v1/messages/delete:
|
|
post:
|
|
tags: ["AdminAPI: Messages"]
|
|
summary: Delete specific private messages
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/CommandMeta"
|
|
- type: object
|
|
required: [owner_user_id, peer, ids]
|
|
properties:
|
|
owner_user_id: { type: integer, format: int64 }
|
|
peer: { $ref: "#/components/schemas/Peer" }
|
|
ids: { type: array, items: { type: integer } }
|
|
revoke: { type: boolean }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/messages/delete-history:
|
|
post:
|
|
tags: ["AdminAPI: Messages"]
|
|
summary: Delete a private chat's history
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/CommandMeta"
|
|
- type: object
|
|
required: [owner_user_id, peer]
|
|
properties:
|
|
owner_user_id: { type: integer, format: int64 }
|
|
peer: { $ref: "#/components/schemas/Peer" }
|
|
max_id: { type: integer }
|
|
min_date: { type: integer }
|
|
max_date: { type: integer }
|
|
just_clear: { type: boolean }
|
|
revoke: { type: boolean }
|
|
max_batches: { type: integer }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/stickers/set-archived:
|
|
post:
|
|
tags: ["AdminAPI: Stickers"]
|
|
summary: Archive/unarchive a sticker set
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [set_id, archived], properties: { set_id: { type: integer, format: int64 }, archived: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/stickers/set-sort-order:
|
|
post:
|
|
tags: ["AdminAPI: Stickers"]
|
|
summary: Reorder a sticker set
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [set_id, sort_order], properties: { set_id: { type: integer, format: int64 }, sort_order: { type: integer } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/stickers/rename:
|
|
post:
|
|
tags: ["AdminAPI: Stickers"]
|
|
summary: Rename a sticker set
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [set_id, title], properties: { set_id: { type: integer, format: int64 }, title: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/stickers/delete:
|
|
post:
|
|
tags: ["AdminAPI: Stickers"]
|
|
summary: Delete a sticker set
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [set_id], properties: { set_id: { type: integer, format: int64 } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/stickers/create:
|
|
post:
|
|
tags: ["AdminAPI: Stickers"]
|
|
summary: Create a sticker set
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required: [file, metadata]
|
|
properties:
|
|
file: { type: string, format: binary }
|
|
metadata: { description: "JSON — CommandMeta + title, short_name, kind, emoji, keywords (opt.)", type: string }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/stickers/add:
|
|
post:
|
|
tags: ["AdminAPI: Stickers"]
|
|
summary: Add a sticker to a set
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required: [file, metadata]
|
|
properties:
|
|
file: { type: string, format: binary }
|
|
metadata: { description: "JSON — CommandMeta + set_id (int64), emoji, keywords (opt.)", type: string }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/stickers/remove:
|
|
post:
|
|
tags: ["AdminAPI: Stickers"]
|
|
summary: Remove a sticker from a set
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [set_id, document_id], properties: { set_id: { type: integer, format: int64 }, document_id: { type: integer, format: int64 } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/stickers/documents/{id}/animation:
|
|
get:
|
|
tags: ["AdminAPI: Stickers"]
|
|
summary: Sticker animation
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses: { "200": { description: Animation bytes }, "400": { $ref: "#/components/responses/AdminApiCodedError" }, "404": { $ref: "#/components/responses/AdminApiCodedError" } }
|
|
|
|
/v1/gif-catalog/create:
|
|
post:
|
|
tags: ["AdminAPI: GIF Catalog"]
|
|
summary: Add a GIF catalog entry
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required: [file, metadata]
|
|
properties:
|
|
file: { type: string, format: binary }
|
|
metadata: { description: "JSON — CommandMeta + title, content_sha256 (opt.)", type: string }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/gif-catalog/set-enabled:
|
|
post:
|
|
tags: ["AdminAPI: GIF Catalog"]
|
|
summary: Enable/disable a GIF catalog entry
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [id, enabled], properties: { id: { type: integer, format: int64 }, enabled: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/gif-catalog/set-sort-order:
|
|
post:
|
|
tags: ["AdminAPI: GIF Catalog"]
|
|
summary: Reorder a GIF catalog entry
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [id, sort_order], properties: { id: { type: integer, format: int64 }, sort_order: { type: integer } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/gif-catalog/set-category:
|
|
post:
|
|
tags: ["AdminAPI: GIF Catalog"]
|
|
summary: Set a GIF catalog entry's category
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [id, category], properties: { id: { type: integer, format: int64 }, category: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/gif-catalog/auto-categorize:
|
|
post:
|
|
tags: ["AdminAPI: GIF Catalog"]
|
|
summary: Auto-categorize uncategorized GIFs
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/CommandMeta" }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/gif-catalog/delete-uncategorized:
|
|
post:
|
|
tags: ["AdminAPI: GIF Catalog"]
|
|
summary: Delete every uncategorized GIF catalog entry
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/CommandMeta" }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/gif-catalog/delete:
|
|
post:
|
|
tags: ["AdminAPI: GIF Catalog"]
|
|
summary: Delete a GIF catalog entry
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [id], properties: { id: { type: integer, format: int64 } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/gif-catalog/documents/{id}/preview:
|
|
get:
|
|
tags: ["AdminAPI: GIF Catalog"]
|
|
summary: GIF preview
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses: { "200": { description: Preview bytes }, "400": { $ref: "#/components/responses/AdminApiCodedError" }, "404": { $ref: "#/components/responses/AdminApiCodedError" } }
|
|
|
|
/v1/emoji/{id}/animation:
|
|
get:
|
|
tags: ["AdminAPI: Health"]
|
|
summary: Custom emoji Lottie animation
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses: { "200": { description: "Animation JSON bytes (Content-Type forced to application/json)" }, "400": { $ref: "#/components/responses/AdminApiCodedError" }, "404": { $ref: "#/components/responses/AdminApiCodedError" } }
|
|
|
|
/v1/storage/manual-purge:
|
|
post:
|
|
tags: ["AdminAPI: Storage"]
|
|
summary: Manually purge storage by category
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/CommandMeta"
|
|
- type: object
|
|
required: [categories]
|
|
properties:
|
|
categories:
|
|
type: array
|
|
items: { type: string, enum: [photo, video, round_video, gif, music, voice, file] }
|
|
include_avatars: { type: boolean }
|
|
created_before: { type: [string, "null"], format: date-time, description: "RFC3339; null = no age filter" }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/moderation/cases:
|
|
get:
|
|
tags: ["AdminAPI: Moderation"]
|
|
summary: List moderation cases
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters:
|
|
- { name: limit, in: query, schema: { type: integer, default: 50 } }
|
|
- { name: assigned_to, in: query, schema: { type: string } }
|
|
- { name: statuses, in: query, description: comma-separated, schema: { type: string } }
|
|
- { name: target_type, in: query, schema: { type: string } }
|
|
- { name: target_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { name: before_updated_at, in: query, schema: { type: string, format: date-time } }
|
|
- { name: before_id, in: query, schema: { type: integer, format: int64 } }
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, properties: { cases: { type: array, items: { type: object, additionalProperties: true } } } } } } }
|
|
|
|
/v1/moderation/cases/{id}:
|
|
get:
|
|
tags: ["AdminAPI: Moderation"]
|
|
summary: Moderation case detail
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses:
|
|
"200": { description: "domain.ModerationCaseDetail (Decisions/Actions/Appeals nil-normalized to [])", content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"404": { $ref: "#/components/responses/AdminApiModerationError" }
|
|
|
|
/v1/moderation/reports/{id}:
|
|
get:
|
|
tags: ["AdminAPI: Moderation"]
|
|
summary: Moderation report detail
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses:
|
|
"200": { description: "domain.ModerationReport", content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"404": { $ref: "#/components/responses/AdminApiModerationError" }
|
|
|
|
/v1/moderation/cases/{id}/claim:
|
|
post:
|
|
tags: ["AdminAPI: Moderation"]
|
|
summary: Claim a moderation case
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [expected_version, actor]
|
|
properties: { expected_version: { type: integer, format: int64 }, actor: { type: string } }
|
|
responses:
|
|
"200": { description: "domain.ModerationCase", content: { application/json: { schema: { type: object, additionalProperties: true } } } }
|
|
"409": { $ref: "#/components/responses/AdminApiModerationError" }
|
|
|
|
/v1/moderation/cases/{id}/decide:
|
|
post:
|
|
tags: ["AdminAPI: Moderation"]
|
|
summary: Decide a moderation case
|
|
description: >-
|
|
`kind` = domain.ModerationDecisionKind. `actions[].kind` includes
|
|
`restrict_account`/`unrestrict_account` (the account spam-restriction
|
|
sanction), `freeze_account`/`unfreeze_account`, `mark_scam`,
|
|
`mark_fake`, `clear_peer_flags`, `delete_private_message`,
|
|
`delete_channel_message`, `delete_account`.
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [expected_version, actor, reason, kind]
|
|
properties:
|
|
expected_version: { type: integer, format: int64 }
|
|
actor: { type: string }
|
|
reason: { type: string }
|
|
command_id: { type: string }
|
|
kind: { type: string, description: "domain.ModerationDecisionKind" }
|
|
actions:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
kind: { type: string, description: "domain.ModerationActionKind, e.g. restrict_account" }
|
|
payload: { type: object, additionalProperties: true }
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, properties: { created: { type: boolean }, case: { type: object, additionalProperties: true } } } } } }
|
|
"400": { $ref: "#/components/responses/AdminApiModerationError" }
|
|
"409": { $ref: "#/components/responses/AdminApiModerationError" }
|
|
|
|
/v1/moderation/cases/{id}/appeals:
|
|
post:
|
|
tags: ["AdminAPI: Moderation"]
|
|
summary: Submit an appeal on a moderation case
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [appellant_user_id, text]
|
|
properties: { appellant_user_id: { type: integer, format: int64 }, text: { type: string } }
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, properties: { created: { type: boolean }, appeal: { type: object, additionalProperties: true } } } } } }
|
|
|
|
/v1/moderation/cases/{id}/appeals/{appeal_id}/review:
|
|
post:
|
|
tags: ["AdminAPI: Moderation"]
|
|
summary: Review an appeal
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters:
|
|
- { $ref: "#/components/parameters/PathId" }
|
|
- { name: appeal_id, in: path, required: true, schema: { type: integer, format: int64 } }
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [expected_version, actor, reason, granted]
|
|
properties:
|
|
expected_version: { type: integer, format: int64 }
|
|
actor: { type: string }
|
|
reason: { type: string }
|
|
command_id: { type: string }
|
|
granted: { type: boolean, description: "maps to ModerationDecisionAppealGrant/Deny" }
|
|
actions:
|
|
type: array
|
|
items: { type: object, properties: { kind: { type: string }, payload: { type: object, additionalProperties: true } } }
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, properties: { created: { type: boolean }, case: { type: object, additionalProperties: true } } } } } }
|
|
"409": { $ref: "#/components/responses/AdminApiModerationError" }
|
|
|
|
/v1/collectible-usernames/mint:
|
|
post:
|
|
tags: ["AdminAPI: Collectible Usernames"]
|
|
summary: Mint a collectible username
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/CommandMeta"
|
|
- type: object
|
|
required: [username, currency, amount]
|
|
properties:
|
|
username: { type: string }
|
|
owner_user_id: { type: string, description: "int64 as decimal string; at most one owner_*" }
|
|
owner_channel_id: { type: string, description: "int64 as decimal string" }
|
|
currency: { type: string }
|
|
amount: { type: string, description: "int64 as decimal string" }
|
|
crypto_currency: { type: string }
|
|
crypto_amount: { type: string, description: "int64 as decimal string" }
|
|
url: { type: string }
|
|
purchase_date: { type: integer, format: int64, description: "unix seconds" }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/collectible-usernames/transfer:
|
|
post:
|
|
tags: ["AdminAPI: Collectible Usernames"]
|
|
summary: Transfer a collectible username
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [username], properties: { username: { type: string }, to_user_id: { type: string, description: "int64 as decimal string" }, to_channel_id: { type: string, description: "int64 as decimal string" } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/collectible-usernames/revoke:
|
|
post:
|
|
tags: ["AdminAPI: Collectible Usernames"]
|
|
summary: Revoke (or burn) a collectible username
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [username], properties: { username: { type: string }, expected_owner_user_id: { type: string, description: "int64 as decimal string" }, burn: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/collectible-usernames/delete:
|
|
post:
|
|
tags: ["AdminAPI: Collectible Usernames"]
|
|
summary: Delete a collectible username
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [username], properties: { username: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/collectible-usernames:
|
|
get:
|
|
tags: ["AdminAPI: Collectible Usernames"]
|
|
summary: List collectible usernames
|
|
description: All int64 ids/amounts in the response are decimal strings, to avoid float64 precision loss.
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters:
|
|
- { name: status, in: query, schema: { type: string } }
|
|
- { name: q, in: query, schema: { type: string } }
|
|
- { name: owner_user_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { name: owner_channel_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
- { name: before_id, in: query, schema: { type: integer, format: int64 } }
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, properties: { assets: { type: array, items: { type: object, additionalProperties: true } } } } } } }
|
|
"400": { $ref: "#/components/responses/AdminApiCollectibleError" }
|
|
|
|
/v1/collectible-usernames/{id}:
|
|
get:
|
|
tags: ["AdminAPI: Collectible Usernames"]
|
|
summary: Collectible username detail + transfer log
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters:
|
|
- { $ref: "#/components/parameters/PathId" }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
responses:
|
|
"200":
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
asset: { type: object, additionalProperties: true }
|
|
transfers: { type: array, items: { type: object, additionalProperties: true } }
|
|
"404": { $ref: "#/components/responses/AdminApiCollectibleError" }
|
|
|
|
/v1/reserved-usernames/reserve:
|
|
post:
|
|
tags: ["AdminAPI: Reserved Usernames"]
|
|
summary: Add a username to the operator reserved-username blocklist
|
|
description: >-
|
|
`Username` is sent with a **capitalized, untagged** JSON key
|
|
(`{"Username": "..."}`, not `username`) — a source-level quirk
|
|
(missing `json:` struct tag), not a spec error. Every other request
|
|
body in this document uses lowercase `snake_case` keys.
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [Username], properties: { Username: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/reserved-usernames/unreserve:
|
|
post:
|
|
tags: ["AdminAPI: Reserved Usernames"]
|
|
summary: Remove a username from the operator reserved-username blocklist
|
|
description: Same `Username` (capitalized, untagged) quirk as `/v1/reserved-usernames/reserve`.
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [Username], properties: { Username: { type: string } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" } }
|
|
|
|
/v1/reserved-usernames:
|
|
get:
|
|
tags: ["AdminAPI: Reserved Usernames"]
|
|
summary: List reserved usernames
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters:
|
|
- { name: q, in: query, schema: { type: string } }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
- { name: offset, in: query, schema: { type: integer } }
|
|
responses:
|
|
"200":
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
reserved:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
username: { type: string }
|
|
reason: { type: string }
|
|
actor: { type: string }
|
|
created_at: { type: integer, format: int64, description: unix seconds }
|
|
"500": { description: "list failed", content: { application/json: { schema: { $ref: "#/components/schemas/ErrorEnvelope" } } } }
|
|
|
|
/v1/verification/applications:
|
|
get:
|
|
tags: ["AdminAPI: Official Verification"]
|
|
summary: List official-verification applications
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters:
|
|
- { name: target_type, in: query, schema: { type: string } }
|
|
- { name: reviewer, in: query, schema: { type: string } }
|
|
- { name: q, in: query, schema: { type: string } }
|
|
- { name: status, in: query, description: comma-separated, schema: { type: string } }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
- { name: before_id, in: query, schema: { type: integer, format: int64 } }
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, properties: { applications: { type: array, items: { type: object, additionalProperties: true } } } } } } }
|
|
"403": { $ref: "#/components/responses/AdminApiForbidden" }
|
|
|
|
/v1/verification/applications/{id}:
|
|
get:
|
|
tags: ["AdminAPI: Official Verification"]
|
|
summary: Application detail
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters:
|
|
- { $ref: "#/components/parameters/PathId" }
|
|
- { name: limit, in: query, description: events, schema: { type: integer } }
|
|
responses:
|
|
"200":
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
application: { type: object, additionalProperties: true }
|
|
events: { type: array, items: { type: object, additionalProperties: true } }
|
|
target: { type: object, additionalProperties: true }
|
|
target_error: { type: string }
|
|
"403": { $ref: "#/components/responses/AdminApiForbidden" }
|
|
|
|
/v1/verification/counts:
|
|
get:
|
|
tags: ["AdminAPI: Official Verification"]
|
|
summary: Application counts by status
|
|
security: [{ adminApiBearer: [] }]
|
|
responses:
|
|
"200": { description: OK, content: { application/json: { schema: { type: object, properties: { counts: { type: object, additionalProperties: { type: string } } } } } } }
|
|
"403": { $ref: "#/components/responses/AdminApiForbidden" }
|
|
|
|
/v1/verification/applications/{id}/claim:
|
|
post:
|
|
tags: ["AdminAPI: Official Verification"]
|
|
summary: Claim an application
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
requestBody: { $ref: "#/components/requestBodies/AdminApiVersionedNote" }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" }, "403": { $ref: "#/components/responses/AdminApiForbidden" }, "409": { $ref: "#/components/responses/AdminApiVerificationError" } }
|
|
|
|
/v1/verification/applications/{id}/approve:
|
|
post:
|
|
tags: ["AdminAPI: Official Verification"]
|
|
summary: Approve an application (grants the badge)
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
requestBody: { $ref: "#/components/requestBodies/AdminApiVersionedNote" }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" }, "403": { $ref: "#/components/responses/AdminApiForbidden" }, "409": { $ref: "#/components/responses/AdminApiVerificationError" } }
|
|
|
|
/v1/verification/applications/{id}/reject:
|
|
post:
|
|
tags: ["AdminAPI: Official Verification"]
|
|
summary: Reject an application
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
requestBody: { $ref: "#/components/requestBodies/AdminApiVersionedNote" }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" }, "403": { $ref: "#/components/responses/AdminApiForbidden" }, "409": { $ref: "#/components/responses/AdminApiVerificationError" } }
|
|
|
|
/v1/verification/revoke:
|
|
post:
|
|
tags: ["AdminAPI: Official Verification"]
|
|
summary: Strip an official-verification badge
|
|
description: Requires BOTH `verification.review` and `verification.revoke` (or master token). Addresses the target directly, not an application id.
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/CommandMeta"
|
|
- type: object
|
|
required: [target_type, target_id]
|
|
properties:
|
|
target_type: { type: string, description: "domain.VerificationTargetType" }
|
|
target_id: { type: integer, format: int64 }
|
|
internal_note: { type: string }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" }, "403": { $ref: "#/components/responses/AdminApiForbidden" } }
|
|
|
|
/v1/botverification/verifiers:
|
|
get:
|
|
tags: ["AdminAPI: Bot Verification"]
|
|
summary: List third-party verifier bots
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters:
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
- { name: enabled_only, in: query, schema: { type: string, description: "1/true/yes/on" } }
|
|
responses:
|
|
"200": { description: "PascalCase fields: BotID, IconDocumentID, CompanyName, ... (id/version fields as decimal strings)", content: { application/json: { schema: { type: object, properties: { rows: { type: array, items: { type: object, additionalProperties: true } } } } } } }
|
|
"403": { $ref: "#/components/responses/AdminApiForbidden" }
|
|
|
|
/v1/botverification/icons:
|
|
get:
|
|
tags: ["AdminAPI: Bot Verification"]
|
|
summary: List verification icon catalog
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters:
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
- { name: active_only, in: query, schema: { type: string } }
|
|
responses:
|
|
"200": { description: "PascalCase fields: ID, DocumentID, OwnerBotID, Name, Active, ...", content: { application/json: { schema: { type: object, properties: { rows: { type: array, items: { type: object, additionalProperties: true } } } } } } }
|
|
"403": { $ref: "#/components/responses/AdminApiForbidden" }
|
|
|
|
/v1/botverification/marks:
|
|
get:
|
|
tags: ["AdminAPI: Bot Verification"]
|
|
summary: List active third-party marks
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters:
|
|
- { name: peer_type, in: query, schema: { type: string, enum: [user, channel] } }
|
|
- { name: verifier_bot_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { name: before_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
- { name: q, in: query, schema: { type: string } }
|
|
responses:
|
|
"200": { description: "PascalCase fields: ID, VerifierBotID, PeerType, PeerID, ...", content: { application/json: { schema: { type: object, properties: { rows: { type: array, items: { type: object, additionalProperties: true } }, has_more: { type: boolean }, next_before_id: { type: string } } } } } }
|
|
"403": { $ref: "#/components/responses/AdminApiForbidden" }
|
|
|
|
/v1/botverification/requests:
|
|
get:
|
|
tags: ["AdminAPI: Bot Verification"]
|
|
summary: List third-party verification requests
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters:
|
|
- { name: peer_type, in: query, schema: { type: string } }
|
|
- { name: status, in: query, description: comma-separated, schema: { type: string } }
|
|
- { name: verifier_bot_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { name: before_id, in: query, schema: { type: integer, format: int64 } }
|
|
- { $ref: "#/components/parameters/Limit" }
|
|
- { name: q, in: query, schema: { type: string } }
|
|
responses:
|
|
"200": { description: "PascalCase fields incl. ApplicantUserID, PeerTitle/Username, Reason, Status, InternalNote, ...", content: { application/json: { schema: { type: object, properties: { rows: { type: array, items: { type: object, additionalProperties: true } }, has_more: { type: boolean }, next_before_id: { type: string } } } } } }
|
|
"403": { $ref: "#/components/responses/AdminApiForbidden" }
|
|
|
|
/v1/botverification/requests/{id}:
|
|
get:
|
|
tags: ["AdminAPI: Bot Verification"]
|
|
summary: Request detail
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
responses:
|
|
"200":
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
request: { type: object, additionalProperties: true }
|
|
verifier: { type: object, additionalProperties: true, description: "present even if verifier is gone" }
|
|
verifier_error: { type: string }
|
|
mark_active: { type: boolean }
|
|
mark_error: { type: string }
|
|
"403": { $ref: "#/components/responses/AdminApiForbidden" }
|
|
"404": { $ref: "#/components/responses/AdminApiBotVerificationError" }
|
|
|
|
/v1/botverification/counts:
|
|
get:
|
|
tags: ["AdminAPI: Bot Verification"]
|
|
summary: Request counts by status
|
|
security: [{ adminApiBearer: [] }]
|
|
responses:
|
|
"200": { description: "counts for pending/approved/rejected/revoked, zero-filled", content: { application/json: { schema: { type: object, properties: { counts: { type: object, additionalProperties: { type: string } } } } } } }
|
|
"403": { $ref: "#/components/responses/AdminApiForbidden" }
|
|
|
|
/v1/botverification/requests/{id}/approve:
|
|
post:
|
|
tags: ["AdminAPI: Bot Verification"]
|
|
summary: Approve a third-party verification request
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
requestBody: { $ref: "#/components/requestBodies/AdminApiVersionedNote" }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" }, "403": { $ref: "#/components/responses/AdminApiForbidden" }, "409": { $ref: "#/components/responses/AdminApiBotVerificationError" } }
|
|
|
|
/v1/botverification/requests/{id}/reject:
|
|
post:
|
|
tags: ["AdminAPI: Bot Verification"]
|
|
summary: Reject a third-party verification request
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
requestBody: { $ref: "#/components/requestBodies/AdminApiVersionedNote" }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" }, "403": { $ref: "#/components/responses/AdminApiForbidden" }, "409": { $ref: "#/components/responses/AdminApiBotVerificationError" } }
|
|
|
|
/v1/botverification/requests/{id}/revoke:
|
|
post:
|
|
tags: ["AdminAPI: Bot Verification"]
|
|
summary: Revoke a granted third-party verification
|
|
security: [{ adminApiBearer: [] }]
|
|
parameters: [{ $ref: "#/components/parameters/PathId" }]
|
|
requestBody: { $ref: "#/components/requestBodies/AdminApiVersionedNote" }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" }, "403": { $ref: "#/components/responses/AdminApiForbidden" }, "409": { $ref: "#/components/responses/AdminApiBotVerificationError" } }
|
|
|
|
/v1/botverification/verifiers/grant:
|
|
post:
|
|
tags: ["AdminAPI: Bot Verification"]
|
|
summary: Appoint a bot as a third-party verifier
|
|
description: Requires `botverification.manage`.
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/CommandMeta"
|
|
- type: object
|
|
required: [bot_id, company_name, version]
|
|
properties:
|
|
bot_id: { type: integer, format: int64 }
|
|
icon_document_id: { type: integer, format: int64 }
|
|
company_name: { type: string }
|
|
default_description: { type: string }
|
|
can_modify_custom_description: { type: boolean }
|
|
version: { type: integer, format: int64, description: "0 = new grant" }
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" }, "403": { $ref: "#/components/responses/AdminApiForbidden" } }
|
|
|
|
/v1/botverification/verifiers/set-enabled:
|
|
post:
|
|
tags: ["AdminAPI: Bot Verification"]
|
|
summary: Enable/disable a verifier bot
|
|
description: Requires `botverification.manage`.
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [bot_id, enabled], properties: { bot_id: { type: integer, format: int64 }, enabled: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" }, "403": { $ref: "#/components/responses/AdminApiForbidden" } }
|
|
|
|
/v1/botverification/verifiers/revoke:
|
|
post:
|
|
tags: ["AdminAPI: Bot Verification"]
|
|
summary: Strip a bot's verifier status
|
|
description: Requires `botverification.manage`.
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [bot_id], properties: { bot_id: { type: integer, format: int64 } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" }, "403": { $ref: "#/components/responses/AdminApiForbidden" } }
|
|
|
|
/v1/botverification/icons/upsert:
|
|
post:
|
|
tags: ["AdminAPI: Bot Verification"]
|
|
summary: Add/edit a verification-icon catalog entry
|
|
description: Requires `botverification.manage`.
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [document_id, name], properties: { document_id: { type: integer, format: int64 }, name: { type: string }, owner_bot_id: { type: integer, format: int64 } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" }, "403": { $ref: "#/components/responses/AdminApiForbidden" } }
|
|
|
|
/v1/botverification/icons/set-active:
|
|
post:
|
|
tags: ["AdminAPI: Bot Verification"]
|
|
summary: Enable/disable a verification icon
|
|
description: Requires `botverification.manage`.
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [icon_id, active], properties: { icon_id: { type: integer, format: int64 }, active: { type: boolean } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" }, "403": { $ref: "#/components/responses/AdminApiForbidden" } }
|
|
|
|
/v1/botverification/marks/revoke:
|
|
post:
|
|
tags: ["AdminAPI: Bot Verification"]
|
|
summary: Strip a third-party mark from a peer
|
|
description: Requires `botverification.manage`.
|
|
security: [{ adminApiBearer: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf: [{ $ref: "#/components/schemas/CommandMeta" }, { type: object, required: [verifier_bot_id, peer_type, peer_id], properties: { verifier_bot_id: { type: integer, format: int64 }, peer_type: { type: string, enum: [user, channel] }, peer_id: { type: integer, format: int64 } } }]
|
|
responses: { "200": { $ref: "#/components/responses/AdminApiCommandOK" }, "403": { $ref: "#/components/responses/AdminApiForbidden" } }
|
|
|
|
components:
|
|
securitySchemes:
|
|
panelSession:
|
|
type: apiKey
|
|
in: cookie
|
|
name: telesrv_admin_session
|
|
description: Signed session cookie issued by POST /api/login. 12h default TTL, no server-side store.
|
|
panelCsrf:
|
|
type: apiKey
|
|
in: header
|
|
name: X-CSRF-Token
|
|
description: >-
|
|
Must match the telesrv_admin_csrf cookie's value. Required on every
|
|
mutating panel request except POST /api/login. Origin header is also
|
|
checked when present.
|
|
adminApiBearer:
|
|
type: http
|
|
scheme: bearer
|
|
description: >-
|
|
The master token (TELESRV_ADMIN_API_TOKEN, implicit "*" permission)
|
|
or a scoped token (TELESRV_ADMIN_SCOPED_TOKENS) carrying specific
|
|
permissions. Compared with subtle.ConstantTimeCompare against every
|
|
configured token unconditionally, to avoid timing side-channels.
|
|
|
|
parameters:
|
|
PathId:
|
|
name: id
|
|
in: path
|
|
required: true
|
|
schema: { type: integer, format: int64 }
|
|
Limit:
|
|
name: limit
|
|
in: query
|
|
schema: { type: integer }
|
|
|
|
requestBodies:
|
|
PanelVersionedDecision:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/PanelCommandFields"
|
|
- type: object
|
|
required: [version]
|
|
properties:
|
|
version: { $ref: "#/components/schemas/FlexInt64" }
|
|
internal_note: { type: string }
|
|
PanelUserAvatarUpload:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required: [metadata, file]
|
|
properties:
|
|
metadata:
|
|
description: "JSON — common fields + user_id (int64)"
|
|
type: string
|
|
file: { type: string, format: binary }
|
|
PanelAdminUserAction:
|
|
description: >-
|
|
Shared by create/update-access/set-password for a named admin
|
|
operator account. `reason` is mandatory here specifically
|
|
(`decodeAdminUserAction` 400s on blank reason), stricter than the
|
|
generic action envelope.
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/PanelCommandFields"
|
|
- type: object
|
|
properties:
|
|
id: { type: integer, format: int64 }
|
|
username: { type: string }
|
|
password: { type: string }
|
|
permissions: { type: array, items: { type: string } }
|
|
enabled: { type: [boolean, "null"] }
|
|
PanelSetFrozen:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/PanelCommandFields"
|
|
- type: object
|
|
required: [user_id, frozen]
|
|
properties:
|
|
user_id: { type: integer, format: int64 }
|
|
frozen: { type: boolean }
|
|
freeze_until: { type: string, format: date-time }
|
|
freeze_appeal_url: { type: string }
|
|
AdminApiVersionedNote:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/CommandMeta"
|
|
- type: object
|
|
required: [version]
|
|
properties:
|
|
version: { type: integer, format: int64 }
|
|
internal_note: { type: string }
|
|
|
|
responses:
|
|
PanelUnauthorized:
|
|
description: >-
|
|
Missing/expired session (`{"error":"not authenticated"}`), or a
|
|
named-account session invalidated server-side since it was issued —
|
|
password changed, permissions edited, or account disabled — caught
|
|
on every request by re-checking `admin_console_users` against the
|
|
session's `epoch` claim (`{"error":"session is no longer valid"}`).
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/ErrorEnvelope" } } }
|
|
PanelForbidden:
|
|
description: >-
|
|
Missing/mismatched CSRF cookie or header, Origin mismatch (plain
|
|
`ErrorEnvelope`), or an authenticated session lacking the required
|
|
permission (`PermissionErrorEnvelope`, adds a `permission` field —
|
|
`{"error":"permission accounts.manage is required","code":"FORBIDDEN","permission":"accounts.manage"}`).
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/PermissionErrorEnvelope" } } }
|
|
PanelNotFound:
|
|
description: Not found
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/ErrorEnvelope" } } }
|
|
PanelConflict:
|
|
description: >-
|
|
Optimistic-locking conflict — another reviewer already decided this
|
|
row, or `version` is stale. Only the verification/bot-verification
|
|
decision routes preserve this status from the upstream Admin API;
|
|
every other action route flattens upstream errors to 502 instead
|
|
(see `PanelActionUpstreamError`).
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/CommandResult" } } }
|
|
PanelActionOK:
|
|
description: >-
|
|
Command accepted. Response body is the same `CommandResult` shape
|
|
the Admin API returns — the panel relays it as-is from
|
|
`callAdminAPI`/`callAdminMultipart`/`callAdminCommand`, or builds an
|
|
equivalent `CommandResult` locally for the handful of actions that
|
|
operate on local state (admin operators, server settings) instead
|
|
of calling through to the Admin API.
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/CommandResult" } } }
|
|
PanelActionUpstreamError:
|
|
description: >-
|
|
The upstream Admin API call failed (transport error, or the command
|
|
itself failed). `writeCommandResultAPI` answers this as HTTP 502
|
|
with `CommandResult{Status:"failed", Error: <upstream message>}` —
|
|
NOT the upstream's own status code. Verification and bot-verification
|
|
decision routes are the exception: they preserve the real upstream
|
|
status (404/409/429/400) instead of flattening to 502.
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/CommandResult" } } }
|
|
PanelCursorList:
|
|
description: Cursor-paginated list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
query: { type: string }
|
|
limit: { type: integer }
|
|
rows: { type: array, items: { type: object, additionalProperties: true } }
|
|
has_more: { type: boolean }
|
|
next_before_id: { type: integer, format: int64 }
|
|
listing: { type: object, additionalProperties: true }
|
|
AdminApiCommandOK:
|
|
description: >-
|
|
Command result. Success is HTTP 200; a failed command (err != nil)
|
|
is answered as HTTP 400 (not 500) by the shared writeCommandResult
|
|
helper, with the same CommandResult body shape (Status:"failed").
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/CommandResult" } } }
|
|
AdminApiCommandError:
|
|
description: Command failed (validation or execution error)
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/CommandResult" } } }
|
|
AdminApiForbidden:
|
|
description: Missing bearer token, or token lacks the required permission
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/PermissionErrorEnvelope" } } }
|
|
AdminApiCodedError:
|
|
description: Coded error envelope
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/CodedErrorEnvelope" } } }
|
|
AdminApiModerationError:
|
|
description: Moderation-family coded error (404/403/409/429/400/500 depending on admin.Code*)
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/CodedErrorEnvelope" } } }
|
|
AdminApiCollectibleError:
|
|
description: Collectible-username coded error (404/409/400/500 depending on admin.Code*)
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/CodedErrorEnvelope" } } }
|
|
AdminApiVerificationError:
|
|
description: >-
|
|
Official-verification coded error. Status derives from
|
|
admin.VerificationErrorCode: NotFound→404;
|
|
Conflict/TargetOccupied/TargetVerified→409;
|
|
{StatusInvalid,ReasonRequired,TargetInvalid,TargetNotPublic,TargetRestricted,TargetSystem,NotOwner,UserTargetsDisabled,Invalid}→400;
|
|
default→400 (forced down from 500 on the command path). On conflict,
|
|
`message` is overwritten with a "reload and decide again" prompt.
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/CommandResult" } } }
|
|
AdminApiBotVerificationError:
|
|
description: >-
|
|
Bot-verification coded error. Status derives from
|
|
admin.BotVerificationErrorCode: *NotFound codes→404;
|
|
{Conflict,Limit,RequestExists}→409; RateLimited→429;
|
|
{Forbidden,DescriptionForbidden,Invalid,IconInactive,IconInvalid,StatusInvalid,ReasonRequired,TargetInvalid,TargetSystem,VerificationInvalid}→400
|
|
(explicitly 400 not 403 — the refusal is about the *subject* bot/peer,
|
|
not the caller's authorization); default→400.
|
|
content: { application/json: { schema: { $ref: "#/components/schemas/CommandResult" } } }
|
|
|
|
schemas:
|
|
ErrorEnvelope:
|
|
type: object
|
|
required: [error]
|
|
properties:
|
|
error: { type: string }
|
|
code: { type: string }
|
|
CodedErrorEnvelope:
|
|
allOf:
|
|
- $ref: "#/components/schemas/ErrorEnvelope"
|
|
- type: object
|
|
required: [code]
|
|
PermissionErrorEnvelope:
|
|
allOf:
|
|
- $ref: "#/components/schemas/ErrorEnvelope"
|
|
- type: object
|
|
properties:
|
|
permission: { type: string, description: "present on 403s from a missing-permission check" }
|
|
|
|
PanelCommandFields:
|
|
type: object
|
|
description: Common fields on every Panel API POST /api/actions/* (and moderation/verification decision) body.
|
|
required: [reason, confirm]
|
|
properties:
|
|
command_id: { type: string, description: "Idempotency key; server-generated if omitted." }
|
|
reason: { type: string, description: "Mandatory audit reason." }
|
|
confirm: { type: boolean, description: "Operator confirmation; must be true." }
|
|
|
|
FlexInt64:
|
|
description: >-
|
|
Accepts either a JSON number or a numeric JSON string (custom
|
|
UnmarshalJSON on the Go side, `flexInt64`) — used for Telegram-scale
|
|
ids where a bare JSON number risks float64 precision loss in JS.
|
|
Distinct from a `json:",string"`-tagged field (see field
|
|
descriptions), which requires a JSON string specifically.
|
|
oneOf:
|
|
- { type: integer, format: int64 }
|
|
- { type: string }
|
|
FlexUnix:
|
|
description: >-
|
|
Accepts a JSON number (unix seconds), or a string — either a numeric
|
|
unix-seconds string or an RFC3339 date (`flexUnix`).
|
|
oneOf:
|
|
- { type: integer, format: int64, description: unix seconds }
|
|
- { type: string, description: "numeric unix-seconds string, or RFC3339" }
|
|
|
|
CommandMeta:
|
|
type: object
|
|
description: Common fields embedded in nearly every Admin API (internal/adminapi) request body.
|
|
properties:
|
|
command_id: { type: string, description: "Idempotency key." }
|
|
actor: { type: string, description: "Auto-filled from the scoped-token principal name if omitted." }
|
|
reason: { type: string }
|
|
dry_run: { type: boolean }
|
|
|
|
CommandResult:
|
|
type: object
|
|
description: Response shape for nearly every Admin API POST route.
|
|
properties:
|
|
command_id: { type: string }
|
|
action: { type: string }
|
|
status: { type: string }
|
|
already_executed: { type: boolean }
|
|
dry_run: { type: boolean }
|
|
target_user_id: { type: integer, format: int64 }
|
|
target_peer: { $ref: "#/components/schemas/Peer" }
|
|
message: { type: string }
|
|
details: { type: object, additionalProperties: true }
|
|
error: { type: string }
|
|
|
|
Peer:
|
|
type: object
|
|
properties:
|
|
Type: { type: string, description: "domain.PeerType, e.g. user/channel/chat" }
|
|
ID: { type: integer, format: int64 }
|
|
|
|
PeerColorInput:
|
|
type: object
|
|
description: Shared shape for every *-set-color request (accounts/channels, both APIs).
|
|
properties:
|
|
for_profile: { type: boolean }
|
|
has_color: { type: boolean }
|
|
color: { type: integer }
|
|
background_emoji_id: { type: integer, format: int64, description: "sent with json:\",string\" on the Admin API side" }
|
|
|
|
EmojiStatusInput:
|
|
type: object
|
|
description: Shared shape for every *-set-emoji-status request (accounts/channels, both APIs).
|
|
properties:
|
|
document_id: { type: integer, format: int64, description: "sent with json:\",string\" on the Admin API side" }
|
|
until: { type: integer, description: unix seconds }
|
|
|
|
AccountRow:
|
|
type: object
|
|
description: >-
|
|
`cmd/telesrv-admin/readstore.go` AccountRow — fields are NOT JSON-tagged,
|
|
so they serialize with Go's default PascalCase field names, not
|
|
snake_case like the rest of this API.
|
|
properties:
|
|
ID: { type: integer, format: int64 }
|
|
Phone: { type: string }
|
|
Username: { type: string }
|
|
FirstName: { type: string }
|
|
LastName: { type: string }
|
|
Collectibles:
|
|
type: array
|
|
description: Collectible usernames in display order; distinct from the editable Username slot.
|
|
items:
|
|
type: object
|
|
properties: { Username: { type: string }, Active: { type: boolean } }
|
|
CreatedAt: { type: string, format: date-time }
|
|
UpdatedAt: { type: string, format: date-time }
|
|
Frozen: { type: boolean }
|
|
Reason: { type: string, description: "The freeze reason given when Frozen was last set true. Empty if never frozen." }
|
|
Verified: { type: boolean }
|
|
Scam: { type: boolean }
|
|
Fake: { type: boolean }
|
|
PremiumUntil: { type: integer, format: int64 }
|
|
LastActiveAt: { type: string, format: date-time }
|
|
DeviceCount: { type: integer }
|
|
LoginEmail: { type: string }
|