Table of contents
- Overview
- Usage
- Schema
- Getting Started
- Configuration
- Authentication
- Cross Origin Resource Sharing (CORS)
- API
API Integration
Overview
This describes the resources that make up the official Flying Donut API
Usage
With this integration, you will be able to retrieve all data of your project stored in Flying Donut. You may use it to export data to generate your custom reports, or even to keep a local backup if you wish.
Schema
All API access is over HTTPS, and accessed from the www.flying.donut/api/
url. All data is sent and received as JSON.
Timestamp entries have a $date
attribute containing the value of the timestamp in a structure like the following one:
"day": {
"$date": "2013-05-18T21:00:00.000Z"
}
All timestamps are returned in ISO 8601
format:
YYYY-MM-DDTHH:MM:SSZ
The majority of the attributes used in the Flying Donut are versioned. You will see the following structure in the json returned in several cases you should use the value
to get data:
"attributeName": {
"value": "a value of the attribute",
"version": 1
}
You will also see attributes that have aggregated data. For example the following attribute has aggregated task counters where the tasks are broken down into done
, to do
and doing
states:
"taskCounters": {
"value": {
"done": 2,
"todo": 0,
"inProgress": 0,
"total": 2,
"status": "done"
},
"version": 6
}
Getting Started
-
Navigate to your project and locate its settings. If you have admin permissions, you will see the integrations tab. Click on the enable button to enable the API integration. Only project administrators (or owners) are allowed to set up API integration.
-
Click on the
Details
button to see the API configuration details.
Configuration
-
Generate a new API endpoint URL. To use the API integration you click on the
Generate a new API endpoint URL
button. -
Use the Secret. Once you generate the new the secret you can start using the API endpoints from your scripts and applications.
Authentication
Requests that require authentication will return 403 Forbidden to all unauthorized users even if the project does not exist.
Secret
The secret generated by Flying Donut is to be used as a token. The secret is not a personalized OAuth token. It is a project specific one and is valid only for API calls to the project. To use it in you API calls, include the secret in the Authorization
http header. For security reasons we only allow authorization via the http header.
$ curl -v -H "Authorization: secret THE-SECRET" \
https://www.flyingdonut.io/api/projects/PROJECT-ID
Replace THE-SECRET with the secret and the PROJECT-ID with the project id and the api call will look like this:
$ curl -v -H "Authorization: secret 68300163a5d8b2d71d60fff19f056ab3" \
https://www.flyingdonut.io/api/projects/54744060c955ca8169c61ee6
Cross Origin Resource Sharing (CORS)
Cross Origin Resource Sharing (CORS) for AJAX requests is not supported by the API. If you need to use the API directly for AJAX requests contact [email protected].
API
Fetch Project
GET /api/projects/{projectId}
Response
{
"_id": {
"$oid": "54744060c955ca8169c61ee6"
},
"activityCounter": {
"value": 12,
"version": 12
},
"backlogBuckets": {
"value": [
{
"title": "Default",
"id": {
"$oid": "54744060c955ca8169c61ee5"
}
}
],
"version": 0
},
"endDate": {
"value": "2015-11-12T22:00:00.000Z",
"version": 1
},
"integrations": {
"api": {
"enabled": true
}
},
"owner": {
"value": "stormy",
"version": 0
},
"startDate": {
"value": "2014-10-26T22:00:00.000Z",
"version": 1
},
"summary": {
"value": "",
"version": 0
},
"timezone": {
"value": "America/Los_Angeles",
"version": 0
},
"title": {
"value": "Stormy Logbook",
"version": 0
},
"type": {
"value": "PRIVATE",
"version": 0
},
"userCounters": {
"value": {
"total": 4,
"observers": 1,
"participants": 3
},
"version": 4
},
"version": 15
}
Fetch Backlog Cards
GET /api/projects/{projectId}/backlog/items
Response
[
{
"bucket": "Default",
"id": {
"$oid": "590e04cc276e03287520db7a"
},
"items": [
{
"_id": {
"$oid": "54744c20c955ca8169c61eef"
},
"cid": 2,
"estimate": {
"value": 8,
"version": 1
},
"isStandaloneTP": false,
"iteration": {
"value": null,
"version": 0
},
"iterationReview": {
"value": "",
"version": 0
},
"order": {
"value": "000000001.0",
"version": 0
},
"owner": {
"value": null,
"version": 0
},
"ownerType": {
"value": null,
"version": 0
},
"project": {
"value": {
"$oid": "54744060c955ca8169c61ee6"
},
"version": 0
},
"state": {
"value": {
"$oid": "54744060c955ca8169c61ee5"
},
"version": 0
},
"summary": {
"value": "",
"version": 0
},
"taskCounters": {
"value": null,
"version": 0
},
"title": {
"value": "Define API",
"version": 0
},
"totalAttachments": {
"value": 0,
"version": 0
},
"totalComments": {
"value": 0,
"version": 0
},
"totalDiscussions": {
"value": 0,
"version": 0
},
"type": {
"value": {
"version": 0
},
"version": 0
},
"version": 1,
"_order": 0,
}
]
}
]
Fetch Backlog Buckets
GET /api/projects/{projectId}/backlog/buckets
Response
[
{
"bucket": "Default",
"id": {
"$oid": "590e04cc276e03287520db7a"
}
}
]
Fetch Backlog Bucket
GET /api/projects/{projectId}/backlog/buckets/{bucketId}
Response
{
"bucket": "Default",
"id": {
"$oid": "590e04cc276e03287520db7a"
}
}
Fetch Backlog Bucket Cards
GET /api/projects/{projectId}/backlog/buckets/{bucketId}/items
Response
[
{
"_id": {
"$oid": "54744c20c955ca8169c61eef"
},
"cid": 2,
"estimate": {
"value": 8,
"version": 1
},
"isStandaloneTP": false,
"iteration": {
"value": null,
"version": 0
},
"iterationReview": {
"value": "",
"version": 0
},
"order": {
"value": "000000001.0",
"version": 0
},
"owner": {
"value": null,
"version": 0
},
"ownerType": {
"value": null,
"version": 0
},
"project": {
"value": {
"$oid": "54744060c955ca8169c61ee6"
},
"version": 0
},
"state": {
"value": {
"$oid": "54744060c955ca8169c61ee5"
},
"version": 0
},
"summary": {
"value": "",
"version": 0
},
"taskCounters": {
"value": null,
"version": 0
},
"title": {
"value": "Define API",
"version": 0
},
"totalAttachments": {
"value": 0,
"version": 0
},
"totalComments": {
"value": 0,
"version": 0
},
"totalDiscussions": {
"value": 0,
"version": 0
},
"type": {
"value": {
"version": 0
},
"version": 0
},
"version": 1,
"_order": 0,
}
]
Create Backlog Bucket Card
POST /api/projects/{projectId}/backlog/buckets/{bucketId}/items
Request
Due to the lack of OAuth2 or a user specific authentication, one needs to provide a valid username that is a member of the project (with write permissions) to be able to create a new card.
{
"username":"username_Of_User_Creating_the_card",
"title": {
"value": "5th Test card"
},
"summary": {
"value": {
"markdown":"My test card description"
}
},
"estimate":{
"value":"5"
}
}
Response
{
"_id": {
"$oid": "54744c20c955ca8169c61eef"
},
"cid": 2,
"estimate": {
"value": 8,
"version": 1
},
"isStandaloneTP": false,
"iteration": {
"value": null,
"version": 0
},
"iterationReview": {
"value": "",
"version": 0
},
"order": {
"value": "000000001.0",
"version": 0
},
"owner": {
"value": null,
"version": 0
},
"ownerType": {
"value": null,
"version": 0
},
"project": {
"value": {
"$oid": "54744060c955ca8169c61ee6"
},
"version": 0
},
"state": {
"value": {
"$oid": "54744060c955ca8169c61ee5"
},
"version": 0
},
"summary": {
"value": {
"markdown": "My test card description",
"html": "<p>My test card description</p>\n"
},
"version": 0
},
"taskCounters": {
"value": null,
"version": 0
},
"title": {
"value": "5th Test card",
"version": 0
},
"totalAttachments": {
"value": 0,
"version": 0
},
"totalComments": {
"value": 0,
"version": 0
},
"totalDiscussions": {
"value": 0,
"version": 0
},
"type": {
"value": {
"version": 0
},
"version": 0
},
"version": 1,
"_order": 0,
}
In a single api call you can create multiple cards by including the cards in an array.
[
{
"username":"username_Of_User_Creating_the_card",
"title": {
"value": "5th Test card"
},
"summary": {
"value": {
"markdown":"My test card description"
}
},
"estimate":{
"value":"5"
}
}
]
Response
The response is an array of the cards created.
[
{
"_id": {
"$oid": "54744c20c955ca8169c61eef"
},
"cid": 2,
"estimate": {
"value": 8,
"version": 1
},
"isStandaloneTP": false,
"iteration": {
"value": null,
"version": 0
},
"iterationReview": {
"value": "",
"version": 0
},
"order": {
"value": "000000001.0",
"version": 0
},
"owner": {
"value": null,
"version": 0
},
"ownerType": {
"value": null,
"version": 0
},
"project": {
"value": {
"$oid": "54744060c955ca8169c61ee6"
},
"version": 0
},
"state": {
"value": {
"$oid": "54744060c955ca8169c61ee5"
},
"version": 0
},
"summary": {
"value": {
"markdown": "My test card description",
"html": "<p>My test card description</p>\n"
},
"version": 0
},
"taskCounters": {
"value": null,
"version": 0
},
"title": {
"value": "5th Test card",
"version": 0
},
"totalAttachments": {
"value": 0,
"version": 0
},
"totalComments": {
"value": 0,
"version": 0
},
"totalDiscussions": {
"value": 0,
"version": 0
},
"type": {
"value": {
"version": 0
},
"version": 0
},
"version": 1,
"_order": 0
}
]
Fetch Sprints
GET /api/projects/{projectId}/iterations
Response
[
{
"_id": {
"$oid": "54744d10c955ca8169c61ef2"
},
"endDate": {
"value": {
"$date": "2014-12-20T21:59:59.999Z"
},
"version": 0
},
"estimate": {
"value": null,
"version": 1
},
"itemCounters": {
"value": null,
"version": 1
},
"project": {
"value": {
"$oid": "54744060c955ca8169c61ee6"
},
"version": 0
},
"startDate": {
"value": {
"$date": "2014-12-03T22:00:00.000Z"
},
"version": 0
},
"summary": {
"value": "",
"version": 0
},
"taskCounters": {
"value": null,
"version": 1
},
"taskEstimate": {
"value": null,
"version": 1
},
"title": {
"value": "Initial Sprint",
"version": 0
},
"version": 3,
"_order": 0,
"isFuture": true,
"isActive": false,
"isPast": false
}
]
Fetch Sprint
GET /api/projects/{projectId}/iterations/{iterationId}
Response
{
"_id": {
"$oid": "54744d10c955ca8169c61ef2"
},
"endDate": {
"value": {
"$date": "2014-12-20T21:59:59.999Z"
},
"version": 0
},
"estimate": {
"value": null,
"version": 1
},
"itemCounters": {
"value": null,
"version": 1
},
"project": {
"value": {
"$oid": "54744060c955ca8169c61ee6"
},
"version": 0
},
"startDate": {
"value": {
"$date": "2014-12-03T22:00:00.000Z"
},
"version": 0
},
"summary": {
"value": "",
"version": 0
},
"taskCounters": {
"value": null,
"version": 1
},
"taskEstimate": {
"value": null,
"version": 1
},
"title": {
"value": "Initial Sprint",
"version": 0
},
"version": 3,
"_order": 0,
"isFuture": true,
"isActive": false,
"isPast": false
}
Fetch Sprint Cards
GET /api/projects/{projectId}/iterations/{iterationId}/items
Response
[
{
"_id": {
"$oid": "54744d10c955ca8169c61ef3"
},
"cid": 3,
"estimate": {
"value": null,
"version": 0
},
"isStandaloneTP": true,
"iteration": {
"value": {
"$oid": "54744d10c955ca8169c61ef2"
},
"version": 0
},
"iterationReview": {
"value": null,
"version": 0
},
"order": {
"value": "000000001.0",
"version": 0
},
"owner": {
"value": null,
"version": 0
},
"ownerType": {
"value": null,
"version": 0
},
"project": {
"value": {
"$oid": "54744060c955ca8169c61ee6"
},
"version": 0
},
"state": {
"value": null,
"version": 0
},
"summary": {
"value": null,
"version": 0
},
"taskCounters": {
"value": {
"done": 0.0,
"todo": 0.0,
"inProgress": 1.0,
"total": 1.0,
"status": "in-progress"
},
"version": 2
},
"taskEstimate": {
"value": 8.0,
"version": 2
},
"title": {
"value": "Placeholder for all tasks that are unrelated to iteration items",
"version": 0
},
"totalAttachments": {
"value": 0,
"version": 0
},
"totalComments": {
"value": null,
"version": 0
},
"totalDiscussions": {
"value": null,
"version": 0
},
"type": {
"value": "",
"version": 0
},
"version": 4,
"_order": 0
},
{
"_id": {
"$oid": "54744f6cc955ca8169c61ef5"
},
"cid": 4,
"estimate": {
"value": 8,
"version": 1
},
"owner": {
"value": {
"$oid": "54744d10c955ca8169c61ef3"
},
"version": 0
},
"ownerType": {
"value": "",
"version": 0
},
"project": {
"value": {
"$oid": "54744060c955ca8169c61ee6"
},
"version": 0
},
"state": {
"value": "in-progress",
"version": 1
},
"summary": {
"value": "",
"version": 0
},
"timeRemaining": [
{
"duration": 5,
"when": {
"$date": "2014-11-25T09:44:31.092Z"
},
"who": "stormy"
}
],
"title": {
"value": "T1",
"version": 1
},
"type": {
"value": "",
"version": 0
},
"users": [
{
"when": {
"$date": "2014-11-25T09:44:26.728Z"
},
"who": "stormy",
"user": "stormy"
}
],
"version": 3,
"_order": 1
}
]
Fetch Sprint Burndown Chart
GET /api/projects/{projectId}/iterations/{iterationId}/burndown-chart
Response
{
"_id": {
"$oid": "51c739ffe4b02243265f16d2"
},
"items": [
{
"cid": 81,
"originalEstimate": 1,
"timeRemaining": [
1,
1,
1,
1,
1,
1,
0
],
"title": "Placeholder for all tasks that are unrelated to iteration items"
},
{
"cid": 84,
"originalEstimate": 0.5,
"timeRemaining": [
0.5,
0.5,
0,
0,
0,
0,
0
],
"title": "Project invitations are sent out even if a user role is not selected"
}
],
"numDays": 7,
"originalEstimate": 1.5,
"timeRemaining": [
1.5,
1.5,
1,
1,
1,
1,
0
],
"when": {
"$date": "2014-11-07T10:54:50.019Z"
},
"startDate": {
"$date": "2013-06-24T05:00:00.000Z"
},
"endDate": {
"$date": "2013-06-30T18:59:59.000Z"
}
}
Fetch Card
GET /api/projects/{projectId}/items/{itemId}
Response
{
"_id": {
"$oid": "54744c20c955ca8169c61eef"
},
"cid": 2,
"estimate": {
"value": 8,
"version": 1
},
"isStandaloneTP": false,
"iteration": {
"value": null,
"version": 0
},
"iterationReview": {
"value": "",
"version": 0
},
"order": {
"value": "000000001.0",
"version": 0
},
"owner": {
"value": null,
"version": 0
},
"ownerType": {
"value": null,
"version": 0
},
"project": {
"value": {
"$oid": "54744060c955ca8169c61ee6"
},
"version": 0
},
"state": {
"value": {
"$oid": "54744060c955ca8169c61ee5"
},
"version": 0
},
"summary": {
"value": {
"markdown": "My test card description",
"html": "<p>My test card description</p>\n"
},
"version": 0
},
"taskCounters": {
"value": null,
"version": 0
},
"title": {
"value": "5th Test card",
"version": 0
},
"totalAttachments": {
"value": 0,
"version": 0
},
"totalComments": {
"value": 0,
"version": 0
},
"totalDiscussions": {
"value": 0,
"version": 0
},
"type": {
"value": {
"version": 0
},
"version": 0
},
"version": 1,
"_order": 0
}
Update Card
PUT /api/projects/{projectId}/items/{itemId}
Request
Due to the lack of OAuth2 or a user specific authentication, one needs to provide a valid username that is a member of the project (with write permissions) to be able to update a card.
Include only the attributes you want to update in the payload. We are implementing optimistic lock, so you have to include the current version of each attribute you update. If the version included does not match the current version, then the update will fail, and the response will include current values stored in the system. To force update you set the version to -1.
{
"username":"username_Of_User_Creating_the_card",
"title": {
"value": "5th Test card",
"version": 1
},
"summary": {
"value": {
"markdown": "My test card description",
"html": "<p>My test card description</p>\n"
},
"version": 2
},
"estimate":{
"value": 13,
"version": 6
}
}
Response
{
"_id": {
"$oid": "54744c20c955ca8169c61eef"
},
"version": 177,
"estimate": {
"value": 13,
"version": 7
},
"iteration": {
"value": null,
"version": 0
},
"project": {
"value": {
"$oid": "54744060c955ca8169c61ee6"
},
"version": 0
},
"state": {
"value": {
"$oid": "54744060c955ca8169c61ee5"
},
"version": 0
},
"title": {
"value": "5th Test card",
"version": 2
}
"summary": {
"value": {
"markdown": "My test card description",
"html": "<p>My test card description</p>\n"
},
"version": 3
}
}
Fetch Card Tasks
GET /api/projects/{projectId}/items/{itemId}/tasks
Response
[
{
"_id": {
"$oid": "6000882d5898d474b09b205e"
},
"version": 1,
"cid": 62,
"project": {
"value": {
"$oid": "5f592445507a9824b8ec287f"
},
"version": 0
},
"owner": {
"value": {
"$oid": "600086fe5898d474b09b205c"
},
"version": 0
},
"ownerType": {
"value": null,
"version": 0
},
"title": {
"value": "6th Task",
"version": 0
},
"summary": {
"value": {
"markdown": "My test task description"
},
"version": 0
},
"estimate": {
"value": 5,
"version": 0
},
"type": {
"value": null,
"version": 0
},
"state": {
"value": "todo",
"version": 0
},
"order": {
"value": "000000001.0",
"version": 0
},
"timeEntriesTotal": 0,
"_order": 0
}
]
Create Card Task
POST /api/projects/{projectId}/items/{itemId}/tasks
Request
Due to the lack of OAuth2 or a user specific authentication, one needs to provide a valid username that is a member of the project (with write permissions) to be able to create a new task.
The estimate value is in hours. To add a value in minutes you have to use decimal points (example: 5 minutes = 0.83)
{
"username":"username_Of_User_Creating_the_task",
"title": {
"value": "1st Test task"
},
"summary": {
"value": {
"markdown": "My test task description"
}
},
"estimate":{
"value": 13
}
}
Response
{
"_id": {
"$oid": "60015b87eae07d716cddfee0"
},
"cid": 80,
"version": 0,
"project": {
"value": {
"$oid": "54744060c955ca8169c61ee6"
},
"version": 0
},
"estimate": {
"value": 13,
"version": 0
},
"title": {
"value": "1st Test task",
"version": 0
},
"summary": {
"value": {
"markdown": "My test task description",
"html": "<p>My test task description</p>\n"
},
"version": 0
},
"state": {
"value": "todo",
"version": 0
},
"order": {
"value": "000000001.0",
"version": 0
}
}
In a single api call you can create multiple tasks by including the tasks in an array.
[
{
"username":"username_Of_User_Creating_the_task",
"title": {
"value": "1st Test task",
},
"summary": {
"value": {
"markdown": "My test task description",
}
},
"estimate":{
"value": 13,
}
}
]
The response is an array of the tasks created.
[
{
"_id": {
"$oid": "60015b87eae07d716cddfee0"
},
"cid": 80,
"version": 0,
"project": {
"value": {
"$oid": "54744060c955ca8169c61ee6"
},
"version": 0
},
"estimate": {
"value": 13,
"version": 0
},
"title": {
"value": "1st Test task",
"version": 0
},
"summary": {
"value": {
"markdown": "My test task description",
"html": "<p>My test task description</p>\n"
},
"version": 0
},
"state": {
"value": "todo",
"version": 0
},
"order": {
"value": "000000001.0",
"version": 0
}
}
]
Fetch Task
GET /api/projects/{projectId}/tasks/{taskId}
Response
{
"_id": {
"$oid": "6000882d5898d474b09b205e"
},
"version": 1,
"cid": 62,
"project": {
"value": {
"$oid": "5f592445507a9824b8ec287f"
},
"version": 0
},
"owner": {
"value": {
"$oid": "600086fe5898d474b09b205c"
},
"version": 0
},
"ownerType": {
"value": null,
"version": 0
},
"title": {
"value": "6th Task",
"version": 0
},
"summary": {
"value": {
"markdown": "My test task description"
},
"version": 0
},
"estimate": {
"value": 5,
"version": 0
},
"state": {
"value": "todo",
"version": 0
},
"order": {
"value": "000000001.0",
"version": 0
},
"timeEntriesTotal": 0,
"_order": 0
}
Update Task
PUT /api/projects/{projectId}/tasks/{taskId}
Request
Due to the lack of OAuth2 or a user specific authentication, one needs to provide a valid username that is a member of the project (with write permissions) to be able to update a task.
Include only the attributes you want to update in the payload. We are implementing optimistic lock, so you have to include the current version of each attribute you update. If the version included does not match the current version, then the update will fail and, the response will include current values stored in the system. To force update you set the version to -1.
The estimate value is in hours. To add a value in minutes you have to use decimal points (example: 5 minutes = 0.83)
{
"username":"username_Of_User_Updating_the_task",
"title": {
"value": "5th Test task",
"version": 1
},
"summary": {
"value": {
"markdown": "My test task description",
"html": "<p>My test task description</p>\n"
},
"version": 2
},
"estimate": {
"value": 60,
"version": 6
},
"state": {
"value": "in-progress", //one-of "todo", "in-progress", "done"
"version": 9
}
}
Response
{
"_id": {
"$oid": "54744c20c955ca8169c61eef"
},
"project": {
"value": {
"$oid": "54744060c955ca8169c61ee6"
},
"version": 0
},
"owner": {
"value": {
"$oid": "600086fe5898d474b09b205c"
},
"version": 0
},
"title": {
"value": "5th Test task",
"version": 2
},
"summary": {
"value": {
"markdown": "My test task description",
"html": "<p>My test card description</p>\n"
},
"version": 3
},
"estimate": {
"value": 60,
"version": 7
},
"state": {
"value": "in-progress",
"version": 9
},
"version": 3
}