Webhooks
Webhooks allow you to receive real-time HTTP notifications when events occur on the platform — a playtest is submitted, a submission is accepted, a payment completes, etc.
Webhook Events
Section titled “Webhook Events”| Event | Trigger |
|---|---|
slot.reserved | A playtester claimed a playtest slot |
slot.submitted | A playtester submitted a video |
slot.accepted | Game owner accepted a submission |
slot.rejected | Game owner rejected a submission |
slot.expired | Slot deadline expired without a submission |
payout.completed | Payout was processed and sent |
payout.failed | Payout failed |
payment.completed | Stripe payment succeeded |
payment.failed | Stripe payment failed |
chat.message | New chat message received |
Payload Format
Section titled “Payload Format”All webhook deliveries send a JSON payload:
{ "event": "slot.submitted", "timestamp": "2026-03-02T12:00:00Z", "data": { "slotId": "slot_abc", "playtestId": "pt_xyz", "gameId": "game_123", "playerId": "usr_tester1", "submittedAt": "2026-03-02T12:00:00Z" }}The data object varies by event type and contains the relevant resource details.
Signature Verification
Section titled “Signature Verification”Every webhook delivery includes headers for verifying authenticity:
| Header | Description |
|---|---|
X-WPG-Signature | HMAC-SHA256 hex digest of the signed payload |
X-WPG-Timestamp | Unix timestamp (seconds) when the delivery was sent |
X-WPG-Signature-Version | Signature version (v1) |
The signature is computed over {timestamp}.{body}, where body is the raw JSON request body. The signing secret is the secret value returned when you create a webhook (prefixed with whsec_). Store it securely — it is only shown once.
Verification Example
Section titled “Verification Example”import crypto from 'crypto';
function verifyWebhook( body: string, signature: string, timestamp: string, secret: string,): boolean { // Reject deliveries older than 5 minutes const age = Math.floor(Date.now() / 1000) - parseInt(timestamp); if (age > 300) return false;
const expected = crypto .createHmac('sha256', secret) .update(`${timestamp}.${body}`) .digest('hex');
return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(expected), );}
// In your Express handler:app.post('/webhooks/wpg', (req, res) => { const isValid = verifyWebhook( JSON.stringify(req.body), req.headers['x-wpg-signature'] as string, req.headers['x-wpg-timestamp'] as string, process.env.WPG_WEBHOOK_SECRET!, );
if (!isValid) { return res.status(401).json({ error: 'Invalid signature' }); }
// Process the event const { event, data } = req.body; console.log(`Received ${event}:`, data);
res.status(200).json({ received: true });});import hmacimport hashlibimport time
def verify_webhook(body: str, signature: str, timestamp: str, secret: str) -> bool: # Reject deliveries older than 5 minutes age = int(time.time()) - int(timestamp) if age > 300: return False
expected = hmac.new( secret.encode(), f"{timestamp}.{body}".encode(), hashlib.sha256, ).hexdigest()
return hmac.compare_digest(signature, expected)Replay Protection
Section titled “Replay Protection”Always check the X-WPG-Timestamp header and reject deliveries older than 5 minutes. The timestamp is included in the HMAC signature, so it cannot be tampered with.
Retry Policy
Section titled “Retry Policy”Failed deliveries (non-2xx response or network error) are retried with exponential backoff:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
| 6 | 12 hours |
After 5 failed retries (6 total attempts), the delivery is marked as failed.
Auto-Disable
Section titled “Auto-Disable”Webhooks are automatically disabled after 10 consecutive failures across any deliveries. You receive an email notification when this happens.
To re-enable a disabled webhook: POST /api/v1/webhooks/:id/enable. This resets the failure count.
Secret Rotation
Section titled “Secret Rotation”Rotate your webhook secret at any time via POST /api/v1/webhooks/:id/rotate-secret. The old secret is immediately invalidated — update your verification code before rotating.
Managing Webhooks
Section titled “Managing Webhooks”See Webhook Management Endpoints for the full API reference.