Outgoing webhooks
Notify a Discord channel (or an integration) on every application, warrant, BOLO, leave request, thread, update or purchase.
Updated on Oct 5, 2026, 1:36 p.m.
On this page
In short. Administration → Webhooks sends a message when something happens. One webhook = one event. They do not depend on any license.
Add a webhook for Discord #
- In Discord: Channel settings → Integrations → Webhooks → New Webhook → Copy Webhook URL (official Discord help: Intro to Webhooks).
- In Agora: Administration → Webhooks.
- Pick the Event, paste the Address (https), leave the format on Discord embed.
- Save, then click Test: a sample event is sent with dummy values.
Events #
| Event | Fired when |
|---|---|
application.received | An application was just submitted |
application.approved / application.rejected | Staff accept or reject an application |
warrant.issued | A warrant is issued (without the targeted citizen's name) |
bolo.created | A BOLO is issued |
leave.requested / leave.reviewed | Leave is requested (never its reason: it may be health-related), then decided |
thread.created | A thread is opened on the forum |
report.created | A member has just reported a forum message or thread (Moderation group) |
court.case.filed / court.judgment.rendered | A case is filed at court, then judged |
article.published | A journal article is published |
txadmin.announcement / txadmin.restart | txAdmin announces a message or a scheduled restart (relayed by the resource, txAdmin 8.0 or newer) |
update.available | A new version of Agora is available: one announcement per version, when Agora spots it |
vehicle.purchased | A vehicle is bought at the dealership with in-game money, once delivered. A real-money (PayPal) or Tebex purchase is not announced by this webhook |
There are 16 events, grouped on screen: Applications, MDT, Court, HR, Forum and journal, Moderation, Dealership, System, txAdmin. None is announced until a webhook ticks it.
A webhook announces that something happened and where to look. It never copies a record: no application answer, no medical report, no post content. Emails, keys and Discord IDs are masked automatically.
Reports in a Discord channel #
report.created tells neither who reported, nor their comment, nor who is targeted: only the section, the thread title and the reason, with a link to Moderation → Reports. For a thread in a restricted section (readable by some groups only), the section and title are left out: the Discord channel does not have the same read rights as the forum. The reporter gets a notification, "Your report was handled by the staff" (without the outcome or the reason), when the staff handles their report. See Handle reports.
Refused addresses #
Only public https:// addresses are accepted: no loopback, no private network, no credentials in the URL. This protects the server.
Failures and cut-off #
- 5-second timeout, 3 attempts per delivery.
- After 3 consecutive failures, the webhook is cut off and shows the Stopped badge.
- Fix the address, then Test: a successful test puts it back in service. A webhook you switched off by hand is never switched back on by a test.
- A failure is counted for the address that suffered it: if you fix the address while a delivery to the old one is failing, the new one is not cut off wrongly.
A webhook never blocks the action that fires it. When an event is tied to a department, the message in the department's Discord channel goes out at the same time as the webhooks, without waiting for them to finish.
For a custom integration: signed JSON #
Pick the Other integration (signed JSON) format and a signing secret (16 to 200 characters, never shown again). Each delivery carries the X-Agora-Event, X-Agora-Delivery and X-Agora-Signature headers (t=timestamp,v1=HMAC-SHA256). The signature is the HMAC-SHA256 of timestamp.body with your secret. Refuse a delivery older than 300 seconds and compare signatures in constant time.
The body contains event, at, id, site, title, summary, url and data. data gives each field under its translated label ("Form"), and data._byKey the same values under their stable technical key (form, applicant, member…). Read _byKey instead: it does not change with the site language.
Was this article helpful?
Related articles
- Applications and examsBuild a form (whitelist, police…), add a timed exam graded automatically, then handle requests in Moderation → Applications.
- Reports, warrants, BOLOs and arrestsThe everyday records: each has its page, its attachments, a complete log and a printable version.
- Employees and HR: ranks, shifts, leave, time zoneWho serves, who is away, how many hours and who is slipping: hours come from in-game presence, managers handle ranks and leave with a reason.