---
title: "Test Jira Webhooks Locally | WebhookRelay"
meta:
  "og:description": "Test Jira webhooks locally and receive them on localhost without deploying. Inspect the real payload, forward to your handler, and verify the signature."
  "og:title": "Test Jira Webhooks Locally"
  description: "Test Jira webhooks locally and receive them on localhost without deploying. Inspect the real payload, forward to your handler, and verify the signature."
---

![Stripes](https://webhookrelay.com/images/stripes.svg)

# **Test Jira Webhooks Locally**

Test Jira webhooks locally and receive them on localhost without deploying. Inspect the real payload, forward to your handler, and verify the signature.

![Test Jira Webhooks Locally (Receive Jira Webhooks on localhost)](https://webhookrelay.com/images/blog/heroes/localhost.jpg)

You are building a Jira integration and you need to watch your handler react to a real event. The problem hits immediately: Jira will only POST to a **public URL**, and your handler is running on `localhost:8080`. Jira has no way to reach it.

The usual workarounds are slow. Deploying to a staging environment for every code change kills your iteration speed. Copying a sample payload out of the docs into curl gives you a _guess_ at the real request, not the exact headers and body Jira actually sends. What you really want is to **test Jira webhooks locally** — real events, hitting your local handler, on a URL that does not change every time you restart.

This guide shows how to do exactly that.

## [Why testing Jira webhooks locally is tricky](#why-testing-jira-webhooks-locally-is-tricky)

A webhook is just an HTTP request that Jira sends to a URL when something changes. Jira lives on the public internet; your dev machine usually does not. It sits behind a router, a corporate firewall, or both, with no public IP and no inbound ports open.

So you need something in the middle: a public endpoint Jira can hit that relays each request down to your laptop without you opening a single firewall port. That is what [Webhook Relay](https://my.webhookrelay.com/register) does — and unlike a random tunnel URL, the endpoint is **stable**, so you configure Jira once and never touch it again.

## [Step 1: Inspect the real payload with Webhook Bin](#step-1-inspect-the-real-payload-with-webhook-bin)

Before you write any handler code, find out what Jira actually sends. Open the free [Webhook Bin](https://webhookrelay.com/webhook-bin/) — no signup — and you get an instant public URL.

1. Copy the Webhook Bin URL.
2. In Jira, go to **Settings → System → Webhooks → Create a WebHook**, paste the URL, and pick the events and a JQL filter. For signed deliveries, register a **dynamic** webhook via the REST API with a `secret`.
3. Trigger a real event and inspect the captured request.

You will see the full body and every header. The body is JSON with a `webhookEvent` field plus the changed `issue`, `comment` or `user` objects and a `changelog` for updates. You can also narrow deliveries with a JQL filter when you create the webhook.

Now you know the exact shape of the data before writing a line of code. For more on this approach, see [How to test webhooks](https://webhookrelay.com/blog/how-to-test-webhooks/) and [What is a webhook](https://webhookrelay.com/blog/what-is-webhook/).

## [Step 2: Forward the events to localhost with the relay agent](#step-2-forward-the-events-to-localhost-with-the-relay-agent)

Once you know the payload, route those same events into your local handler. [Sign up for Webhook Relay](https://my.webhookrelay.com/register), install the `relay` agent (CLI or Docker), and create a bucket — say `jira`. The bucket gives you a stable public input endpoint.

Start forwarding to your local server:

```
relay forward --bucket jira http://localhost:8080/webhook
```

The agent opens an **outbound** connection to Webhook Relay and streams every incoming request down to `http://localhost:8080/webhook`. Because the connection is outbound, there are **no firewall ports to open and no public IP needed** — this works from your laptop, behind a corporate proxy, or inside a Kubernetes cluster. Running in Docker? The same command works in the official `webhookrelay/webhookrelayd` image. Full details are in the [localhost forwarding docs](https://webhookrelay.com/docs/webhooks/internal/localhost/).

Now point the Jira webhook at your Webhook Relay endpoint (or create it there from the start), trigger an event, and watch it arrive on `localhost`.

## [Jira-specific configuration and quirks](#jira-specific-configuration-and-quirks)

A few Jira details worth knowing:

- **Two ways to register:** **Settings → System → Webhooks** in the admin UI, or the REST API for **dynamic** webhooks (which support a signing `secret`).
- **JQL filter:** scope deliveries to specific projects or issue types with a JQL filter so you don't get the whole instance's traffic.
- **Payload shape:** JSON with `webhookEvent`, the changed entity, and a `changelog` on updates.
- **Signing varies:** dynamic webhooks sign with `X-Hub-Signature`; classic ones don't — see the verification step.

## [Step 3: Verify the Jira webhook signature](#step-3-verify-the-jira-webhook-signature)

How you verify depends on how the webhook was created. If you register a **dynamic webhook** through Jira's REST API with a `secret`, Jira signs the raw body with **HMAC-SHA256** and sends it as `sha256=...` in the **`X-Hub-Signature`** header — recompute and compare in constant time. Classic webhooks created in the admin UI are **not** signed; for those, put a hard-to-guess secret in the webhook URL and check it, and/or restrict inbound traffic to Atlassian's IP ranges.

To sanity-check an HMAC implementation, paste a captured body, your secret, and the received signature into the free [HMAC signature verifier](https://webhookrelay.com/hmac-verification/). For language-specific code and the common pitfalls (reading the body _after_ a JSON parser has already consumed it, timing-safe comparison), read [Verify a webhook signature](https://webhookrelay.com/blog/verify-webhook-signature/).

## [Replay and iterate](#replay-and-iterate)

This is where local development gets fast:

- **Replay from Webhook Relay** — past requests are stored on your bucket, so you can resend a captured event against your handler without touching Jira at all.
- **Iterate on your handler** by editing code and replaying the same delivery until it behaves correctly. No commits, no pushes, no deploys just to test a single code path.
- **Keep `relay forward` running** while you work — events stream straight to `localhost` as you trigger them in Jira.

Because the Webhook Relay endpoint is stable, you can stop and restart the agent, reboot your machine, or come back next week — the Jira configuration never needs to change.

## [Get started](#get-started)

1. Inspect the real payload in the free [Webhook Bin](https://webhookrelay.com/webhook-bin/) — no signup needed.
2. [Create a Webhook Relay account](https://my.webhookrelay.com/register), install the agent, and run `relay forward --bucket jira http://localhost:8080/webhook`.
3. Point your Jira webhook at the stable endpoint, trigger an event, and watch it hit `localhost`.

You will be testing real Jira events against your local handler in a few minutes — no deploys, no open firewall ports, and a URL you configure exactly once.

## **Frequently asked questions**

### **How do I test Jira webhooks locally?**

Jira can only POST to a public URL, so you bridge the public internet to your machine. Create a Webhook Relay bucket, paste its endpoint as the webhook URL in Jira Settings → System → Webhooks (or the REST API for dynamic webhooks), then run the relay agent: 'relay forward --bucket jira http://localhost:8080/webhook'. The agent connects outbound, so there are no firewall ports to open and no public IP required.

### **Can I test a Jira webhook on localhost without deploying?**

Yes. Inspect the payload first in a free Webhook Bin to see exactly what Jira sends, then forward the same events to your local server with the relay agent. You develop and debug your handler entirely on localhost while Jira sends live events.

### **How does Jira sign its webhooks?**

It depends. Dynamic webhooks registered via Jira's REST API with a secret are signed with HMAC-SHA256 in the X-Hub-Signature header (sha256=...). Classic admin-UI webhooks are not signed — secure them with a secret in the URL or by allowlisting Atlassian's IP ranges.