Stripe Webhook Specs, Events, and Examples

Stripe uses webhooks to notify third-party apps of events such as payments processed, refund requested, product (skus) created, and charges expired. Stripe events can be used to trigger action in other systems such as changing user access in your systems after a payment is processed.

Specifications

Supported Events

Security Headers

  • Signature Header: Stripe-Signature
  • Hash: sha256
  • Encode: hex
  • Signature Header Format: t=timestamp,v0=none,v1=hash

    Note: Stripe does not use contents from v0

  • payload: timestamp.request_body
  • Timestamp Format: Unix Date

Documentation

SDKs and Sample Code

Stripe provide SDKs with an interactive webhook builder for the following programming languages:

Sample Validation

const crypto = require('crypto')
const sigHeader = 'Stripe-Signature'
const hashAlgo = 'sha256'
const encode = 'hex'
const hmacSecret = process.env.WEBHOOK_SECRET
app.post('/stripe-webhook', (req, res) => {
    //01: Get timestamp and signature
    const stripeHeaders = request.headers[sigHeader].split(',');
    const timestamp = stripeHeaders.find(e => e.startsWith('t=')).substring(1);
    const signature = stripeHeaders.find(e => e.startsWith('v1='));


    //02: Validate replay prevention with 5 minute timeframe
    const requestTimestamp = timestamp * 1000;
    const tolerance = Date.now() - (5 * 60 * 1000);
    if (requestTimestamp < tolerance) {
        res.status(403).send('Request expired')
    }else{
        //03: Validate signature
        const message = `${timestamp}.${req.body}`
        const digest = "v1="+crypto.createHmac(hashAlgo, hmacSecret).update(message).digest(encode)
        if (signature !== digest) {
            res.status(401).send('Request unauthorized')
        }else{
            //04: Process message
            res.json({ message: "Success" })
        }
    }
})