Skip to content
Hoody.com

Register a channel bot into a container, start and stop its long-polling worker, manage its channel surface (commands and profile), read and set its admission policy, audit what it has done, and revoke chat-user sessions or every token lineage at once.

Every operation on this page is a management-class endpoint. Calls require Authorization: Bearer <your own Hoody token>, and the calling account must own the container the kit runs in. The channel bot token is sent once in the register body over HTTPS, verified with the channel, stored encrypted on the container, and never echoed back or logged. A new registration is created stopped; run hoody bot start <registration> to begin polling.

Use these four endpoints to create a registration, list what you have, read one, and delete it. The channel bot token is sent once in the register body; what comes back is the registration without its token.

List the registrations owned by the calling account.

This endpoint takes no parameters.

Terminal window
curl -X GET \
"https://{projectId}-{containerId}-bot-1.{server}.containers.hoody.com/api/v1/bot/registrations" \
-H "Authorization: Bearer $HOODY_TOKEN"

The channel bot token is read on the client side and sent in this body over HTTPS. It is verified with the channel, stored encrypted and never echoed. What comes back is the registration without its token.

NameTypeRequiredDescription
channelstringYesThe channel the bot is registered with. The only supported value is telegram.
tokenstringYesThe channel bot token. Read on the client side and sent over HTTPS; the kit verifies it with the channel, encrypts it on the container, and never echoes it.
labelstringNoA short operator label (up to 64 characters).
Terminal window
curl -X POST \
"https://{projectId}-{containerId}-bot-1.{server}.containers.hoody.com/api/v1/bot/registrations" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"channel": "telegram",
"token": "7123456789:AAF-AAaBcDeFgHiJkLmNoPqRsTuVwXyZ",
"label": "AcmeBot"
}'

GET /api/v1/bot/registrations/{registrationId}

Section titled “GET /api/v1/bot/registrations/{registrationId}”

Read one registration.

NameInTypeRequiredDescription
registrationIdpathstringYesRegistration id returned by register or list.
Terminal window
curl -X GET \
"https://{projectId}-{containerId}-bot-1.{server}.containers.hoody.com/api/v1/bot/registrations/{registrationId}" \
-H "Authorization: Bearer $HOODY_TOKEN"

DELETE /api/v1/bot/registrations/{registrationId}

Section titled “DELETE /api/v1/bot/registrations/{registrationId}”

Deletes the registration and its stored channel token, and stops its poller.

NameInTypeRequiredDescription
registrationIdpathstringYesRegistration id returned by register or list.
Terminal window
curl -X DELETE \
"https://{projectId}-{containerId}-bot-1.{server}.containers.hoody.com/api/v1/bot/registrations/{registrationId}" \
-H "Authorization: Bearer $HOODY_TOKEN"

The registration state is stored as running or stopped, so a started registration comes back up at the next start of the kit. The long-polling worker is brought up here.

POST /api/v1/bot/registrations/{registrationId}/start

Section titled “POST /api/v1/bot/registrations/{registrationId}/start”

Records the intent to poll and starts the worker. The registration state is stored, so a started registration is brought back up at the next start of the kit.

NameInTypeRequiredDescription
registrationIdpathstringYesRegistration id returned by register or list.
Terminal window
curl -X POST \
"https://{projectId}-{containerId}-bot-1.{server}.containers.hoody.com/api/v1/bot/registrations/{registrationId}/start" \
-H "Authorization: Bearer $HOODY_TOKEN"

POST /api/v1/bot/registrations/{registrationId}/stop

Section titled “POST /api/v1/bot/registrations/{registrationId}/stop”

Stop long-polling for a registration. The registration and its stored channel token are kept.

NameInTypeRequiredDescription
registrationIdpathstringYesRegistration id returned by register or list.
Terminal window
curl -X POST \
"https://{projectId}-{containerId}-bot-1.{server}.containers.hoody.com/api/v1/bot/registrations/{registrationId}/stop" \
-H "Authorization: Bearer $HOODY_TOKEN"

Two operations publish the bot’s surface to the channel: the registered commands and the bot profile (name, descriptions, default admin rights). The profile is stored before it is published, so a channel failure leaves the stored value ready to be republished by repeating the request.

POST /api/v1/bot/registrations/{registrationId}/commands/sync

Section titled “POST /api/v1/bot/registrations/{registrationId}/commands/sync”

Runs the bot’s one publication reconciliation, the same one an activation runs, and answers with the readback diff: commands per scope, obsolete scopes deleted, the menu button, and the stored profile. Idempotent: a second run reports changed: false.

NameInTypeRequiredDescription
registrationIdpathstringYesRegistration id returned by register or list.
Terminal window
curl -X POST \
"https://{projectId}-{containerId}-bot-1.{server}.containers.hoody.com/api/v1/bot/registrations/{registrationId}/commands/sync" \
-H "Authorization: Bearer $HOODY_TOKEN"

PUT /api/v1/bot/registrations/{registrationId}/profile

Section titled “PUT /api/v1/bot/registrations/{registrationId}/profile”

Stores the bot profile and publishes it to the channel. An absent key leaves the stored value unchanged, null stops the kit managing that field, and an empty string clears it at the channel. The three are different operations. The profile is stored before it is published, so a channel failure leaves the stored value ready to be republished by repeating the request.

NameInTypeRequiredDescription
registrationIdpathstringYesRegistration id returned by register or list.
NameTypeRequiredDescription
namestringNoThe bot name to publish (up to 64 characters).
descriptionstringNoThe bot description to publish (up to 512 characters).
short_descriptionstringNoThe bot short description to publish (up to 120 characters).
language_codestringNoThe IETF tag the three texts belong to.
administrator_rightsobjectNoDefault administrator rights to publish for groups and channels. Each sub-object maps capability names to booleans.
Terminal window
curl -X PUT \
"https://{projectId}-{containerId}-bot-1.{server}.containers.hoody.com/api/v1/bot/registrations/{registrationId}/profile" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Bot",
"description": "Acme operations bot.",
"short_description": "Acme ops",
"language_code": "en"
}'

Each registration stores a mode (a stored label, single or multi) and two allowlists (users and chats). Admission is decided by the allowlists; mode is a label the kit records, not a constraint on the number of signed-in accounts.

GET /api/v1/bot/registrations/{registrationId}/policy

Section titled “GET /api/v1/bot/registrations/{registrationId}/policy”

Returns the registration’s mode and allowlists as the gate enforces them. A null users allowlist admits every user; a null chats allowlist means direct messages only, so a group is admitted only when the chats list names it; an empty array admits nobody.

NameInTypeRequiredDescription
registrationIdpathstringYesRegistration id returned by register or list.
Terminal window
curl -X GET \
"https://{projectId}-{containerId}-bot-1.{server}.containers.hoody.com/api/v1/bot/registrations/{registrationId}/policy" \
-H "Authorization: Bearer $HOODY_TOKEN"

PUT /api/v1/bot/registrations/{registrationId}/policy

Section titled “PUT /api/v1/bot/registrations/{registrationId}/policy”

Sets the mode and allowlists. mode is required; an absent allowlist key is left alone, an explicit null takes that list out of force, and an empty array admits nobody. The answer is the policy read back from the store. The allowlists take effect on the next update the bot receives: an unadmitted actor or chat is refused before the chat user is looked up, and the refusal is written to the audit log.

NameInTypeRequiredDescription
registrationIdpathstringYesRegistration id returned by register or list.
NameTypeRequiredDescription
modestringYesThe stored mode label, single or multi.
allowlistsobjectNoThe allowlists to apply. An absent key leaves the stored list alone; an explicit null takes it out of force; an empty array admits nobody.
allowlists.usersarrayNoChannel user ids this bot serves. null admits every user; an empty array admits nobody.
allowlists.chatsarrayNoChat ids this bot serves. null means direct messages only; a non-empty list is exhaustive and includes direct messages; an empty array admits no chat.
Terminal window
curl -X PUT \
"https://{projectId}-{containerId}-bot-1.{server}.containers.hoody.com/api/v1/bot/registrations/{registrationId}/policy" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"mode": "single",
"allowlists": {
"users": null,
"chats": null
}
}'

Every action the kit takes on behalf of a registration lands in a per-registration log. The log is redacted on write and paged by cursor. A 90-day retention window applies; purging inside the window is refused unless waived.

GET /api/v1/bot/registrations/{registrationId}/logs

Section titled “GET /api/v1/bot/registrations/{registrationId}/logs”

Returns the redacted audit log, newest first. Paging is by cursor (next_before_id), not by offset, so a cursor stays valid across the retention sweep.

NameInTypeRequiredDescription
registrationIdpathstringYesRegistration id returned by register or list.
actorquerystringNoNarrow the page to one chat user. Matched exactly against the stored actor value, which carries the channel prefix, for Telegram telegram:<user id>, not the bare id the revoke path takes.
sincequeryintegerNoDrop entries older than this epoch-millisecond timestamp. A filter on the page, not a cursor: paging continues past it.
limitqueryintegerNoPage size; capped by the store at 500. The answer reports the size actually used.
before_idqueryintegerNoThe cursor: the next_before_id of the previous page. Omit for the newest page.
Terminal window
curl -X GET \
"https://{projectId}-{containerId}-bot-1.{server}.containers.hoody.com/api/v1/bot/registrations/{registrationId}/logs?actor=telegram%3A7123456789&limit=100" \
-H "Authorization: Bearer $HOODY_TOKEN"

DELETE /api/v1/bot/registrations/{registrationId}/logs

Section titled “DELETE /api/v1/bot/registrations/{registrationId}/logs”

Deletes this registration’s audit entries at or below a cutoff. A cutoff inside the 90-day retention window is refused rather than clamped; all=true waives the floor.

NameInTypeRequiredDescription
registrationIdpathstringYesRegistration id returned by register or list.
older_thanqueryintegerNoDelete entries at or below this epoch-millisecond timestamp. Defaults to the 90-day retention boundary.
allquerystringNoWaive the 90-day retention floor. Without it a cutoff inside the retention window is refused, never clamped. Literal values: true, false.
Terminal window
curl -X DELETE \
"https://{projectId}-{containerId}-bot-1.{server}.containers.hoody.com/api/v1/bot/registrations/{registrationId}/logs?older_than=1700000000000&all=true" \
-H "Authorization: Bearer $HOODY_TOKEN"

Revoke a single chat user’s lineage, or every chat user of the registration at once. The leaf is deleted through the parent, the parent is forgotten, and any intents, wizards and subscriptions bound to that lineage are invalidated.

POST /api/v1/bot/registrations/{registrationId}/sessions/{channelUserId}/revoke

Section titled “POST /api/v1/bot/registrations/{registrationId}/sessions/{channelUserId}/revoke”

Revokes one chat user’s login as the operator: the leaf is deleted through the parent, the parent is forgotten, and the intents, wizards and subscriptions bound to that lineage are invalidated. A parent the platform refused to delete is reported by id for hoody auth tokens delete.

NameInTypeRequiredDescription
registrationIdpathstringYesRegistration id returned by register or list.
channelUserIdpathstringYesThe channel’s own id for the chat user (the Telegram user id), without a channel prefix. The audit log’s actor column spells the same user differently, telegram:<user id>, so a value copied from there is not accepted here.
Terminal window
curl -X POST \
"https://{projectId}-{containerId}-bot-1.{server}.containers.hoody.com/api/v1/bot/registrations/{registrationId}/sessions/7123456789/revoke" \
-H "Authorization: Bearer $HOODY_TOKEN"

POST /api/v1/bot/registrations/{registrationId}/tokens/revoke-all

Section titled “POST /api/v1/bot/registrations/{registrationId}/tokens/revoke-all”

Revokes every chat user of this registration. A failure does not stop the sweep: each one is recorded and the rest are still revoked.

NameInTypeRequiredDescription
registrationIdpathstringYesRegistration id returned by register or list.
Terminal window
curl -X POST \
"https://{projectId}-{containerId}-bot-1.{server}.containers.hoody.com/api/v1/bot/registrations/{registrationId}/tokens/revoke-all" \
-H "Authorization: Bearer $HOODY_TOKEN"