Netlify · event: Deploy succeeded (state: ready) ·
content type: application/json
This is a representative sample — fake IDs, real structure. To see a payload with your data, point the provider at a capture URL (button below).
One click creates a free capture bin with this exact payload already in it — pretty-printed, headers inspectable, replayable to your own endpoint:
Then paste the bin's URL into Netlify's webhook settings to capture a real delivery. No signup.
content-type: application/json x-webhook-signature: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJuZXRsaWZ5Iiwic2hhMjU2IjoiNGZjOGE4MzlmODdjZDUxNWM2OWNmN2ZiOTU1N2Y4YjEzOGMzMmIyOTA0MzVjM2YzOGYwMDAxOTIxNTJmOTNmZCJ9.XY67AYiGKRQYZuOzewvjNSCmYqUZytg5Kh8UbUItIXI
{
"id": "68b2f4a91c9e8d0008a73c52",
"site_id": "f2b8c1d4-9e37-4a60-b5c8-2d1f7e94a3b6",
"build_id": "68b2f49e1c9e8d0008a73c4d",
"state": "ready",
"name": "acme-marketing",
"url": "http://acme-marketing.netlify.app",
"ssl_url": "https://acme-marketing.netlify.app",
"admin_url": "https://app.netlify.com/projects/acme-marketing",
"deploy_url": "http://main--acme-marketing.netlify.app",
"deploy_ssl_url": "https://main--acme-marketing.netlify.app",
"commit_ref": "59b20b8d5c6ff8d09518454d4dd8b7b30f095ab5",
"commit_url": "https://github.com/acme/marketing/commit/59b20b8d5c6f",
"branch": "main",
"context": "production",
"error_message": null,
"review_id": null,
"committer": "ada",
"title": "fix: handle empty webhook payloads",
"deploy_time": 42,
"created_at": "2026-08-30T10:04:57.000Z",
"updated_at": "2026-08-30T10:05:41.000Z",
"published_at": "2026-08-30T10:05:40.000Z"
}
X-Webhook-Signature carries an HS256
JWS whose claims are
{ "iss": "netlify", "sha256": "<hex SHA-256 of the raw body>" }.
Generic HMAC testers (including this site's signature
debugger) structurally can't verify it — use any JWT library instead: verify with the
secret, pin algorithms: ["HS256"] and
issuer: "netlify" (the classic alg-confusion guard), then compare
the sha256 claim to your own hex SHA-256 of the raw body.netlify_jws_sample_secret_Rk4tYw9Qz2 — decode it and the
sha256 claim equals the SHA-256 of the body shown here, byte for byte.state: "ready" is what "Deploy succeeded" looks like;
failed deploys arrive with state: "error" and an
error_message. Fields here are representative and trimmed — real payloads
carry many more.Reproduce this delivery against any endpoint (your handler, a bin, staging):
$ curl -X POST https://your-endpoint.example/hook \
-H 'content-type: application/json' \
-H 'x-webhook-signature: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJuZXRsaWZ5Iiwic2hhMjU2IjoiNGZjOGE4MzlmODdjZDUxNWM2OWNmN2ZiOTU1N2Y4YjEzOGMzMmIyOTA0MzVjM2YzOGYwMDAxOTIxNTJmOTNmZCJ9.XY67AYiGKRQYZuOzewvjNSCmYqUZytg5Kh8UbUItIXI' \
-d '{
"id": "68b2f4a91c9e8d0008a73c52",
"site_id": "f2b8c1d4-9e37-4a60-b5c8-2d1f7e94a3b6",
"build_id": "68b2f49e1c9e8d0008a73c4d",
"state": "ready",
"name": "acme-marketing",
"url": "http://acme-marketing.netlify.app",
"ssl_url": "https://acme-marketing.netlify.app",
"admin_url": "https://app.netlify.com/projects/acme-marketing",
"deploy_url": "http://main--acme-marketing.netlify.app",
"deploy_ssl_url": "https://main--acme-marketing.netlify.app",
"commit_ref": "59b20b8d5c6ff8d09518454d4dd8b7b30f095ab5",
"commit_url": "https://github.com/acme/marketing/commit/59b20b8d5c6f",
"branch": "main",
"context": "production",
"error_message": null,
"review_id": null,
"committer": "ada",
"title": "fix: handle empty webhook payloads",
"deploy_time": 42,
"created_at": "2026-08-30T10:04:57.000Z",
"updated_at": "2026-08-30T10:05:41.000Z",
"published_at": "2026-08-30T10:05:40.000Z"
}'