Bitbucket webhook not working?

Bitbucket Cloud webhooks have one trap that catches almost everyone: the delivery log is off by default. Until you switch it on, Bitbucket records nothing — so when a webhook misbehaves, you're debugging blind and it feels like events simply vanish. Start there, then work down this list.

1. Enable the request log (it records nothing until you do)

Open Repository settings → Webhooks → View requests and select Enable history. From that point on Bitbucket logs every delivery; use Load new requests to refresh the list. Each row shows the triggering event, the request time, and the outcome:

View details on a row shows the exact request headers and body Bitbucket sent and the response your server gave back. Two quirks worth knowing: a client timeout appears as response status -1 in the details view, and if your server never managed to respond, the Response tabs simply don't appear.

Because history is opt-in, anything that failed before you enabled it is gone. If you want a delivery record that's always on, point the webhook at a capture bin (button below, or curl https://hookden.pages.dev/new) — every request is stored with full headers and raw body, and you can replay any of them at your real endpoint once it's fixed.

2. Webhook fires but fails: timeout and retry behavior

Bitbucket gives your endpoint 10 seconds to respond. Slower than that and the delivery is logged as TIMEOUT — so acknowledge with a quick 200 first and do expensive work after responding, not inline.

If your endpoint answers with a 5xx status, Bitbucket automatically resends the request up to two more times. The X-Attempt-Number header on each request (and the Request attempts count in the log details) tells you which attempt you're looking at — and it means your handler must tolerate duplicates, because attempt 2 can arrive after attempt 1 actually succeeded but responded too slowly.

3. Webhook never fires at all

To split "Bitbucket never sent it" from "my server never received it": point the webhook at a capture bin for a minute and trigger the event. If the delivery shows up in the bin, Bitbucket's side is fine and the problem is your endpoint, DNS, TLS, or firewall. If nothing arrives, the problem is the webhook config or a silent payload-size failure.

4. Verifying X-Hub-Signature (it's sha256 here, not GitHub's sha1)

When you set a Secret on a Bitbucket Cloud webhook, each delivery carries an X-Hub-Signature header in WebSub's method=signature form — currently sha256=<hex>, an HMAC-SHA256 of the raw request body using your secret. Three classic failure modes:

Capture one delivery in a bin, paste the secret into the bin's signature settings (scheme: generic HMAC over raw body), and the ✓/✗ badge tells you whether the header matches the raw bytes — which side of the handshake is lying.

5. Self-signed certificates

Deliveries to an HTTPS endpoint with a self-signed certificate fail TLS verification. Bitbucket offers a Skip certificate verification option per webhook; it works, but it removes the guarantee that payloads reach your server, so treat it as a last resort and prefer a real certificate.

6. Developing locally? Bitbucket Cloud can't reach localhost

http://localhost:3000/hook isn't reachable from Bitbucket's cloud. Instead of running a tunnel, use a capture URL as the webhook target and relay deliveries to your machine:

$ curl -s https://hookden.pages.dev/cli -o hookden && chmod +x hookden
$ curl https://hookden.pages.dev/new
$ ./hookden relay YOUR_BIN http://localhost:3000

Bodies are re-delivered byte-identical, so the X-Hub-Signature HMAC still verifies against the raw bytes Bitbucket signed. Details: webhooks to localhost without a tunnel.

7. Quick reference: Bitbucket Cloud webhook limits

Same problem on a different host? See GitHub webhook not working and GitLab webhook not working.

No signup needed. Or from your terminal: curl https://hookden.pages.dev/new

← All guides · Docs · Hookden vs webhook.site