-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Webhook and header types #294
Comments
Hello @NatoBoram! Could you please define which exact endpoints should to have these headers? |
If you go to https://webhook.site then create a WebHook in Jira at For example, I made a test board with a test issue and I received these headers: connection: close
accept-encoding: gzip,deflate
user-agent: Atlassian Webhook HTTP Client
host: webhook.site
content-type: application/json; charset=UTF-8
content-length: 7157
x-b3-sampled: 0
x-b3-spanid: 6349452bd099e495
x-b3-traceid: a4ecf355b72258e87c3b2215d1628c5c
accept: */*
x-atlassian-webhook-flow: Primary
x-atlassian-webhook-identifier: 69312270414585119 I also got this request body: {
"timestamp": 1704303069063,
"webhookEvent": "jira:issue_created",
"issue_event_type_name": "issue_created",
"user": {
"self": "https://natoboram.atlassian.net/rest/api/2/user?accountId=5c19e3e3f9cb4734ae1b918e",
"accountId": "5c19e3e3f9cb4734ae1b918e",
"avatarUrls": {
"48x48": "https://secure.gravatar.com/avatar/bdc89ce7df863d04f08e3b1c980938d3?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FNB-1.png",
"24x24": "https://secure.gravatar.com/avatar/bdc89ce7df863d04f08e3b1c980938d3?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FNB-1.png",
"16x16": "https://secure.gravatar.com/avatar/bdc89ce7df863d04f08e3b1c980938d3?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FNB-1.png",
"32x32": "https://secure.gravatar.com/avatar/bdc89ce7df863d04f08e3b1c980938d3?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FNB-1.png"
},
"displayName": "Nato Boram",
"active": true,
"timeZone": "America/Toronto",
"accountType": "atlassian"
},
"issue": {
"id": "10000",
"self": "https://natoboram.atlassian.net/rest/api/2/10000",
"key": "TEST-1",
"fields": {
"statuscategorychangedate": "2024-01-03T12:31:09.209-0500",
"issuetype": {
"self": "https://natoboram.atlassian.net/rest/api/2/issuetype/10001",
"id": "10001",
"description": "Tasks track small, distinct pieces of work.",
"iconUrl": "https://natoboram.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10318?size=medium",
"name": "Task",
"subtask": false,
"avatarId": 10318,
"entityId": "9baea660-ceab-4eaa-8046-9f53e3558981",
"hierarchyLevel": 0
},
"timespent": null,
"customfield_10030": null,
"customfield_10031": null,
"project": {
"self": "https://natoboram.atlassian.net/rest/api/2/project/10000",
"id": "10000",
"key": "TEST",
"name": "Test Project",
"projectTypeKey": "software",
"simplified": true,
"avatarUrls": {
"48x48": "https://natoboram.atlassian.net/rest/api/2/universal_avatar/view/type/project/avatar/10423",
"24x24": "https://natoboram.atlassian.net/rest/api/2/universal_avatar/view/type/project/avatar/10423?size=small",
"16x16": "https://natoboram.atlassian.net/rest/api/2/universal_avatar/view/type/project/avatar/10423?size=xsmall",
"32x32": "https://natoboram.atlassian.net/rest/api/2/universal_avatar/view/type/project/avatar/10423?size=medium"
}
},
"customfield_10032": null,
"fixVersions": [],
"aggregatetimespent": null,
"resolution": null,
"customfield_10027": null,
"customfield_10028": null,
"customfield_10029": null,
"resolutiondate": null,
"workratio": -1,
"lastViewed": null,
"watches": {
"self": "https://natoboram.atlassian.net/rest/api/2/issue/TEST-1/watchers",
"watchCount": 0,
"isWatching": true
},
"issuerestriction": { "issuerestrictions": {}, "shouldDisplay": true },
"created": "2024-01-03T12:31:08.939-0500",
"customfield_10020": null,
"customfield_10021": null,
"customfield_10022": null,
"customfield_10023": null,
"priority": {
"self": "https://natoboram.atlassian.net/rest/api/2/priority/3",
"iconUrl": "https://natoboram.atlassian.net/images/icons/priorities/medium.svg",
"name": "Medium",
"id": "3"
},
"customfield_10024": null,
"customfield_10025": null,
"customfield_10026": null,
"labels": [],
"customfield_10016": null,
"customfield_10017": null,
"customfield_10018": {
"hasEpicLinkFieldDependency": false,
"showField": false,
"nonEditableReason": {
"reason": "PLUGIN_LICENSE_ERROR",
"message": "The Parent Link is only available to Jira Premium users."
}
},
"customfield_10019": "0|hzzzzz:",
"aggregatetimeoriginalestimate": null,
"timeestimate": null,
"versions": [],
"issuelinks": [],
"assignee": null,
"updated": "2024-01-03T12:31:08.939-0500",
"status": {
"self": "https://natoboram.atlassian.net/rest/api/2/status/10000",
"description": "",
"iconUrl": "https://natoboram.atlassian.net/",
"name": "To Do",
"id": "10000",
"statusCategory": {
"self": "https://natoboram.atlassian.net/rest/api/2/statuscategory/2",
"id": 2,
"key": "new",
"colorName": "blue-gray",
"name": "New"
}
},
"components": [],
"timeoriginalestimate": null,
"description": null,
"customfield_10010": null,
"customfield_10014": null,
"timetracking": {},
"customfield_10015": null,
"customfield_10005": null,
"customfield_10006": null,
"security": null,
"customfield_10007": null,
"customfield_10008": null,
"aggregatetimeestimate": null,
"attachment": [],
"customfield_10009": null,
"summary": "This is a new issue, created in Jira.",
"creator": {
"self": "https://natoboram.atlassian.net/rest/api/2/user?accountId=5c19e3e3f9cb4734ae1b918e",
"accountId": "5c19e3e3f9cb4734ae1b918e",
"avatarUrls": {
"48x48": "https://secure.gravatar.com/avatar/bdc89ce7df863d04f08e3b1c980938d3?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FNB-1.png",
"24x24": "https://secure.gravatar.com/avatar/bdc89ce7df863d04f08e3b1c980938d3?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FNB-1.png",
"16x16": "https://secure.gravatar.com/avatar/bdc89ce7df863d04f08e3b1c980938d3?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FNB-1.png",
"32x32": "https://secure.gravatar.com/avatar/bdc89ce7df863d04f08e3b1c980938d3?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FNB-1.png"
},
"displayName": "Nato Boram",
"active": true,
"timeZone": "America/Toronto",
"accountType": "atlassian"
},
"subtasks": [],
"reporter": {
"self": "https://natoboram.atlassian.net/rest/api/2/user?accountId=5c19e3e3f9cb4734ae1b918e",
"accountId": "5c19e3e3f9cb4734ae1b918e",
"avatarUrls": {
"48x48": "https://secure.gravatar.com/avatar/bdc89ce7df863d04f08e3b1c980938d3?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FNB-1.png",
"24x24": "https://secure.gravatar.com/avatar/bdc89ce7df863d04f08e3b1c980938d3?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FNB-1.png",
"16x16": "https://secure.gravatar.com/avatar/bdc89ce7df863d04f08e3b1c980938d3?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FNB-1.png",
"32x32": "https://secure.gravatar.com/avatar/bdc89ce7df863d04f08e3b1c980938d3?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FNB-1.png"
},
"displayName": "Nato Boram",
"active": true,
"timeZone": "America/Toronto",
"accountType": "atlassian"
},
"aggregateprogress": { "progress": 0, "total": 0 },
"customfield_10001": null,
"customfield_10002": null,
"customfield_10003": null,
"customfield_10004": null,
"environment": null,
"duedate": null,
"progress": { "progress": 0, "total": 0 },
"votes": {
"self": "https://natoboram.atlassian.net/rest/api/2/issue/TEST-1/votes",
"votes": 0,
"hasVoted": false
}
}
},
"changelog": {
"id": "10000",
"items": [
{
"field": "priority",
"fieldtype": "jira",
"fieldId": "priority",
"from": null,
"fromString": null,
"to": "3",
"toString": "Medium"
},
{
"field": "reporter",
"fieldtype": "jira",
"fieldId": "reporter",
"from": null,
"fromString": null,
"to": "5c19e3e3f9cb4734ae1b918e",
"toString": "Nato Boram",
"tmpFromAccountId": null,
"tmpToAccountId": "5c19e3e3f9cb4734ae1b918e"
},
{
"field": "Status",
"fieldtype": "jira",
"fieldId": "status",
"from": null,
"fromString": null,
"to": "10000",
"toString": "To Do"
},
{
"field": "summary",
"fieldtype": "jira",
"fieldId": "summary",
"from": null,
"fromString": null,
"to": null,
"toString": "This is a new issue, created in Jira."
}
]
}
} |
It's not actually for an endpoint on Jira's side, it's for requests that the Jira server itself sends when you add webhooks at https://natoboram.atlassian.net/plugins/servlet/webhooks. Example: When you receive these events, it looks like this: For example, I'm making a program that interacts with the API to add comments to issues. This can be done with Jira.js. However, this program needs to know when an issue is created, so I'm registering a webhook on Jira's side so Jira can tell me when there's a new issue. This would require additional types that I haven't seen in Jira.js. |
Oh okay I catch it. You wanna extract headers from response |
Yep, both headers and body for WebHook types |
How you imagine library can handle this webhook response? |
I don't think this library should "handle" them, but rather, expose the types for these. Something like this: // Example enum for webhook events
const webhookEvents = {
issue_created: "jira:issue_created",
issue_updated: "jira:issue_updated",
} as const
type WebhookEvent = (typeof webhookEvents)[keyof typeof webhookEvents]
const issueEventTypeNames = {
issue_created: "issue_created",
issue_updated: "issue_updated",
} as const
type IssueEventTypeName =
(typeof issueEventTypeNames)[keyof typeof issueEventTypeNames]
// Example interfaces for webhook bodies
interface JiraWebHookBase {
readonly webhookEvent: WebhookEvent
readonly issue_event_type_name: IssueEventTypeName
}
interface JiraWebHookIssueCreated extends JiraWebHookBase {
readonly webhookEvent: typeof webhookEvents.issue_created
readonly issue_event_type_name: typeof issueEventTypeNames.issue_created
}
interface JiraWebHookIssueUpdated extends JiraWebHookBase {
readonly webhookEvent: typeof webhookEvents.issue_updated
readonly issue_event_type_name: typeof issueEventTypeNames.issue_updated
}
type JiraWebHook = JiraWebHookIssueCreated | JiraWebHookIssueUpdated
// Example headers for webhooks
interface JiraHeaders {
readonly "x-atlassian-webhook-flow": "Primary"
} Someone using this library would just have to import and use these types with whatever router they are using. const router = express()
router.post("/jira", (req: Request<undefined, undefined, JiraWebHook>, res) => {
switch (req.body.webhookEvent) {
case webhookEvents.issue_created:
// `req.body` is now narrowed to `JiraWebHookIssueCreated`
console.log("req.body", req.body)
return res.sendStatus(200)
case webhookEvents.issue_updated:
// `req.body` is now narrowed to `JiraWebHookIssueUpdated`
console.log("req.body", req.body)
return res.sendStatus(200)
default:
// `req.body` is now narrowed to `never`
console.log("req.body", req.body)
return res.sendStatus(400)
}
}) |
Hi @MrRefactoring and @NatoBoram There haven't been any comments on this since January, but the issue is still open. Is it still a feature request, or something you are actually working on? :-) |
+1 |
I realize this might be out of scope for this library, but I would like for this library to expose types for Jira's webhooks and the headers that come with it.
For example, here's a Jira headers, taken from https://developer.atlassian.com/cloud/jira/software/webhooks/
The text was updated successfully, but these errors were encountered: