Overview
Enterprise outbound webhooks send signed JSON events to your configured HTTPS endpoint in server.webhookUrl.
- Configured by
PATCH /api/v3/servers/{serverId}withwebhookUrl, orPOST /api/v3/servers/{serverId}/webhook-secret- Payload
- Signed JSON with
event,timestamp,server, anddata.
| Configured by | Payload |
|---|---|
PATCH /api/v3/servers/{serverId} with webhookUrl, or POST /api/v3/servers/{serverId}/webhook-secret | Signed JSON with event, timestamp, server, and data. |
Enterprise Outbound Webhooks
Enterprise outbound webhooks are dispatched by dispatchWebhookEvent. The dispatcher silently skips delivery unless both webhookUrl and webhookSecret are set.
{
"event": "member.verified",
"timestamp": "2026-06-07T10:30:00.000Z",
"server": {
"guildId": "123456789012345678",
"name": "Community"
},
"data": {
"userId": "111111111111111111",
"username": "alice#0000",
"avatar": "avatar-hash",
"ip": "203.0.113.10",
"countryCode": "US",
"isNewMember": true
}
}Event Types
- Event
member.verified- Emitted from local source
- OAuth callback after successful verification
- Representative data
userId,username,avatar,ip,countryCode,isNewMember
- Event
member.denied- Emitted from local source
- OAuth callback when firewall, alt, wireless, or account-age checks deny a user
- Representative data
userId,username,reason,details
- Event
firewall.block- Emitted from local source
- Firewall engine when access is denied
- Representative data
- Firewall action data from engine context
- Event
firewall.allow- Emitted from local source
- Firewall engine when access is allowed
- Representative data
- Firewall action data from engine context
- Event
firewall.password- Emitted from local source
- Firewall engine for password success/failure paths
- Representative data
- Firewall password/action data from engine context
- Event
snapshot.create- Emitted from local source
- Snapshot creation route after service accepts job
- Representative data
snapshotId,snapshotName
- Event
snapshot.restore- Emitted from local source
- Snapshot restore route after service accepts job
- Representative data
snapshotId,snapshotName,targetGuildId,restoreMessageCount,clearServer
| Event | Emitted from local source | Representative data |
|---|---|---|
member.verified | OAuth callback after successful verification | userId, username, avatar, ip, countryCode, isNewMember |
member.denied | OAuth callback when firewall, alt, wireless, or account-age checks deny a user | userId, username, reason, details |
firewall.block | Firewall engine when access is denied | Firewall action data from engine context |
firewall.allow | Firewall engine when access is allowed | Firewall action data from engine context |
firewall.password | Firewall engine for password success/failure paths | Firewall password/action data from engine context |
snapshot.create | Snapshot creation route after service accepts job | snapshotId, snapshotName |
snapshot.restore | Snapshot restore route after service accepts job | snapshotId, snapshotName, targetGuildId, restoreMessageCount, clearServer |
The top-level envelope is stable in source. The nested data object is event-specific and may grow as the emitting feature adds fields.
Signatures
Enterprise webhooks include an HMAC SHA-256 signature over the exact JSON request body.
- Header
Content-Type- Value
application/json
- Header
X-Webhook-Event- Value
- Event type, for example
member.verified.
- Header
X-Signature-256- Value
sha256=<hex hmac>using the server webhook secret.
| Header | Value |
|---|---|
Content-Type | application/json |
X-Webhook-Event | Event type, for example member.verified. |
X-Signature-256 | sha256=<hex hmac> using the server webhook secret. |
import crypto from "crypto";
function isValidRestoreCordWebhook(rawBody: string, header: string, secret: string) {
const expected = "sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
return crypto.timingSafeEqual(Buffer.from(header), Buffer.from(expected));
}Configure Webhooks
Configure Enterprise outbound webhooks by setting an HTTPS webhookUrl on the server. The server update route generates a fresh secret when the URL changes. You can also generate a secret explicitly.
/api/v3/servers/{serverId}Set webhook URL
Enterprise-only server update field.
serverIdRequired- Location
- path
- Type
- string
webhookUrlRequired- Location
- body
- Type
- string | null
{
"webhookUrl": "https://api.example.com/restorecord/webhooks"
}{
"success": true,
"message": "Server settings updated successfully.",
"server": {
"guildId": "123456789012345678",
"webhookUrl": "https://api.example.com/restorecord/webhooks"
},
"webhookSecret": "whsec_generated_secret"
}/api/v3/servers/{serverId}/webhook-secretGenerate webhook secret
Generate and store a webhook secret for an Enterprise server with webhookUrl already set.
serverIdRequired- Location
- path
- Type
- string
{
"success": true,
"webhookSecret": "whsec_generated_secret"
}- Requirement
- Plan
- Source behavior
- Enterprise required for
webhookUrland explicit secret generation.
- Requirement
- URL
- Source behavior
webhookUrlmust be HTTPS.
- Requirement
- Secret generation
- Source behavior
- Changing
webhookUrlgenerates a new secret; explicit generation requires an existing URL.
- Requirement
- Rate limit
- Source behavior
- Secret generation is limited to 10 requests per minute per user in source.
| Requirement | Source behavior |
|---|---|
| Plan | Enterprise required for webhookUrl and explicit secret generation. |
| URL | webhookUrl must be HTTPS. |
| Secret generation | Changing webhookUrl generates a new secret; explicit generation requires an existing URL. |
| Rate limit | Secret generation is limited to 10 requests per minute per user in source. |
Delivery Behavior
- Behavior
- Enterprise signed JSON delivery
- Details
- Best-effort. The dispatcher catches delivery errors and does not retry in source.
- Behavior
- Timeout
- Details
- Enterprise dispatcher uses a 5 second request timeout.
- Behavior
- HTTP status handling
- Details
- Enterprise dispatcher sets
validateStatus: () => true, so non-2xx receiver responses do not throw and are not retried.
- Behavior
- Proxy
- Details
- Outbound requests use the configured HTTPS proxy agent.
- Behavior
- Secret rotation
- Details
- Set a new
webhookUrlor call the secret endpoint to rotate. Store the returned secret immediately.
| Behavior | Details |
|---|---|
| Enterprise signed JSON delivery | Best-effort. The dispatcher catches delivery errors and does not retry in source. |
| Timeout | Enterprise dispatcher uses a 5 second request timeout. |
| HTTP status handling | Enterprise dispatcher sets validateStatus: () => true, so non-2xx receiver responses do not throw and are not retried. |
| Proxy | Outbound requests use the configured HTTPS proxy agent. |
| Secret rotation | Set a new webhookUrl or call the secret endpoint to rotate. Store the returned secret immediately. |
- Verify signatures using the exact raw request body.
- Make your receiver idempotent; RestoreCord events include a timestamp but no dedicated event id in source.
- Return a 2xx quickly. Long processing should be queued on your side.