Introduction



Overview

===

The following are REST API cookbook recipes for users and partners creating integrations using The Jama Connect REST API. They intended to answer frequently asked questions from users attempting to create Jama integrations and to encourage best practices in Jama API usage.


THIS IS A LIVING DOCUMENT:

If you or your team have suggestions that should be included in this documentation, Jama is all ears. Talk to us and let us know what pain-points you are experiencing so we can work best practices into the flow.

Cookbook Topics



Jama's Throttling Limits for the API

Jama reserves the right to throttle API usage to ensure a satisfying experience for all our customers. Because REST clients may make unlimited requests, we must protect our systems from slow performance due to these types of calls. We will describe our throttling techniques below.


When will my REST API requests be throttled?

When you exceed 15-requests per seconds and you exceed the 750-request burst limit. Afterwards you will receive 429 response codes.

These throttling rates should be considered temporary as we plan to make changes as our architecture evolves. You may not experience these throttling rates but be prepared to handle them. Stay tuned for more updates.



Efficiently Sync data into and out of Jama through the API

This guide is not intended to provide exact implementation but offer guidance and some best practices for the Jama side of your integration.

Searching for Relevant Data and Detecting the Latest Changes

When integrating with Jama it is important to try to be able to filter on precisely what you are trying to sync without pulling in more data than you need.


Using Abstract Items for Search

Abstract items are the best way to create filters on the fly in our API. You will not be able to create as advanced queries as the filter option, but you do not depend on any filter being set up beforehand. Check out Cookbook section Searching with the Abstract items endpoint for details on how you can select the items you want to be synced from Jama.

Once you have defined the query you want to use, you should be able to page through all the results in an initial import. After that you may use the 'lastActivityDate' query parameter with /abstractitems to find what has changed since your last sync window. You can learn more about the what activities update the last activity date in cookbook section What triggers the Last Activity Date?.


Pros:

· On the fly filter that can be dynamically changed
· Set up requires no interaction in the UI


Cons:

· Paging may not be reliable with real-time data due to the sorting and potential changes in the data between requests.


Using Filters for Search

In Jama's UI you can create advanced filters to query with. This may be a better solution than abstract items if you require more specific items than what abstract items offers. Once you have saved your filter, you may view the results of the filter in the API. Just like with abstract items, you can page through all the results first for your initial sync, and then you can use the lastActivityDate query parameter on the results the same way you would in abstract items. This will allow you to see only what has changed recently so you know what needs to be updated.


Pros:

· Advanced filtering allows for nested AND / OR groupings. You may filter on an items specific location within a project.


Cons:

· You must create the filter in the UI and you cannot update it from the UI.
· Paging may not be reliable with real-time data due to the sorting and potential changes in the data between requests.


Using Activities to Detect Changes

An alternative to using last activity date and filters, you can use the activities endpoint to page through a log of changes made. You will not be able to have the same level of filtering, but you will be able to see events in the order that they happen without missing anything. You will have to use abstract items for your initial sync, but after that you should be able to follow the logs in activities to track changes.


Pros:

· Append only log that is much easier to keep track of changes. No tricky pagination problems with the real-time data
· You can get more detailed information about what has changed.


Cons:

· Only basic filtering, project and item type
· Endpoint lacks documentation and has confusing model.
· Must unwrap batch events


Detecting Comments added to Relevant Items

Last activity date does update when a comment is added directly to an item. For now, you must check for any new comments off the /items/id/comments endpoint.


What is this Realtime Paging Issue?

If you are sort items by its last activity date, you may see items change order when they are updated between your requests. We do not have a good solution for this yet except for using the activities endpoint.


What is the Lagging Index Issue?

An Items last activity date is updated at the time it is committed to the database. There is a small but non-zero amount of time between when then and when you can read the item from the REST API. This means you may not see an item show up in the results when you sort by last activity date. Consider giving yourself a little buffer so that your sync intervals overlap slightly, maybe 5 seconds.


Detecting Changes by Your Integration

You should always consider the modifiedBy attribute on items when reading for changes. If the modifiedBy is from your syncing integration user, that is a strong signal that you do not need to read the item for more changes.


Reading Data From the API

When you have detected that an Item has changed, you will naturally want to download the data and sync it to the other system. Ideally you should be able to the information you need when pulling for changes. If you are using /filters or /abstractitems, you should utilize the includes parameter to download as much as you can without having to make extra calls. You should determine what fields you are interested in so that you can include them on every request. Read more about the includes feature on the Jama developer portal. Basically, it allows you to retrieve all referenced objects on an item, so you do not have to pull for more information in another call.


Downloading Attachments from Rich Text Fields

Jama's rich text editor lets user add images and other attachments to the rich text content. This process is stream lined and does not necessarily work the same way as the attachments widget. When you read the content of a rich text field, you may come across an image or link that looks like this:

https://{jama-base-url}/attachment/65/someImage.png

REST authentication methods don't work for these paths and you must use a work around in order to download the image. You can download the image with our /files endpoint like so:

GET https://{jama-base-url}/rest/v1/files?url=https://{jama-base-url}/attachment/65/someImage.png
* With URL encoding

Writing to Jama with the API

Items can be updated through the API. If the item is locked by someone else, you will have to unlock it or wait for the other user to unlock it. You may also lock an item to prevent others from updating the item while you sync. However, you probably want to make changes as quickly as possible without locking the item for a very long time. We provide two methods for updating an Item, PATCH and PUT.

With PUT, you must provide the entire contents of the item. If a writable field is omitted, the API will assume you want to remove the data from that field. Another problem is that you need to take extra care making sure you have the latest version of the item so that you do not overwrite it with old data that you did not intend to change. To verify that you are updating the item exactly how you expect, it is recommended you follow these steps:

Lock the item

PUT {jama-base-url}/rest/v1/items/{itemId}
{ "locked" : true }

Now get the most recent version of the item.

GET {jama-base-url/rest/v1/items/{itemId}

Copy the "data" object from that response and apply the changes you would like to make using that.

Now use PUT to update the item's content. Note, you cannot update read-only fields. However, if your value matches the existing value on the item, the API will still accept your request. If you supply a read only field value that is different than the existing value, you will get a 400 error.

PUT {jama-base-url}/rest/v1/items{itemId}
{ item payload }

Now unlock the item.

PUT {jama-base-url}/rest/v1/items/{itemId}
{ "locked" : false }

You may choose to not lock the item before using PUT. This is very reasonable because the locking increases the number of requests used to update an Item. However, locking the item does ensure you do not unintentionally overwrite data that has been changes since you retrieved the content of the item.

A better method for updating items is to use PATCH because you do not need to lock the item and get the latest state of the item to make an update without fear of overwriting recent changes. Instead, you will be able to specify exactly which fields you would like to update without affecting anything else in the item. For example, you can update the name and description of an item like this.

PATCH {jama-base-url}/rest/v1/items/{itemId}
[
{
"op": "replace",
"path": "/fields/name",
"value": "Updated Name"
},
{
"op": "replace",
"path": "/fields/description",
"value": "Updated Description"
}
]

Please read more about PATCH here on the Dev channel.


Updatable fields only by API

In your item type configuration, you may specify a field to be read only. When you do this an option will appear to make it editable for the API. This allows you to create fields specifically for your integration and ensures no one in the UI will accidentally edit the value but through the API, you will be able to update the value. If you would like to configure a field like this, edit your item type in the UI Admin screen, and configure the field to be "Read Only" and "Allow API Overwrite".


Updating Test plans, Test Cycles, and Test runs

Test center's API is a little different from your project tree type items. Test Center is built on a work flow that the API is required to follow at the moment. If you need to sync test center items, please refer to cookbook section: '
Executing Tests through the Jama REST API
'


How to update an item

You may use PUT or PATCH. PATCH allows you to update an item without providing the whole context, its more 'atomic'. See Developer Portal


Adding/removing Relationships

Adding and removing relationships should be straight forward with our API. Some project may be configured with relationship rules that you must follow.

To create a relationship, you may make a call like this:

POST {jama-base-url}/rest/v1/relationships
{
"fromItem": 1,
"toItem": 2,
"relationshipType": 12
}

To remove a relationship, you must know the relationship ID. If you know one of the related items, you may find the relationship id with the following methods:

GET {jama-base-url}/rest/v1/abstractitems/{id}/upstreamrelationships
GET {jama-base-url}/rest/v1/abstractitems/{id}/downstreamrelationships


And then to delete the relationship, you may use DELETE:

DELETE {jama-base-url}/rest/v1/relationships/{relationshipId}

You may also call PUT on the relationship if you intend to update the relationship's toItem, fromItem, or relationshipType.


Creating Attachments

Attachments are currently a little more complicated that it should be in the API. Please follow the documentation provided in cookbook sections REST Attachments and Attachments Attachments Attachments!


Creating Comments

If you need to create a comment, use the POST /rest/v1/comments endpoint. You will be able to specify a project or item for the comment location. You may also create a reply to a comment with the inReplyTo field. Just use the ID of the comment you would like to reply to.


Moving an Item

You can move items around in a project with the REST API. You must use the PUT /rest/v1/items/{id}/location endpoint. This endpoint allows you to set the parent of the item, weather it is the project root, or some other item. You will not be able to specify the order the item is placed near its siblings, it will always be placed in the last position. There is no location for test plans, test cycles, or test runs so you cannot update their location.


Links and Tags

Links and Tags may be configured to be added to an item type. There are specific endpoints for each of these item facets. You can GET, PUT, POST, and DELETE tags and links with the /tags and /links endpoints off the item (e.g. /rest/v1/items/{id}/tags or /rest/v1/testplans/{id}/links).



Executing Tests through the Jama REST API

In Jama Connect, there is a flow for executing test cases through the API. This guide will give you an overview of the testing-related objects in Jama Connect and show you the API calls needed to take a test all the way through execution. Some examples will be given from some of our own implementations at Jama.


Getting Familiar with Jama Connect Test Center Objects and Concepts


There are some core objects and concepts to have in mind when working with the Test Center.


Test Case Item


A Test Case Item is like a regular item in Jama, with extra fields (such as steps) and capabilities (it can be executed). Test Cases are created inside Projects just like items, independent of Test Plans. They are also versioned like other items.


Test Run Items


A Test Run Item can be thought of as an execution instance of a Test Case Item. They are created by the system when a Test Cycle is created inside a Test Plan, and they are updated with a status and actual results when executed. A Test Case could have many Test Runs associated with it. These cannot be created directly; this is the reason there is no POST in the /testruns REST endpoint.


Test Plans


A Test Plan is a collection of Test Cases grouped into Groups for organization and Cycles for execution. Test Plans can be created directly.


Test Groups


Test Groups are a grouping of Test Cases inside a Test Plan. They have no direct impact on the way Test Cases are executed; they exist mostly to allow users to group Test Cases into some sort of meaningful sections. For instance, a Test Plan could have groups based on functional breakdowns like "Tree Operations", "Items", etc. Although they are not pertinent to execution, each Test Plan must have at least one Test Group in which to place tests. Test Plans are created with a group called "Default Test Group" which can be used or replaced with custom groups.


Test Cycles


Test Cycles are a collection of Test Run Items that correspond to a particular execution of a Test Plan. For example, you could have a Test Cycle for each release candidate build, or Test Cycles for different browsers, depending on what makes sense for your testing. This terminology may be a bit confusing at first when coming from other test management systems, but the thing to keep in mind is that a "Test Run" is a single item, and a "Test Cycle" is a collection of Test Runs that have been run together at the same time for the same organizational purpose.

When a Test Cycle is created, all Test Case Items in that Test Plan have corresponding Test Run Items created in the system for that Test Cycle. Accordingly, a Test Cycle must be created before any Test Case can be executed. Test Cycles cannot be created independently of a Test Plan (there is no POST in the /testcycles endpoint).

An Example: These concepts as written definitions are a bit tricky, so here is a bit of a rundown on how we test internally:

We have a master regression library with hundreds of
Test Case Items
that we can test. At the time of each release regression, we create a few different
Test Plans
based on different configurations of the product, in our case, "Release 8.20 - Hosted", "Release 8.20 - Clients", "Release 8.20 - Server & Database". Inside those Test Plans, we add all, or a subset, of the Test Cases in the regression library, grouped by hierarchy, which, in our case, corresponds to areas of the product like "Stream" and "Projects". To execute these tests, we create one or more
Test Cycles
in the Test Plan. The "Release 8.20 - Clients" plan, for instance, tests different browsers, so there are cycles like "MacOS Chrome", "Windows Firefox", "Internet Explorer", etc.

Much of our regression library is automated, and our automation tooling executes, and updates results via the API using methods similar (but with much more wrapping) to what will be outlined below.

The Process

This process assumes you already have created Test Case Items that you want to execute. If you are only updating existing executions, you may need to skip further down in the guide.


Creating a Test Plan


First, a Test Plan must be created. If you are planning to use an existing Test Plan that has already been created (using the API or UI), you can skip this section.

POST
/testplans
with a payload like:

{

"project": 43,

"fields": {

"name": "Connect Plan 1"

}

}


project
is the API ID of the project where the Test Plan will be created


name
is the only required field in the payload

If successful, you will get a response like:

{
"meta": {
"status": "Created",
"timestamp": "2018-06-07T18:46:54.094+0000",
"location": "https://yourjama.jamasoftware.net/rest/latest/testplans/20494",
"id": 20494
}
}

You will need the
id
for further operations.


Adding Test Cases to a Test Plan


Test Cases are organized in Test Plans by groups. These groups are only for classification and bear no bearing on the way that Test Cases are executed. However, test cases

must
be added to a Group in the Test Plan; they cannot be added to a Test Plan directly. You can either use the "Default Test Group" present in every Test Plan, or create new groups.


To find the default group:

GET
/testplans/{testPlanId}/testgroups


where {testPlanId} is the API ID of the existing test plan, (from above, 20494)

If successful, you will get a response like:

{
"meta": {
"status": "OK",
"timestamp": "2018-06-07T19:16:01.311+0000",
"pageInfo": {
"startIndex": 0,
"resultCount": 1,
"totalResults": 1
}
},
"links": {},
"data": [
{
"id": 157,
"name": "Default Test Group"
}
]
}

In a brand-new Test Plan, "Default Test Group" will be the only group. You will need its
id
if you plan to add test cases to it, or:


To add your own group:

POST
/testplans/{testPlanId}/testgroups
with a payload like:

where {testPlanId} is the API ID of the existing test plan (from above, 20494)

{
"name": "Stream"
}


name
is the only required field in the payload

If successful, you will get a response like:

{
"meta": {
"status": "Created",
"timestamp": "2018-06-07T19:20:35.340+0000",
"location": "https://yourjama.jamasoftware.net/rest/latest/testplans/20494/testgroups/160",
"id": 160
}
}

You will need the
id
for further operations


To add a Test Case to a Group:


At this time, there is no batch operation for adding Test Cases, so each test case must be added individually using:

POST
/testplans/{testPlanId}/testgroups/{testGroupId}/testcases
with a payload containing a single test case id like:


where {testPlanId} is the API ID of the existing test plan (from above, 20494) and {testGroupId} is the API ID of the Test Group (from above, 157 for the default group, 160 for the custom)

{
"testCase": 20497
}


testCase
is the only item in the payload and should be set to the API ID of the Test Case you want to add

If successful, you will get a response like:

{
"meta": {
"status": "Created",
"timestamp": "2018-06-07T19:36:44.452+0000",
"location": "https://yourjama.jamasoftware.net/rest/latest/testplans/20494/testgroups/160/testcases/20497",
"id": 20497
}
}

The
id
returned in this case should match the id of the Test Case you provided in the payload


Creating a Test Cycle


A Test Cycle must be created to execute tests. Test Cycles are created through an existing Test Plan.

POST
/testplans/{testPlanId}/testcycles
with a payload like:

where {testPlanId} is the API ID of the existing test plan (from above, 20494)

{
"fields": {
"name": "Internet Explorer",
"startDate": "2018-06-06",
"endDate": "2018-06-13"
}
}


name, startDate,
and
endDate
are the only required fields in the payload. Note that there are other payload options for specifying which Test Groups and statuses that are added to the Cycle, but those won't be discussed here. Consult the API documentation for those options.

If successful, you will get a response like:

{
"meta": {
"status": "Created",
"timestamp": "2018-06-07T20:39:05.921+0000",
"location": "https://yourjama.jamasoftware.net/rest/latest/testcycles/20536",
"id": 20536
}
}

You will need the
id
for further operations


Finding an Existing Test Cycle:


If you need to work with an existing Test Cycle, it can be found in this manner.

GET
/testplans/{testPlanId}/testcycles


where {testPlanId} is the API ID of the existing test plan (from above, 20494)

If successful, you will get a response like:

{
"meta": {
"status": "OK",
"timestamp": "2018-06-08T15:57:09.863+0000",
"pageInfo": {
"startIndex": 0,
"resultCount": 2,
"totalResults": 2
}
},
"links": {
... omitted for brevity ...
},
"data": [
{

"id": 20510,

"documentKey": "JEET1-TSTCY-17",

"globalId": "70957",

"itemType": 36,

"project": 43,

"createdDate": "2018-06-07T19:58:19.000+0000",

"modifiedDate": "2018-06-07T19:58:19.000+0000",

"lastActivityDate": "2018-06-07T19:58:19.000+0000",

"createdBy": 5,

"modifiedBy": 5,

"fields": {

"documentKey": "JEET1-TSTCY-17",

"globalId": "70957",

"name": "Build 2018-06-06",

"testPlan": 20494,

"startDate": "2018-06-07",

"endDate": "2018-06-15",

"description": "",

"project": 43

},

"resources": {

"self": {

"allowed": [

"GET",

"PUT",

"PATCH",

"DELETE"

]

}

},

"type": "testcycles"

},

... second object omitted for brevity ...

]

}

You will need the
id
for further operations


Executing a Test


You now have almost all the data needed to record a test execution. Before you can do that, though, you need to find the actual Test Run object created when you created the Test Cycle. You will need the
id
of the Test Case Item, the Test Plan, and the Test Cycle

GET
/rest/latest/testruns?testCycle={testCycleId}&testCase={testCaseId}&testPlan={testPlanId}


where {testPlanId} is the API ID of the existing test plan (from above, 20494), {testCycleId} is the API ID of the Test Cycle (from above, 20536 for the created one, 20510 for the existing), {testCaseId} is the API ID of the Test Case to be executed (from above, 20497)

If successful, you will get a response that looks like:

{

"meta": {

"status": "OK",

"timestamp": "2018-06-07T21:01:36.530+0000",

"pageInfo": {

"startIndex": 0,

"resultCount": 1,

"totalResults": 1

}

},

"links": { ... removed for brevity ...

},

"data": [

{

"id": 20539,

"documentKey": "JEET1-TSTRN-520",

"globalId": "70962",

"itemType": 37,

"project": 43,

"createdDate": "2018-06-07T20:39:02.000+0000",

"modifiedDate": "2018-06-07T20:39:02.000+0000",

"lastActivityDate": "2018-06-07T20:39:02.000+0000",

"createdBy": 5,

"modifiedBy": 5,

"fields": {

"documentKey": "JEET1-TSTRN-520",

"globalId": "70962",

"name": "One",

"testPlan": 20494,

"testCycle": 20536,

"testRunSetName": "Internet Explorer",

"testCase": 20497,

"description": "",

"modifiedDate": "2018-06-07",

"testRunStatus": "NOT_RUN",

"project": 43,

"forcePassed": false

},

"resources": {

"self": {

"allowed": [

"GET",

"PUT",

"PATCH"

]

}

},

"testCaseVersionNumber": 1,

"testCaseCurrentVersionNumber": 1,

"sortOrderFromTestGroup": 1,

"testGroup": [

20536,

160

],

"type": "testruns"

}

]

}

If you have specified the id for Test Case, Test Plan, and Test Cycle, you should get

one

Test Run result in the data. You will need the
id
for further operations.

Next, you will need to either use PUT
or
PATCH to update the status of this test run:


Test Runs

without
Steps:


On test runs without steps, you can simply update the testRunStatus field.

PATCH
/rest/latest/testruns/{testRunId}
with a payload like:

where {testRunId} is the API ID of the Test Run (from above, 20539)

[

{

"op": "REPLACE",

"path": "/fields/testRunStatus",

"value": "PASSED"

}

]

PUT
/rest/latest/testruns/{testRunId}
with a payload like:

where {testRunId} is the API ID of the Test Run (from above, 20539)

{

"fields": {

"testRunStatus": "BLOCKED"

}

}

Valid values for /fields/testRunStatus are PASSED, NOT_RUN, FAILED, INPROGRESS, and BLOCKED.

If successful, you will get a response like:

{

"meta": {

"status": "OK",

"timestamp": "2018-06-07T21:14:14.611+0000"

}

}

Test Runs

with
Steps

On test runs with steps, you must pass the entire array of test steps (in the original order) with new statuses.

Here is an example of a Test Run object with steps. Note that the testRunSteps array is implicitly ordered by the step number as seen in the UI:

{

"id": 20569,

"documentKey": "JEET1-TSTRN-525",

"globalId": "70967",

"itemType": 37,

"project": 43,

"createdDate": "2018-06-11T21:34:09.000+0000",

"modifiedDate": "2018-06-11T21:34:09.000+0000",

"lastActivityDate": "2018-06-11T21:34:09.000+0000",

"createdBy": 5,

"modifiedBy": 5,

"fields": {

"documentKey": "JEET1-TSTRN-525",

"globalId": "70967",

"name": "One",

"testPlan": 20494,

"testCycle": 20536,

"testRunSetName": "Internet Explorer",

"testCase": 20497,

"description": "",

"testRunSteps": [

{

"action": "You do something",

"expectedResult": "Something happens",

"notes": "",

"status": "NOT_RUN"

},

{

"action": "You do something else",

"expectedResult": "Something else happens",

"notes": "",

"status": "NOT_RUN"

}

],

"modifiedDate": "2018-06-11",

"testRunStatus": "NOT_RUN",

"project": 43,

"forcePassed": false

}

Given the two steps above, you can do the following:

PUT
/rest/latest/testRuns/{testRunId}
with a payload like:

{

"fields": {

"testRunSteps": [

{

"status": "PASSED"

},

{

"status": "PASSED"

}

]

}

}

or

{

"fields": {

"testRunSteps": [

{

"status": "FAILED"

},

{

"status": "PASSED"

}

]

}

}

The testRunStatus for the Test Run will then be set automatically according to the status field on the steps.



Congratulations! You've executed a Test Case through the API!



What triggers the Last Activity Date?

Along with create date and modified date, we record the last activity date on every item. While modified date tracks the last time an item was saved, last activity date tracks when the last activity around the item happened. Below we list the types of events that last activity date should be triggered by.

· Item Updates
· Create new Item
· Edit and save Item
----- Note: deleted items cannot be seen so the last activity date is not visible.
· Comments On an Item
· Adding a comment directly to the item
· Deleting a comment that is directly on the item
· Relationships To and From an Item
· Adding a relationship to and from the item
· Removing a relationship to or from the item
· Tags on an Item
· Adding a tag to the item
· Removing a tag to the item
· Attachments on an Item
· Adding attachment to an Item
----- Note: Updating an attachment does not change the last activity date for the items it is a part of.
· Links on an Item
· Adding a link to an Item
· Editing a link on an Item
· Removing a link on an Item
· Reviews and Baseline
----- Sending items and creating baselines does NOT update the last activity date
· Executing Test Run *Only* updates test run's last activity date



Abstract Search - Lucene Parameters, Functions, and Limitations

-----------

Jama uses a version of Lucene search to help drill down into Abstract Items. It is important to understand the viable Parameters that are available, and the expected results from these parameters. below you will find a breakdown of the Parameters. If we missed a scenario, please let us know!

Admins and API Developers should also be aware of the limitations of Lucene searches - For example, Jama will NOT be able to guarantee an exact match with out using parameters to refine the search results. With the way Lucene data is indexed, exact match is difficult at best. Jama plans to continue to review ways to fine-tune these processes.

Example:

Assume 5 items have been created in the same project:

Item 1 - Name: Alpha
Item 2 - Name: Alpha Beta
Item 3 - Name: Beta Alpha
Item 4 - Name: Beta
Item 5 - Name: Happy Path with an item Description: includes the word "Alphabet"

Parameter

Contain's Term

Result count of 5 Examples

Detail

No Parameter

Alpha

3

Finds only Items 1, 2, 3

Result is limited to instances with an exact representation of "Alpha" as one of the terms avail.

Double Quotes (")

"Alpha"

4

Finds four of five Item results

Uses Wildcards to search for the term inside other terms (such as "Alphabet")

"Alpha Beta"

5

Finds all five Item results

Uses Wildcards to search for the term inside other terms (such as "Alphabet")

Single Quotes (')

'Alpha'

3

Same as No Parameter

Double Quotes and Wildcards ("*")

"A*pha"

4

Searches for any results with any character in the second place.

Add Field

"name:"Alpha""

3

Only returns items where Alpha is in the Name field.

Quotes with Plus/Minus ("+/-")

"+Alpha Beta"

4

Finds items 1, 2, 3, 5

Counts + element as a requirement

"Alpha +Beta"

3

Finds items 1, 2, 3

Counts + element as a requirement

"Alpha -Beta"

2

Finds items 1, 5

All results with the word Beta are omitted

"+Alpha +Beta"

2

Finds Items 2, 3

Only results that include both Alpha and Beta are returned.

"-Alpha Beta"

1

Only Beta is returned




REST Attachments

Attachments can be uploaded through our REST API and associated with an item in three calls. First, you must create an attachment item, then upload the file, and finally associate the attachment to an item. This should be straight forward after you have done it once. This document should help explain the steps clearly.

I will be sharing how to do this with Postman, a Google chrome extension.


Step 1: Create an Attachment Item

Attachment Items are items that contain the meta data for an attachment. You may define the name and description, or any other fields associated with the attachments item type.

This is exactly like filling out the name and description when you create an attachment in the UI:


Attachment Item JSON

{
"fields":{
"name":
"Poppy Flower",
"description":
"A pretty picture"
}
}

Only the name field is required to create an attachment item unless the Item Type has been configured differently.

Post your attachment Item to this path:


POST /rest/v1/projects/{projectID}/attachments

You should get a response back saying the attachment was created. Use the location to determine the id:

{
"meta":{
"status":
"Created",
"timestamp":
"2015-02-09T21:53:06.576+0000",
"location":
"http://localhost:8080/contour/rest/latest/attachments/1133"
}
}

Great, now you have an Attachment item. Next you need to upload the file to this item!


Step 2: Upload the file

You can upload a file using a PUT with form-data. the endpoint is
/rest/v1/attachments/{attachmentID}/file
. The key for the form data should be 'file'. Here is a screenshot of what it looks like in Postman:


Step 3: Associate Attachment Item with Item

To be clear, the attachment item is an item that has the meta data about an attachment. An Item is any old item you are familiar with in Jama, a requirement, test run, or anything else. You must have the Attachment widget enable on the item type before associating attachments to items.

You simply POST the attachment item ID to the attachment endpoint of the item you would like to associate with. Any of these paths are acceptable:

/rest/v1/items/{id}/attachments

/rest/v1/testplans/{id}/attachments

/rest/v1/testruns/{id}/attachments

The JSON is very simple:

{
"attachment":
1133
}

That's it! You can make some other attachment related operations listed below:

URL

Description

GET /rest/v1/attachments{attachmentId}

Gets attachment meta data

PUT /rest/v1/attachment/{attachmentId}/file

Uploads file to attachment

GET /rest/v1/attachment/{attachmentId}/file

Download the attached file

GET /rest/v1/attachments/{attachmentId}/comments

Gets all comments for attachment Item

GET /rest/v1/items/{id}/attachments

Gets attachments on an Item. This also works for test plans and test runs.

POST /rest/v1/items/{id}/attachments

Associates attachment item to the item

DELETE /rest/v1/item/{id}/attachments/{attachmentId}

Removes the association from the item. The attachment item still exists.



Attachments Attachments Attachments!

What are Attachments?

Jama is designed to allow for great flexibility of content, making it the ultimate definition of a system of record. While many of our customers are busy tapping away at the keyboard, they are often associating their content with documents, images, graphs, tables, equations, and so much more. External documents and images are referred to as attachments in Jama.

Uploading Attachments via REST API

There are two main ways to utilize attachments within in Jama:
· Attach a file to an item
· Embed a clickable link to an attachment within an item's text


Attaching a File to a Jama Item

Attachments can be uploaded through our REST API and associated with an item in three quick steps:

Step 1: Create an Attachment Item

Attachment Items are items that contain the meta data for an attachment. A name, description, and any other fields associated with the attachments item type can be defined in the JSON payload.
This is exactly like filling out the name and description when an attachment is created in the UI:


Attachment Item JSON Payload

{
"fields"
: {

"name"
: "Poppy Flower",

"description"
: "A pretty picture"
}
}

Note: By default, Name is the only required field in the Attachment item type.

POST the attachment Item using the following endpoint:

POST /rest/v1/projects/{projectID}/attachments

You should receive a response confirming the attachment was created. Use the location to determine the ID of the newly created attachment item:

{
"meta"
: {
"status"
: "Created",
"timestamp"
:"2015-02-09T21:53:06.576+0000",
"location"
:"http://{base_url}/rest/latest/attachments/1133"
}
}

You have successfully created an attachment item!

Step 2: Upload the attachment file

Files can be uploaded to Jama using a PUT with form-data to the following endpoint:

PUT /rest/v1/attachments/{attachmentID}/file

The attachmentID is the ID retrieved from the response location in step #1.

If you receive a 200/201 response status, you have successfully uploaded a file to the Jama attachment!

Step 3: Associate the attachment with an item

To associate an attachment item with a Jama item, the attachment widget must be enabled on the Jama item's item type prior to establishing an association.

Attachments can be associated with items that contain a POST method for an attachment. The attachment item ID is required in all cases. The following attachment endpoints are available:

POST /rest/v1/items/{itemID}/attachments
POST /rest/v1/testPlans/{testPlanID}/attachments
POST /rest/v1/testRuns/{testRunID}/attachments

The JSON payload should contain the attachment item ID:

{
"attachment"
:1133
}

You should receive a response indicating the status of your POST as shown below:

{
"meta"
: {
"status"
: "Created",
"timestamp"
:"2017-08-25T21:21:49.789+0000",
"location"
:"http://{base_url}/rest/latest/items/2209254/attachments/1133"
}
}

The result should appear in the attachment widget section of the object in Jama like this:

You have successfully associated an attachment with a Jama item using the REST API!

Embedding a Link to an Attachment in a Jama Object

Embedding clickable hyperlinks for attachments within content is also possible through our REST API. These appear in Rich Text fields as clickable links that can be used to download attachments. Once an attachment item is created, and the attachment's file is uploaded (steps #1 and 2 from the approach above), there are three steps to creating a clickable link to the attachment:

Step 1: Get the attachment's attachment value and filename

Once an attachment is created in Jama, and its file has been uploaded, GET the attachment item using the following endpoint:

GET /rest/v1/attachments/{attachmentID}

and retrieve the attachment value from the fields section, as well as the attachment's fileName (highlighted below):

{
"data"
: {
"id":
1133,
"documentKey":
"INF-ATT-31",
"globalId":
"GID-ATT-115929",
"itemType":
89027,
"project":
20319,
"createdDate":
"2017-08-25T21:21:49.789+0000",
"modifiedDate":
"2017-08-25T21:21:49.789+0000",
"lastActivityDate":
"2017-08-25T21:21:49.789+0000",
"createdBy":
18368,
"modifiedBy":
18368,
"fields":
{
"attachment":
78574,
"globalId":
"GID-ATT-115929",
"name"
: Poppy Flower,
"description":
A pretty picture,
}
"resources":
{
"self": {
"allowed": [
"GET"
]
}
},
"fileName":
"poppy.jpeg",
"mimeType":
"image/jpeg",
"fileSize":
7295,
"type":
"attachments"
}
}

Note: the attachment value is

not
the attachment item's ID, rather the attachment value stored in the
fields
section of an attachment object.


Step 2: Create a Hyperlink to your Attachment Item

Create a string with the following form:

<a href="https://{base_url}/attachment/{attachmentValue}/attachmentFileName">Clickable Text</a>


Step 3: Update a Jama Item's Rich Text Field

The string from step #2 now needs to be inserted into a Rich Text field of an Item to be accessible via the UI. Any endpoint that creates or updates a Jama Item's content can be used to update/generate an item with the clickable link embedded in a Rich Text field. Below are a few available endpoints:

POST /rest/v1/items
PUT, PATCH /rest/v1/items/{itemID}
POST /rest/v1/testplans
PUT, PATCH /rest/v1/testplans/{testPlanID}
POST /rest/v1/testruns
PUT, PATCH /rest/v1/testruns/{testRunID}

A clickable link should now appear in the object's Rich Text field as shown below:

Clicking on the hyperlink text should result in the attachment being downloaded:

You have successfully embedded a link to your Jama attachment item!

Downloading Linked Attachments

An attachment's file can be downloaded using the previously created attachment link in three steps:

Step 1: Retrieve the Attachment Link

Retrieve the object containing an embedded attachment link. Below are a few available endpoints:

GET /rest/v1/items/{itemID}
GET /rest/v1/testplans/{testPlanID}
GET /rest/v1/testruns/{testRunID}

Step 2: Parse out the Attachment Link

Parse out the embedded attachment link from the retrieved object's Rich Text field's content. Parsing libraries such as JSOUP for Java and BeautifulSoup for Python are helpful for this step.

Step 3: Download the Attachment File

Download the file using the following endpoint:

GET /rest/v1/files

The request payload should contain the link URL that was parsed out in step #2 and will look like this:

https://{base_url}/attachment/{attachmentValue}/attachmentFileName

If a response status of 200/201 is received, then you've successfully downloaded your attachment's file to your working directory!


Need help getting started?

For help getting started on uploading and downloading attachment files from Jama, check out our starter scripts available on GitHub. (https://github.com/JamaSoftware/UploadAttachments)



API Relationship Rules, Empty rule sets

When creating Relationships between items in Jama Connect, API Users sometimes experience API behavior which appears to contradict my Project Relationship rules, resulting in a “Bad Request” and a “Relationship violates rules configured for the project: from item ID: X, to item ID: Y”

Two things to pay attention to here:

  1. API request directions From-To matters!
  2. Relationships Rules: Small differences can have big impact.

API request directions From-To matters!

Users of the API should be cognizant that fromItem and toItem are specific functions and dictate which rules are to be used.

  • The input value fromItem is the for a Key item that will be looked at to check for Relationship rules.
  • Conversely, toItem is always the element which is being linked to.
  • If the rules for a projects are different for each item, then the From and To will definitely matter


Relationships Rules: Small differences can have big impact.

Relationship Rules are Fickle on purpose. Because Relationship Rules will likely vary between orgs and projects, it is impossible to hit every scenario, but check below for one very complex scenario which hits on many of the major themes in Relationship creation and cross project usage.

In one scenario, ProjA and ProjB are expected to relate to each other

ProjA

ProjB

1 Automotive System Req (ASYS)

1 Automotive System Req (ASYS)

1 Feature (FEAT)

1 Feature (FEAT)

  • Project A has rules that allows Features to be Derived From Requirements

  • Project B has also been applied to a rule set, but where no rules were created.
    • This was a purposeful action by the Admin
    • The creation (and application) of this empty rule set states to Jama “Items in this Project are not allowed to be related.”

  • When linking an ASYS Req in ProjA to a Feat in ProjB, the Admin and users have an expectation that this will function.
    • In the above scenario, all links fromItem ProjA --> toItem ProjB would be blocked and marked as “Bad Request”.
      While the rules of ProjA would allow a relationship, ProjB (which is purposefully empty) denies that these relationships are allowed.
    • The Jama API is required to look at both rule sets and trust/follow instructions as presented.
    • To allow creation of these relationships across projects, one of the following is required
      • Fix: ProjB rules should be clicked to “Allow relationships with item types not in this rule”
        Data would be allowed to link to ProjB items to other ProjB in any manner as no rules are expressed
        Data would only be allowed to link ProjB to ProjA items that follow ProjA rules.
      • Fix: ProjB is removed from the empty Rule set.
        Data would then be linkable as it is no longer using explicitly omitted rules.
      • Fix: ProjB has rules created that match Admin prescribed functions.