Debugging webhooks is painful. You can't see what's being sent, signature verification fails mysteriously, and testing edge cases requires complex setups.
In this tutorial, I'll show you how to debug webhook integrations in minutes using Webhook Debugger & Logger.
What You'll Accomplish
By the end of this tutorial, you'll:
- β Capture webhook requests from any service
- β Inspect headers, body, and metadata in real-time
- β Test webhook signature verification
- β Replay requests to test idempotency
- β Export logs for analysis
β±οΈ Time required: ~10 minutes
Prerequisites
- Free Apify account (sign up with email or GitHub)
- A service that sends webhooks (Stripe, GitHub, Shopify, etc.)
- No coding required for basic usage
What You'll Achieve
By the end, you'll have a complete webhook debugging workflow that:
- Captures every incoming request
- Shows raw data for signature debugging
- Allows you to replay requests for testing
- Exports logs as JSON/CSV
Real example: I debugged a Stripe payment webhook in 8 minutes using this approach. Previously took me 3+ hours.
Step 1: Access Webhook Debugger & Logger
Go to the Webhook Debugger page on Apify Store.
If you don't have an Apify account:
- Click "Try for free"
- Sign up with email or GitHub (takes 30 seconds)
- You'll be redirected to Apify Console
What to expect: You'll see the Actor's input configuration page.
Step 2: Configure Basic Settings
You'll see the input form with these key fields:
URL Count (required)
How many webhook URLs to generate (1-10)
{
"urlCount": 3
}
Example: If you're testing Stripe payments, GitHub webhooks, and Shopify orders, set this to 3.
Retention Hours (required)
How long to keep the URLs and logs (1-72 hours)
{
"retentionHours": 24
}
π‘ Tip: For quick debugging, 24 hours is plenty. For ongoing testing, use 72 hours.
Basic configuration example:
{
"urlCount": 3,
"retentionHours": 24
}
Step 3: Advanced Configuration (Optional)
For more control, expand the advanced settings:
Max Payload Size
Maximum request body size (default: 10MB)
{
"maxPayloadSize": 10485760
}
Enable JSON Parsing
Automatically parse JSON payloads (default: true)
{
"enableJSONParsing": true
}
JSON Schema Validation (v2.0+)
Reject invalid payloads automatically:
{
"jsonSchema": {
"type": "object",
"required": ["event", "amount"],
"properties": {
"event": {"type": "string"},
"amount": {"type": "number"}
}
}
}
When to use: Testing API integrations that must conform to a specific payload structure.
Step 4: Run the Actor
- Click the "Start" button
- Status changes to "Running"
- Typically takes 5-10 seconds to spin up
β οΈ Tip: You can close the page - the Actor continues running in the background.
What's happening: The Actor is starting a serverless container and generating your webhook URLs.
Step 5: Get Your Webhook URLs
Once running, there are two ways to get your URLs:
Method 1: Live View
Click "Live View" tab to see the web interface with your URLs (as shown in the previous screenshot).
Method 2: Key-Value Store
- Go to Storage β Key-value stores
- Look for "WEBHOOK_STATE" key
- You'll see your webhook IDs
URL Format
https://<actor-run-id>.runs.apify.net/webhook/<webhook-id>
Example:
https://abc123xyz.runs.apify.net/webhook/wh_abc123
https://abc123xyz.runs.apify.net/webhook/wh_def456
https://abc123xyz.runs.apify.net/webhook/wh_ghi789
π‘ Pro tip: Bookmark these URLs for the duration of your testing.
Step 6: Configure Your Service
Now configure your webhook source (Stripe, GitHub, etc.) to send to your URL.
Example: Stripe
- Go to Stripe Dashboard β Developers β Webhooks
- Click "Add endpoint"
- Paste your webhook URL:
https://<run-id>.runs.apify.net/webhook/wh_abc123 - Select events (e.g.,
payment_intent.succeeded) - Save
Example: GitHub
- Go to Repository β Settings β Webhooks
- Click "Add webhook"
- Paste your URL
- Select events (e.g.,
push,pull_request) - Save
What happens next: Any webhook sent to this URL will be captured and logged.
Step 7: Trigger a Test Webhook
There are two ways to test:
Method 1: Service Test Button
Most services have a "Send test webhook" button. Use it!
Method 2: Manual cURL
curl -X POST https://<run-id>.runs.apify.net/webhook/wh_abc123 \
-H "Content-Type: application/json" \
-d '{"event": "payment.success", "userId": "user_123", "amount": 9999}'
What you'll see: Request appears in the Dataset within 1-2 seconds.
Step 8: View Results in Real-Time
Option 1: Dataset Tab
- Go to Storage β Dataset
- See all captured requests
- Click any item to see full details
Option 2: Real-time Streaming (Advanced)
Use Server-Sent Events (SSE) for live monitoring:
curl -N https://<run-id>.runs.apify.net/log-stream
What You'll See
Each captured request includes:
{
"timestamp": "2025-12-25T14:31:45Z",
"webhookId": "wh_abc123",
"method": "POST",
"headers": {
"content-type": "application/json",
"user-agent": "Stripe/1.0",
"stripe-signature": "t=1735137105,v1=abc123..."
},
"body": "{\"type\": \"payment.success\", \"amount\": 9999}",
"queryParams": {},
"size": 78,
"contentType": "application/json",
"processingTime": 12,
"remoteIp": "54.187.174.169",
"statusCode": 200
}
Step 9: Debug Signature Verification
This is where raw data access becomes crucial.
The Problem
Signature verification fails because you're comparing the signature against the PARSED JSON, not the raw bytes.
The Solution
Use the captured raw body:
const crypto = require('crypto');
// From Webhook Debugger logs:
const rawBody = '{"type": "payment.success", "amount": 9999}';
const signature = 't=1735137105,v1=abc123...'; // from stripe-signature header
const secret = 'whsec_yourStripeSecret';
// Extract timestamp and signature
const [t, v1] = signature.split(',').map(s => s.split('=')[1]);
// Compute expected signature
const payload = `${t}.${rawBody}`;
const hmac = crypto.createHmac('sha256', secret);
hmac.update(payload, 'utf8');
const expectedSignature = hmac.digest('hex');
// Verify
const isValid = crypto.timingSafeEqual(
Buffer.from(v1),
Buffer.from(expectedSignature)
);
console.log('Signature valid:', isValid);
π‘ Key insight: You MUST use the raw body from the logs, not your parsed JSON object.
Step 10: Test Idempotency with Replay
Use the /replay API to test duplicate event handling:
curl -X POST https://<run-id>.runs.apify.net/replay/wh_abc123 \
-H "Content-Type: application/json" \
-d '{
"destination": "https://myapp.com/webhook",
"headers": {
"X-Test-Replay": "true"
}
}'
This resends the captured webhook to your destination, allowing you to verify that your app handles duplicates correctly.
Step 11: Export and Analyze
Export your logs for further analysis:
Via Console:
- Go to Storage β Dataset
- Click "Export"
- Choose format (JSON, CSV, Excel)
- Download
Via API:
curl "https://api.apify.com/v2/datasets/<dataset-id>/items?format=json&clean=1" \
-H "Authorization: Bearer <your-api-token>"
Use cases for exported data:
- Share with team members
- Import into analytics tools
- Create custom reports
- Archive for compliance
Pro Tips for Better Results
1. Use Specific Webhook IDs
Create different IDs for different services:
-
wh_stripefor Stripe -
wh_githubfor GitHub -
wh_shopifyfor Shopify
2. Filter Logs
Use query parameters to filter:
/logs?webhookId=wh_stripe&method=POST&statusCode=200
3. Force Status Codes
Test error handling:
https://<run-id>.runs.apify.net/webhook/wh_abc123?__status=500
4. Simulate Latency (v2.0+)
Test timeout handling:
{
"customResponseDelay": 5000 // 5 second delay
}
Troubleshooting
Issue: "Webhook not found or expired"
Solution: Check that:
- The webhook ID is correct
- The Actor is still running
- The retention period hasn't expired
Use /info endpoint to verify:
curl https://<run-id>.runs.apify.net/info
Issue: Requests not appearing
Solution:
- Verify the URL is correct
- Check that the Actor is in "Running" state
- Ensure the service is actually sending webhooks
Issue: JSON parsing errors
Solution: Check the enableJSONParsing setting and verify the payload is valid JSON.
Conclusion
You now have a complete webhook debugging workflow! π
What you learned:
β
How to capture webhooks without localhost tunneling
β
How to inspect raw request data for signature debugging
β
How to replay webhooks to test idempotency
β
How to export and analyze webhook logs
Time saved: What used to take 3-4 hours now takes 10-15 minutes.
Try Webhook Debugger yourself: https://apify.com/ar27111994/webhook-debugger-logger
Questions? Drop them in the comments! π
π If this tutorial helped you, please give it a like and follow for more webhook debugging tips!





Top comments (0)