{"@context":"https://schema.org","@graph":[{"@type":"WebPage","@id":"https://inquir.org/use-cases/stripe-webhooks#webpage","url":"https://inquir.org/use-cases/stripe-webhooks","name":"Process Stripe webhooks serverlessly with retries and logs","headline":"Process Stripe webhooks serverlessly with retries and logs","description":"Serverless Stripe webhook processor: HMAC signature verification on raw body, fast ACK before Stripe retries, idempotency keys for duplicate events, and async pipeline for fulfillment.","inLanguage":"en-US","isPartOf":{"@id":"https://inquir.org/#website"},"author":{"@type":"Organization","name":"Inquir"},"datePublished":"2025-01-01T00:00:00.000Z","dateModified":"2026-04-20T00:00:00.000Z","citation":"https://inquir.org/docs"},{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://inquir.org"},{"@type":"ListItem","position":2,"name":"Use cases","item":"https://inquir.org/use-cases"},{"@type":"ListItem","position":3,"name":"Stripe webhooks","item":"https://inquir.org/use-cases/stripe-webhooks"}]},{"@type":"HowTo","@id":"https://inquir.org/use-cases/stripe-webhooks#howto","name":"Process Stripe webhooks serverlessly with retries and logs","description":"Serverless Stripe webhook processor: HMAC signature verification on raw body, fast ACK before Stripe retries, idempotency keys for duplicate events, and async pipeline for fulfillment.","inLanguage":"en-US","author":{"@type":"Organization","name":"Inquir"},"step":[{"@type":"HowToStep","position":1,"name":"Verify HMAC on raw body","text":"Read event.body as string. Call stripe.webhooks.verifySignature with raw body and stripe-signature header."},{"@type":"HowToStep","position":2,"name":"Write idempotency key, return 200","text":"Upsert evt.id in your events table. Return immediately—do not start fulfillment yet."},{"@type":"HowToStep","position":3,"name":"Trigger fulfillment orchestration","text":"Call global.durable.startNew with event type and data. The orchestration handles retries, email, and inventory updates independently."}],"isPartOf":{"@id":"https://inquir.org/use-cases/stripe-webhooks#webpage"}},{"@type":"FAQPage","@id":"https://inquir.org/use-cases/stripe-webhooks#faq","url":"https://inquir.org/use-cases/stripe-webhooks","isPartOf":{"@id":"https://inquir.org/use-cases/stripe-webhooks#webpage"},"mainEntity":[{"@type":"Question","name":"Which Stripe events should I handle?","acceptedAnswer":{"@type":"Answer","text":"payment_intent.succeeded for purchase fulfillment; invoice.payment_failed for subscription dunning; customer.subscription.deleted for access revocation."}},{"@type":"Question","name":"How do I test without real Stripe traffic?","acceptedAnswer":{"@type":"Answer","text":"Use stripe listen --forward-to <local URL> for local testing, or stripe trigger payment_intent.succeeded to send a test event to your deployed function."}}]}]}