Webhooks
Outbound events to your Discord or to an endpoint of your own, and the inbound erasure webhook that has to stay available whether or not you ever look at it.
Last updated 10 August 2026
Overview
Two directions, and they have nothing to do with each other beyond the word.
- Outbound. GROUPSPACE tells your Discord, or an endpoint you run, that something happened in the workspace. Optional, per workspace, per event type.
- Inbound. Roblox tells GROUPSPACE that a user has exercised their right to erasure. Not optional, not configurable, and covered at the bottom of this page.
Outbound webhooks sit alongside the other notification channels rather than replacing them. A workspace member can receive a given notification type in the app, by email, or through Discord, and the preference is per type rather than all-or-nothing.
Events
Envelope
Every outbound event to a generic endpoint uses the same envelope. The data object varies by type.
- Treat
idas an idempotency key. A redelivery reuses it, so store it and ignore duplicates. - Ignore fields you do not recognise. New fields will be added inside the same event type.
- Events carry references, not payloads. A record webhook gives you the record id, not the record body — visibility rules live in GROUPSPACE and a webhook is not a way around them.
Discord webhooks
Discord is a first-class target rather than an afterthought, because it is how these communities actually consume notifications. It is also the cheapest of the three channels to run, which is why it ships at launch alongside in-app and email.
Setting one up
- Create a webhook on the Discord channel you want, in that channel’s integration settings, and copy the URL.
- Paste it into the workspace notification settings and pick the event types that should go to it.
- Point different event types at different channels. Enforcement in one, hiring in another, payouts somewhere only finance can see.
What arrives
GROUPSPACE posts a formatted embed rather than the raw envelope — a title, the subject, the actor, the organization, and a link back into the workspace. The generic envelope above is what a signed endpoint of your own receives; Discord gets something a human can read in a channel.
Signed endpoints
For anything that is not Discord, register an HTTPS URL and GROUPSPACE will POST the envelope to it, signed with the same scheme the game API uses in the other direction.
Verifying
- Compute the HMAC over the timestamp concatenated with the raw body bytes, before any JSON parsing. A re-serialised body will not match.
- Compare in constant time. A naive string comparison leaks the signature a byte at a time.
- Reject anything with a timestamp more than 300 seconds from your own clock.
- Keep a short-lived cache of signatures you have already accepted and reject repeats inside that window.
- Verify before you parse, and parse before you act. An unverified body is attacker-controlled input.
Responding
- Any 2xx is success. Everything else is a failure and will be retried.
- Answer quickly and do the work afterwards. Acknowledge, enqueue, return — do not hold the connection open while you process.
- Deliveries are at-least-once. Deduplicate on
id. - Ordering is not guaranteed. Two events about the same subject can arrive out of order, so use
occurredAtrather than arrival order.
Retries and failure
A failed delivery is retried with exponential backoff and jitter across a bounded number of attempts. After that the delivery is abandoned and recorded as failed rather than retried forever.
- A 4xx that is clearly permanent — 401, 404, 410 — is not retried. Something is misconfigured and retrying will not fix it.
- A 5xx, a timeout or a connection error is retried.
- An endpoint that fails continuously is marked unhealthy and surfaced in the workspace, so an operator finds out from their own settings screen rather than from the silence.
- Failed deliveries are visible with their status code and response, which is usually enough to tell a bad URL from a bad handler.
Right to erasure
Roblox sends a RightToErasureRequest webhook when a user exercises their right to have their data deleted. GROUPSPACE operates the handler. This section is here because you need to understand what it does to data your game depends on, and because operators keep asking whether they should build their own.
How the handler is built
What gets purged
For the supplied user id, across every workspace in the deployment that holds data for them: records, game sessions, chat messages and operation participation. This is deletion, not anonymisation, and it is not reversible.
- A record filed against an erased user is removed, which means moderation history for that user disappears. That is the correct outcome and it is not a bug report.
- Aggregate figures that were already rolled up may still reflect the session that was deleted. Aggregates carry no user id and are not personal data.
- Erasure is independent of bans. A user who was banned and then erased is no longer in the blocklist, because the blocklist entry is data about them.
- All data is expunged on access revocation as well, not only on an explicit erasure request.
Platforms without an erasure webhook
The capability is a flag on the game provider, and it is true for Roblox and false elsewhere. Steam, FiveM and custom integrations have no equivalent platform signal, so erasure for those users runs through a manual request flow instead — same purge, same audit entry, different trigger.
