Turn Server Project Webhooks Guide
This guide explains how to configure and handle webhook notifications for your TURN Server Projects, including how to verify webhook authenticity using an HMAC signature.
Overview
When you create or edit a TURN Server Project, you can optionally provide a Webhook URL. Once configured, the system will send HTTP POST
requests with JSON payloads to your specified URL in the following scenarios:
80% Quota Reached
- Event Name:
project_quota_80_percent
- Triggered when your project usage crosses 80% of the configured quota
- Event Name:
100% Quota Reached (Quota Exceeded)
- Event Name:
project_quota_exceeded
- Triggered when your project usage crosses 100% of the configured quota
- Event Name:
Configuring Webhooks
1. Create or Edit a Project
- From the Turn Servers dashboard, add or edit a project
- In the Webhook URL field, specify the HTTPS endpoint that should receive notifications
- If you do not provide a URL, no webhook will be sent when the quota thresholds are reached
2. Choose the Quota Exceeded Action
You can configure what happens once the project crosses its quota:
- notify: Send email/webhook notifications but do not disable credentials
- disable: Send notifications and disable credentials, preventing further usage
- none: No notification (email or webhook) and no action
3. Save Your Changes
- Once saved, the webhook configuration is active immediately
- The system will automatically trigger webhooks once the usage meets or exceeds the relevant thresholds
Webhook Payload
When a webhook is triggered, an HTTP POST
request is sent to your specified URL with a JSON body. Below are examples of the payload structure for each event.
1. 80% Quota Event
Triggered when the project usage crosses 80% of the configured quota.
{
"event": "project_quota_80_percent",
"project": "PROJECT_ID",
"projectName": "YOUR_PROJECT_NAME",
"app": "APP_ID",
"quota": 500000000,
"usage": 400000000
}
Field | Description |
---|---|
event | Always project_quota_80_percent for the 80% quota event |
project | Unique ID of the project |
projectName | The name of the project, as specified in the dashboard |
app | The ID of the app (associated with the TURN server embed/add-on) |
quota | The total quota (in bytes) configured for this project |
usage | Current usage (in bytes) for the project at the time of the notification |
2. 100% Quota Event
Triggered when the project usage crosses 100% (exceeds) the configured quota.
{
"event": "project_quota_exceeded",
"project": "PROJECT_ID",
"projectName": "YOUR_PROJECT_NAME",
"app": "APP_ID",
"quota": 500000000,
"usage": 500000001
}
Field | Description |
---|---|
event | Always project_quota_exceeded for the 100% quota event |
project | Unique ID of the project |
projectName | The name of the project, as specified in the dashboard |
app | The ID of the app (associated with the TURN server embed/add-on) |
quota | The total quota (in bytes) configured for this project |
usage | Current usage (in bytes) for the project at the time of the notification |
Webhook Security & Verification
HMAC Signature
All webhook requests sent from the platform include an HMAC-SHA256 signature to help you verify authenticity. The header used is:
X-Metered-Signature-256: sha256=GENERATED_SIGNATURE
1. Signature Generation
- Before sending the webhook, we compute an HMAC-SHA256 signature using the raw request body (the exact JSON payload) and your Project API Key as the secret
- The result is hex-encoded and appended to the string "sha256=", creating the final header value
2. How to Verify
- On your server, read the header
X-Metered-Signature-256
from the incoming webhook request - Recompute the HMAC-SHA256 using the same raw body content and your Project API Key:
import { createHmac } from "crypto";
function verifyWebhookSignature(
rawBody: string,
signatureHeader: string,
projectApiKey: string
): boolean {
// Remove "sha256=" prefix if present
const expectedSignature = signatureHeader.replace(/^sha256=/, "");
// Compute HMAC using your project's API Key
const computedHmac = createHmac("sha256", projectApiKey)
.update(rawBody, "utf8")
.digest("hex");
// Compare in a timing-safe way
return computedHmac === expectedSignature;
}
- If the signatures match, the request is authentic
3. Troubleshooting
- Make sure you pass the exact raw request body (including the same spacing and JSON encoding) to your HMAC computation. Any modification can cause signature mismatches
- Confirm you are using the correct Project API Key from the dashboard
Additional Security Tips
- Use HTTPS: Always secure your webhook endpoint with TLS (HTTPS) to protect the payload in transit
- Check Timestamps: You can also include a timestamp in your payload or headers to guard against replay attacks
- Error Handling & Retries: If the webhook delivery fails or times out, our system may retry. Ensure your verification process is idempotent
Receiving and Handling Webhooks
Endpoint Requirements
- Method: POST
- Content-Type: application/json
- Signature Header: X-Metered-Signature-256
Example Handling Logic (Node.js / TypeScript)
import express, { Request, Response } from "express";
import { createHmac } from "crypto";
const app = express();
// Capture raw body for signature verification
app.use(
express.json({
verify: (req: any, res, buf: Buffer) => {
req.rawBody = buf;
},
})
);
app.post("/my-webhook-endpoint", (req: Request, res: Response) => {
const signatureHeader = req.header("X-Metered-Signature-256") || "";
const rawBody = req.rawBody.toString("utf8");
const projectApiKey = "YOUR_PROJECT_API_KEY"; // Retrieve from secure storage
// Recompute HMAC
const expectedSignature = signatureHeader.replace(/^sha256=/, "");
const computedHmac = createHmac("sha256", projectApiKey)
.update(rawBody, "utf8")
.digest("hex");
if (computedHmac !== expectedSignature) {
console.error("Signature mismatch. Potential spoofed request.");
return res.sendStatus(401);
}
// Signature is valid — process the webhook
const eventPayload = req.body;
console.log("Event received:", eventPayload.event);
// Return a 2xx to acknowledge receipt
res.sendStatus(200);
});
app.listen(3000, () => {
console.log("Webhook listener running on port 3000");
});
Testing Your Webhook
1. Use a Public Testing URL
- Services like webhook.site let you inspect incoming requests in real time
2. Manual Quota Trigger
- Temporarily set a low quota on a project and generate enough TURN usage to reach 80% or 100%
3. Signature Verification
- Check that your server logs confirm an HMAC match
Troubleshooting
No Webhook Received
- Ensure the Webhook URL is correct and publicly accessible
- Confirm no firewall or security group is blocking the requests
Repeated Notifications
- The platform may retry if your endpoint fails to respond with a 2xx status
- Ensure you always return a successful status once you've processed (and verified) the webhook
Usage Not Updating
- Verify that your TURN credentials under the project are indeed being used
- Wait a brief interval for usage to update
Frequently Asked Questions
Q: What if I set my project quota to 0?
A: A quota of 0 means unlimited usage. Webhooks will not be triggered for quota events in that case. However, usage is still tracked for reporting.
Q: Do I receive multiple notifications if usage fluctuates around 80% or 100%?
A: No, you will receive only one webhook notification when usage reaches 80% and one when it reaches 100%. You can also receive additional webhook notifications if you modify the project quota - in that case, new webhooks will be triggered when usage reaches 80% or 100% of the new quota.
Q: Can I modify the request headers or add custom fields?
A: The primary headers and fields in the webhook (including the signature format) are fixed. However, you can maintain a mapping on your side to correlate by project or other identifiers.
Summary
Webhook notifications for TURN Server Projects give you real-time alerts when usage crosses key thresholds (80% and 100% of quota). To ensure these notifications are authentic, the request includes an HMAC-SHA256 signature (X-Metered-Signature-256
header) generated with your Project API Key. By verifying this signature, you can confidently process the events in your own systems without fear of spoofed or tampered requests.
If you have any questions or need assistance, feel free to reach out to our support team.