The loop
Create an endpoint and it prints a permanent ingest URL. Everything sent there is captured whole — headers, body, the exact bytes — before anything else happens. Stream those events to a port on your machine, and replay any one of them as often as you like while you fix the handler. Forwarding runs from your own machine, so it isn't a billable delivery.
What's different about Jira
You can usually point a webhook wherever you like and sort out reachability afterwards. Jira Cloud decides up front whether it will talk to you at all: the URL has to be HTTPS with a certificate signed by a globally trusted authority, and the destination port must sit on Atlassian's allowlist — 443, 8443, 8080, 1880-1890 and a short list of others, with port 80 refused outright. There's also no test-send control anywhere in the admin UI, so an unreachable endpoint stays quiet until someone does real work in a project. Get the URL accepted first, then go hunting for events.
Where the URL goes
You need the Administer Jira global permission to touch webhooks at all. From there it's Settings, then System, then WebHooks under the Advanced heading. Create a new webhook, paste your ingest URL, and tick the events you want. Leave Exclude body alone — checking it strips the JSON payload. The optional Secret field is write-once: Jira won't show it to you again after save.
Nothing in Jira replays or synthesises a delivery. Atlassian's own testing guide has you perform the real action and then go look at your endpoint, which is the whole method. So pick a scratch project, subscribe to jira:issue_created and jira:issue_updated, create an issue and edit its summary — two deliveries, both genuine. Comment and worklog events need their own actions: leave a comment, log some time.
What Jira sends
Identifiers are snake_case resource_action pairs, but the namespacing is inconsistent enough to catch you out. Issue and version events carry a jira: prefix; comment, worklog, sprint and project events don't. Don't extrapolate the rule: jira_expression_evaluation_failed uses an underscore rather than the colon, and worklog events lost their prefix in a deprecation rather than by rule. The prefixed jira:worklog_updated is on its way out; worklog_updated replaces it. The same string reappears in the payload's webhookEvent field.
- jira:issue_created
- jira:issue_updated
- jira:issue_deleted
- comment_created
- comment_updated
- worklog_created
Worth knowing first
Retries are slow and selective
Only 408, 409, 425, 429, any 5xx, and connection failures or timeouts earn a retry. A 400 or 404 counts as a failed trigger but is never resent. Jira Cloud retries up to five times, each attempt landing five to fifteen minutes after the last, and after roughly half an hour of continuous failure it degrades to a single attempt per webhook. Retried requests carry X-Atlassian-Webhook-Retry.
The secret is write-once
Fill in the Secret field and Jira Cloud signs the raw request body with HMAC, sending X-Hub-Signature formatted as method=signature. Read the algorithm out of the method prefix rather than assuming sha256. Once saved, the secret can't be viewed or retrieved, so keep your own copy. Webhooks registered dynamically by OAuth 2.0 apps use bearer authentication instead.
Duplicates and out-of-order arrivals
Delivery is at-least-once, so dedupe on X-Atlassian-Webhook-Identifier, which is unique within a Jira Cloud tenant and stable across retries of the same event. Ordering is never promised: Jira opens many concurrent connections per tenant and URL host, more for primary-flow webhooks than for secondary bulk ones, and X-Atlassian-Webhook-Flow tells you which class you received. Payloads over 25 MB are dropped rather than retried, and Atlassian reserves the right to move that number without notice.
Cloud rules aren't Data Center rules
All of the above comes from Atlassian's Jira Cloud webhooks documentation. The Server and Data Center page shares only the part about a 200 meaning success: it documents no retry schedule, no payload ceiling, no delivery-time expectation and no HTTPS requirement. If you're building against self-hosted Jira, assume none of the Cloud behaviour carries over.
Signature checking is handled for you once the secret is registered — you can also check a captured signature by hand in the signature verifier.