This document outlines the setup and usage of ZenHub's API: a RESTful API with JSON responses.
All requests to the API need an API token. Generate a token in the Settings section of your ZenHub Dashboard. Note: Each user may only have one token, so generating a new token will make any previous tokens invalid.
The token is sent in the X-Authentication-Token
header. For example, using curl
it'd be curl -H 'X-Authentication-Token: TOKEN' URL
. Alternatively, you can send the token in the URL using the access_token
query string attribute. To do so, add ?access_token=TOKEN
to any url.
Please follow the instruction in https://{{zenhub_enterprise_host}}/setup/howto/api
Here are the current endpoints available for ZenHub's API.
GET https://api.zenhub.io/p1/repositories/:repo_id/issues/:issue_number
Please note: repo_id
is the ID of the repository, not its full name. For example, the ID of the ZenHubIO/support
repository is 13550592
.
To find out the ID of your repository, use GitHub's API.
Issue number is the same as displayed in your GitHub Issues page. For example, to fetch the ZenHub API issue information, the URL would be https://api.zenhub.io/p1/repositories/13550592/issues/172
.
The endpoint returns that issue's assigned Time Estimate (if applicable), its Pipeline in the Board, an is epic flag (true/false), as well as any +1s.
NOTE: Closed issues might take up to one minute to show up in the Closed pipeline. Similarly, reopened issues might take up to one minute to show in the right pipeline.
Here is an example of returned JSON data:
{
"estimate": {
"value": 8
},
"plus_ones": [
{
"user_id": 16717,
"created_at": "2015-12-11T18:43:22.296Z"
}
],
"pipeline": {
"name": "In Progress"
},
"is_epic": true
}
GET https://api.zenhub.io/p1/repositories/:repo_id/issues/:issue_number/events
Please note: repo_id
is the ID of the repository, not its full name. For example, the ID of the ZenHubIO/support
repository is 13550592
.
To find out the ID of your repository, use GitHub's API.
Issue number is the same one displayed in your GitHub Issues page. For example, to fetch the ZenHub Public API issue information, the URL would be https://api.zenhub.io/p1/repositories/13550592/issues/172
.
The endpoint returns that issue's events, sorted by most recent. Each event contains the User ID of the person who performed the change, the Creation Date of the event, and Type. Type can be either estimateIssue
or transferIssue
. Old and new values are included for both event types.
Here is an example of returned JSON data:
[
{
"user_id": 16717,
"type": "estimateIssue",
"created_at": "2015-12-11T19:43:22.296Z",
"from_estimate": {
"value": 8
}
},
{
"user_id": 16717,
"type": "estimateIssue",
"created_at": "2015-12-11T18:43:22.296Z",
"from_estimate": {
"value": 4
},
"to_estimate": {
"value": 8
}
},
{
"user_id": 16717,
"type": "estimateIssue",
"created_at": "2015-12-11T13:43:22.296Z",
"to_estimate": {
"value": 4
}
},
{
"user_id": 16717,
"type": "transferIssue",
"created_at": "2015-12-11T12:43:22.296Z",
"from_pipeline": {
"name": "Backlog"
},
"to_pipeline": {
"name": "In progress"
}
},
{
"user_id": 16717,
"type": "transferIssue",
"created_at": "2015-12-11T11:43:22.296Z",
"to_pipeline": {
"name": "Backlog"
}
}
]
GET https://api.zenhub.io/p1/repositories/:repo_id/board
Note: The repo_id
is the ID of the repository, not the full name. For example, the ID of the ZenHubIO/support
repository is 13550592
. Use GitHub's API to find out your repository's ID.
For example, the URL to fetch the ZenHubIO/support board would be https://api.zenhub.io/p1/repositories/13550592/board
.
The endpoint returns the Board's pipelines, plus the issues contained within each pipeline. It returns each issues' issue number, its position in the board, an is epic flag(true/false), and its Time Estimate (if one is assigned).
Even if the issues are returned in the right order, the position can't be guessed from its index. Notice some issues won't have position – this is because they have not been prioritized on your Board.
Note: The Board returned by the endpoint doesn't include closed issues. To get closed issues for a repository, you can use the GitHub API. Reopened issues might take up to one minute to appear in the correct pipeline.
This is an example of returned JSON data:
{
"pipelines": [
{
"name": "New Issues",
"issues": [
{
"issue_number": 279,
"estimate": {
"value": 40
},
"position": 0,
"is_epic": true
},
{
"issue_number": 142,
"is_epic": false
}
]
},
{
"name": "Backlog",
"issues": [
{
"issue_number": 303,
"estimate": {
"value": 40
},
"position": 3,
"is_epic": false
}
]
},
{
"name": "To Do",
"issues": [
{
"issue_number": 380,
"estimate": {
"value": 1
},
"position": 0,
"is_epic": true
},
{
"issue_number": 284,
"position": 2,
"is_epic": false
},
{
"issue_number": 329,
"estimate": {
"value": 8
},
"position": 7,
"is_epic": false
}
]
}
]
}
GET https://api.zenhub.io/p1/repositories/:repo_id/epics
Please note: repo_id
is the ID of the repository, not its full name. For example, the ID of the ZenHubIO/support
repository is 13550592
.
To find out the ID of your repository, use GitHub's API.
For example, the URL to fetch the ZenHubIO/support epics would be https://api.zenhub.io/p1/repositories/13550592/epics
.
The endpoint returns an array of the repository's epics. For each epic, issue number, repository ID, and the GitHub issue URL is provided.
Note: If an issue is only an issue belonging to an epic (and not a parent epic), it is not considered an epic and won't be included in the return array.
Here is an example of returned JSON data:
{
"epic_issues": [
{
"issue_number": 3953,
"repo_id": 1234567,
"issue_url": "https://github.com/RepoOwner/RepoName/issues/3953"
},
{
"issue_number": 1342,
"repo_id": 1234567,
"issue_url": "https://github.com/RepoOwner/RepoName/issues/1342"
},
]
}
GET https://api.zenhub.io/p1/repositories/:repo_id/epics/:epic_id
Please note: repo_id
is the ID of the repository, not its full name. For example, the ID of the ZenHubIO/support
repository is 13550592
.
To find out the ID of your repository, use GitHub's API.
epic_id
is the GitHub issue number (you may fetch the list of epics using Get Epics for a repository endpoint).
The endpoint returns the total estimate epic value (the sum of the epic's estimate, plus all estimates contained within it), the estimate of the epic, pipeline name the epic is in, and the issues belonging to it. For each issue belonging to the epic, its issue number, repo id, estimate value, is epic flag (true/false) are provided; in addition, if the issue is from the same repository as the epic, the ZenHub Board's pipeline name (from the repo the epic is in) is attached.
NOTE: If an issue is from a different repository than the epic it belongs to, the pipeline name is not attached.
{
"total_epic_estimates": {
"value": 60
},
"issues": [
{
"issue_number": 3161,
"is_epic": true,
"repo_id": 1099029,
"estimate": {
"value": 40
},
"pipeline": {
"name": "New Issues"
}
},
{
"issue_number": 2,
"is_epic": false,
"repo_id": 1234567,
"estimate": {
"value": 10
},
"pipeline": {
"name": "New Issues"
}
},
{
"issue_number": 1,
"is_epic": false,
"repo_id": 1234567
},
{
"issue_number": 6,
"is_epic": false,
"repo_id": 1234567
},
{
"issue_number": 7,
"is_epic": true,
"repo_id": 9876543
}
],
"estimate": {
"value": 10
},
"pipeline": {
"name": "Backlog"
}
}
Moves an issue between the pipelines in your repository.
POST https://api.zenhub.io/p1/repositories/:repo_id/issues/:issue_number/moves
Please note: repo_id
is the ID of the repository, not its full name. For example, the ID of the ZenHubIO/support
repository is 13550592
.
To find out the ID of your repository, use GitHub's API.
issue_number
is the desired issue or epic that will be moved between pipelines.
{
"pipeline_id":"58bf13aba426771426665e60",
"position":"top"
}
pipeline_id
is the id for one of the pipelines in your repository (i.e: In Progress
, Done
, QA
). In order to obtain this id, you can use the Get the ZenHub Board data for a repository endpoint.
position
can be either a String with the values top
or bottom
, which will move the issue to the top or the bottom of the specified pipeline. They can also be specified as numbers (i.e "position": 3
), which will define the desired slot that the issue should take in the pipeline. This number is based off a zero index, which means 0 is equal to the top
of the pipeline.
200
if the move was successful.
Does not return any body in the response.
Sets an estimate value for an issue.
PUT https://api.zenhub.io/p1/repositories/:repo_id/issues/:issue_number/estimate
Please note: repo_id
is the ID of the repository, not its full name. For example, the ID of the ZenHubIO/support
repository is 13550592
.
To find out the ID of your repository, use GitHub's API.
issue_number
is the issue that we want to set the estimate for.
{
"estimate":15
}
estimate
is a number that represents the value that we want to set as estimate.
200
if the estimate was set successfully.
{
"estimate":15
}
estimate
is the estimate number that was set for the specified issue.
Converts an issue to an epic, along with any issues that should be part of it.
POST https://api.zenhub.io/p1/repositories/:repo_id/issues/:issue_number/convert_to_epic
Please note: repo_id
is the ID of the repository, not its full name. For example, the ID of the ZenHubIO/support
repository is 13550592
.
To find out the ID of your repository, use GitHub's API.
issue_number
refers to the issue that we want to convert to an epic.
{
"issues":[
{
"repo_id":13550592,
"issue_number":3
},
{
"repo_id":13550592,
"issue_number":1
}
]
}
issues
are the issues that we want to be added to the epic. They should be specified as an array containing objects with the issue's repo_id
and issue_number
.
200
if the issue was converted to epic successfully
Does not return any body in the response.
400
if the informed issue is already an epic
Converts an epic back to an issue.
POST https://api.zenhub.io/p1/repositories/:repo_id/epics/:issue_number/convert_to_issue
Please note: repo_id
is the ID of the repository, not its full name. For example, the ID of the ZenHubIO/support
repository is 13550592
.
To find out the ID of your repository, use GitHub's API.
issue_number
refers to the epic that we want to convert back to an issue.
200
if the epic was converted to issue successfully
Does not return any body in the response.
Bulk add or remove issues to an epic. The result returns which issue was added or removed from the epic.
POST https://api.zenhub.io/p1/repositories/:repo_id/epics/:issue_number/update_issues
Please note: repo_id
is the ID of the repository, not its full name. For example, the ID of the ZenHubIO/support
repository is 13550592
.
To find out the ID of your repository, use GitHub's API.
issue_number
is the epic's issue number which we want to add or remove issues from.
{
"remove_issues":[
{
"repo_id":13550592,
"issue_number":3
}
],
"add_issues":[
{
"repo_id":13550592,
"issue_number":2
},
{
"repo_id":13550592,
"issue_number":1
}
]
}
remove_issues
is an array that indicates with issues we want to remove from the specified epic. They should be specified as an array containing objects with the issue's repo_id
and issue_number
.
add_issues
is an array that indicates with issues we want to add to the specified epic. They should be specified as an array containing objects with the issue's repo_id
and issue_number
.
200
if the issue was updated.
{
"removed_issues":[
{
"repo_id":3887883,
"issue_number":3
}
],
"added_issues":[
{
"repo_id":3887883,
"issue_number":2
},
{
"repo_id":3887883,
"issue_number":1
}
]
}
removed_issues
shows which issues were removed in this operation.
add_issues
shows which issues were added in this operation.
404
if the epic does not exist
We allow 100 requests per minute to our API. All requests responses include some headers related to this limitation.
Header | Meaning |
---|---|
X-RateLimit-Limit | Total number of requests allowed before the reset time |
X-RateLimit-Used | Number of requests sent in the current cycle. Will be set to 0 at the reset time. |
X-RateLimit-Reset | Time in UTC epoch seconds when the usage gets reset. |
To avoid time differences between your computer and our servers, we suggest to use the Date
header in the response to know exactly when the limit is reset.
The ZenHub API can return the following errors:
Status Code | Meaning |
---|---|
401 | The token is not valid. See Authentication. |
403 | Reached request limit to the API. See API Limits. |
404 | Not found. |
You can use our webhooks to fetch or store your ZenHub data, in real time, across services like Slack, Gitter, Spark, HipChat, or something custom!
To set up an integration, head on over to our Dashboard, navigate to your organization, and select the Integrations tab. From there, you may choose one of the 5 services (Slack, HipChat, Gitter, Spark, or Custom).
For instructions, you'll notice the How to create a webhook
link changes dynamically based on the service you select. Simply choose a repository with which to connect, add an optional description, paste your webhook, and click "Add" to save your new integration.
Our custom webhook sends a POST request to your webhook for multiple events that occur on your ZenHub board:
{
"type": "issue_transfer",
"github_url": "https://github.com/ZenHubIO/support/issues/618",
"organization": "ZenHubHQ",
"repo": "support",
"user_name": "ZenHubIO",
"issue_number": "618",
"issue_title": "ZenHub Change Log",
"to_pipeline_name": "New Issues",
"from_pipeline_name": "Discussion"
}
{
"type": "estimate_set",
"github_url": "https://github.com/ZenHubIO/support/issues/618",
"organization": "ZenHubHQ",
"repo": "support",
"user_name": "ZenHubIO",
"issue_number": "618",
"issue_title": "ZenHub Change Log",
"estimate": "8"
}
{
"type": "estimate_cleared",
"github_url": "https://github.com/ZenHubIO/support/issues/618",
"organization": "ZenHubHQ",
"repo": "support",
"user_name": "ZenHubIO",
"issue_number": "618",
"issue_title": "ZenHub Change Log",
}
{
"type": "issue_reprioritized",
"github_url": "https://github.com/ZenHubIO/support/issues/618",
"organization": "ZenHubHQ",
"repo": "support",
"user_name": "ZenHubIO",
"issue_number": "618",
"issue_title": "ZenHub Change Log",
"to_pipeline_name": "Backlog",
"from_position": "4",
"to_position": "0"
}
As an example, here's a simple Node/Express app that would be able receive the webhooks(using ngrok):
var express = require('express');
var http = require('http');
var bodyParser = require('body-parser');
var app = express();
http.createServer(app).listen('6000', function(){
console.log('Listening on 6000');
});
app.use(bodyParser());
app.post('*', function( req, res) {
console.dir(req.body);
});
We'd love to hear from you. If you have any questions, concerns, or ideas related to the ZenHub API, open an issue in our Support repo or find us on Twitter.