[Deprecated] Zenhub's legacy REST API
[!WARNING] This API has not been updated since 2021 is scheduled for deprecation. Please use our new GraphQL API at https://developers.zenhub.com
If you have any questions or feedback, contact support. You can submit feature requests here.
The ZenHub API root endpoint for Cloud is different than that of ZenHub On-Premise Enterprise instances and has also changed across Enterprise versions. Please refer to the table below for the appropriate endpoint.
ZenHub Version | API Root Endpoint |
---|---|
Cloud | https://api.zenhub.com/ |
Enterprise 2 | https://<zenhub_enterprise_host>/ |
Enterprise 3 | https://<zenhub_enterprise_host>/api/ |
All requests to the API need an API token. Generate a token in the API Tokens section of your ZenHub Dashboard (for ZenHub Enterprise, refer to the table below for the proper link).
ZenHub Enterprise Version | Auth Token Generation Page |
---|---|
Enterprise 2 | https://<zenhub_enterprise_host>/app/dashboard/tokens |
Enterprise 3 | https://<zenhub_enterprise_host>/dashboard/tokens |
The token is sent in the X-Authentication-Token
header. For example, using curl
it would be:
curl -H 'X-Authentication-Token: TOKEN' URL
Alternatively, you can choose to send the token in the URL using the access_token
query string attribute. To do so, add ?access_token=TOKEN
to any URL.
Our REST API only supports JSON content for requests with a body and for responses.
For each request containing a body with JSON, you will need to attach the header 'Content-Type: application/json'
with your request. For example, using curl
it’d be:
curl -H 'Content-Type: application/json' URL
We allow a maximum of 100 requests per minute to our API. All requests responses include the following headers related to this limitation.
Header | Description |
---|---|
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 | Description |
---|---|
401 |
The token is not valid. See Authentication. |
403 |
Reached request limit to the API. See API Limits. |
404 |
Not found. |
repo_id
is the ID of the repository, not its full name. For example, the ID of the ZenHubIO/API
repository is 47655910
. To find out the ID of your repository, use GitHub’s API, or copy it from the URL of the Board (for this repo, the Board URL is https://github.com/ZenHubIO/API#boards?repos=47655910).workspace_id
is the ID of the ZenHub Workspace. This is found in the URL for the Workspace after the name of the workspace. For example, the workspace_id
for https://app.zenhub.com/workspaces/workflows---product--design-workspace-5f6b5c9ab4fd7d76a3e5b7d8/board?
is 5f6b5c9ab4fd7d76a3e5b7d8
.Get the data for a specific issue.
GET /p1/repositories/:repo_id/issues/:issue_number
Name | Type | Comments |
---|---|---|
repo_id |
Number |
Required |
issue_number |
Number |
Required |
{
"estimate": {
"value": 8
},
"plus_ones": [
{
"created_at": "2015-12-11T18:43:22.296Z"
}
],
"pipeline": {
"name": "QA",
"pipeline_id": "5d0a7a9741fd098f6b7f58a7",
"workspace_id": "5d0a7a9741fd098f6b7f58ac"
},
"pipelines": [
{
"name": "QA",
"pipeline_id": "5d0a7a9741fd098f6b7f58a7",
"workspace_id": "5d0a7a9741fd098f6b7f58ac"
},
{
"name": "Done",
"pipeline_id": "5d0a7cea41fd098f6b7f58b7",
"workspace_id": "5d0a7cea41fd098f6b7f58b8"
}
],
"is_epic": true
}
plus_ones[].user_id
was removed from the response.pipeline
object references the oldest Workspace pipeline this issue is in.
pipeline
value will describe the Pipeline that the issue was in prior to the issue being closed. The ZenHub API does not consider the "Closed" Pipeline to be a distinct Pipeline at this time and you should not use the Pipeline value to determine whether or not an issue is closed or open (use status
instead).pipelines
contains all pipelines in all Workspaces this issue is in.Get the events for an issue.
GET /p1/repositories/:repo_id/issues/:issue_number/events
Name | Type | Comments |
---|---|---|
repo_id |
Number |
Required |
issue_number |
Number |
Required |
[
{
"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"
},
"workspace_id": "5d0a7a9741fd098f6b7f58ac"
},
{
"user_id": 16717,
"type": "transferIssue",
"created_at": "2015-12-11T11:43:22.296Z",
"to_pipeline": {
"name": "Backlog"
}
}
]
estimateIssue
or transferIssue
. The values before and after the event are included in the event data.transferIssue
events include a workspace_id
indicating in which Workspace the transfer occurred.Moves an issue between Pipelines in a Workspace
POST /p2/workspaces/:workspace_id/repositories/:repo_id/issues/:issue_number/moves
Name | Type | Comments |
---|---|---|
workspace_id |
String |
Required |
repo_id |
Number |
Required |
issue_number |
Number |
Required |
Name | Type | Comments |
---|---|---|
pipeline_id |
String |
Required |
position |
String or Number |
Required |
workspace_id
is the ID of the Workspace you're transferring the issue in. To get a list of Workspaces for repo_id
, you can use the Get ZenHub Workspaces for a repository endpoint.pipeline_id
is the ID for one of the Pipelines in the Workspace specified by workspace_id
(i.e: In Progress, Done, QA). In order to obtain this ID, you can use the Get a ZenHub Board for a repository endpoint.position
can be specified as top
or bottom
, or a 0
-based position in the Pipeline such as 1
, which would be the second position in the Pipeline.{
"pipeline_id": "58bf13aba426771426665e60",
"position": "top"
}
Status 200
for a successful move. No response body.
Moves an issue between Pipelines for a repository in your oldest Workspace
POST /p1/repositories/:repo_id/issues/:issue_number/moves
Name | Type | Comments |
---|---|---|
repo_id |
Number |
Required |
issue_number |
Number |
Required |
Name | Type | Comments |
---|---|---|
pipeline_id |
String |
Required |
position |
String or Number |
Required |
pipeline_id
is the ID for one of the Pipelines in your oldest Workspace(i.e: In Progress, Done, QA). In order to obtain this ID, you can use the Get the oldest ZenHub Board for a repository endpoint.position
can be specified as top
or bottom
, or a 0
-based position in the Pipeline such as 1
, which would be the second position in the Pipeline.{
"pipeline_id": "58bf13aba426771426665e60",
"position": "top"
}
Status 200
for a successful move. No response body.
PUT /p1/repositories/:repo_id/issues/:issue_number/estimate
Name | Type | Comments |
---|---|---|
repo_id |
Number |
Required |
issue_number |
Number |
Required |
Name | Type | Comments |
---|---|---|
estimate |
Number |
Required, number representing estimate value |
{ "estimate": 15 }
{ "estimate": 15 }
Get all Epics for a repository
GET /p1/repositories/:repo_id/epics
Name | Type | Comments |
---|---|---|
repo_id |
Number |
Required |
{
"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 the data for an Epic issue.
GET /p1/repositories/:repo_id/epics/:epic_id
Name | Type | Comments |
---|---|---|
repo_id |
Number |
Required |
epic_id |
Number |
Required, Github issue number |
epic_id
is the GitHub issue number. You may fetch the list of Epics using Get Epics for a repository
endpoint.pipeline
(the oldest Workspace's pipeline) and pipelines
(all Workspace Pipelines that issue is in).{
"total_epic_estimates": { "value": 60 },
"estimate": { "value": 10 },
"pipeline": {
"workspace_id": "5d0a7a9741fd098f6b7f58ac",
"name": "Backlog",
"pipeline_id": "5d0a7a9741fd098f6b7f58a8"
},
"pipelines": [
{
"workspace_id": "5d0a7a9741fd098f6b7f58ac",
"name": "Backlog",
"pipeline_id": "5d0a7a9741fd098f6b7f58a8"
},
{
"workspace_id": "5d0a7cea41fd098f6b7f58b8",
"name": "In Progress",
"pipeline_id": "5d0a7cea41fd098f6b7f58b5"
}
],
"issues": [
{
"issue_number": 3161,
"is_epic": true,
"repo_id": 1099029,
"estimate": { "value": 40 },
"pipelines": [
{
"workspace_id": "5d0a7a9741fd098f6b7f58ac",
"name": "Backlog",
"pipeline_id": "5d0a7a9741fd098f6b7f58a8"
},
{
"workspace_id": "5d0a7cea41fd098f6b7f58b8",
"name": "In Progress",
"pipeline_id": "5d0a7cea41fd098f6b7f58b5"
}
],
"pipeline": {
"workspace_id": "5d0a7a9741fd098f6b7f58ac",
"name": "Backlog",
"pipeline_id": "5d0a7a9741fd098f6b7f58a8"
}
},
{
"issue_number": 2,
"is_epic": false,
"repo_id": 1234567,
"estimate": { "value": 10 },
"pipelines": [
{
"workspace_id": "5d0a7a9741fd098f6b7f58ac",
"name": "Backlog",
"pipeline_id": "5d0a7a9741fd098f6b7f58a8"
},
{
"workspace_id": "5d0a7cea41fd098f6b7f58b8",
"name": "In Progress",
"pipeline_id": "5d0a7cea41fd098f6b7f58b5"
}
],
"pipeline": {
"workspace_id": "5d0a7a9741fd098f6b7f58ac",
"name": "Backlog",
"pipeline_id": "5d0a7a9741fd098f6b7f58a8"
}
}
]
}
The endpoint returns:
For each issue belonging to the Epic:
is_epic
flag (true
or false
)Converts an Epic back to a regular issue.
POST /p1/repositories/:repo_id/epics/:issue_number/convert_to_issue
Name | Type | Comments |
---|---|---|
repo_id |
Number |
Required |
issue_number |
Number |
Required, the number of the issue to be converted |
200
if the issue was converted to Epic successfullyDoes not return any body in the response.
Converts an issue to an Epic, along with any issues that should be part of it.
POST /p1/repositories/:repo_id/issues/:issue_number/convert_to_epic
Name | Type | Comments |
---|---|---|
repo_id |
Number |
Required |
issue_number |
Number |
Required |
Name | Type | Comments |
---|---|---|
issues |
[{repo_id: Number, issue_number: Number}] |
Required, array of Objects with repo_id and issue_number |
{
"issues": [
{ "repo_id": 13550592, "issue_number": 3 },
{ "repo_id": 13550592, "issue_number": 1 }
]
}
Does not return any body in the response.
200
if the issue was converted to Epic successfully400
if the supplied issue is already an EpicBulk add or remove issues to an Epic. The result returns which issue was added or removed from the Epic.
POST /p1/repositories/:repo_id/epics/:issue_number/update_issues
Name | Type | Comments |
---|---|---|
repo_id |
Number |
Required |
issue_number |
Number |
Required |
Name | Type | Comments |
---|---|---|
remove_issues |
[{repo_id: Number, issue_number: Number} ] |
Required, array of Objects with repo_id and issue_number |
add_issues |
[{repo_id: Number, issue_number: Number} ] |
Required, array of Objects with repo_id and issue_number |
{
"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
.{
"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 doesn’t existGets all Workspaces containing repo_id
GET /p2/repositories/:repo_id/workspaces
Name | Type | Comments |
---|---|---|
repo_id |
Number |
Required |
[
{
"name": "Design and UX",
"description": null,
"id": "5d0a7a9741fd098f6b7f58ac",
"repositories": [12345678, 912345]
},
{
"name": "Roadmap",
"description": "Feature planning and enhancements",
"id": "5d0a7cea41fd098f6b7f58b8",
"repositories": [12345678]
}
]
Get ZenHub Board data for a repository (repo_id
) within the Workspace (workspace_id
)
GET /p2/workspaces/:workspace_id/repositories/:repo_id/board
Name | Type | Comments |
---|---|---|
repo_id |
Number |
Required |
workspace_id |
String |
Required |
{
"pipelines": [
{
"id": "595d430add03f01d32460080",
"name": "New Issues",
"issues": [
{
"issue_number": 279,
"estimate": { "value": 40 },
"position": 0,
"is_epic": true
},
{
"issue_number": 142,
"is_epic": false
}
]
},
{
"id": "595d430add03f01d32460081",
"name": "Backlog",
"issues": [
{
"issue_number": 303,
"estimate": { "value": 40 },
"position": 3,
"is_epic": false
}
]
},
{
"id": "595d430add03f01d32460082",
"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 /p1/repositories/:repo_id/board
Name | Type | Comments |
---|---|---|
repo_id |
Number |
Required |
{
"pipelines": [
{
"id": "595d430add03f01d32460080",
"name": "New Issues",
"issues": [
{
"issue_number": 279,
"estimate": { "value": 40 },
"position": 0,
"is_epic": true
},
{
"issue_number": 142,
"is_epic": false
}
]
},
{
"id": "595d430add03f01d32460081",
"name": "Backlog",
"issues": [
{
"issue_number": 303,
"estimate": { "value": 40 },
"position": 3,
"is_epic": false
}
]
},
{
"id": "595d430add03f01d32460082",
"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
}
]
}
]
}
is_epic
flag (true
or false
), and its Estimate (if set).POST /p1/repositories/:repo_id/milestones/:milestone_number/start_date
Name | Type | Comments |
---|---|---|
repo_id |
Number |
Required |
milestone_number |
Number |
Required |
Name | Type | Comments |
---|---|---|
start_date |
ISO8601 date string | Required |
{ "start_date": "2010-11-13T01:38:56.842Z" }
{ "start_date": "2010-11-13T01:38:56.842Z" }
GET /p1/repositories/:repo_id/milestones/:milestone_number/start_date
Name | Type | Comments |
---|---|---|
repo_id |
Number |
Required |
milestone_number |
Number |
Required |
{ "start_date": "2010-11-13T01:38:56.842Z" }
GET /p1/repositories/:repo_id/dependencies
Name | Type | Comments |
---|---|---|
repo_id |
Number |
Required |
{
"dependencies": [
{
"blocking": {
"issue_number": 3953,
"repo_id": 1234567
},
"blocked": {
"issue_number": 1342,
"repo_id": 1234567
}
},
{
"blocking": {
"issue_number": 5,
"repo_id": 987
},
"blocked": {
"issue_number": 1342,
"repo_id": 1234567
}
}
]
}
repo_id
param in the URL.POST /p1/dependencies
Name | Type | Comments |
---|---|---|
blocking |
Object |
Required |
blocking.repo_id |
Number |
Required |
blocking.issue_number |
Number |
Required |
blocked |
Object |
Required |
blocked.repo_id |
Number |
Required |
blocked.issue_number |
Number |
Required |
{
"blocking": {
"repo_id": 92563409,
"issue_number": 14
},
"blocked": {
"repo_id": 92563409,
"issue_number": 13
}
}
{
"blocking": {
"repo_id": 92563409,
"issue_number": 14
},
"blocked": {
"repo_id": 92563409,
"issue_number": 13
}
}
dependency
in the Body (see description above).DELETE /p1/dependencies
Name | Type | Comments |
---|---|---|
blocking |
Object |
Required |
blocking.repo_id |
Number |
Required |
blocking.issue_number |
Number |
Required |
blocked |
Object |
Required |
blocked.repo_id |
Number |
Required |
blocked.issue_number |
Number |
Required |
{
"blocking": {
"repo_id": 92563409,
"issue_number": 14
},
"blocked": {
"repo_id": 92563409,
"issue_number": 13
}
}
dependency
in the Body (see description above).POST /p1/repositories/:repo_id/reports/release
Name | Type | Comments |
---|---|---|
repo_id |
Number |
Required |
Name | Type | Comments |
---|---|---|
title |
String |
Required |
description |
String |
Optional |
start_date |
ISO8601 date string | Required |
desired_end_date |
ISO8601 date string | Required |
repositories |
[Number] |
Optional |
{
"title": "Great title",
"description": "Amazing description",
"start_date": "2007-01-01T00:00:00Z",
"desired_end_date": "2007-01-01T00:00:00Z",
"repositories": [103707262]
}
{
"release_id": "59dff4f508399a35a276a1ea",
"title": "Great title",
"description": "Amazing description",
"start_date": "2007-01-01T00:00:00.000Z",
"desired_end_date": "2007-01-01T00:00:00.000Z",
"created_at": "2017-10-12T23:04:21.795Z",
"closed_at": null,
"state": "open",
"repositories": [103707262]
}
repo_id
param in the URL.repositories
parameterrepo_id
parameter, but associated with repositories in the request body repositories
parameter will also be associated to the Release Report.GET /p1/reports/release/:release_id
Name | Type | Comments |
---|---|---|
release_id |
String |
Required |
{
"release_id": "59d3cd520a430a6344fd3bdb",
"title": "Test release",
"description": "",
"start_date": "2017-10-01T19:00:00.000Z",
"desired_end_date": "2017-10-03T19:00:00.000Z",
"created_at": "2017-10-03T17:48:02.701Z",
"closed_at": null,
"state": "open",
"repositories": [105683718]
}
GET /p1/repositories/:repo_id/reports/releases
Name | Type | Comments |
---|---|---|
repo_id |
Number |
Required |
[
{
"release_id": "59cbf2fde010f7a5207406e8",
"title": "Great title for release 1",
"description": "Great description for release",
"start_date": "2000-10-10T00:00:00.000Z",
"desired_end_date": "2010-10-10T00:00:00.000Z",
"created_at": "2017-09-27T18:50:37.418Z",
"closed_at": null,
"state": "open"
},
{
"release_id": "59cbf2fde010f7a5207406e8",
"title": "Great title for release 2",
"description": "Great description for release",
"start_date": "2000-10-10T00:00:00.000Z",
"desired_end_date": "2010-10-10T00:00:00.000Z",
"created_at": "2017-09-27T18:50:37.418Z",
"closed_at": null,
"state": "open"
}
]
PATCH /p1/reports/release/:release_id
Name | Type | Comments |
---|---|---|
release_id |
String |
Required |
Name | Type | Comments |
---|---|---|
title |
String |
Required |
description |
String |
Optional |
start_date |
ISO8601 date string | Optional |
desired_end_date |
ISO8601 date string | Optional |
state |
String |
Optional, open or closed |
{
"title": "Amazing title",
"description": "Amazing description",
"start_date": "2007-01-01T00:00:00Z",
"desired_end_date": "2007-01-01T00:00:00Z",
"state": "closed"
}
{
"release_id": "59d3d6438b3f16667f9e7174",
"title": "Amazing title",
"description": "Amazing description",
"start_date": "2007-01-01T00:00:00.000Z",
"desired_end_date": "2007-01-01T00:00:00.000Z",
"created_at": "2017-10-03T18:26:11.700Z",
"closed_at": "2017-10-03T18:26:11.700Z",
"state": "closed",
"repositories": [105683567, 105683718]
}
POST /p1/reports/release/:release_id/repository/:repo_id
Name | Type | Comments |
---|---|---|
release_id |
String |
Required |
repo_id |
Number |
Required |
DELETE /p1/reports/release/:release_id/repository/:repo_id
Name | Type | Comments |
---|---|---|
release_id |
String |
Required |
repo_id |
Number |
Required |
GET /p1/reports/release/:release_id/issues
Name | Type | Comments |
---|---|---|
release_id |
String |
Required |
[
{ "repo_id": 103707262, "issue_number": 2 },
{ "repo_id": 103707262, "issue_number": 3 }
]
PATCH /p1/reports/release/:release_id/issues
Name | Type | Comments |
---|---|---|
release_id |
String |
Required |
Name | Type | Comments |
---|---|---|
add_issues |
[{repo_id: Number, issue_number: Number}] |
Required, array of Objects with repo_id and issue_number |
remove_issues |
[{repo_id: Number, issue_number: Number}] |
Required, array of Objects with repo_id and issue_number |
add_issues
and remove_issues
keys are required, but can be an empty array when not used{
"add_issues": [{ "repo_id": 103707262, "issue_number": 3 }],
"remove_issues": []
}
{
"added": [{ "repo_id": 103707262, "issue_number": 3 }],
"removed": []
}
add_issues
and remove_issues
keys.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 Slack & 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. See below for examples of the events and data that they will contain. Please note that the content type in the examples has been written in JSON, however the actual data is sent in x-www-form-urlencoded format.
The POST request is sent in the x-www-form-urlencoded format.
Example:
field1=value1&field2=value2
{
"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",
"workspace_id": "603fc3e575de63001cc163f9",
"workspace_name": "My Workspace",
"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",
"workspace_id": "603fc3e575de63001cc163f9",
"workspace_name" "My Workspace"
}
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, please reach us at [email protected] or find us on Twitter.