How to set up webhooks with Jira on Tenklo
Learn how to receive real-time Jira events in your app using Tenklo webhooks
Jira Cloud offers two separate ways to get webhooks to your Tenklo webhook URL: your OAuth app can register a scoped dynamic webhook via the REST API, or a Jira admin can register an admin webhook — either through Jira's admin console UI or its own REST endpoint — which also supports a shared secret for signature verification. This guide covers both.
How it works
- When a connection is created, Tenklo automatically fetches the connected site's URL from Jira's accessible-resources API and stores it as
baseUrlon the connection — no setup needed on your end for routing. - Jira sends a POST request to your Tenklo webhook URL when a subscribed event occurs.
- Tenklo matches the payload's site URL to the correct connection's
baseUrland forwards the event to your app.
Jira signs dynamic webhook requests (/rest/api/3/webhook) with a bearer JWT in the Authorization header, using your app's client secret — Tenklo doesn't verify this today, so treat your Tenklo webhook URL as sensitive if you rely on that path. Admin webhooks (registered via /rest/webhooks/1.0/webhook or the admin console) are different: you set a shared secret when creating them, and Jira signs requests with HMAC-SHA256 in an X-Hub-Signature header. Tenklo verifies that signature when you set the same value as the Webhook secret on the integration in the Tenklo dashboard.
Setup
1. Get your Tenklo webhook URL
In the Tenklo dashboard, open your Jira integration and copy the Webhook URL.
2. Register the webhook in Jira
Scoped to your app. Covers issue, comment, issue property, sprint, and version events only, and expires after 30 days.
- Add both classic scopes
read:jira-workandmanage:jira-webhookin the Atlassian Developer Console's Permissions step, then add them to your Jira integration's Scopes field in the Tenklo dashboard.manage:jira-webhooklets your app call the webhook REST API;read:jira-workcovers the issue, comment, and worklog data behind the events below. See Jira's webhooks reference for the scopes needed by other event categories.
You need both scopes — manage:jira-webhook alone lets you call the endpoint but not read the data behind the events, and registration fails with 401 Unauthorized; scope does not match. You can check which scopes a connection's token actually has by decoding it and inspecting the scope claim.
Scopes are granted at authorization time. Adding a scope to the integration doesn't add it to connections that already exist — re-authorize the connection (or create a new one) after changing scopes.
- Register the webhook through Tenklo's proxy. This example subscribes to issue events:
curl -X POST "https://api.tenklo.dev/proxy/ex/jira/{connectionConfig.cloudId}/rest/api/3/webhook" \
-H "Authorization: Bearer <NANGO-API-KEY>" \
-H "Provider-Config-Key: <INTEGRATION-ID>" \
-H "Connection-Id: <CONNECTION-ID>" \
-H "Content-Type: application/json" \
-d '{
"url": "<NANGO-WEBHOOK-URL>",
"webhooks": [
{
"events": ["jira:issue_created", "jira:issue_updated", "jira:issue_deleted"],
"jqlFilter": "project = PROJ"
}
]
}'If the connection's token doesn't have the required scope for an event, Jira rejects the registration for that event. The response returns a createdWebhookId for each registered webhook — save these IDs, you'll need them to refresh or delete the webhook.
- Refresh the webhook before it expires (30 days after creation, or after your last refresh) using Jira's webhook refresh endpoint with the saved IDs — see Jira's webhooks reference for the exact call. Run this on a schedule, for example from an action function, or Jira will silently stop sending events.
Handle the webhook
Once routed to a connection, you have two options:
- Forward it to your app — Tenklo forwards the event to your webhook URL with connection attribution. See External webhook forwarding.
- Process it in a sync — run a sync when the webhook arrives using
webhookSubscriptionsandonWebhookin a sync script. See Real-time syncs.
Supported events
Tenklo can only route events whose payload includes a self link on issue, comment, sprint, board, worklog, version, issueLink, project, attachment, issuetype, filter, or user. Examples:
| Event | Description | Setup path |
|---|---|---|
jira:issue_created | An issue was created | REST API, Admin console |
jira:issue_updated | An issue was updated | REST API, Admin console |
jira:issue_deleted | An issue was deleted | REST API, Admin console |
comment_created | A comment was added to an issue | REST API, Admin console |
sprint_started | A sprint was started | REST API, Admin console |
jira:version_released | A version was released | REST API, Admin console |
project_created | A project was created | Admin console only |
board_updated | A board's configuration was changed | Admin console only |
worklog_created | A worklog entry was added to an issue | Admin console only |
attachment_created | An attachment was added to an issue | Admin console only |
For the full list, see Jira's webhook events reference.