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: