By 29 April 2019, we will remove personal data from the API that is used to identify users, such as username and userKey, and instead use the Atlassian account ID (accountId). Additionally, will be restricting the visibility of other personal data, such as email, in conjunction with a user's profile privacy settings.
This guide shows you how to update your app or integration to adopt the GDPR-related changes for the Jira Cloud REST APIs. It describes how the user privacy improvements affect the REST APIs, provides a migration path to the new REST APIs, and lists all of the REST API changes.
Atlassian is making a number of changes to our products and APIs to improve user privacy in accordance with the European General Data Protection Regulation (GDPR).
For Jira Cloud, these changes include:
Changes to how users are identified: Personal data that is used to identify users, such as the username and userKey, will be removed from the REST APIs. Users will be identified by their Atlassian account ID (accountId) instead.
Changes to the visibility of user information: Users will be able to restrict the visibility of their personal data through their user profile privacy settings, or in the case of a managed account, the visibility settings that are decided by the site administrator. This means that fields such as email will only be returned by the API if the user has permitted that data to be visible. Note that this means that some fields can be null. The REST API changes will be introduced alongside the existing REST API. The existing REST API will be available until the end of the deprecation period. Until this time, you can use either the GDPR-compliant or non-GDPR compliant version of the REST API. An opt-in mechanism is available which will force Jira Cloud to only use the GDPR-compliant version of the REST API (that is, deprecated data is not used).
Changes to Atlassian Connect APIs: All personal data will be removed from the Connect REST APIs and replaced with accountId where appropriate.
Below is a high-level summary of the REST API changes:
Operations that currently accept a username and/or userKey will also accept an Atlassian account ID. (accountId). After the deprecation period ends, only an accountId will be accepted.
Operations that currently return a username and/or userKey will also return an Atlassian account ID (accountId). After the deprecation period ends, only an accountId will be returned.
Operations that currently use a username and/or userKey as a search clause (for example, JQL queries) will also use an Atlassian account ID (accountId). After the deprecation period ends, only an accountId may be used. To help you update your JQL queries, we’ve introduced a new operation: POST /rest/api/3/jql/pdcleaner which takes one or more JQL queries with user identifiers and converts them to equivalent JQL queries with account IDs.
The User object will change: Identifying personal data, such as username and userKey , will be removed and other personal data, such as email, will be displayed according to user settings.
To update your app or integration, read the list of REST API changes in the next section. The changes are listed by resource and include instructions on what you need to update.
Note that both version 2 and version 3 of the Jira Cloud REST API will be updated according to this document. Version 3 was introduced to support the Atlassian Document Format (ADF). With respect to GDPR, there is no difference between these versions.
lead, assignee, and realAssignee updated to use the new User object.leadUserName will be removed.leadAccountId will be used.| Field | Change | Nullable | Notes |
|---|---|---|---|
lead | CHANGED | N/A | Updated to use the new User object. |
assignee | CHANGED | N/A | Updated to use the new User object. |
realAssignee | CHANGED | N/A | Updated to use the new User object. |
| Field | Change | Nullable | Notes |
|---|---|---|---|
name | REMOVED | N/A | Use accountId instead. |
key | REMOVED | N/A | Use accountId instead. |
accountId | ADDED or CURRENT | No | This field is already present in most REST API methods. |
emailAddress | CURRENT | Yes | Depends on the privacy setting. This can be null. |
displayName | CURRENT | No | Depends on the privacy setting. |
timeZone | CURRENT | Yes | Depends on the privacy setting. This can be null. |
locale | CURRENT | Yes | Depends on the privacy setting. This can be null. |
dashboards array updated.| Field | Change | Nullable | Notes |
|---|---|---|---|
owner | CHANGED | N/A | owner updated to use the new User object. |
| Field | Change | Nullable | Notes |
|---|---|---|---|
name | REMOVED | N/A | Use accountId instead. |
key | REMOVED | N/A | Use accountId instead. |
accountId | ADDED or CURRENT | No | This field is already present in most REST API methods. |
emailAddress | CURRENT | Yes | Depends on the privacy setting. This can be null. |
displayName | CURRENT | No | Depends on the privacy setting. |
timeZone | CURRENT | Yes | Depends on the privacy setting. This can be null. |
locale | CURRENT | Yes | Depends on the privacy setting. This can be null. |
| Field | Change | Nullable | Notes |
|---|---|---|---|
| owner | CHANGED | N/A | owner updated to use the new User object |
| Field | Change | Nullable | Notes |
|---|---|---|---|
name | REMOVED | N/A | Use accountId instead. |
key | REMOVED | N/A | Use accountId instead. |
accountId | ADDED or CURRENT | No | This field is already present in most REST API methods. |
emailAddress | CURRENT | Yes | Depends on the privacy setting. This can be null. |
displayName | CURRENT | No | Depends on the privacy setting. |
timeZone | CURRENT | Yes | Depends on the privacy setting. This can be null. |
locale | CURRENT | Yes | Depends on the privacy setting. This can be null. |
username and userKey will be removed.accountId will be used instead.query parameter to be used to search for user.| Field | Change | Nullable | Notes |
|---|---|---|---|
| UsersAndGroupsBean | CHANGED | N/A | Users array updated to use the new User object. |
| Field | Change | Nullable | Notes |
|---|---|---|---|
name | REMOVED | N/A | Use accountId instead. |
key | REMOVED | N/A | Use accountId instead. |
accountId | ADDED or CURRENT | No | This field is already present in most REST API methods. |
emailAddress | CURRENT | Yes | Depends on the privacy setting. This can be null. |
displayName | CURRENT | No | Depends on the privacy setting. |
timeZone | CURRENT | Yes | Depends on the privacy setting. This can be null. |
locale | CURRENT | Yes | Depends on the privacy setting. This can be null. |
id (for account ID) used instead of name for user fields, such as reporter and assignee.username will be removed.accountId will be used instead.fields array updated.| Field | Change | Nullable | Notes |
|---|---|---|---|
watchers | CHANGED | N/A | watchers array updated to the new User object. |
author | CHANGED | N/A | author updated to the new User object. |
updateAuthor | CHANGED | N/A | updateAuthor updated to the new User object. |
items | CHANGED | N/A | from and to fields will contain accountId instead of userKey. |
| Field | Change | Nullable | Notes |
|---|---|---|---|
name | REMOVED | N/A | Use accountId instead. |
key | REMOVED | N/A | Use accountId instead. |
accountId | ADDED or CURRENT | No | This field is already present in most REST API methods. |
emailAddress | CURRENT | Yes | Depends on the privacy setting. This can be null. |
displayName | CURRENT | No | Depends on the privacy setting. |
timeZone | CURRENT | Yes | Depends on the privacy setting. This can be null. |
locale | CURRENT | Yes | Depends on the privacy setting. This can be null. |
| Field | Change | Nullable | Notes |
|---|---|---|---|
name | REMOVED | N/A | Use accountId instead. |
key | REMOVED | N/A | Use accountId instead. |
accountId | ADDED or CURRENT | No | This field is already present in most REST API methods. |
emailAddress | CURRENT | Yes | Depends on the privacy setting. This can be null. |
displayName | CURRENT | No | Depends on the privacy setting. |
timeZone | CURRENT | Yes | Depends on the privacy setting. This can be null. |
locale | CURRENT | Yes | Depends on the privacy setting. This can be null. |
currentJQL will not allow username or userKey in query. Use accountId instead.To help you update your JQL queries, we’ve introduced a new operation: POST /rest/api/3/jql/pdcleaner which takes one or more JQL queries with user identifiers and converts them to equivalent JQL queries with account IDs.
| Field | Change | Nullable | Notes |
|---|---|---|---|
users | CHANGED | N/A | users array updated to use the new User object. |
| Field | Change | Nullable | Notes |
|---|---|---|---|
name | REMOVED | N/A | Use accountId instead. |
key | REMOVED | N/A | Use accountId instead. |
accountId | ADDED or CURRENT | No | This field is already present in most REST API methods. |
emailAddress | CURRENT | Yes | Depends on the privacy setting. This can be null. |
displayName | CURRENT | No | Depends on the privacy setting. |
timeZone | CURRENT | Yes | Depends on the privacy setting. This can be null. |
locale | CURRENT | Yes | Depends on the privacy setting. This can be null. |
actors array updated.| Field | Change | Nullable | Notes |
|---|---|---|---|
name | REMOVED | N/A | Use accountId instead. |
actorUser.accountId | CURRENT | No | Already present. |
displayName | CURRENT | No | Depends on the privacy setting. |
username or userKey in queries. Use accountId instead.To help you update your JQL queries, we’ve introduced a new operation: POST /rest/api/3/jql/pdcleaner which takes one or more JQL queries with user identifiers and converts them to equivalent JQL queries with account IDs.
| Field | Change | Nullable | Notes |
|---|---|---|---|
| users | CHANGED | N/A | users array updated to use the new User object. |
| Field | Change | Nullable | Notes |
|---|---|---|---|
name | REMOVED | N/A | Use accountId instead. |
key | REMOVED | N/A | Use accountId instead. |
accountId | ADDED or CURRENT | No | This field is already present in most REST API methods. |
emailAddress | CURRENT | Yes | Depends on the privacy setting. This can be null. |
displayName | CURRENT | No | Depends on the privacy setting. |
timeZone | CURRENT | Yes | Depends on the privacy setting. This can be null. |
locale | CURRENT | Yes | Depends on the privacy setting. This can be null. |
name and key will be removed.accountId parameter must be used to identify a user.query parameter must be used to search for a user.| Field | Change | Nullable | Notes |
|---|---|---|---|
name | REMOVED | N/A | Use accountId instead. |
key | REMOVED | N/A | Use accountId instead. |
accountId | ADDED or CURRENT | No | This field is already present in most REST API methods. |
emailAddress | CURRENT | Yes | Depends on the privacy setting. This can be null. |
displayName | CURRENT | No | Depends on the privacy setting. |
html | CURRENT | No | |
avatarUrl | CURRENT | No | |
accountType | ADDED | No | See Webhooks below. |
User objects in a webhook payload have a new field: accountType. This field is used to distinguish different types of users, such as normal users, app users, and Jira Service Desk customers.
Valid values:
atlassian: A regular Atlassian user account.app: A system account used for Connect applications and OAuth 2.0 to represent external systems.customer: A Jira Service Desk account representing an external service deskIn addition, accountType has been added to the User object in the REST API. This means that it can be retrieved via operations such as Get user.
username or userKey in queries. Use accountId instead.To help you update your JQL queries, we’ve introduced a new operation: POST /rest/api/3/jql/pdcleaner which takes one or more JQL queries with user identifiers and converts them to equivalent JQL queries with account IDs.
updateAuthor will contain the updated User object.| Field | Change | Nullable | Notes |
|---|---|---|---|
name | REMOVED | N/A | Use accountId instead. |
key | REMOVED | N/A | Use accountId instead. |
accountId | ADDED or CURRENT | No | This field is already present in most REST API methods. |
emailAddress | CURRENT | Yes | Depends on the privacy setting. This can be null. |
displayName | CURRENT | No | Depends on the privacy setting. |
timeZone | CURRENT | Yes | Depends on the privacy setting. This can be null. |
locale | CURRENT | Yes | Depends on the privacy setting. This can be null. |
usernames array will be removed. Use the accountIds array instead.reporter and values array will contain updated User object.| Field | Change | Nullable | Notes |
|---|---|---|---|
name | REMOVED | N/A | Use accountId instead. |
key | REMOVED | N/A | Use accountId instead. |
accountId | ADDED or CURRENT | No | This field is already present in most REST API methods. |
emailAddress | CURRENT | Yes | Depends on the privacy setting. This can be null. |
displayName | CURRENT | No | Depends on the privacy setting. |
timeZone | CURRENT | Yes | Depends on the privacy setting. This can be null. |
locale | CURRENT | Yes | Depends on the privacy setting. This can be null. |
This example illustrates the most common scenario for updating an API call for GDPR: Replacing the username and/or userKey with the Atlassian account ID.
The current method to fetch a user record by username (GET https://your-domain.atlassian.net/rest/api/3/user?username=your-name) returns:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28{ "self": "https://your-domain.atlassian.net//rest/api/3/user?username=your-name", "key": "your-name", "accountId": "1234567890abcdef12345678", "name": "your-name", "emailAddress": "your-name@your-domain.com", "avatarUrls": { "48x48": "http://your-domain.atlassian.net/secure/useravatar?size=large&ownerId=mia", "32x32": "http://your-domain.atlassian.net/secure/useravatar?size=medium&ownerId=mia", "24x24": "http://your-domain.atlassian.net/secure/useravatar?size=small&ownerId=mia", "16x16": "http://your-domain.atlassian.net/secure/useravatar?size=xsmall&ownerId=mia" }, "displayName": "Your Name", "active": true, "timeZone": "Australia/Sydney", "locale": "en_UK", "groups": { "size": 6, "items": [] }, "applicationRoles": { "size": 3, "items": [] }, "expand": "groups,applicationRoles" }
You will need to update your code to fetch the user by accountId instead. GET https://your-domain.atlassian.net/rest/api/3/user?accountId=1234567890abcdef12345678 returns:
1 2{ "self": "https://your-domain.atlassian.net//rest/api/3/user?accountId=1234567890abcdef12345678", "accountId": "1234567890abcdef12345678", "emailAddress": "your-name@your-domain.com", "avatarUrls": { "48x48": "https://avatar-cdn.atlassian.com/5a67d46ef01d171fcf33ce60?by=id&s=48", "32x32": "https://avatar-cdn.atlassian.com/5a67d46ef01d171fcf33ce60?by=id&s=32", "24x24": "https://avatar-cdn.atlassian.com/5a67d46ef01d171fcf33ce60?by=id&s=24", "16x16": "https://avatar-cdn.atlassian.com/5a67d46ef01d171fcf33ce60?by=id&s=16" }, "displayName": "Your Name", "active": true, "timeZone": "Australia/Sydney", "locale": "en_UK", "groups": { "size": 6, "items": [] }, "applicationRoles": { "size": 3, "items": [] }, "expand": "groups,applicationRoles" }
When it is necessary to find a user for some particular purpose (that is, searching for users assignable to issues), username will no longer be a valid request parameter. Instead, the query request parameter must be used.
For example, GET https://your-domain.atlassian.net/rest/api/3/user/assignable/search?project=ABC&username=your-name currently returns:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19{ "self": "https://your-domain.atlassian.net/rest/api/3/user/assignable/search?project=ABC&username=your-name", "key": "your-name", "accountId": "1234567890abcdef12345678", "name": "your-name", "emailAddress": "your-name@your-domain.com", "avatarUrls": { "48x48": "http://your-domain.atlassian.net/secure/useravatar?size=large&ownerId=mia", "32x32": "http://your-domain.atlassian.net/secure/useravatar?size=medium&ownerId=mia", "24x24": "http://your-domain.atlassian.net/secure/useravatar?size=small&ownerId=mia", "16x16": "http://your-domain.atlassian.net/secure/useravatar?size=xsmall&ownerId=mia" }, "displayName": "Your Name", "active": true, "timeZone": "Australia/Sydney", "locale": "en_UK", }
You will need to update your code to use a method that supports the query request parameter, where the value can be an email address, display name, or any other user attribute.
GET https://your-domain.atlassian.net/rest/api/3/user/assignable/search?project=ABC&query=your-user-attribute returns:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20{ "self": "https://your-domain.atlassian.net/rest/api/3/user/assignable/search?project=ABC&query=your-name@your-domain.com", "accountId": "1234567890abcdef12345678", "emailAddress": "your-name@your-domain.com", "avatarUrls": { "48x48": "https://avatar-cdn.atlassian.com/5a67d46ef01d171fcf33ce60?by=id&s=48", "32x32": "https://avatar-cdn.atlassian.com/5a67d46ef01d171fcf33ce60?by=id&s=32", "24x24": "https://avatar-cdn.atlassian.com/5a67d46ef01d171fcf33ce60?by=id&s=24", "16x16": "https://avatar-cdn.atlassian.com/5a67d46ef01d171fcf33ce60?by=id&s=16" }, "displayName": "Your Name", "active": true, "timeZone": "Australia/Sydney", "locale": "en_UK", "groups": { "size": 6, "items": [] } }
If you want to test your changes, you can force the REST APIs to only use GDPR-compliant functionality by including the x-atlassian-force-account-id: true header in any REST API call. For example, if you get a user and set the x-atlassian-force-account-id: true header, then the response will not include a username and userkey. Note that the X-AUSERNAME header is not returned if the request includes the x-atlassian-force-account-id: true header.
You can use this header until the end of the deprecation period, if you want to opt in early to the new GDPR-compliant REST APIs. Once the deprecation period is over, GDPR-compliant functionality will be enforced in the REST APIs, regardless of the x-atlassian-force-account-id: true header.
The Jira XML-RPC and SOAP APIs have been deprecated since Jira 6.0 and were removed in Jira 7.0. See the announcement Jira SOAP API is waving goodbye for more information. As a result, these APIs will not be updated for GDPR.
Rate this page: