Webhooks
API reference for configuring Enterprise RestoreCord webhooks: set the webhook URL, generate a signing secret, and verify signed event payloads.
Overview
Enterprise outbound webhooks send signed JSON events to your configured HTTPS endpoint in server.webhookUrl.
| Configured by | Payload |
|---|---|
PATCH /api/v3/servers/{serverId} with webhookUrl | Signed JSON with event, timestamp, server, and data. |
Enterprise Outbound Webhooks
Events are only sent when the server has both a webhook URL and a webhook secret.
{
"event": "member.verified",
"timestamp": "2026-06-07T10:30:00.000Z",
"server": {
"guildId": "123456789012345678",
"name": "Community"
},
"data": {
"userId": "111111111111111111",
"username": "alice",
"avatar": "avatar-hash",
"ip": "203.0.113.10",
"countryCode": "US",
"isNewMember": true
}
}Event Types
| Event | When it fires | Representative data |
|---|---|---|
member.verified | A member successfully verifies. | userId, username, avatar, ip, countryCode, isNewMember |
member.denied | Firewall, alt, wireless, or account-age checks deny a member during verification. | userId, username, reason, details |
firewall.block | The firewall denies a verification attempt. | userId, username, ip, countryCode, action, reason |
firewall.allow | The firewall lets a verification attempt through a rule or bypass. | userId, username, ip, countryCode, action, reason |
firewall.password | A member submits a verification password. | userId, username, ip, countryCode, action, reason, success |
member.deauthorized | A member removes your bot from their account; sent to every server using that bot. | userId, reason |
snapshot.create | A snapshot is created. | snapshotId, snapshotName |
The top-level envelope is stable. The nested data object is event-specific and may gain fields over time.
Signatures
Enterprise webhooks include an HMAC SHA-256 signature over the exact JSON request body.
| Header | Value |
|---|---|
Content-Type | application/json |
X-Webhook-Event | Event type, for example member.verified. |
X-Signature-256 | sha256= followed by the hex HMAC-SHA256 of the raw request body, using the server webhook secret. Strip the prefix before comparing. |
import crypto from "crypto";
function verifyRestoreCordSignature(rawBody: Buffer | string, signatureHeader: string, secret: string) {
const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
const actual = signatureHeader.replace(/^sha256=/, "");
const expectedBuffer = Buffer.from(expected, "hex");
const actualBuffer = Buffer.from(actual, "hex");
return expectedBuffer.length === actualBuffer.length && crypto.timingSafeEqual(expectedBuffer, actualBuffer);
}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.
Set webhook URL
Auth: API key with WRITE_SERVERS. Enterprise-only server update field.
PATCH /api/v3/servers/{serverId}Prop
Type
{
"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"
}| Requirement | Details |
|---|---|
| Plan | Enterprise required for webhookUrl. |
| URL | webhookUrl must be HTTPS. |
| Secret generation | Changing webhookUrl generates a new secret. To generate one without changing the URL, use the dashboard. |
Go to Security › Webhook Secret
Delivery Behavior
| Behavior | Details |
|---|---|
| Enterprise signed JSON delivery | Best-effort. Failed deliveries are not retried. |
| Timeout | Each request times out after 5 seconds. |
| HTTP status handling | Non-2xx receiver responses are not retried. |
| Secret rotation | Set a new webhookUrl, or generate a new secret in the dashboard. Store the returned secret immediately. |
- Verify signatures using the exact raw request body.
- Make your receiver tolerate occasional duplicates.
- Return a 2xx quickly. Long processing should be queued on your side.