Playground API
DocsStatsBlogStudio
Documentation Tree
Technical BlogFeature Deep Dives
  • Introduction
  • Quickstart
    5 min
  • How It Works
  • Recipes & Cookbooks
  • Platform Comparisons
  • Real-World Showcase
  • Interactive Studio
    Studio
  • GraphiQL IDE
    IDE
  • Session Quotas & Activity
  • Network Chaos Simulator
  • Atomic Sandbox Reset
  • Overview & Models
    Hub
  • Users Resource
  • Posts Resource
  • Comments Resource
  • Todos Resource
  • Custom Collections
    Custom
  • Multipart File Uploads
    Upload
  • Dynamic SVG Avatars
    SVG
  • Image Thumbnails
    CDN
  • Relational Filtering
  • Full-Text Search
  • Dynamic Sorting
  • Offset Pagination
  • Cursor Pagination
    Scroll
  • CSV & Excel Export & Import
    IO
  • Custom Collections
    CRUD
  • Overview & Architecture
    Hub
  • JWT Auth Flow
  • Refresh Token Rotation
    Mutex
  • RBAC Permission Matrix
    Roles
  • Expiry Simulation
  • Clock Skew Drift
  • Password Recovery Loop
  • Dual-Mode Sandboxing
  • GraphiQL IDE
    IDE
  • Relational Queries
  • Stateful Mutations
  • Realtime Subscriptions
  • Overview & Flowcharts
    Hub
  • Hosted Checkout
    Stripe
  • Payment Intents API
  • 3DS Challenge Modal
    Modal
  • Customers Vault
  • Charges & Refunds
  • Test Cards Catalog
  • Overview & Channels
    Hub
  • Virtual Email Mailbox
    Mailtrap
  • Virtual SMS Terminal
    Phone
  • In-App Notifications
  • Message Dispatcher
  • Realtime Studio
    Studio
  • Native WebSocket (/ws)
  • Socket.io Gateway
  • Presence & Echo Bot
  • Server-Sent Events (SSE)
    SSE
  • Analytics Telemetry
  • Webhook Subscriptions
  • HMAC SHA-256 Signatures
  • Delivery Logs
  • Manual Retry Simulator
  • Network Latency Delay
  • HTTP Status Codes
  • Rate-Limit Simulator
    429
  • Flaky Network & Jitter
    Chaos
  • Session Quotas & Activity
  • JSON Snapshots
    JSON
  • Headless CI/CD Testing
    CI
  • Mobile QR Code Sync
  • System Metrics & Health
  • Atomic Sandbox Reset
  • Official TypeScript SDK
  • Multi-Language Generators
  • DevTools Extension
  • OpenAPI 3.1 Spec
    JSON
  • Postman Collection v2.1
  • Bruno Collection
  • Insomnia Workspace
  • TypeScript .d.ts
    .d.ts
  • AI Prompt Rules
    Rules
  • Context Index (llms.txt)
  • Full Schema (llms-full.txt)
  • Manifest (product.json)
  • All Feature Articles
    Blog
  • React CRUD Without Backend
    Deep Dive
  • Why Static APIs Fail
  • Mocking Stateful Auth
  • WebSockets & SSE Guide
Technical Blog
Articles

In-depth articles explaining stateful mock APIs, WebSockets, payments, and frontend resilience.

Read Articles
PreviousWebhook Subscriptions
NextDelivery Logs
Outgoing Webhooks

HMAC SHA-256 Signatures & Security

Every outgoing webhook payload sent by Playground API includes a cryptographic signature in the X-Playground-Signature header. Verify signatures in your receiver to authenticate origin, prevent payload tampering, and defend against replay attacks.

Interactive HMAC Signature Workbench

Select an event topic to inspect the raw JSON payload and the corresponding cryptographic signature headers:

SubtleCrypto SHA-256
Raw Request Payload (posts.created)
1
{
2
"id": "del_e28c5a14-41bf-4c7b-8392-127810bba104",
3
"event": "posts.created",
4
"timestamp": "2025-09-29T17:00:00.000Z",
5
"data": {
6
"id": 42,
7
"title": "Zero-Trust Webhook Authentication",
8
"author": "Security Lead",
9
"userId": 1
10
}
11
}
1
POST /api/webhooks HTTP/1.1
2
Host: your-receiver.example.com
3
User-Agent: Playground-API-Webhook-Dispatcher/1.0
4
Content-Type: application/json
5
X-Playground-Event: posts.created
6
X-Playground-Delivery: del_e28c5a14-41bf-4c7b-8392-127810bba104
7
X-Playground-Signature: calculating...
8
9
{
10
"id": "del_e28c5a14-41bf-4c7b-8392-127810bba104",
11
"event": "posts.created",
12
"timestamp": "2025-09-29T17:00:00.000Z",
13
"data": {
14
"id": 42,
15
"title": "Zero-Trust Webhook Authentication",
16
"author": "Security Lead",
17
"userId": 1
18
}
19
}

Security & Routing Headers Reference

The Playground API includes the following HTTP request headers on every outgoing webhook dispatch:

HeaderSample ValuePurpose & Description
X-Playground-Signaturet=1759165200,v1=9a2b8...Cryptographic HMAC-SHA256 signature to verify payload authenticity.
X-Playground-Eventposts.createdDomain event name allowing consumers to filter or route payloads.
X-Playground-Deliverydel_4a9e21...Unique transmission UUID for receiver idempotency and de-duplication.
User-AgentPlayground-API-Webhook-Dispatcher/1.0Standard User-Agent identifier sent by the dispatcher client.

Implementation Code Examples

Production signature verification implementations in Node.js, Python, or Go:

1
import crypto from 'crypto';
2
3
/**
4
* Verify Playground API outgoing webhook signature with constant-time equality
5
* @param {string|Buffer} rawBody - Raw unprocessed HTTP request body string
6
* @param {string} signatureHeader - Value of X-Playground-Signature header
7
* @param {string} secret - Webhook endpoint signing secret (whsec_...)
8
* @param {number} toleranceSeconds - Max allowed age of webhook in seconds (default 300)
9
*/
10
export function verifyWebhookSignature(rawBody, signatureHeader, secret, toleranceSeconds = 300) {
11
if (!signatureHeader || !secret) {
12
throw new Error('Missing signature header or secret key');
13
}
14
15
// Support both standard format (sha256=...) and timestamped format (t=...,v1=...)
16
if (signatureHeader.startsWith('sha256=')) {
17
const receivedHash = signatureHeader.slice(7);
18
const expectedHash = crypto
19
.createHmac('sha256', secret)
20
.update(rawBody)
21
.digest('hex');
22
23
if (receivedHash.length !== expectedHash.length) return false;
24
return crypto.timingSafeEqual(Buffer.from(receivedHash), Buffer.from(expectedHash));
25
}
26
27
// Timestamped signature verification (t=...,v1=...)
28
const parts = signatureHeader.split(',');
29
const t = parts.find((p) => p.startsWith('t='))?.split('=')[1];
30
const v1 = parts.find((p) => p.startsWith('v1='))?.split('=')[1];
31
32
if (!t || !v1) {
33
throw new Error('Malformed timestamped signature header');
34
}
35
36
// Replay Attack Defense: Check clock drift
37
const now = Math.floor(Date.now() / 1000);
38
if (Math.abs(now - parseInt(t, 10)) > toleranceSeconds) {
39
throw new Error('Signature timestamp outside tolerance window. Potential replay attack.');
40
}
41
42
const signedPayload = ${t}.${rawBody};
43
const expectedHash = crypto
44
.createHmac('sha256', secret)
45
.update(signedPayload)
46
.digest('hex');
47
48
if (v1.length !== expectedHash.length) return false;
49
return crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expectedHash));
50
}

Zero-Trust Security Checklist

Prevent Timing Attacks

Never use standard string equality (== or ===). Always use constant-time functions like Node's crypto.timingSafeEqual or Python's hmac.compare_digest.

Replay Attack Tolerance Window

Verify that the timestamp t in the header is within 300 seconds (5 minutes) of current server time to reject stale intercepted requests.

Compute over Raw Unparsed Bytes

Do not parse the body to an object and re-stringify it. Key ordering differences will break HMAC verification. Compute HMAC directly over the raw incoming request buffer.

Enforce Idempotency

Store X-Playground-Delivery in Redis or a DB unique index. Acknowledge duplicates with HTTP 200 immediately without reprocessing business actions.