Stripe Webhook Payload Example: JSON, Headers, and Signature
A complete Stripe webhook payload example with Event JSON, Stripe-Signature header, and a cURL you can send to a live inspector.
Search results for “stripe webhook payload example” usually show a truncated Event object. This page is a full request: JSON body, headers, and how Stripe signs it. Paste the inspector URL into the Stripe Dashboard → Webhooks “Send test webhook” action, or replay the cURL below.
Ingestion host:
https://hooks.openwebhook.co/YOUR_UUID/stripe
Open the free inspector to get a UUID, or use a Pro slug such as billing.
HTTP request
POST /stripe HTTP/1.1
Host: hooks.openwebhook.co
Content-Type: application/json
Stripe-Signature: t=1716400000,v1=8f3c0a1b9e2d4c6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f
User-Agent: Stripe/1.0 (+https://stripe.com/docs/webhooks)
Stripe-Signature is t=<unix_seconds>,v1=<hex_hmac_sha256>. The signed payload is t + . + the raw body bytes. Verify with the endpoint’s signing secret (whsec_...), not the secret key. Do not JSON.parse and re-stringify before verifying.
Event object (checkout.session.completed)
{
"id": "evt_1Pexample000000000000000",
"object": "event",
"api_version": "2024-06-20",
"created": 1716400000,
"data": {
"object": {
"id": "cs_test_a1b2c3",
"object": "checkout.session",
"amount_total": 4900,
"currency": "eur",
"customer": "cus_example",
"customer_email": "buyer@example.com",
"mode": "payment",
"payment_status": "paid",
"status": "complete",
"success_url": "https://example.com/ok",
"metadata": {
"order_id": "ord_1042"
}
}
},
"livemode": false,
"pending_webhooks": 1,
"request": {
"id": "req_example",
"idempotency_key": null
},
"type": "checkout.session.completed"
}
Other types you will see often: invoice.paid, customer.subscription.updated, payment_intent.payment_failed, charge.refunded. The envelope is always id, type, data.object. Store id for idempotency.
Send it to the inspector
curl -X POST \
'https://hooks.openwebhook.co/YOUR_UUID/stripe' \
-H 'content-type: application/json' \
-H 'stripe-signature: t=1716400000,v1=test' \
--data-binary @- <<'EOF'
{"id":"evt_1Pexample000000000000000","object":"event","api_version":"2024-06-20","created":1716400000,"type":"checkout.session.completed","data":{"object":{"id":"cs_test_a1b2c3","object":"checkout.session","amount_total":4900,"currency":"eur","payment_status":"paid","status":"complete"}},"livemode":false}
EOF
Keep the tab open. You should see POST /stripe, the signature header, and the JSON. Copy cURL from the inspector to replay against your handler.
For retries, point a custom endpoint at Stripe and return 500 once, then 200.