Setup
1
Create the group
Create a Telegram group and enable Topics in its settings. Topics are a supergroup
feature; a plain group cannot hold them.
2
Add the bot
Add the bot and grant it Manage Topics and Send Messages.
3
Point the bot at it
-100. Forwarding a message from the
group to a bot such as @userinfobot is the usual way to read it.4
Restart the bot
On start the notifier binds every topic, then drains the queue every ten seconds. The
start-up log says which of the two happened:
operator notifications are disabled because no group is configured, or nothing at
all if binding succeeded.bot process delivers notices. The api and worker processes write them into
the queue, so an installation running no bot still accumulates the record of what
happened — it simply has nobody to tell.
The topics
The last two carry something the others deliberately do not: a rendered message body. Everything else here is a set of allowlisted, non-personal fields, and a preview is by definition the copy itself. Both say plainly that nobody else received them — a preview mistaken for a real send is somebody reaching for the pause button. See Campaigns and Message wording.
The incidents topic carries payment anomalies and nothing else today. Each notice names the
order, the provider, the operation, the classification, the currency and amount, and the
order’s state at the time, and is deduplicated per payment intent and classification — a
replayed webhook adds nothing. What each classification means and how it is resolved is in
Orders and payments.
Maintenance is detected in the
api process, which has no Telegram client, so the api
writes each transition into the same operator_notifications queue the bot drains; one
transition is one message, deduplicated per direction and minute.
Backup and restore outcomes are queued the same way by the process that ran them, keyed on
the backup and the outcome, so a retried job reports once. The backups table stays the
record: a notice that cannot be queued is logged and never fails the backup. See Maintenance mode
and Backup and restore.
The anomaly evaluator writes notices under a ninth kind,
anomaly, which the database
accepts but for which the bot has no named topic. Those notices do not reach the group.
Review anomalies at /admin/risk instead — see Risk controls.Configuration
All three are read once at start-up. The
operator_group section on /admin/settings/integrations
stores the same four numbers and changes nothing — see
Installation settings.
When binding fails
A topic that cannot be created is recorded asfailed on operator_topics with a
classified reason rather than silently doing nothing. The raw Telegram message is dropped
because it can echo request content.
Fix the cause and restart the bot, or wait for the next notification for that kind:
delivery re-attempts the binding before it sends.
Changing
APP_OPERATOR_CHAT_ID rebinds everything. Rows whose stored chat no longer
matches have their topic identifier cleared and their status reset to pending, so fresh
topics are created in the new group rather than messages being sent into a group you have
left.
A topic deleted in Telegram is re-created on the next message to it, once, and the message
is then retried.
Delivery
The notifier drains up to 50 pending notices every ten seconds, in creation order, inside one transaction withFOR UPDATE SKIP LOCKED so two bots cannot deliver the same row.
Each notice ends in exactly one terminal state:
A
failed notice is not retried. The row and its payload remain in the database, so the
record of the event survives even when the message did not, but the fix for a persistent
failure is to correct the group and let the next event through rather than to expect a
replay.
Volume control
suppressed with reason
volume_cap and a warning is logged with the kind and the number suppressed in that pass.
The cap is per kind, so a Remnawave outage producing thousands of fulfillment failures
cannot bury the purchase stream, and suppressed notices do not themselves count towards
the cap. Nothing is lost: the rows stay in the database with their payloads.
Set the cap to 0 to send everything.
Deduplication
Every notice carries a dedupe key: the order for a purchase, the refund for a refund, the fulfillment operation for a failure, the event and account for a security notice.operator_notifications (kind, dedupe_key) is unique and the insert is
ON CONFLICT DO NOTHING, so a retried webhook, a second reconciliation pass, and a job
that fails repeatedly all produce one message.
The notice is queued inside the same transaction as the event it describes. A notice
therefore exists exactly when the thing it reports is durable — never for an event that
rolled back, and never missing for one that committed. A queue failure is logged and never
fails the transaction that caused it, because a settled payment must not be undone by a
chat message.
What a notice contains
The renderer prints the topic name, then only fields from a fixed allowlist, then the timestamp. Anything else a payload happens to hold is dropped rather than filtered, so a field added to a payload in future cannot leak by omission:Fulfillment failure notices
A failing provisioning run does not notify immediately. Ordinary backoff is expected to recover, so an operator is told only after three failed attempts, or immediately on a permanent failure. The dedupe key is the operation, so one struggling entitlement produces one message however many times it retries. The notice carries the entitlement, the operation, the current status, and a classified error code such asremnawave_http_502 or remnawave_unavailable. It never carries the
panel’s response body.
Two related cases land in the same topic:
- A digital-goods delivery that the provider could not complete.
- An add-on that settled with no live entitlement — the order keeps its paid state so
the money is never silently lost, and the notice, together with the
addon.no_active_entitlementaudit event, tells an operator exactly what to refund or re-apply.
Related
Telegram
BotFather, webhook versus long polling, and the operator group.
Troubleshooting
What to check when the group has gone quiet.