Formatting
TargetProcess REST API supports XML and JSON response formats. Default format is XML. There are two options to set the response format:
- Define format on the fly via the
formatURL parameter:http://localhost/api/v1/UserStories/35429?format=json http://localhost/api/v1/UserStories/35429?format=xml
- Use HTTP header Accept to specify response format.
For example, to retrieve response in JSON:
GET targetprocess/api/v1/UserStories/ HTTP/1.1 Host: localhost Accept: application/json
Xml format description
All fields except Id and Name are returned as xml elements. Id and Name fields are returned as attributes. If a field is null, the corresponding xml element will have "nil" attribute set to "true".
Xml format uses ISO 8601 for date formatting.
<UserStory Id="376" Name="CRUD operations"> <Description nil="true" /> <CreateDate>2011-09-01T18:20:35</CreateDate> </UserStory>
JSON format description
JSON formatting uses Microsoft AJAX alike format: "\/Date(1198908717056+0300)\/" where the number is again the number of milliseconds since January 1st 1970. Look here for more info.
{
"Id": 376,
"Name": "CRUD operations",
"Description": null,
"CreateDate": "\/Date(1314890435000+0300)\/"
}
JSONP
Starting v.2.22.3 TargetProcess REST API supports JSONP pattern. To return the json padded with your callback, use "callback=functionName" query parameter.
http://localhost/api/v1/UserStories/35429?format=json&callback=parseJson
parseJson({
"Id": 376,
"Name": "CRUD operations",
"Description": null,
"CreateDate": "\/Date(1314890435000+0300)\/"
});
Here is an example with help of jQuery. We extract all projects and show their names.
<script type="text/javascript">
$.getJSON("http://tp/api/v1/projects?&format=json&callback=?", buildProjects);
function buildProjects(data) {
var projectNames = "";
for (i = 0; i < data.Projects.Items.length; i++) {
if (data.Projects.Items[i]) {
projectNames += data.Projects.Items[i].Name;
}
}
alert(projectNames);
}
</script>
Paging
To decrease server load, starting v.2.22.1 all resource collections are returned by pages. By default, only the first 25 items will be returned. You can control the page using 'take' and 'skip' parameters. For example, the following request will return 20 Bugs starting with #11:
http://localhost/targetprocess/api/v1/Bugs?take=20&skip=10
If there are next or previous pages available for the request, the response will contain links to those pages:
Xml format:
<Bugs Prev="http://localhost/targetprocess/api/v1/UserStories?take=10&skip=0"
Next="http://localhost/targetprocess/api/v1/UserStories?take=20&skip=30">
<Bug Id="239" Name="Document with all customers features requests">
...
</Bug>
...
</Bugs>
JSON format:
{
"Prev": "http://localhost/targetprocess/api/v1/UserStories?format=json&take=10&skip=0",
"Next": "http://localhost/targetprocess/api/v1/UserStories?format=json&take=20&skip=30",
"Items": [
{
"Id": 239,
"Name": "Document with all customers features requests",
...
},
...
]
}
If there are no previous or next pages available, there will be no corresponding link in the response:
http://localhost/targetprocess/api/v1/Bugs?take=20
<Bugs Next="http://localhost/targetprocess/api/v1/UserStories?take=20&skip=20"> ... </Bugs>
{
"Next": "http://localhost/targetprocess/api/v1/UserStories?format=json&take=20&skip=30",
"Items": [
...
]
}
You can not have more then 1000 items per request. If you set 'take' parameter greater than 1000, it will be treated as 1000 (including link generation).
Filtering
Starting v.2.22.3 REST API supports filtering by fields and nested fields. To set a requested filter use 'where=condition' query parameter. For example, this request will return all bugs in a "In Progress" state:
http://tp/targetprocess/api/v1/Bugs?where=EntityState.Name eq 'In Progress'
At the moment API supports following filtering operators:
| Operator | Sample |
|---|---|
| Equality | Name eq 'My Name' |
| Not equality | Name ne 'My Name' |
| Greater than | Id gt 5 |
| Greater than or equal | Project.Id gte 5 |
| Less than | CreateDate lt '2011-10-01' |
| Less than or equal | TimeSpent lte 5.0 |
| In list | Id in (155,156) |
| Contains | Name contains 'rest' |
| Is null | Release is null |
| Is not null | Description is not null |
Also you can combine several filtering conditions using operator and:
http://tp/targetprocess/api/v1/Bugs?where=(CreateDate gt '2011-01-01') and (EndDate lt '2011-02-01')
Sorting
You can order the REST API results using any field (simple or nested). Use 'orderby=field' or 'orderbydesc=field' to sort data ascending or descending. For example, this request will return all bugs ordered by creation date (recent bugs on top):
http://tp/targetprocess/api/v1/Bugs?orderByDesc=CreateDate
Partial Response
By default, server returns a full entity with all the Nested Entities. However, you can request an entity with some selected data only. Thus you can reduce traffic, memory and CPU usage.
Includes
You can explicitly specify attributes that you want to have in the response. It is possible to include Fields, Collections and Nested Entities (with inner Fields). The general format is:
http://localhost/targetprocess/api/v1/{Entities}/?include=[Field1,Field2,Collection1,NestedEntity[Field3]]
For example, let's request Bugs with Names, Description, Attachments and Iteration Name
http://localhost/targetprocess/api/v1/Bugs/?include=[Name, Description, Attachments, Iteration[Name]]
<Bugs>
<Bug Id="214" Name="Javascript error (null reference) on form validation">
<Description>Some steps</Description>
<Iteration Id="44" Name="Sprint #2.2"/>
<Attachments/>
</Bug>
<Bug Id="213" Name="Typos on Contacts page">
<Description nil="true"/>
<Iteration Id="44" Name="Sprint #2.2"/>
<Attachments/>
</Bug>
</Bugs>
Entity Id and Nested Entity Id are always included into response. Also if you request Nested Entity without parameters, it will contain Id and Name.
http://localhost/targetprocess/api/v1/Bugs/?include=[Iteration]
<Bugs>
<Bug Id="214">
<Iteration Id="44" Name="Sprint #2.2"/>
</Bug>
<Bug Id="213">
<Iteration Id="44" Name="Sprint #2.2"/>
</Bug>
</Bugs>
http://localhost/targetprocess/api/v1/Bugs/?include=[Iteration[Velocity]]
<Bugs>
<Bug>
<Iteration Id="44">
<Velocity>99.0000</Velocity>
</Iteration>
</Bug>
<Bug Id="213">
<Iteration Id="44">
<Velocity>99.0000</Velocity>
</Iteration>
</Bug
</Bugs>
You can use the same rule for Nested Collections.
http://localhost/targetprocess/api/v1/UserStories/?include=[Tasks[Name,Description,Effort]]
<UserStories Next="http://localhost/TargetProcess/api/v1/UserStories/?include=[Tasks[Name,Description,Effort]]&take=25&skip=25">
<UserStory Id="196">
<Tasks>
<Task Id="197" Name="Design calendar">
<Description nil="true"/>
<Effort>11.0000</Effort>
</Task>
<Task Id="198" Name="Implement calendar">
<Description nil="true"/>
<Effort>10.0000</Effort>
</Task>
</Tasks>
</UserStory>
<UserStory Id="192">
<Tasks/>
</UserStory>
</UserStories>
Excludes
If you want to exclude some attributes from Entity response, you can use exclude parameter. For example, you don't want to have the Description field in the response.
http://localhost/targetprocess/api/v1/UserStories/?exclude=[Description]
It is not possible to use includes and excludes simultaneously in a single request. For example, this request exclude=[Name]&include=[Description] returns 400 error.
Append fields
You can get more information about Entity in a single request. For example, you can retrieve Tasks count for User Story and Bugs count for User Story.
http://localhost/targetprocess/api/v1/UserStories/?append=[Bugs-Count,Tasks-Count]
<UserStories Next="http://localhost/TargetProcess/api/v1/UserStories/?include=[Name, Effort, Description]&take=25&skip=25"> <UserStory Id="196" Name="Set Due Date"> <Bugs-Count>0</Bugs-Count> <Tasks-Count>3</Tasks-Count> </UserStory> <UserStory Id="192" Name="Make Task Important"> <Bugs-Count>10</Bugs-Count> <Tasks-Count>0</Tasks-Count> </UserStory> </UserStories>
You can calculate some metrics in inner Collections. For example, calculate average effort of all the Bugs related to User Story:
http://localhost/api/v1/UserStories/34256?include=[Bugs-Effort-Avg]
<UserStories Next="http://localhost/TargetProcess/api/v1/UserStories/?include=[Tasks[Name,Description,Effort]]&take=25&skip=25">
<UserStory Id="196">
<Bugs-Effort-Avg nil="true"/>
</UserStory>
<UserStory Id="192">
<Bugs-Effort-Avg>12.5<Bugs-Effort-Avg/>
</UserStory>
</UserStories>
Other available calculations are Sum, Min and Max:
http://localhost/api/v1/UserStories/34256?include=[Bugs-Effort-Sum] http://localhost/api/v1/UserStories/34256?include=[Bugs-Effort-Min] http://localhost/api/v1/UserStories/34256?include=[Bugs-Effort-Max]
HTTP Status Codes
TargetProcess REST API returns the following status codes
| Code | Description |
|---|---|
| 200 | Success. Request was handled correctly. |
| 401 | Unauthorized. Wrong or missed credentials. |
| 400 | Bad format. Incorrect parameter or query string. |
| 403 | Forbidden. A user has insufficient rights to perform an action. |
| 404 | Requested Entity not found. |
| 500 | Internal server error. TargetProcess messed up. |
| 501 | Not implemented. The requested action is either not supported or not implemented yet. |
Response contains information about error for 4xx or 5xx HTTP status code.
<Error>
<Status>BadRequest</Status>
<Message>Invalid include field 'Nam'. It isn't defined in 'Tp.Integration.Services.Rest.Dto.UserStoryField'</Message>
<Type>Tp.Integration.Rest.Exceptions.BadRequestException</Type>
<StackTrace> at Tp.Integration.Rest.Web.Controllers.ResourcesController.GetAllInternal[TService,TResource](String format, String include, String exclude, String append, String acid, EndPoint`2 endpoint)
at Tp.Integration.Rest.Web.Controllers.UserStoriesController.GetAll(String format, String include, String exclude, String append, String acid)
at lambda_method(ExecutionScope , ControllerBase , Object[] )
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) in C:\Users\truhtanov\Downloads\mvc2-rtm-sources\mvc2-rtm-sources\src\SystemWebMvc\Mvc\ReflectedActionDescriptor.cs:line 72
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) in C:\Users\truhtanov\Downloads\mvc2-rtm-sources\mvc2-rtm-sources\src\SystemWebMvc\Mvc\ControllerActionInvoker.cs:line 179
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassd.<InvokeActionMethodWithFilters>b__a() in C:\Users\truhtanov\Downloads\mvc2-rtm-sources\mvc2-rtm-sources\src\SystemWebMvc\Mvc\ControllerActionInvoker.cs:line 220
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) in C:\Users\truhtanov\Downloads\mvc2-rtm-sources\mvc2-rtm-sources\src\SystemWebMvc\Mvc\ControllerActionInvoker.cs:line 208
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) in C:\Users\truhtanov\Downloads\mvc2-rtm-sources\mvc2-rtm-sources\src\SystemWebMvc\Mvc\ControllerActionInvoker.cs:line 208
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) in C:\Users\truhtanov\Downloads\mvc2-rtm-sources\mvc2-rtm-sources\src\SystemWebMvc\Mvc\ControllerActionInvoker.cs:line 208
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) in C:\Users\truhtanov\Downloads\mvc2-rtm-sources\mvc2-rtm-sources\src\SystemWebMvc\Mvc\ControllerActionInvoker.cs:line 227
at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) in C:\Users\truhtanov\Downloads\mvc2-rtm-sources\mvc2-rtm-sources\src\SystemWebMvc\Mvc\ControllerActionInvoker.cs:line 153</StackTrace>
<Error>
<Message>Invalid include field 'Nam'. It isn't defined in 'Tp.Integration.Services.Rest.Dto.UserStoryField'</Message>
<Type>Tp.Integration.Rest.Model.Exceptions.FieldNotFoundException</Type>
<StackTrace> at Tp.Integration.Rest.Web.QueryStrategies.IncludeStrategy.<GetFields>d__0.MoveNext()
at System.Linq.Enumerable.<ConcatIterator>d__71`1.MoveNext()
at Tp.BusinessObjects.Services.Reports.FieldsSeparator.NormalizeResourceFields(IEnumerable`1 fields) in d:\src\trunk\Code\Main\Tp.Integration.Rest\Reports\FieldsSeparator.cs:line 74
at Tp.BusinessObjects.Services.Reports.FieldsSeparator..ctor(IResourceField self, IEnumerable`1 fields) in d:\src\trunk\Code\Main\Tp.Integration.Rest\Reports\FieldsSeparator.cs:line 25
at Tp.BusinessObjects.Services.Reports.ExpandableQueryBuilder..ctor(IResourceField resourceField, ProcessInfoDto process, IEnumerable`1 fields, IEnumerable`1 criterias) in d:\src\trunk\Code\Main\Tp.Integration.Rest\Reports\ExpandableQueryBuilder.cs:line 30
at Tp.BusinessObjects.Services.Reports.ResourceQuery.GetResources(ContextDto singleProcessContext) in d:\src\trunk\Code\Main\Tp.Integration.Rest\Reports\ResourceQuery.cs:line 44
at Tp.BusinessObjects.Services.Reports.ResourceQuery.Read(ContextDto context) in d:\src\trunk\Code\Main\Tp.Integration.Rest\Reports\ResourceQuery.cs:line 36
at Tp.BusinessObjects.Services.RestService.Tp.Integration.Services.Rest.IRestService.Read(ContextDto context, IEnumerable`1 fields, IEnumerable`1 criteria) in d:\src\trunk\Code\Main\Tp.Integration.Rest\RestService.cs:line 46
at Tp.BusinessObjects.Services.RestService`1.Read(ContextDto context, IEnumerable`1 fields, IEnumerable`1 criteria) in d:\src\trunk\Code\Main\Tp.Integration.Rest\RestService.cs:line 147
at Tp.Integration.Rest.Web.EndPoint`2.GetAll(String acid, String include, String exclude, String append)
at Tp.Integration.Rest.Web.Controllers.ResourcesController.GetAllInternal[TService,TResource](String format, String include, String exclude, String append, String acid, EndPoint`2 endpoint)</StackTrace>
</Error>
</Error>



