Stitchflow
Atlassian Bitbucket logo

Atlassian Bitbucket User Management API Guide

API workflow

How to automate user lifecycle operations through APIs with caveats that matter in production.

UpdatedFeb 27, 2026

Summary and recommendation

The Bitbucket Cloud REST API (api.bitbucket.org/2.0) supports OAuth 2.0 (Authorization Code, Client Credentials, Implicit), App Passwords via HTTP Basic, and workspace/repository Access Tokens as Bearer tokens. Scopes are defined at the OAuth consumer level and cannot be narrowed per-request. The Resource Owner Password Credentials grant is no longer supported.

Critical caveat: the Bitbucket REST API does not support creating, inviting, or deleting workspace users. User lifecycle operations must go through admin.atlassian.com or the SCIM 2.0 API at api.atlassian.com/scim/directory/{directoryId}/Users, which itself requires an Atlassian Guard Standard subscription and a pre-configured SSO/SAML setup.

For teams needing deeper, pre-built coverage across the Atlassian stack and adjacent identity systems, Stitchflow's MCP server with ~100 deep IT/identity integrations provides a structured alternative to building and maintaining direct API connections for each product.

API quick reference

Has user APIYes
Auth methodOAuth 2.0 (Authorization Code, Client Credentials, Implicit grants); also App Passwords (HTTP Basic) and Repository/Project/Workspace Access Tokens (Bearer)
Base URLOfficial docs
SCIM availableYes
SCIM plan requiredAtlassian Guard Standard subscription (separate add-on, ~$3–4/user/month billed per managed user across the Atlassian organization). SSO must be configured before enabling SCIM.

Authentication

Auth method: OAuth 2.0 (Authorization Code, Client Credentials, Implicit grants); also App Passwords (HTTP Basic) and Repository/Project/Workspace Access Tokens (Bearer)

Setup steps

  1. Go to Workspace Settings > Apps and features > OAuth consumers.
  2. Click 'Add consumer', provide a name and a Callback URL (required for OAuth 2.0).
  3. Select the required permission scopes (e.g., 'account', 'repository:admin').
  4. Save; Bitbucket generates a Client Key and Client Secret.
  5. Exchange the authorization code for an access token via POST https://bitbucket.org/site/oauth2/access_token with grant_type=authorization_code.
  6. Use the returned Bearer token in the Authorization header for all API requests.
  7. Alternatively, create an App Password under Personal Settings > App passwords and use HTTP Basic Auth (email:app_password).
  8. For server-to-server use, create a Workspace/Repository Access Token under Workspace Settings > Access tokens.

Required scopes

Scope Description Required for
account Read access to all account information for the authorizing user. GET /user, GET /user/emails, GET /users/{selected_user}
account:write Ability to change properties on the user's account. Updating account-level properties
email Read access to the user's primary email address only. Lightweight login/identity flows
repository Read access to all repositories the authorizing user can access. GET /repositories, listing repo members
repository:admin Admin access to repositories; required for permission CRUD endpoints. GET/PUT/DELETE /repositories/{workspace}/{repo_slug}/permissions-config/users/{selected_user}
webhook Read and write access to webhook subscriptions on all accessible resources. Creating, listing, and deleting webhooks
read:user:bitbucket Forge/API token scope to read user profile data. API token or Forge app access to /user endpoints
read:workspace:bitbucket Forge/API token scope to read workspace membership data. API token access to /workspaces and /workspaces/{workspace}/members

User object / data model

Field Type Description On create On update Notes
type string Always 'user' for user objects. n/a (read-only) n/a Discriminator field per Bitbucket object model.
uuid string Globally unique identifier for the Atlassian account, formatted as {uuid}. n/a (system-assigned) immutable Preferred stable identifier for API references.
account_id string Atlassian account ID (e.g., 557058:c0b72ad0-...). Primary key for cross-product identity. n/a (system-assigned) immutable Replaced username as the canonical user identifier after April 2019 (GDPR change).
display_name string User's display name; may be controlled by user privacy settings. n/a user-controlled May be obscured if user has restricted visibility.
nickname string User's chosen nickname/handle on Bitbucket. n/a user-controlled Introduced as a replacement for the deprecated username field.
links object HAL-style links including self, avatar (href), and html (profile URL). n/a n/a avatar.href and html.href are informative, not REST resources.
created_on string (ISO 8601) Timestamp when the account was created. n/a (system-assigned) immutable Returned on /user (authenticated user) endpoint.
is_staff boolean Whether the user is an Atlassian staff member. n/a n/a Informational only.
has_2fa_enabled boolean Whether the authenticated user has two-factor authentication enabled. n/a n/a Only returned on GET /user (self); not available for other users.
username string Legacy username field. Deprecated since April 2019. n/a n/a Still returned on GET /user (self only) for backward compatibility; removed from all other user objects.

Core endpoints

Get authenticated user (self)

  • Method: GET
  • URL: https://api.bitbucket.org/2.0/user
  • Watch out for: Requires 'account' OAuth 2.0 scope. This is the only endpoint that still returns the legacy 'username' field.

Request example

curl --request GET \
  --url 'https://api.bitbucket.org/2.0/user' \
  --header 'Authorization: Bearer <access_token>' \
  --header 'Accept: application/json'

Response example

{
  "type": "user",
  "uuid": "{abc123}",
  "account_id": "557058:abc",
  "display_name": "Jane Doe",
  "nickname": "janedoe",
  "created_on": "2020-01-01T00:00:00Z"
}

Get a specific user by account_id or uuid

  • Method: GET
  • URL: https://api.bitbucket.org/2.0/users/{selected_user}
  • Watch out for: Returns only public profile data. Username-based URLs are deprecated; use account_id or uuid. User privacy settings may limit display_name and avatar visibility.

Request example

curl --request GET \
  --url 'https://api.bitbucket.org/2.0/users/557058:abc' \
  --header 'Authorization: Bearer <access_token>'

Response example

{
  "type": "user",
  "uuid": "{abc123}",
  "account_id": "557058:abc",
  "display_name": "Jane Doe",
  "nickname": "janedoe"
}

List authenticated user's email addresses

  • Method: GET
  • URL: https://api.bitbucket.org/2.0/user/emails
  • Watch out for: Requires 'email' or 'account' scope. Returns both confirmed and unconfirmed addresses for the authenticated user only.

Request example

curl --request GET \
  --url 'https://api.bitbucket.org/2.0/user/emails' \
  --header 'Authorization: Bearer <access_token>'

Response example

{
  "pagelen": 10,
  "values": [
    {"type": "email", "email": "jane@example.com",
     "is_primary": true, "is_confirmed": true}
  ]
}

List workspace members

  • Method: GET
  • URL: https://api.bitbucket.org/2.0/workspaces/{workspace}/members
  • Watch out for: Requires workspace membership to call. Does not support adding or removing members via this endpoint; membership is managed through Atlassian Admin or SCIM.

Request example

curl --request GET \
  --url 'https://api.bitbucket.org/2.0/workspaces/myworkspace/members' \
  --header 'Authorization: Bearer <access_token>'

Response example

{
  "pagelen": 10,
  "values": [
    {"type": "workspace_membership",
     "user": {"type": "user", "uuid": "{abc}"},
     "workspace": {"type": "workspace"}}
  ]
}

Get a specific workspace member

  • Method: GET
  • URL: https://api.bitbucket.org/2.0/workspaces/{workspace}/members/{member}
  • Watch out for: Member must be identified by account_id or uuid, not username.

Request example

curl --request GET \
  --url 'https://api.bitbucket.org/2.0/workspaces/myworkspace/members/557058:abc' \
  --header 'Authorization: Bearer <access_token>'

Response example

{
  "type": "workspace_membership",
  "user": {"type": "user", "uuid": "{abc}"},
  "workspace": {"type": "workspace", "slug": "myworkspace"}
}

List repository-level user permissions

  • Method: GET
  • URL: https://api.bitbucket.org/2.0/repositories/{workspace}/{repo_slug}/permissions-config/users
  • Watch out for: Requires 'repository:admin' scope and repository admin permission. Only returns explicit (direct) permissions, not inherited group permissions.

Request example

curl --request GET \
  --url 'https://api.bitbucket.org/2.0/repositories/myws/myrepo/permissions-config/users' \
  --header 'Authorization: Bearer <access_token>'

Response example

{
  "pagelen": 10,
  "values": [
    {"type": "repository_user_permission",
     "permission": "write",
     "user": {"type": "user", "uuid": "{abc}"}}
  ]
}

Set/update a user's repository permission

  • Method: PUT
  • URL: https://api.bitbucket.org/2.0/repositories/{workspace}/{repo_slug}/permissions-config/users/{selected_user}
  • Watch out for: Requires 'repository:admin' scope. Valid permission values: 'read', 'write', 'admin'. Cannot grant permissions higher than the caller's own.

Request example

curl --request PUT \
  --url 'https://api.bitbucket.org/2.0/repositories/myws/myrepo/permissions-config/users/557058:abc' \
  --header 'Authorization: Bearer <access_token>' \
  --header 'Content-Type: application/json' \
  --data '{"permission": "write"}'

Response example

{
  "type": "repository_user_permission",
  "permission": "write",
  "user": {"type": "user", "uuid": "{abc}"}
}

Remove a user's explicit repository permission

  • Method: DELETE
  • URL: https://api.bitbucket.org/2.0/repositories/{workspace}/{repo_slug}/permissions-config/users/{selected_user}
  • Watch out for: Only removes the explicit direct permission. User may still have access via group membership. Requires 'repository:admin' scope.

Request example

curl --request DELETE \
  --url 'https://api.bitbucket.org/2.0/repositories/myws/myrepo/permissions-config/users/557058:abc' \
  --header 'Authorization: Bearer <access_token>'

Response example

HTTP 204 No Content

Rate limits, pagination, and events

  • Rate limits: Rate limits are applied per rolling one-hour window. Authenticated requests are measured per user ID; unauthenticated requests per IP address. A 429 response is returned when the limit is exceeded. Scaled rate limits apply to the 'api resource group' (most /2.0/repositories/* endpoints) for requests made via Access Tokens or Forge asApp, adding 10 requests/hour per paid workspace seat, capped at 10,000 requests/hour.
  • Rate-limit headers: Yes
  • Retry-After header: No
  • Rate-limit notes: Rate limit headers returned for scaled endpoints: X-RateLimit-Limit (total permitted/hour), X-RateLimit-Resource (endpoint group), X-RateLimit-NearLimit (boolean, true when <20% remaining). No Retry-After header is documented; back-off and retry after waiting is recommended. Resource and rate limits are not part of the stable API contract and may change dynamically.
  • Pagination method: offset
  • Default page size: 10
  • Max page size: 100
  • Pagination pointer: pagelen (page size), page (page number)
Plan Limit Concurrent
Unauthenticated 60 requests/hour 0
Authenticated (all plans, standard endpoints) 1,000 requests/hour 0
Scaled (Standard/Premium, Access Token or Forge asApp, api resource group) 1,000 + (10 × paid_seats) requests/hour, max 10,000/hour 0
  • Webhooks available: Yes
  • Webhook notes: Bitbucket Cloud supports repository-scoped and workspace-scoped webhooks. After creation, Bitbucket sends an HTTP POST payload to the configured URL whenever a subscribed event occurs. Webhooks are not rate-limited unlike API requests. The 'webhook' scope is required to create or manage webhook subscriptions.
  • Alternative event strategy: No native user lifecycle webhook events (e.g., user added/removed from workspace) exist in Bitbucket Cloud. For user provisioning events, use the Atlassian SCIM API or poll /workspaces/{workspace}/members.
  • Webhook events: repo:push, repo:fork, repo:updated, repo:commit_comment_created, repo:commit_status_created, repo:commit_status_updated, pullrequest:created, pullrequest:updated, pullrequest:approved, pullrequest:unapproved, pullrequest:fulfilled, pullrequest:rejected, pullrequest:comment_created, pullrequest:comment_updated, pullrequest:comment_deleted, issue:created, issue:updated, issue:comment_created

SCIM API status

  • SCIM available: Yes

  • SCIM version: 2.0

  • Plan required: Atlassian Guard Standard subscription (separate add-on, ~$3–4/user/month billed per managed user across the Atlassian organization). SSO must be configured before enabling SCIM.

  • Endpoint: https://api.atlassian.com/scim/directory/{directoryId}/Users

  • Supported operations: GET /scim/directory/{directoryId}/Users - list users (paginated via startIndex, default 100/page), POST /scim/directory/{directoryId}/Users - create/provision a user, GET /scim/directory/{directoryId}/Users/{userId} - get a single user, PUT /scim/directory/{directoryId}/Users/{userId} - full replace of user attributes, PATCH /scim/directory/{directoryId}/Users/{userId} - partial update (e.g., set active=false to deactivate), DELETE /scim/directory/{directoryId}/Users/{userId} - deprovision/delete a user

Limitations:

  • Group sync (SCIM Groups) is NOT available for Bitbucket - only user account provisioning is supported. Group sync is available for Jira and Confluence only.
  • SCIM only provisions Atlassian accounts; it does not assign repository-level permissions in Bitbucket. Repository access must be managed manually or via the Bitbucket permissions API.
  • SCIM API keys expire after one year (enforced from January 2025); annual rotation is required.
  • The directoryId is generated at setup time in admin.atlassian.com and is not shown again after initial configuration - store it securely.
  • Deactivating a SCIM-provisioned user deactivates them across all Atlassian products in the organization, not just Bitbucket.
  • Updating a SCIM-provisioned user's email must be done via the SCIM API, not the Bitbucket user management API.
  • Batch group membership syncs above 10,000 users will suspend subsequent directory syncs.
  • SSO (SAML) must be configured and domain verified before SCIM provisioning can be enabled.

Common scenarios

Three primary automation scenarios are well-supported by the API, each with explicit constraints to plan around.

Looking up workspace members and permissions: Use GET /workspaces/{workspace}/members (paginated, pagelen max 100) to list members, then GET /repositories/{workspace}/{repo_slug}/permissions-config/users to retrieve explicit repo-level permissions. Note that workspace member listing does not return email addresses - email is only available for the authenticated user via GET /user/emails. Always reference users by account_id or uuid; username-based paths are deprecated since April 2019.

Granting or updating repository permissions: PUT /repositories/{workspace}/{repo_slug}/permissions-config/users/{account_id} with a body of {"permission": "read|write|admin"} requires the repository:admin scope. The caller cannot grant a permission level higher than their own. This sets only the explicit direct permission; group-inherited access is managed separately and is not visible from this endpoint.

Provisioning a new user via SCIM: POST to api.atlassian.com/scim/directory/{directoryId}/Users creates the Atlassian account. SCIM alone does not grant Bitbucket product access or assign any repository permissions - a separate group assignment in Atlassian Admin and a subsequent Bitbucket permissions API call are both required. SCIM API keys expire after one year and must be rotated manually. Group sync via SCIM is not supported for Bitbucket; it is available only for Jira and Confluence.

Look up a workspace member's profile and permissions

  1. Authenticate via OAuth 2.0 (Authorization Code) or App Password with 'account' and 'repository' scopes.
  2. GET https://api.bitbucket.org/2.0/workspaces/{workspace}/members to list all members; paginate using ?page=N&pagelen=50.
  3. Identify the target user's account_id or uuid from the response.
  4. GET https://api.bitbucket.org/2.0/users/{account_id} to retrieve the user's public profile.
  5. GET https://api.bitbucket.org/2.0/repositories/{workspace}/{repo_slug}/permissions-config/users to list explicit repo permissions; filter for the target user.

Watch out for: Workspace member listing does not include email addresses. Email is only available for the authenticated user via GET /user/emails. User privacy settings may hide display_name.

Grant a user write access to a repository

  1. Authenticate with an account that has repository admin rights; use 'repository:admin' scope.
  2. Resolve the target user's account_id (e.g., from GET /workspaces/{workspace}/members).
  3. PUT https://api.bitbucket.org/2.0/repositories/{workspace}/{repo_slug}/permissions-config/users/{account_id} with body {"permission": "write"}.
  4. Verify the response returns the updated permission object (HTTP 200).

Watch out for: You cannot grant a permission level higher than your own. This sets an explicit direct permission; the user may already have access via group membership which is managed separately.

Provision a new user via SCIM and verify Bitbucket access

  1. Ensure Atlassian Guard Standard is active and SSO is configured; retrieve the directoryId and SCIM API key from admin.atlassian.com > Security > Identity providers > Set up user provisioning.
  2. POST https://api.atlassian.com/scim/directory/{directoryId}/Users with SCIM 2.0 user payload (userName, name.givenName, name.familyName, emails[primary]).
  3. Confirm the user appears in admin.atlassian.com under Managed Accounts.
  4. Assign the user to a Bitbucket-access group in Atlassian Admin to grant product access (SCIM alone does not grant Bitbucket access).
  5. Use the Bitbucket permissions API (PUT /repositories/.../permissions-config/users/{account_id}) to assign repository-level permissions as needed.

Watch out for: SCIM creates the Atlassian account but does NOT assign Bitbucket repository permissions or group memberships within Bitbucket. Group sync via SCIM is not supported for Bitbucket. SCIM API keys expire annually and must be rotated manually.

Why building this yourself is a trap

The most significant API trap is the split between account lifecycle and permission management. SCIM handles account creation and deactivation at the Atlassian org level, but it has no mechanism to assign or sync Bitbucket repository or project permissions.

Any automation that stops at SCIM provisioning leaves users with an Atlassian account but no usable Bitbucket access - or, on offboarding, deactivates the account org-wide across all Atlassian products, not just Bitbucket.

Rate limits are applied per rolling one-hour window: 1,000 requests/hour for authenticated standard endpoints, scaling to a maximum of 10,000/hour for Access Token or Forge asApp calls against the api resource group (1,000 + 10 × paid seats). No Retry-After header is returned on 429 responses; implement exponential backoff.

Rate limit thresholds are not part of the stable API contract and may change dynamically.

Additional sharp edges: the directoryId generated during SCIM setup in admin.atlassian.com is not displayed again after initial configuration - store it securely at setup time. Access tokens (workspace/project/repository) appear as a bot user in logs and cannot call the /user (self) endpoint. The /user/workspaces endpoint is deprecated and scheduled for removal by end of 2025.

Automate Atlassian Bitbucket 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.

Every app coverage, including apps without APIs
60+ app integrations plus browser automation for apps without APIs
IT graph reconciliation across apps and your IdP
Less than a week to launch, maintained as APIs and admin consoles change
SOC 2 Type II. ~2 hours of your team's time

UpdatedFeb 27, 2026

* Details sourced from official product documentation and admin references.

Keep exploring

Related apps

15Five logo

15Five

Full API + SCIM
AutomationAPI + SCIM
Last updatedFeb 2026

15Five uses a fixed role-based permission model with six predefined roles: Account Admin, HR Admin, Billing Admin, Group Admin, Manager, and Employee. No custom roles can be constructed. User management lives at Settings gear → People → Manage people p

1Password logo

1Password

Full API + SCIM
AutomationAPI + SCIM
Last updatedFeb 2026

1Password's admin console at my.1password.com covers the full user lifecycle — invitations, group assignments, vault access, suspension, and deletion — without any third-party tooling. Like every app that mixes role-based and resource-level permissions

8x8 logo

8x8

Full API + SCIM
AutomationAPI + SCIM
Last updatedFeb 2026

8x8 Admin Console supports full lifecycle user management — create, deactivate, and delete — across its X Series unified communications platform. Every app a user can access (8x8 Work desktop, mobile, web, Agent Workspace) is gated by license assignmen