How to Test Outgoing Webhooks and HMAC Signatures Without Setting Up an Event Server

Learn how to simulate outgoing webhook dispatches, verify HMAC-SHA256 signatures, test automatic retries, and inspect delivery logs using Playground API.

NK
Nilesh Kumar
Creator of Playground API
How to Test Outgoing Webhooks and HMAC Signatures Without Setting Up an Event Server

How to Test Outgoing Webhooks and HMAC Signatures Without Setting Up an Event Server

When building integrations for payment gateways, SaaS workflows, or third-party webhooks, testing incoming event consumers is famously cumbersome. You typically need:

  1. A live public URL (using Ngrok or Cloudflare Tunnels).
  2. An active subscription or event trigger on a third-party service.
  3. Cryptographic signature generation (HMAC-SHA256) to ensure your security verification middleware works under pressure.
  4. A way to simulate failed deliveries (HTTP 500, timeouts) to test your exponential retry and alerting systems.

In this guide, we'll explore how Playground API provides a complete outgoing webhook dispatcher, delivery inspector, and cryptographic signature generator with zero server setup.


1. Registering an Outgoing Webhook Endpoint

To start receiving webhook events from Playground API, send a POST request to register your destination URL and subscribed topics:

Terminal
1
curl -X POST https://playground.nileslabs.com/api/v1/webhooks \
2
-H "Content-Type: application/json" \
3
-d {
4
"url": "https://api.yourdomain.com/webhooks/incoming",
5
"events": ["post.created", "user.updated", "order.completed"],
6
"secret": "whsec_test_secret_key_849204"
7
}

Response:

json
1
{
2
"id": "whk_9a8b7c6d5e",
3
"url": "https://api.yourdomain.com/webhooks/incoming",
4
"events": ["post.created", "user.updated", "order.completed"],
5
"status": "active",
6
"secret": "whsec_test_secret_key_849204",
7
"created_at": "2026-09-19T18:30:00.000Z"
8
}

2. Triggering Test Webhook Dispatches

Whenever a mutation occurs in your Playground API sandbox (e.g. POST /posts or POST /orders), the dispatcher automatically packages the event payload and fires an HTTP POST request to your registered destination URL.

You can also trigger a manual test dispatch directly via the API:

Terminal
1
curl -X POST https://playground.nileslabs.com/api/v1/webhooks/whk_9a8b7c6d5e/test \
2
-H "Content-Type: application/json" \
3
-d {
4
"event": "order.completed",
5
"data": {
6
"order_id": "ord_10492",
7
"amount": 99.00,
8
"currency": "USD"
9
}
10
}

3. Verifying Cryptographic HMAC-SHA256 Signatures

Every webhook sent by Playground API includes security headers:

  • X-Playground-Signature: t=1758306600,v1=9e8b7c4a3...
  • X-Playground-Event: order.completed
  • X-Playground-Delivery-ID: del_3f920a

Here is how you verify this in a Node.js / Express middleware:

typescript
1
import crypto from 'crypto';
2
import { Request, Response, NextFunction } from 'express';
3
4
export function verifyWebhookSignature(req: Request, res: Response, next: NextFunction) {
5
const signatureHeader = req.headers['x-playground-signature'] as string;
6
const secret = process.env.PLAYGROUND_WEBHOOK_SECRET!;
7
8
if (!signatureHeader) {
9
return res.status(401).json({ error: 'Missing signature header' });
10
}
11
12
const parts = Object.fromEntries(
13
signatureHeader.split(',').map((part) => part.split('='))
14
);
15
16
const timestamp = parts['t'];
17
const signature = parts['v1'];
18
19
// Prevent replay attacks (5 minute window)
20
const currentTimestamp = Math.floor(Date.now() / 1000);
21
if (Math.abs(currentTimestamp - parseInt(timestamp, 10)) > 300) {
22
return res.status(400).json({ error: 'Timestamp expired' });
23
}
24
25
// Compute expected HMAC hash
26
const rawBody = (req as any).rawBody || JSON.stringify(req.body);
27
const expectedSignature = crypto
28
.createHmac('sha256', secret)
29
.update(${timestamp}.${rawBody})
30
.digest('hex');
31
32
if (crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature))) {
33
return next();
34
}
35
36
return res.status(403).json({ error: 'Invalid HMAC signature' });
37
}

4. Live In-Browser Delivery Inspector

You can view the status of every dispatch, inspect request headers, payload bodies, response status codes, and retry counts directly in the Playground API documentation:

👉 https://playground.nileslabs.com/docs/webhooks

Features in the Inspector:

  • 📊 Real-time Status Badges: 200 OK, 500 Server Error, Timed Out.
  • 🔁 One-Click Redelivery: Re-send any failed webhook event with preserved delivery IDs.
  • ⏱️ Latency Timings: Measure response times from your server down to the millisecond.

Conclusion

Testing webhooks should not require mocking raw HTTP requests or setting up complex third-party test accounts. Playground API gives you a complete, stateful dispatcher with cryptographic security out of the box.

Start testing webhooks right now: https://playground.nileslabs.com/docs/webhooks

Tags:#webdev#javascript#api#security

Try Playground API in Your Own App

Stateful mock REST & GraphQL API with private sandbox overlays.