How to Capture and Inspect Webhooks with a Free API
If you've ever built a Stripe integration, a GitHub Action, or a Shopify app, you know the pain of testing webhooks during development. You set up an endpoint, trigger an event, and then... where did the data go?
In this tutorial, I'll show you how to use the Webhook Receiver API to capture, inspect, and retrieve webhook payloads — all without setting up any infrastructure.
The Problem
During development, you need to:
- Receive webhooks from external services (Stripe, GitHub, etc.)
- See what data they're sending
- Verify headers, signatures, and payload structure
Most developers use console.log and pray. There's a better way.
Quick Start (2 minutes)
Step 1: Create an Endpoint
curl -X POST https://hookray.com/api/endpoints
Response:
{
"endpoint": {
"slug": "a1b2c3d4",
"expires_at": "2026-03-21T00:00:00Z",
"request_count": 0,
"max_requests": 100
}
}
Your webhook URL is now: https://hookray.com/api/hook/a1b2c3d4
Step 2: Send a Webhook
Point any service to your URL, or test manually:
curl -X POST https://hookray.com/api/hook/a1b2c3d4 \
-H "Content-Type: application/json" \
-H "X-Custom-Header: my-value" \
-d '{"event": "order.completed", "amount": 49.99}'
Response: {"ok": true}
Step 3: Retrieve Captured Data
curl https://hookray.com/api/hook/a1b2c3d4/requests
Response:
{
"endpoint": {
"slug": "a1b2c3d4",
"request_count": 1,
"max_requests": 100
},
"requests": [
{
"method": "POST",
"headers": {
"content-type": "application/json",
"x-custom-header": "my-value"
},
"body": "{\"event\": \"order.completed\", \"amount\": 49.99}",
"query_params": {},
"source_ip": "203.0.113.1",
"created_at": "2026-03-20T12:00:00Z"
}
]
}
Every header, every byte of the body, every query parameter — captured and stored.
Real-World Example: Testing Stripe Webhooks
# 1. Create endpoint
SLUG=$(curl -s -X POST https://hookray.com/api/endpoints | jq -r '.endpoint.slug')
echo "Webhook URL: https://hookray.com/api/hook/$SLUG"
# 2. Set this URL in Stripe Dashboard → Developers → Webhooks
# 3. Trigger a test event in Stripe
# 4. Retrieve the webhook data
curl -s "https://hookray.com/api/hook/$SLUG/requests" | jq '.requests[0].body' -r | jq .
Python Example
import requests
# Create endpoint
resp = requests.post("https://hookray.com/api/endpoints")
slug = resp.json()["endpoint"]["slug"]
print(f"Webhook URL: https://hookray.com/api/hook/{slug}")
# ... configure your service to send webhooks to the URL ...
# Retrieve captured webhooks
resp = requests.get(f"https://hookray.com/api/hook/{slug}/requests")
for req in resp.json()["requests"]:
print(f"{req['method']} - {req['content_type']} - {req['created_at']}")
print(req["body"])
Node.js Example
const BASE = "https://hookray.com";
// Create endpoint
const { endpoint } = await fetch(`${BASE}/api/endpoints`, {
method: "POST",
}).then((r) => r.json());
console.log(`Webhook URL: ${BASE}/api/hook/${endpoint.slug}`);
// Retrieve captured webhooks
const { requests } = await fetch(
`${BASE}/api/hook/${endpoint.slug}/requests`
).then((r) => r.json());
requests.forEach((req) => {
console.log(`${req.method} ${req.content_type} ${req.created_at}`);
console.log(JSON.parse(req.body));
});
Features
- Any HTTP method: GET, POST, PUT, PATCH, DELETE — all captured
- Full headers: Every request header is stored
-
Query parameters:
?key=valuepairs are parsed and stored - Source IP: Know where the request came from
- Free tier: 100 requests per endpoint, expires in 24 hours
- No signup required: Create an endpoint and start capturing immediately
Try It Now
The API is available on RapidAPI with a free tier, or use it directly at hookray.com.
You can also use the web dashboard at hookray.com/app for a visual, real-time view of incoming webhooks.
Built by @ShotaTanikawa. If this helped you, a ⭐ on the API listing would be appreciated!
Top comments (0)