Summary and recommendation
SonarQube exposes user management through its Web API under /api/users/*, /api/user_groups/*, and - on Enterprise Edition - /api/scim/v2.
Authentication uses HTTP Basic with a user token as the username and an empty password, or an Authorization: Bearer <token> header.
All write operations on /api/users/* and /api/user_groups/* use HTTP POST with form-encoded body parameters, not JSON - this is a common integration mistake.
The API is not versioned;
endpoints can change between major SonarQube releases.
Always validate against the built-in /web_api explorer on your specific instance before building integrations.
The 'Administer System' global permission is required for all user and group write operations;
a token scoped to a lower-permission account will return 403s silently on some endpoints.
API quick reference
| Has user API | Yes |
| Auth method | HTTP Basic Auth with user token (token as username, empty password) or Bearer token header |
| Base URL | Official docs |
| SCIM available | Yes |
| SCIM plan required | Enterprise Edition |
Authentication
Auth method: HTTP Basic Auth with user token (token as username, empty password) or Bearer token header
Setup steps
- Log in to SonarQube as an administrator.
- Navigate to My Account → Security → Generate Tokens.
- Choose token type: User Token, Project Analysis Token, or Global Analysis Token.
- Copy the generated token; it is shown only once.
- Use the token as the HTTP Basic Auth username with an empty password, or pass it as 'Authorization: Bearer
' header. - For user-management operations (create/delete/deactivate users), the token must belong to an account with the 'Administer System' global permission.
Required scopes
| Scope | Description | Required for |
|---|---|---|
| Administer System | Global permission required to create, update, deactivate, and manage users and groups. | POST /api/users/create, POST /api/users/update, POST /api/users/deactivate, /api/user_groups/* |
| Administer (project-level) | Project-level permission required to manage project-scoped user access. | POST /api/permissions/add_user, POST /api/permissions/remove_user |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| login | string | Unique login/username identifier. | required | required (identifies user) | Immutable after creation in most configurations. |
| name | string | Display name of the user. | required | optional | |
| string | User email address. | optional | optional | Used for notifications. | |
| password | string | Password for local accounts. | required for local auth | optional | Not returned in GET responses. |
| local | boolean | True if the user is a local (non-SSO) account. | auto-set | read-only | |
| active | boolean | Whether the user account is active. | auto-set to true | read-only via this field; use /deactivate | |
| groups | array |
List of group names the user belongs to. | not set here | managed via /api/user_groups/add_user | |
| scmAccounts | array |
SCM account identifiers linked to the user. | optional | optional | Used to associate commits to the user. |
| tokensCount | integer | Number of tokens the user has generated. | n/a | n/a | Read-only, returned in search results. |
| lastConnectionDate | string (ISO 8601) | Timestamp of last login. | n/a | n/a | Read-only. |
| externalIdentity | string | Identity from external auth provider (SSO/LDAP). | auto-set by IdP | read-only | |
| externalProvider | string | Name of the external auth provider. | auto-set by IdP | read-only | |
| avatar | string | Gravatar hash derived from email. | auto-derived | auto-derived | Read-only. |
| managed | boolean | True if the user is managed by an external provisioning system (e.g., SCIM). | auto-set | read-only | Managed users cannot be edited via Web API. |
Core endpoints
Search / List Users
- Method: GET
- URL:
/api/users/search - Watch out for: Requires 'Administer System' permission to see all users; otherwise returns only the authenticated user.
Request example
GET /api/users/search?q=john&p=1&ps=50
Response example
{
"paging": {"pageIndex":1,"pageSize":50,"total":2},
"users": [
{"login":"john","name":"John Doe","email":"john@example.com","active":true,"local":true}
]
}
Create User
- Method: POST
- URL:
/api/users/create - Watch out for: Only creates local accounts. SSO/LDAP users are provisioned on first login or via SCIM. Requires 'Administer System' permission.
Request example
POST /api/users/create
login=jdoe&name=Jane+Doe&email=jdoe@example.com&password=Secret123
Response example
{
"user": {
"login":"jdoe","name":"Jane Doe",
"email":"jdoe@example.com",
"active":true,"local":true
}
}
Update User
- Method: POST
- URL:
/api/users/update - Watch out for: Cannot update users where managed=true (SCIM-managed). Requires 'Administer System' permission.
Request example
POST /api/users/update
login=jdoe&name=Jane+Smith&email=jsmith@example.com
Response example
{
"user": {
"login":"jdoe","name":"Jane Smith",
"email":"jsmith@example.com","active":true
}
}
Deactivate User
- Method: POST
- URL:
/api/users/deactivate - Watch out for: Deactivation is soft-delete; the login is anonymized and cannot be reused. SCIM-managed users must be deprovisioned via SCIM/IdP.
Request example
POST /api/users/deactivate
login=jdoe
Response example
{
"user": {
"login":"jdoe","name":"Jane Smith",
"active":false
}
}
Get Current User
- Method: GET
- URL:
/api/users/current - Watch out for: Returns the user associated with the token used for authentication.
Request example
GET /api/users/current
Response example
{
"login":"admin","name":"Administrator",
"email":"admin@example.com",
"local":true,"groups":["sonar-administrators"]
}
Add User to Group
- Method: POST
- URL:
/api/user_groups/add_user - Watch out for: Group must already exist. Use /api/user_groups/create first if needed. Requires 'Administer System'.
Request example
POST /api/user_groups/add_user
login=jdoe&name=my-group
Response example
HTTP 204 No Content
Remove User from Group
- Method: POST
- URL:
/api/user_groups/remove_user - Watch out for: Cannot remove a user from the last group if it is their only group membership in some configurations.
Request example
POST /api/user_groups/remove_user
login=jdoe&name=my-group
Response example
HTTP 204 No Content
Revoke / Delete User Token
- Method: POST
- URL:
/api/user_tokens/revoke - Watch out for: Admins can revoke tokens for any user by specifying 'login'. Without 'login', revokes a token for the authenticated user only.
Request example
POST /api/user_tokens/revoke
login=jdoe&name=my-ci-token
Response example
HTTP 204 No Content
Rate limits, pagination, and events
Rate limits: SonarQube does not publish explicit rate-limit thresholds in its official documentation. No rate-limit headers or Retry-After behavior is documented.
Rate-limit headers: No
Retry-After header: No
Rate-limit notes: No documented rate limits. Practical limits depend on server resources and JVM configuration. SonarQube Cloud (SonarCloud) may enforce undocumented limits.
Pagination method: offset
Default page size: 50
Max page size: 500
Pagination pointer: p (page number, 1-based), ps (page size)
Webhooks available: No
Webhook notes: SonarQube webhooks are outbound notifications triggered by analysis events (e.g., project analysis completion), not user-management events. There are no webhooks for user creation, update, or deactivation.
Alternative event strategy: Poll /api/users/search periodically to detect user changes, or use SCIM provisioning events from the IdP side.
Webhook events: analysis_completed
SCIM API status
SCIM available: Yes
SCIM version: 2.0
Plan required: Enterprise Edition
Endpoint: https://
/api/scim/v2 Supported operations: GET /Users – list/search provisioned users, POST /Users – provision a new user, PUT /Users – replace a user record, PATCH /Users – update user attributes (e.g., active=false to deprovision), GET /Groups – list/search groups, POST /Groups – create a group, PUT /Groups – replace a group, PATCH /Groups – update group membership, DELETE /Groups – delete a group
Limitations:
- Requires Enterprise Edition; not available on Community or Developer editions.
- SSO (SAML or OIDC) must be configured and enabled as a prerequisite.
- Once SCIM is enabled, user lifecycle must be managed exclusively through the IdP/SCIM; direct Web API edits to managed users are blocked.
- Officially tested with Okta and Microsoft Entra ID (Azure AD); other IdPs may work but are not officially supported.
- DELETE /Users is not supported; deprovisioning is done via PATCH with active=false.
- SCIM provisioning does not support Google Workspace or OneLogin natively.
Common scenarios
Three scenarios cover the majority of programmatic user management needs:
Provision a local user and assign to a group: POST /api/users/create (login, name, email, password), then POST /api/user_groups/add_user. This flow is only valid for local accounts; if SCIM is active, direct creation conflicts with managed user state and returns a 400.
Deprovision a user (soft-delete): GET /api/users/search?q=
first to check managed=false. If unmanaged, POST /api/users/deactivate - this anonymizes the login immediately and is irreversible. If managed=true, the deprovision must go through the IdP via PATCH /api/scim/v2/Users/ with active=false; the Web API will reject direct deactivation attempts. Bulk-list users for an audit: GET /api/users/search?p=1&ps=500 with an admin token. Pagination is offset-based (p = page index, ps = page size, max 500). Check paging.total and iterate pages; filter client-side on active=true. There is no cursor-based pagination, so large instances require sequential requests.
Provision a local user and assign to a group
- POST /api/users/create with login, name, email, password to create the local account.
- POST /api/user_groups/create with name to create the group if it does not exist.
- POST /api/user_groups/add_user with login and name (group name) to assign the user.
Watch out for: This flow only applies to local (non-SSO) users. If SCIM is enabled, user provisioning must go through the IdP; direct creation will conflict with managed user state.
Deprovision a user (soft-delete)
- GET /api/users/search?q=
to confirm the user exists and check managed=false. - If managed=false: POST /api/users/deactivate with login.
- If managed=true (SCIM): send a PATCH /api/scim/v2/Users/
with {"Operations":[{"op":"replace","path":"active","value":false}]} from the IdP, or deprovision via the IdP admin console.
Watch out for: Deactivation via Web API anonymizes the login immediately and is irreversible. SCIM-managed users must be deprovisioned through the IdP.
Bulk-list all active users for an audit
- GET /api/users/search?p=1&ps=500 with an admin token.
- Check paging.total in the response; if total > 500, iterate pages by incrementing p until all users are retrieved.
- Filter results client-side on active=true.
Watch out for: Maximum page size is 500. There is no cursor-based pagination; use p (page index) and ps (page size). Large instances may require many requests.
Why building this yourself is a trap
The managed=true field is the most consequential field in the user object for any integration that touches the identity graph. Once SCIM is enabled, any user provisioned through the IdP is marked managed=true, and the Web API blocks create, update, and deactivate operations on those users with a 400 error.
This means a mixed environment - some SCIM-managed users, some local users - requires branching logic in any automation that calls /api/users/deactivate.
Two additional traps are worth flagging explicitly. First, deactivation via the Web API anonymizes the login string permanently; the same login cannot be reused, which breaks re-hire or username-recycling workflows.
Second, SonarQube Cloud (SonarCloud) is a separate product with a different API surface - endpoint parity with SonarQube Server is not guaranteed, and the SCIM base path (/api/scim/v2 rather than the standard /scim/v2 root) can cause silent failures with IdP auto-discovery. No rate-limit thresholds are documented; practical limits depend on server resources and JVM configuration.
Automate SonarQube 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.