Summary and recommendation
The JSM API surface spans two distinct base paths: the Jira platform REST API v3 (`/rest/api/3`) for user lookup and group management, and the JSM Service Desk API (`/rest/servicedeskapi/`) for customer and service desk operations. Auth is either HTTP Basic with a user-scoped API token (Base64-encoded email:token) or OAuth 2.0 three-legged for user-context flows.
A critical architectural constraint: the REST API cannot directly provision licensed agents - agent access requires an invitation flow through Atlassian Admin or SCIM.
For teams building automated provisioning pipelines, Stitchflow's MCP server with ~100 deep IT/identity integrations handles the Atlassian Guard SCIM layer, cross-product seat reconciliation, and token rotation gaps that the raw API leaves unaddressed.
API quick reference
| Has user API | Yes |
| Auth method | OAuth 2.0 (3-legged for user-context) or HTTP Basic Auth with API token (server-to-server) |
| Base URL | Official docs |
| SCIM available | Yes |
| SCIM plan required | Atlassian Guard Standard (separate subscription required; SSO prerequisite) |
Authentication
Auth method: OAuth 2.0 (3-legged for user-context) or HTTP Basic Auth with API token (server-to-server)
Setup steps
- For API token auth: log in to id.atlassian.com, navigate to Security > API tokens, create a token (expires after 1 year).
- Use the token as the password in HTTP Basic Auth with the user's email as the username, Base64-encoded.
- For OAuth 2.0: register an app at developer.atlassian.com/console, select 'OAuth 2.0 (3LO)', configure redirect URI, and request the required scopes.
- Exchange the authorization code for an access token via POST https://auth.atlassian.com/oauth/token.
- Pass the Bearer token in the Authorization header for all API requests.
Required scopes
| Scope | Description | Required for |
|---|---|---|
| read:jira-user | Read user profile information | GET user, search users |
| write:jira-work | Create and update Jira content including user assignments | Assigning users to issues |
| manage:jira-configuration | Manage Jira configuration including user roles and groups | Adding/removing users from groups, managing project roles |
| read:servicedesk-request | Read JSM service desk requests and customer data | GET JSM customers/participants |
| write:servicedesk-request | Create and update JSM service desk requests and customers | Create/remove JSM customers |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| accountId | string | Unique Atlassian account ID (AAID) | system-assigned | immutable | Primary identifier; replaces deprecated 'key' and 'name' fields |
| emailAddress | string | User's email address | required | not updatable via REST API; managed via Atlassian Admin | May be hidden based on profile visibility settings |
| displayName | string | User's display name | optional | not updatable via REST API | Managed via Atlassian account profile |
| active | boolean | Whether the user account is active | system-assigned (true) | read-only via REST; managed via Atlassian Admin or SCIM | Deactivation must be done via Atlassian Admin or SCIM API |
| avatarUrls | object | Map of avatar image URLs (16x16, 24x24, 32x32, 48x48) | system-assigned | read-only | |
| accountType | string | Type of account: 'atlassian', 'app', or 'customer' | system-assigned | immutable | JSM customers have accountType 'customer' |
| timeZone | string | User's time zone (IANA format) | optional | read-only via REST | |
| locale | string | User's locale (e.g., 'en_US') | optional | read-only via REST | |
| groups | object | Groups the user belongs to (returned when expand=groups) | not set here | managed via group membership endpoints | Use expand=groups query param to include |
| applicationRoles | object | Application roles assigned to the user | system-assigned | read-only | Use expand=applicationRoles to include |
Core endpoints
Get user by accountId
- Method: GET
- URL:
https://your-domain.atlassian.net/rest/api/3/user?accountId={accountId} - Watch out for: accountId is required; legacy 'username' and 'key' params are deprecated and removed in v3.
Request example
GET /rest/api/3/user?accountId=5b10a2844c20165700ede21g
Authorization: Basic <base64(email:token)>
Response example
{
"accountId": "5b10a2844c20165700ede21g",
"emailAddress": "user@example.com",
"displayName": "Jane Doe",
"active": true,
"accountType": "atlassian"
}
Search users
- Method: GET
- URL:
https://your-domain.atlassian.net/rest/api/3/user/search?query={query}&startAt=0&maxResults=50 - Watch out for: Returns up to 1000 results. Email search may be restricted by profile visibility settings.
Request example
GET /rest/api/3/user/search?query=jane&maxResults=50
Authorization: Basic <base64(email:token)>
Response example
[
{
"accountId": "5b10a2844c20165700ede21g",
"displayName": "Jane Doe",
"emailAddress": "jane@example.com",
"active": true
}
]
Create JSM customer
- Method: POST
- URL:
https://your-domain.atlassian.net/rest/servicedeskapi/customer - Watch out for: This creates a portal-only (customer) account, not a licensed agent. Use the Jira platform user invite for agents.
Request example
POST /rest/servicedeskapi/customer
Content-Type: application/json
{
"email": "customer@example.com",
"displayName": "New Customer"
}
Response example
{
"accountId": "qm:abc123",
"emailAddress": "customer@example.com",
"displayName": "New Customer",
"active": true,
"accountType": "customer"
}
Add customers to service desk
- Method: POST
- URL:
https://your-domain.atlassian.net/rest/servicedeskapi/servicedesk/{serviceDeskId}/customer - Watch out for: Requires the user to already have an Atlassian account. Returns 204 on success with no body.
Request example
POST /rest/servicedeskapi/servicedesk/1/customer
Content-Type: application/json
{
"accountIds": ["5b10a2844c20165700ede21g"]
}
Response example
HTTP 204 No Content
Remove customers from service desk
- Method: DELETE
- URL:
https://your-domain.atlassian.net/rest/servicedeskapi/servicedesk/{serviceDeskId}/customer - Watch out for: DELETE with a request body is non-standard; ensure your HTTP client supports it.
Request example
DELETE /rest/servicedeskapi/servicedesk/1/customer
Content-Type: application/json
{
"accountIds": ["5b10a2844c20165700ede21g"]
}
Response example
HTTP 204 No Content
Get users in group
- Method: GET
- URL:
https://your-domain.atlassian.net/rest/api/3/group/member?groupId={groupId}&startAt=0&maxResults=50 - Watch out for: Use groupId (UUID), not groupname; groupname is deprecated in v3.
Request example
GET /rest/api/3/group/member?groupId=276f955c-63d7-42c8-9520-92d01dca0625
Authorization: Basic <base64(email:token)>
Response example
{
"startAt": 0,
"maxResults": 50,
"total": 2,
"values": [
{"accountId": "abc", "displayName": "Jane", "active": true}
]
}
Add user to group
- Method: POST
- URL:
https://your-domain.atlassian.net/rest/api/3/group/user?groupId={groupId} - Watch out for: Requires manage:jira-configuration scope. Adding to the wrong group may grant unintended product access.
Request example
POST /rest/api/3/group/user?groupId=276f955c-63d7-42c8-9520-92d01dca0625
Content-Type: application/json
{
"accountId": "5b10a2844c20165700ede21g"
}
Response example
{
"groupId": "276f955c-63d7-42c8-9520-92d01dca0625",
"name": "jira-service-desk-users"
}
Get service desk customers
- Method: GET
- URL:
https://your-domain.atlassian.net/rest/servicedeskapi/servicedesk/{serviceDeskId}/customer?query={query}&start=0&limit=50 - Watch out for: JSM Service Desk API uses 'start'/'limit' pagination params, not 'startAt'/'maxResults' like the Jira platform API.
Request example
GET /rest/servicedeskapi/servicedesk/1/customer?query=jane&limit=50
Authorization: Basic <base64(email:token)>
Response example
{
"size": 1,
"start": 0,
"limit": 50,
"values": [
{"accountId": "abc", "displayName": "Jane", "emailAddress": "jane@example.com"}
]
}
Rate limits, pagination, and events
- Rate limits: Atlassian Cloud enforces rate limits per user token and per app. Limits are not publicly documented with exact numbers; Atlassian uses a token-bucket model and returns HTTP 429 when exceeded.
- Rate-limit headers: Yes
- Retry-After header: Yes
- Rate-limit notes: HTTP 429 is returned when rate limited. The Retry-After header indicates when to retry. Atlassian recommends exponential backoff. SCIM endpoints may have separate limits.
- Pagination method: offset
- Default page size: 50
- Max page size: 1000
- Pagination pointer: startAt / maxResults
| Plan | Limit | Concurrent |
|---|---|---|
| All Cloud plans | Not publicly specified; Atlassian states limits vary by endpoint and usage patterns | 0 |
- Webhooks available: Yes
- Webhook notes: Jira Cloud supports webhooks registered via the REST API or app descriptor. Events fire for issue and user-related changes. JSM-specific events (e.g., request created) are also available.
- Alternative event strategy: Atlassian Forge or Connect apps can subscribe to lifecycle events including user provisioning events via the app descriptor.
- Webhook events: jira:issue_created, jira:issue_updated, jira:issue_deleted, user_created, user_updated, user_deleted, jira:worklog_updated, comment_created, comment_updated
SCIM API status
SCIM available: Yes
SCIM version: 2.0
Plan required: Atlassian Guard Standard (separate subscription required; SSO prerequisite)
Endpoint: https://api.atlassian.com/scim/directory/{directoryId}
Supported operations: GET /Users – list users, GET /Users/{userId} – get user, POST /Users – create user, PUT /Users/{userId} – replace user, PATCH /Users/{userId} – update user (activate/deactivate), DELETE /Users/{userId} – delete user, GET /Groups – list groups, GET /Groups/{groupId} – get group, POST /Groups – create group, PUT /Groups/{groupId} – replace group, PATCH /Groups/{groupId} – update group membership, DELETE /Groups/{groupId} – delete group, GET /Schemas – list supported schemas, GET /ServiceProviderConfig – get SCIM config
Limitations:
- Requires Atlassian Guard Standard subscription (separate from JSM license)
- SSO must be configured before enabling SCIM
- SCIM manages Atlassian organization-level accounts, not JSM-specific roles; product access is controlled separately
- SCIM tokens expire and must be rotated manually
- Filtering support is limited; not all SCIM filter operators are supported
- Group membership changes via SCIM affect Atlassian user groups, which then control product access
Common scenarios
Three scenarios cover the majority of programmatic access management needs.
To provision a portal-only customer: POST to /rest/servicedeskapi/customer to create the account, capture the returned accountId, then POST to /rest/servicedeskapi/servicedesk/{serviceDeskId}/customer to grant service desk access - this does not create a licensed agent. To sync users in bulk from an IdP, SCIM 2.
0 is available at https://api.atlassian.com/scim/directory/{directoryId} but requires Atlassian Guard Standard and a pre-configured SSO setup; SCIM provisions org-level accounts only, and JSM product access must still be mapped separately via group-to-product rules in Atlassian Admin.
To deactivate a user programmatically, the Jira REST API v3 exposes no deactivate endpoint - deactivation requires either a SCIM PATCH (active: false) or manual action in the Admin UI.
Provision a new JSM customer (portal-only user)
- POST /rest/servicedeskapi/customer with {email, displayName} to create the customer account.
- Capture the returned accountId.
- POST /rest/servicedeskapi/servicedesk/{serviceDeskId}/customer with {accountIds: [accountId]} to grant access to the specific service desk.
Watch out for: This creates a portal-only customer, not a licensed agent. If the email already has an Atlassian account, the existing account is linked rather than a new one created.
Sync users from IdP via SCIM (bulk provisioning)
- Ensure Atlassian Guard Standard is active and SSO is configured for the organization.
- In Atlassian Admin, navigate to Security > Identity providers > User provisioning and generate a SCIM token.
- Configure the IdP (Okta, Entra ID, etc.) with the SCIM base URL (https://api.atlassian.com/scim/directory/{directoryId}) and the token.
- Map IdP attributes to SCIM schema fields (userName → email, givenName, familyName, active).
- Assign users/groups in the IdP; the IdP will POST /Users to create accounts and PATCH /Users/{id} to update or deactivate.
Watch out for: SCIM provisions Atlassian accounts at the org level. Product access (JSM agent license) must still be assigned separately via Atlassian Admin group-to-product mappings or manually.
Find and deactivate a user
- GET /rest/api/3/user/search?query={email} to find the user's accountId.
- Confirm the user is active via the 'active' field in the response.
- To deactivate: use SCIM PATCH /Users/{userId} with {op: 'replace', path: 'active', value: false} if SCIM is configured, OR deactivate via Atlassian Admin UI.
- Optionally, remove the user from JSM service desks via DELETE /rest/servicedeskapi/servicedesk/{serviceDeskId}/customer.
Watch out for: The Jira REST API v3 does not expose a deactivate endpoint. Deactivation requires SCIM or Atlassian Admin. Removing a customer from a service desk does not deactivate their Atlassian account.
Why building this yourself is a trap
Several API behaviors create silent failure modes worth flagging explicitly. The emailAddress field can be hidden from API responses by profile visibility settings even when using an admin token, making email-based lookups unreliable - accountId is the only stable identifier in v3.
The JSM Service Desk API uses start/limit pagination parameters, while the Jira platform API uses startAt/maxResults; mixing them in a unified pipeline will produce silent truncation.
API tokens expire after exactly one year with no programmatic renewal path and no expiry warning via the API - deactivating the owning user account revokes the token immediately with no grace period.
Rate limits are not publicly documented with exact thresholds; Atlassian returns HTTP 429 with a Retry-After header and recommends exponential backoff, but the token-bucket model means limits vary by endpoint and usage pattern. SCIM filter operator support is partial, so complex IdP sync rules may silently fall back to full syncs.
Automate Atlassian Jira Service Management workflows without one-off scripts
Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.