Security
To make any calls to the API, you’ll have to provide your username and password via an HTTP Basic authentication header. Wikipedia will tell you
everything you need to know about what the Authorization header needs to look like.
Additionally, each request you make needs to be signed with your personal API token. This prevents someone from intercepting a request you’ve made
to the API and changing the parameters of the request unless they know your secret API token, so keep it safe.
You can find your API token on
the Profile page of your DoneDone account.
Follow these steps below to sign your requests.
- Start with the URL you are requesting exactly as you sent it – case sensitive and inclusive of query parameters.
If the request you’re making is a GET request, go to step 3. Otherwise continue with step 2.
- If your request is a POST or a PUT, take the parameter keys you’re sending with your request and sort them alphabetically.
Do not include the file data or keys if you’re uploading any files with your request.
- Go through this alphabetical list of keys and append the lowercased parameter name to the value sent with this parameter with no delimiters.
- Append all of these key-value pairs to the string you had at the end of step 1 (the URL you’ve requested).
- Sign your request using HMAC-SHA1 using your API token as the key and then Base64 encode this signature.
- Send this signature in an HTTP header called X-DoneDone-Signature with your request.
An Example
If you were making a GET request to:
- https://wearemammoth.mydonedone.com/issuetracker/api/projects
- using the username “test”
- a password of “password”
- and an API token 5F4CAC0C16977B21F4CE3766D913FE74
your request header should have the following headers in it:
- X-DoneDone-Signature: KwEBfDBdNN+tM5bzyMKfR5dCz4k=
- Authorization: Basic dGVzdCUzQXBhc3N3b3Jk
Here’s the code we’re using in C# to calculate a signature, given a key.
/// <summary>
/// calculates the hmac shal signature of a string given a key
/// </summary>
/// the string you are hashing
/// the key
/// the hashed value
public static string CalculateHMACSHA1(this string s, string key)
{
using (HMACSHA1 hmac = new HMACSHA1(System.Text.Encoding.UTF8.GetBytes(key), true))
{
return Convert.ToBase64String(hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(s)));
}
}
All requests are made to: https://youraccountdomain.mydonedone.com/IssueTracker/API/MethodName/{parameters}
Methods
Get all Projects you have access to with the API enabled
URL: [GET] /Projects/{load_with_issues}
Note: The parameter load_with_issues is optional. If provided, it must be ‘true’ or ‘false’ (without single quotes).
Passing true will deep load all of the projects as well as all of their active issues. It is a potentially heavy call, so be careful using it.
[
{
"ID":123,
"Name":"First Project",
"Issues": null
},
{
"ID":456,
"Name":"Proj 2",
"Issues": null
}
]
Get all Priority Levels. You must pass the ID of the priority level you need when creating or editing issues.
URL: [GET] /PriorityLevels
[
{
"ID":1,
"Value":"Low"
},
{
"ID":2,
"Value":"Medium"
},
{
"ID":3,
"Value":"High"
},
{
"ID":4,
"Value":"Critical"
}
]
Get all People in a Project. You must pass the ID of the person when assigning or reassigning issues.
URL: [GET] /PeopleInProject/{project_id}
[
{
"ID":1,
"Value":"Ka Wai Cheung"
},
{
"ID":2,
"Value":"Mustafa Shabib"
}
]
Get all Issues in a Project
URL: [GET] /IssuesInProject/{project_id}
[
{
"PriorityLevel":"Low",
"State":"Open",
"LastUpdatedDate":"\/Date(1314996892513)\/",
"LastViewedDate":null,
"CreateDate":"\/Date(1314996892513)\/",
"Title":"Test for API",
"OrderNumber":536,
"ProjectID":26,
"Tester":{
"ID":157,
"Value":"Tester's Name"
},
"Resolver":{
"ID":63,
"Value":"Resolver's Name"
},
"Creator":{
"ID":26,
"Value":"Ka Wai Cheung"
}
}
]
Does an Issue Exist?
URL: [GET] /DoesIssueExist/{project_id}/{issue_id}
{
"IssueExists": true
}
List of Allowed Statuses An Issue Can Transition To. You must pass the ID of the issue status when editing an issue.
URL: [GET] /PotentialStatusesForIssue/{project_id}/{issue_id}
Note: If you are an admin, you’ll get both all allowed statuses as well as ALL statuses back from the server
{
"PotentiallyAllowedStatusesForIssue":[
{
"ID":13,
"Value":"In progress"
},
{
"ID":14,
"Value":"Not an issue"
},
{
"ID":15,
"Value":"Not reproducible"
},
{
"ID":16,
"Value":"Missing information"
},
{
"ID":19,
"Value":"Ready for retest"
},
{
"ID":21,
"Value":"Closed"
}
],
"AllStatusesSinceYouAreAnAdmin":[
{
"ID":12,
"Value":"Open"
},
{
"ID":13,
"Value":"In progress"
},
{
"ID":14,
"Value":"Not an issue"
},
{
"ID":15,
"Value":"Not reproducible"
},
{
"ID":16,
"Value":"Missing information"
},
{
"ID":17,
"Value":"Pushed back"
},
{
"ID":18,
"Value":"Ready for next release"
},
{
"ID":19,
"Value":"Ready for retest"
},
{
"ID":20,
"Value":"Fix not confirmed"
},
{
"ID":21,
"Value":"Closed"
}
]
}
Issue Details
URL: [GET] /Issue/{project_id}/{issue_id}
Note: You can use this to check if an issue exists as well, since it will return a 404 if the issue does not exist.
{
"Title":"Test for API",
"ProjectTitle":"First Project",
"ProjectID":123,
"OrderNumber":456,
"Description":"This is a description in MARKDOWN format.",
"PriorityLevel":"Low",
"PriorityLevelID":1,
"IssueState":"Open",
"IssueStateID":12,
"Resolver":{
"ID":3,
"Value":"Ka Wai Cheung"
},
"Tester":{
"ID":2,
"Value":"Mustafa Shabib"
},
"Creator":{
"ID":1,
"Value":"Craig Bryant"
},
"Watchers":[
{
"ID":4,
"Value":"Michael Sanders"
},
{
"ID":26,
"Value":"Ka Wai Cheung"
}
],
"Tags":[
{
"ID": 122,
"Value": "api"
}
],
"UserRoleIDs":[
3,
4,
5
],
"CompaniesAndPeopleOnIssue":[
{
"ID":1,
"Name":"We Are Mammoth",
"People":[
{
"ID":1,
"FirstName":"Mustafa",
"LastName":"Shabib",
"AccountRoleID":1,
"EmailAddress":"mustafa.shabib@wearemammoth.com"
}
]
},
{
"ID":102,
"Name":"Chicago Cubs",
"People":[
{
"ID":162,
"FirstName":"Andre",
"LastName":"Dawson",
"AccountRoleID":1,
"EmailAddress":null
}
]
}
],
"TesterResolverAndWatcherIDs":[
2,
3,
4,
26
],
"Attachments":[
{
"ID":0,
"FileUpload":"http://c3362733.r33.cf0.rackcdn.com/7a72328a-00f2-4985-80a8-6f9da3043f31_smalla.jpg",
"Bytes":162597.00,
"RelatedActionableItemHistoryID":58036,
"RelatedActionableItemHistory":null
}
],
"Histories":[
{
"ID":57406,
"AvatarURL":"http://c3363003.r3.cf0.rackcdn.com/e48bd3f6-d9be-457c-8cf3-901e99a8b8cf_kc.jpg",
"CreateDate":"\/Date(1314996892513)\/",
"Action":"Craig Bryant created the issue.",
"Description":"Assigned to *Ka Wai Cheung* as the resolver, and to *Mustafa Shabib* as the tester. This issue is marked as *Low*.",
"HistoryType":11,
"Attachments":[
]
}
]
}
People that this issue can be reassigned to
URL: [GET] /PeopleForIssueAssignment/{project_id}/{issue_id}
[
{
"ID":162,
"Value":"Andre Dawson"
},
{
"ID":22,
"Value":"Anthony Bruno"
}
]
Create an Issue
URL: [POST] /Issue/{project_id}
Post Data (parameter name, type, required or optional):
- title: string, required.
- description: string, optional.
- tags: comma-delimited string, optional.
- priority_level_id: short, required. Get a list of valid priority levels from the method documented above.
- resolver_id: int, required. Get a list of people on this project from the method documented above.
- tester_id: int, required. Get a list of people on this project from the method documented above.
- watcher_ids: comma delimited string of people’s ids. Optional.
Files can be attached by posting the form with the content-type multipart/form-data.
{
"IssueID":128,
"IssueURL":"http://wearemammoth.mydonedone.com/issuetracker/projects/77/issues/128",
"SuccesfullyAttachedFiles": "true"
}
Updating an Issue
URL: [PUT] /issue/{project_id}/{issue_id}
Using this method you can update the tags, title, description, priority level, state (open, in progress, etc.), resolver, or tester of an issue.
If you provide any parameters then the value you pass will be used to update the issue. If you wish to keep the value that’s already on an issue,
then do not provide the parameter in your PUT data. Any value you provide, including tags, will overwrite the existing values on the issue.
If you wish to retain the tags for an issue and update it by adding one new tag, then you’ll have to provide all of the existing tags as well as the new
tag in your tags_list parameter, for example.
Put Data (parameter name, type):
- title: string, optional.
- description: string, optional.
- tags: comma-delimited string, optional.
- priority_level_id: short, optional. Get a list of valid priority levels from the method documented above.
- state_id: short, Optional. Get a list of valid states that this issue can transition to from the method documented above.
- resolver_id: int. Get a list of people on this project from the method documented above.
- tester_id: int. Get a list of people on this project from the method documented above.
{
"IssueURL":"http://wearemammoth.mydonedone.com/issuetracker/projects/77/issues/129"
}
Client Libraries
DoneDone’s client libraries provide an easy-to-use interface for accessing the API calls.
We currently offer client libraries in three different languages: C#, PHP, and Python. To use these libraries with a DoneDone project, you will
need to enable the API option under the Project Settings page.
You can download the DoneDone client libraries from GitHub here.
Each of the libraries provides a generic method to access DoneDone’s IssueTracker API and shorthands to call the
corresponding API methods directly. The result will be a JSON string returned by the server.
C#
Download the C# client library.
Initializing
using DoneDone;
var domain = "YOUR_COMPANY_DOMAIN"; /* e.g. wearemammoth */
var token = "YOUR_API_TOKEN";
var username = "YOUR_USERNAME";
var password = "YOUR_PASSWORD";
var issueTracker = new DoneDone.IssueTracker(domain, token, username, password);
Calling the API
issueTracker.API("GetProjects");
/* This will get all your projects with the API enabled. */
issueTracker.GetProjects();
/* This is the same as the above. */
PHP
Download the PHP client library.
Initializing
require_once "DoneDone.php";
$domain = "YOUR_COMPANY_DOMAIN"; /* e.g. wearemammoth */
$token = "YOUR_API_TOKEN";
$username = "YOUR_USERNAME";
$password = "YOUR_PASSWORD";
$issueTracker = new IssueTracker($domain, $token, $username, $password);
Calling the API
$issueTracker->API("GetProjects");
/* This will get all your projects with the API enabled. */
$issueTracker->getProjects();
/* This is the same as the above. */
Python
Download the Python client library or a sample use case.
Initializing
from DoneDone import IssueTracker
domain = "YOUR_COMPANY_DOMAIN" #e.g. wearemammoth
token = "YOUR_API_TOKEN"
username = "YOUR_USERNAME"
password = "YOUR_PASSWORD"
issueTracker = IssueTracker(domain, token, username, password)
Calling the API
issueTracker.API("GetProjects")
#This will get all your projects with the API enabled.
issueTracker.getProjects()
#This is the same as the above.
Responses
All responses will contain JSON-encoded data, with the response Content-Type set to application/json.
Successes
200 – OK – the requested data or a success message with relevant details on POST and PUT requests
will be provided as JSON encoded data described above.
Errors
Any request may respond with the following errors, each of which also provides some additional details (if any)
as a simple JSON object with a message.
400 – Invalid – you are missing a required parameter or sending an invalid value for a parameter (an integer where a short was expected, for example). Check what you’re sending to the API compared to what’s expected in the documentation.
401 – Unauthorized – you need to provide correct credentials via the basic authentication header
403 – Forbidden – you’re authenticated, but you aren’t authorized to perform the request
404 – Not Found – We can’t find whatever you asked for (bad method, no issue found, no project found, etc.)
409 – Conflict – You’ve made too many requests to the same resource. You can only request the same URL from the same IP address once every five seconds. We may adjust this rate limit in the future.
500 – Internal error – We did something wrong. Let us know on our support page.
Example Error Response
Here’s an example 404 response when attempting to update an issue that does not exist.
< HTTP/1.1 404 Not Found
< Server: ASP.NET Development Server/9.0.0.0
< Date: Mon, 26 Sep 2011 18:38:14 GMT
< Cache-Control: private
< Content-Type: application/json; charset=utf-8
< Content-Length: 26
< Connection: Close
<
{ "Message": "Not found."}