Developer’s API

Enabling the API

You’ll need to enable the API for any projects you’d like to use with the API.

How to enable API

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.

  1. 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.
  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.
  3. Go through this alphabetical list of keys and append the lowercased parameter name to the value sent with this parameter with no delimiters.
  4. Append all of these key-value pairs to the string you had at the end of step 1 (the URL you’ve requested).
  5. Sign your request using HMAC-SHA1 using your API token as the key and then Base64 encode this signature.
  6. 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"
						}
						

Create a Comment

URL: [POST] /Comment/{project_id}/{issue_id}

Post Data (parameter name, type, required or optional):

  • comment: string, required.
  • people_to_cc_ids: comma delimited string of people’s ids. Optional.

Files can be attached by posting the form with the content-type multipart/form-data.

						{
						   "CommentURL":"http://wearemammoth.mydonedone.com/issuetracker/projects/77/issues/129#history-58182",
						   "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."}