Stripe Webhooks

Stripe Webhooks, Delivered.

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 Shopify GitHub Twilio SendGrid

What Stripe actually does

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 documentation

Why teams still lose Stripe events

Even with Stripe's built-in retries, production incidents happen. EventDock adds the safety net you need.

Retry + Backoff

Smart retry schedule: 0s → 10s → 30s → 2m → 10m → 30m → 2h with configurable caps.

  • Retries included—no per-retry billing
  • Exponential backoff prevents stampedes
  • Configurable max retry duration

DLQ & Replay

Never drop events. One-click replay to production or staging with full audit trail.

  • Failed events stored in DLQ
  • Replay to prod or staging
  • Complete audit trail

Signature & Idempotency

Verify Stripe-Signature and show why mismatches occur with visual diff.

  • Timestamp/secret/body diff
  • Idempotency helpers
  • Prevent double-processing

Stripe Quick-Start

Add EventDock to your Stripe webhooks in under 5 minutes

1

Create an endpoint in EventDock

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}'}
2

Configure Stripe Dashboard

In Stripe Dashboard → Developers → Webhooks, add the EventDock URL as your endpoint and copy the signing secret.

3

Test & verify

Send a test event from Stripe, view it in EventDock's Stream, and click Replay to verify your idempotency logic.

4

Enable alerts

Turn on email or Slack alerts for DLQ events so you're notified before incidents affect customers.

Test your Stripe signature with curl
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.

Implementation examples

Verify Stripe signatures and implement idempotency correctly

Signature verification (Node.js)

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);
}

Idempotency pattern

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' };
}

EventDock vs DIY vs Hookdeck

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.

Simple, transparent pricing

Start free, scale as you grow

Free

$0 /month
  • 5,000 events/month
  • 3 endpoints
  • 7-day retention
  • Email alerts
Start Free
Most Popular

Starter

$29 /month
  • 50,000 events/month
  • 10 endpoints
  • 30-day retention
  • Slack alerts
Start Free

Team

$99 /month
  • 250,000 events/month
  • 50 endpoints
  • 90-day retention
  • Custom retries
Start Free

View full pricing →

Frequently Asked Questions

Does Stripe already retry webhooks?

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.

Will replaying a Stripe webhook charge customers again?

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.

How do I debug Stripe signature verification failures?

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.

Do webhook retries cost extra with EventDock?

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.

How many events does the EventDock free tier include?

EventDock's free tier includes 5,000 events per month with full retry, DLQ, and replay capabilities. No credit card required.

Can I test Stripe webhooks before going live?

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.

Start free — keep every Stripe webhook

5,000 events/month free. No credit card required. 5-minute setup.

Start Free Trial

Other providers: Shopify · GitHub