API Reference
The WebhookWhisper REST API lets you manage endpoints, retrieve events, configure forwarding rules, and send test webhooks programmatically. All responses are JSON. Base URL: https://webhookwhisper.com
webhookwhisper.comJSON (application/json)Bearer token or API keyAuthentication
Most endpoints require authentication. Pass your token in the Authorization header:
Authorization: Bearer sess_abc123... # Or with an API key (Pro plan only): Authorization: Bearer wf_live_abc123...
Get a session token from POST /api/auth/login. Get API keys (Pro only) from your dashboard settings.
Authentication
/api/auth/registerCreate a new user account. Returns a session token.
name—string — display name (2–100 chars)email—string — valid email addresspassword—string — min 8 characters{
"data": {
"user": { "id": "uuid", "name": "Jane", "email": "[email protected]", "plan": "free" },
"token": "sess_abc123...",
"expiresAt": "2026-05-09T00:00:00.000Z"
}
}/api/auth/loginSign in and receive a session token.
email—stringpassword—string{
"data": {
"user": { "id": "uuid", "name": "Jane", "email": "[email protected]", "plan": "free" },
"token": "sess_abc123...",
"expiresAt": "2026-05-09T00:00:00.000Z"
}
}/api/auth/logoutInvalidate the current session token.
{ "data": { "message": "Logged out successfully" } }/api/auth/meGet the currently authenticated user.
{
"data": {
"user": { "id": "uuid", "name": "Jane", "email": "[email protected]", "plan": "free", "role": "user" }
}
}Receiving Webhooks
/hook/:slugYour webhook endpoint URL. Accepts any HTTP method (GET, POST, PUT, PATCH, DELETE). Every incoming request is captured, stored, and forwarded per your rules. Returns immediately with a 200 response.
{ "received": true }Endpoints
/api/endpointsList all your webhook endpoints with event counts and last activity.
{
"data": [
{
"id": "uuid",
"name": "My Stripe Endpoint",
"slug": "abc123xyz",
"description": "Stripe payments",
"isActive": true,
"webhookUrl": "https://webhookwhisper.com/hook/abc123xyz",
"eventCount": 42,
"ruleCount": 2,
"lastEventAt": "2026-04-09T10:00:00.000Z",
"createdAt": "2026-04-01T00:00:00.000Z"
}
]
}/api/endpointsCreate a new webhook endpoint. Returns the endpoint with its unique webhook URL.
name—string — required (1–100 chars)description—string — optional (max 500 chars)secretKey—string — optional, for signature verification{
"data": {
"id": "uuid",
"name": "My Stripe Endpoint",
"slug": "abc123xyz",
"webhookUrl": "https://webhookwhisper.com/hook/abc123xyz",
"isActive": true,
"createdAt": "2026-04-09T00:00:00.000Z"
}
}/api/endpoints/:idGet a single endpoint with its forwarding rules and last 20 events.
{
"data": {
"endpoint": { "id": "uuid", "name": "...", "webhookUrl": "...", "isActive": true },
"rules": [ { "id": "uuid", "targetUrl": "https://myapp.com/hooks", "isActive": true } ],
"recentEvents": [ { "id": "uuid", "method": "POST", "receivedAt": "..." } ]
}
}/api/endpoints/:idUpdate endpoint name, description, active status, or custom response settings.
name—string — optionaldescription—string — optionalisActive—boolean — optionalcustomResponseStatus—number — optional, 200–599 (Pro only)customResponseBody—string — optional JSON string (Pro only)customResponseHeaders—string — optional JSON string (Pro only){ "data": { "id": "uuid", "name": "Updated Name", "isActive": false } }/api/endpoints/:idDelete an endpoint and all its events and forwarding rules.
{ "data": { "message": "Endpoint deleted successfully" } }Events
/api/endpoints/:endpointId/eventsList events for an endpoint, paginated. Supports filtering by HTTP method and body search.
page—number — default 1limit—number — default 50, max 100method—string — filter by HTTP method (GET, POST, etc.)search—string — search within request body{
"data": [
{
"id": "uuid",
"method": "POST",
"headers": { "content-type": "application/json", "x-stripe-signature": "t=..." },
"query": {},
"body": "{"type":"payment_intent.succeeded","amount":2999}",
"bodyJson": { "type": "payment_intent.succeeded", "amount": 2999 },
"sourceIp": "54.187.0.1",
"size": 1024,
"receivedAt": "2026-04-09T10:00:00.000Z",
"deliveryCount": 2,
"successCount": 2
}
],
"meta": { "page": 1, "limit": 50, "total": 142, "totalPages": 3 }
}/api/endpoints/:endpointId/events/:eventIdGet a single event with full headers, body, and all delivery attempt details.
{
"data": {
"event": {
"id": "uuid",
"method": "POST",
"headers": { "content-type": "application/json" },
"body": "{"type":"checkout.session.completed"}",
"bodyJson": { "type": "checkout.session.completed" },
"receivedAt": "2026-04-09T10:00:00.000Z"
},
"deliveries": [
{
"id": "uuid",
"targetUrl": "https://myapp.com/webhooks",
"status": "success",
"statusCode": 200,
"durationMs": 145,
"attempt": 1,
"deliveredAt": "2026-04-09T10:00:01.000Z"
}
]
}
}/api/endpoints/:endpointId/events/:eventId/replayReplay an event to all active forwarding rules. Re-enqueues delivery with retry logic.
{
"data": {
"message": "Event replayed to 2 rule(s)",
"rulesCount": 2,
"jobIds": ["job_abc", "job_xyz"]
}
}Forwarding Rules
/api/endpoints/:endpointId/rulesList all forwarding rules for an endpoint.
{
"data": [
{
"id": "uuid",
"endpointId": "uuid",
"targetUrl": "https://myapp.com/webhooks",
"httpMethod": "SAME",
"retryCount": 3,
"timeoutMs": 10000,
"isActive": true,
"customHeaders": "{}",
"createdAt": "2026-04-01T00:00:00.000Z"
}
]
}/api/endpoints/:endpointId/rulesCreate a forwarding rule. Webhooks received at the endpoint will be forwarded to targetUrl.
targetUrl—string — required, valid URL (e.g. https://myapp.com/hooks or http://localhost:3000/hooks)httpMethod—string — SAME | GET | POST | PUT | DELETE | PATCH. Default: SAME (mirrors incoming method)retryCount—number — 0–10. Default: 3timeoutMs—number — 1000–30000ms. Default: 10000customHeaders—string — JSON object of extra headers to add. Default: {}isActive—boolean — Default: true{
"data": {
"id": "uuid",
"targetUrl": "https://myapp.com/webhooks",
"httpMethod": "SAME",
"retryCount": 3,
"timeoutMs": 10000,
"isActive": true,
"createdAt": "2026-04-09T00:00:00.000Z"
}
}/api/endpoints/:endpointId/rules/:ruleIdUpdate a forwarding rule.
targetUrl—string — optionalhttpMethod—string — optionalretryCount—number — optionaltimeoutMs—number — optionalcustomHeaders—string — optional JSONisActive—boolean — optional{ "data": { "id": "uuid", "targetUrl": "https://newurl.com/hooks", "isActive": false } }/api/endpoints/:endpointId/rules/:ruleIdDelete a forwarding rule.
{ "data": { "message": "Rule deleted successfully" } }Test Sender
/api/test/samplesGet all 35+ available sample payloads (Stripe, GitHub, Shopify, Razorpay, etc.).
{
"data": {
"samples": [
{
"id": "uuid",
"provider": "stripe",
"eventName": "payment_intent.succeeded",
"category": "stripe",
"description": "Payment Intent Succeeded",
"method": "POST",
"headers": { "content-type": "application/json", "stripe-signature": "..." },
"payload": { "type": "payment_intent.succeeded", "data": { "object": { "amount": 2000 } } }
}
]
}
}/api/test/sendSend a custom HTTP request to any URL. Returns the response status, headers, body, and latency.
targetUrl—string — required, URL to send tomethod—string — GET | POST | PUT | DELETE | PATCH. Default: POSTheaders—object — optional key/value headersbody—string — optional request body{
"data": {
"success": true,
"statusCode": 200,
"responseHeaders": { "content-type": "application/json" },
"responseBody": "{"ok":true}",
"durationMs": 145
}
}/api/test/send-sampleSend a pre-built sample payload from a specific provider to a target URL.
sampleId—string — ID from GET /api/test/samplestargetUrl—string — URL to send the sample to{
"data": {
"success": true,
"statusCode": 200,
"durationMs": 120,
"sampleUsed": { "provider": "stripe", "eventType": "payment_intent.succeeded", "name": "Payment Intent Succeeded" }
}
}API Keys
/api/keysList your API keys (key prefix and metadata only — full keys are never shown again).
{
"data": [
{
"id": "uuid",
"name": "Production Key",
"keyPrefix": "wf_live_abc",
"lastUsedAt": "2026-04-09T10:00:00.000Z",
"createdAt": "2026-04-01T00:00:00.000Z"
}
]
}/api/keysCreate an API key. The full key is shown only once — save it immediately.
name—string — label for this key (1–100 chars){
"data": {
"id": "uuid",
"name": "Production Key",
"keyPrefix": "wf_live_abc",
"key": "wf_live_abc123xyz...",
"warning": "Save this key now. You will not be able to see it again.",
"createdAt": "2026-04-09T00:00:00.000Z"
}
}/api/keys/:idRevoke an API key. This immediately invalidates the key.
{ "data": { "message": "API key revoked successfully" } }Stats
/api/statsGet your account stats: endpoint count, event totals, delivery success rate, avg latency. Pro accounts also get hourly chart data.
{
"data": {
"endpoints": { "total": 3, "active": 3 },
"events": { "total": 1420, "today": 87, "lastHour": 12 },
"deliveries": { "success": 85, "failed": 2, "pending": 0 },
"rules": { "total": 5, "active": 5 },
"successRate": 97.7,
"avgLatencyMs": 143
}
}Error Responses
All errors return JSON with an error field:
{ "error": "Endpoint not found" }
// Validation errors include details:
{
"error": "Validation failed",
"details": [{ "path": ["name"], "message": "String must contain at least 1 character(s)" }]
}
// Plan limit errors include upgrade info:
{
"error": "API keys are a Pro feature",
"upgradeRequired": true
}| Status | Meaning |
|---|---|
200 | OK — request succeeded |
201 | Created — resource created successfully |
400 | Bad Request — validation failed or malformed JSON |
401 | Unauthorized — missing or invalid token |
403 | Forbidden — feature requires a higher plan, or you don't own this resource |
404 | Not Found — endpoint, event, or rule doesn't exist |
410 | Gone — guest endpoint has expired |
429 | Too Many Requests — rate limit exceeded |
500 | Internal Server Error — something went wrong on our end |
Code Examples
Create an endpoint and get its URL
# 1. Login to get a token
curl -X POST https://webhookwhisper.com/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"yourpassword"}'
# Response: { "data": { "token": "sess_abc...", "user": {...} } }
# 2. Create an endpoint
curl -X POST https://webhookwhisper.com/api/endpoints \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sess_abc..." \
-d '{"name":"My Stripe Endpoint","description":"Production payments"}'
# Response includes webhookUrl: "https://webhookwhisper.com/hook/abc123xyz"
# 3. Add a forwarding rule to your local server
curl -X POST https://webhookwhisper.com/api/endpoints/{endpointId}/rules \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sess_abc..." \
-d '{"targetUrl":"http://localhost:3000/webhooks","retryCount":3}'List recent events
curl https://webhookwhisper.com/api/endpoints/{endpointId}/events?limit=10 \
-H "Authorization: Bearer sess_abc..."Send a Stripe test payload
# 1. Get sample IDs
curl https://webhookwhisper.com/api/test/samples
# 2. Send the sample to your endpoint
curl -X POST https://webhookwhisper.com/api/test/send-sample \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sess_abc..." \
-d '{
"sampleId": "uuid-of-stripe-sample",
"targetUrl": "https://webhookwhisper.com/hook/abc123xyz"
}'Rate Limits
| Endpoint | Limit |
|---|---|
POST /api/test/send | Daily limit per user (plan-dependent) |
POST /api/test/send-sample | Daily limit per user (plan-dependent) |
POST /hook/:slug (receiving) | No limit on receiving webhooks |
All other API endpoints | Standard rate limits apply |