Stripe retries for up to 3 days—but teams still lose events to timeouts, deploys, and bad signatures. EventDock gives you retries, DLQ, replay, and signature diff in minutes.
Works with webhooks from
Stripe attempts delivery for up to three days with exponential backoff in live mode. If your endpoint fails or responds too slowly, deliveries keep retrying automatically.
However, you still need idempotency, DLQ, replay, and signature verification to avoid duplicates, lost events during deploys, and debugging pain when webhooks fail.
Stripe webhook documentationEven with Stripe's built-in retries, production incidents happen. EventDock adds the safety net you need.
Smart retry schedule: 0s → 10s → 30s → 2m → 10m → 30m → 2h with configurable caps.
Never drop events. One-click replay to production or staging with full audit trail.
Verify Stripe-Signature and show why mismatches occur with visual diff.
Add EventDock to your Stripe webhooks in under 5 minutes
Select Stripe as the provider and paste your upstream URL (where you want events delivered).
EventDock will give you an ingest URL like:
https://api.eventdock.app/in/{'{your-endpoint-id}'}
In Stripe Dashboard → Developers → Webhooks, add the EventDock URL as your endpoint and copy the signing secret.
Send a test event from Stripe, view it in EventDock's Stream, and click Replay to verify your idempotency logic.
Turn on email or Slack alerts for DLQ events so you're notified before incidents affect customers.
curl -s https://api.eventdock.app/in/<endpoint-id> \
-H "Stripe-Signature: t=1731264000,v1=<hex-digest>" \
-H "Content-Type: application/json" \
--data '{"type":"invoice.paid","id":"evt_123"}'
In EventDock, open Stream → verify signature verdict and replay to staging.
Verify Stripe signatures and implement idempotency correctly
IMPORTANT: Use raw body middleware, not JSON parser. Stripe signs webhook payloads with Stripe-Signature. Verify within 5 minutes of timestamp to prevent replay attacks.
const crypto = require('crypto');
// Express: IMPORTANT – use raw body, not JSON parser
app.post('/stripe-webhook',
express.raw({ type: 'application/json' }),
(req, res) => {
const sigHeader = req.header('stripe-signature');
const secret = process.env.STRIPE_SIGNING_SECRET;
const payload = req.body.toString('utf8'); // raw bytes → string
const ok = verifyStripeSignature(payload, sigHeader, secret);
if (!ok) return res.status(400).send('Bad signature');
// handle event...
res.sendStatus(200);
});
function verifyStripeSignature(payload, signatureHeader, secret) {
// Header contains t=timestamp and v1=signature(s)
const parts = Object.fromEntries(signatureHeader.split(',')
.map(p => p.split('=')));
const timestamp = parseInt(parts.t, 10);
const v1 = parts.v1;
// 5 minute tolerance
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - timestamp) > 300) return false;
const signed = `${timestamp}.${payload}`;
const expectedHex = crypto.createHmac('sha256', secret)
.update(signed)
.digest('hex');
// Compare hex digests in constant time (CRITICAL: specify 'hex' encoding)
const a = Buffer.from(v1, 'hex');
const b = Buffer.from(expectedHex, 'hex');
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Store processed event IDs for 24 hours to prevent double-processing during replays.
async function processStripeEvent(event) {
const eventId = event.id;
const ttl = 24 * 60 * 60; // 24 hours
// Check if already processed
const exists = await kv.get(`stripe:${eventId}`);
if (exists) {
console.log(`Event ${eventId} already processed, skipping`);
return { status: 'duplicate' };
}
// Process the event
await handleEvent(event);
// Mark as processed
await kv.set(`stripe:${eventId}`, '1', { ttl });
return { status: 'processed' };
}
| Feature | EventDock | DIY Solution | Hookdeck |
|---|---|---|---|
| Retries included | ✓ | Manual implementation | ✓ |
| Dead letter queue | ✓ | Build yourself | ✓ |
| One-click replay UI | ✓ | ✗ | ✓ |
| Signature diff/debugging | ✓ | ✗ | Basic |
| Time to first event | <5 min | Days/weeks | 10-15 min |
| Pricing | Free → $29/mo | Dev time + infra | Free → $39/mo |
Note: Hookdeck Developer plan is free with up to 10,000 events and 3-day retention. EventDock focuses on receiver-side simplicity with 5,000 events on the free tier.
Start free, scale as you grow
Yes, Stripe attempts to deliver events for up to three days with exponential backoff in live mode. However, you still need idempotency handling, DLQ for failed events, and replay capabilities to ensure no events are lost during deploys, timeouts, or signature issues.
No, if you implement proper idempotency. Use event.id to store processed event IDs in your database or KV store for 24 hours, and short-circuit if an event has already been processed. This prevents double-processing during replays.
Stripe signature failures typically occur due to: (1) Timestamp skew beyond the 5-minute tolerance window, (2) Incorrect or rotated webhook secret, (3) Request body mutation before verification. EventDock shows you exactly which part failed with a visual diff.
No—retries are included in all EventDock plans at no additional cost, similar to Hookdeck's policy. You only pay for unique events received, not for retry attempts.
EventDock's free tier includes 5,000 events per month with full retry, DLQ, and replay capabilities. No credit card required.
Yes. Create an endpoint in EventDock, point it to your staging environment, use Stripe's test mode webhooks, and replay events as many times as needed to verify your idempotency logic works correctly.
5,000 events/month free. No credit card required. 5-minute setup.
Start Free Trial