Rate this page:
The purpose of this section is to describe how to authenticate when making API calls using the Bitbucket REST API.
Our OAuth 2 implementation is merged in with our existing OAuth 1 in such a way that existing OAuth 1 consumers automatically become valid OAuth 2 clients. The only thing you need to do is edit your existing consumer and configure a callback URL.
Once that is in place, you'll have the following 2 URLs:
1 2https://bitbucket.org/site/oauth2/authorize https://bitbucket.org/site/oauth2/access_token
For obtaining access/bearer tokens, we support three of RFC-6749's grant flows, plus a custom Bitbucket flow for exchanging JWT tokens for access tokens. Note that Resource Owner Password Credentials Grant (4.3) is no longer supported.
The full-blown 3-LO flow. Request authorization from the end user by sending their browser to:
1 2https://bitbucket.org/site/oauth2/authorize?client_id={client_id}&response_type=code
The callback includes the ?code={}
query parameter that you can swap
for an access token:
1 2$ curl -X POST -u "client_id:secret" \ https://bitbucket.org/site/oauth2/access_token \ -d grant_type=authorization_code -d code={code}
This flow is useful for browser-based add-ons that operate without server-side backends.
Request the end user for authorization by directing the browser to:
1 2https://bitbucket.org/site/oauth2/authorize?client_id={client_id}&response_type=token
That will redirect to your preconfigured callback URL with a fragment
containing the access token
(#access_token={token}&token_type=bearer
) where your page's js can
pull it out of the URL.
Somewhat like our existing "2-LO" flow for OAuth 1. Obtain an access token that represents not an end user, but the owner of the client/consumer:
1 2$ curl -X POST -u "client_id:secret" \ https://bitbucket.org/site/oauth2/access_token \ -d grant_type=client_credentials
If your Atlassian Connect add-on uses JWT authentication, you can swap a JWT for an OAuth access token. The resulting access token represents the account for which the add-on is installed.
Make sure you send the JWT token in the Authorization request header using the "JWT" scheme (case sensitive). Note that this custom scheme makes this different from HTTP Basic Auth (and so you cannot use "curl -u").
1 2$ curl -X POST -H "Authorization: JWT {jwt_token}" \ https://bitbucket.org/site/oauth2/access_token \ -d grant_type=urn:bitbucket:oauth2:jwt
Once you have an access token, as per RFC-6750, you can use it in a request in any of the following ways (in decreasing order of desirability):
Authorization: Bearer {access_token}
access_token={access_token}
?access_token={access_token}
Since add-ons will not be able to upload their own SSH keys to clone with, access tokens can be used as Basic HTTP Auth credentials to clone securely over HTTPS. This is much like GitHub, yet slightly different:
1 2$ git clone https://x-token-auth:{access_token}@bitbucket.org/user/repo.git
The literal string x-token-auth
as a substitute for username is
required (note the difference with GitHub where the actual token is in
the username field).
Our access tokens expire in one hour. When this happens you'll get 401 responses.
Most access tokens grant responses (Implicit and JWT excluded). Therefore, you should include a refresh token that can then be used to generate a new access token, without the need for end user participation:
1 2$ curl -X POST -u "client_id:secret" \ https://bitbucket.org/site/oauth2/access_token \ -d grant_type=refresh_token -d refresh_token={refresh_token}
Bitbucket's API applies a number of privilege scopes to endpoints. In order to access an endpoint, a request will need to have the necessary scopes.
Scopes are declared in the descriptor as a list of strings, with each string being the name of a unique scope.
A descriptor lacking the scopes
element is implicitly assumed to require all scopes and as a result, Bitbucket will require end users authorizing/installing the add-on
to explicitly accept all scopes.
Our best practice suggests you add the scopes your add-on needs, but no more than it needs.
Invalid scope strings will cause the descriptor to be rejected and the installation to fail.
Following is the set of all currently available scopes.
Gives the add-on read access to all the repositories the authorizing user has access to. Note that this scope does not give access to a repository's pull requests.
Gives the add-on write (not admin) access to all the repositories the authorizing user has access to. No distinction is made between public or private repos. This scope implies repository
, which does not need to be requested separately.
This scope alone does not give access to the pull requests API.
Gives the add-on admin access to all the repositories the authorizing user has access to. No distinction is made between public or private repos. This scope does not imply repository
or repository:write
. It gives access to the admin features of a repo only, not direct access to its contents. Of course it can be (mis)used to grant read access to another user account who can then clone the repo, but repos that need to read of write source code would also request explicit read or write.
This scope comes with access to the following functionality:
Gives the add-on read access to all the snippets the authorizing user has access to. No distinction is made between public and private snippets (public snippets are accessible without any form of authentication).
Gives the add-on write access to all the snippets the authorizing user can edit. No distinction is made between public and private snippets (public snippets are accessible without any form of authentication). This implies the Snippet Read scope which does not need to be requested separately.
Ability to interact with issue trackers the way non-repo members can. This scope does not imply any other scopes and does not give implicit access to the repository the issue is attached to.
This implies issue
, but adds the ability to transition and delete issues.
This scope does not imply any other scopes and does not give implicit access to the repository the issue is attached to.
Gives access to wikis. No distinction is made between read and write as wikis are always editable by anyone. This scope does not imply any other scopes and does not give implicit access to the repository the wiki is attached to.
Gives the add-on read access to pull requests.
This scope implies repository
, giving read access to the pull request's destination repository.
Implies pullrequest
but adds the ability to create, merge and decline pull requests.
This scope implies repository:write
, giving write access to the pull request's destination repository. This is necessary to facilitate merging.
Ability to see the user's primary email address. This should make it easier to use Bitbucket Cloud as a login provider to add-ons or external applications.
Ability to see all the user's account information. Note that this does not include any ability to mutate any of the data.
Ability to change properties on the user's account.
The ability to find out what teams the current user is part of. This is covered by the teams endpoint.
Implies team
, but adds the ability to manage the teams that the authorizing user is an admin on.
Gives access to webhooks. This scope is required for any webhook related operation.
This scope gives read access to existing webhook subscriptions on all
resources you can access, without needing further scopes. This means that
a client can list all existing webhook subscriptions on repository
foo/bar
(assuming the principal user has access to this repo). The
additional repository
scope is not required for this.
Likewise, existing webhook subscriptions for a repo's issue tracker can be
retrieved without holding the issue
scope. All that is required is the
webhook
scope.
However, to create a webhook for issue:created
, the client will need to
have both the webhook
as well as issue
scope.
Gives read-only access to pipelines, steps, deployment environments and variables.
Gives write access to pipelines. This scope allows a user to:
This scope is not needed to trigger a build via a push. The act to doing push will trigger the build. The token doing the push only needs repository:write scope.
This does not give write access to create variables.
Gives write access to create variables in pipelines at the various levels:
Gives read-only access to pipelines runners setup against a workspace or repository.
Gives write access to create/edit/disable/delete pipelines runners setup against a workspace or repository.
Basic HTTP Authentication as per RFC-2617 (Digest not supported). Note that Basic Auth is available only with username and app password as credentials.
App passwords allow users to make API calls to their Bitbucket account through apps such as Sourcetree.
Some important points about app passwords:
You cannot view an app password or adjust permissions after you create the app password. Because app passwords are encrypted on our database and cannot be viewed by anyone. They are essentially designed to be disposable. If you need to change the scopes or lost the password just create a new one.
You cannot use them to log into your Bitbucket account.
You cannot use app passwords to manage team actions.
App passwords are tied to an individual account's credentials and should not be shared. If you're sharing your app password you're essentially giving direct, authenticated, access to everything that password has been scoped to do with the Bitbucket API's.
You can use them for API call authentication, even if you don't have two-step verification enabled.
You can set permission scopes (specific access rights) for each app password.
To create an app password:
That's all there is to creating an app password. See your applications documentation for how to apply the app password for a specific application.
You can query the 2.0 API for specific objects using a simple language which resembles SQL.
Note that filtering and querying by username has been deprecated, due to privacy changes. See the announcement for details.
Most 2.0 API resources that return paginated collections of objects support a single, shared, generic querying language that is used to filter down a result set.
This includes, but is in no way limited to:
1 2/2.0/repositories/{username} /2.0/repositories/{username}/{slug}/refs /2.0/repositories/{username}/{slug}/refs/branches /2.0/repositories/{username}/{slug}/refs/tags /2.0/repositories/{username}/{slug}/forks /2.0/repositories/{username}/{slug}/src /2.0/repositories/{username}/{slug}/issues /2.0/repositories/{username}/{slug}/pullrequests
Filtering and sorting supports several distinct operators and data types as well as basic features, like logical operators (AND, OR).
As examples, the following queries could be used on the issue tracker endpoint (/2.0/repositories/{workspace}/{slug}/issues/
):
1 2(state = "open" OR state = "new") AND assignee = null reporter.nickname != "evzijst" AND priority >= "major" (title ~ "unicode" OR content.raw ~ "unicode") AND created_on > 2015-10-04T14:00:00-07:00
Filter queries can be added to the URL using the q=
1 2/2.0/repositories/foo/bar/issues?q=state="new"&sort=-updated_on
Filtering and sorting supports the following operators:
Operator | Definition | Example |
---|---|---|
"=" | test for equality | nickname = "evzijst" |
"!=" | not equal | is_private != true |
"~" | case-insensitive text contains | description ~ "beef" |
"!~" | case-insensitive not contains | description !~ "fubar" |
">" | greater than | priority > "major" |
">=" | greater than or equal | priority <= "trivial" |
"<" | less than | id < 1234 |
"<=" | less than or equal | updated_on <= 2015-03-04 |
Filtering and sorting supports the following data types:
Type | Description | Example |
---|---|---|
String | any text inside double quotes | "foo" |
Number | arbitrary precision integers and floats | 1, -10.302 |
Null | to test for the absence of a value | null |
boolean | the unquoted strings true or false | true, false |
datetime | an unquoted [ISO-8601][iso-8601] date time string with the timezone offset, milliseconds and entire time component being optional | 2015-03-04T14:08:59.123+02:00 , 2015-03-04T14:08:59 Date time strings are assumed to be in UTC, unless an explicit timezone offset is provided |
Objects can be filtered based on their properties. In principle, every element in an object's JSON document schema can be used as a filter criterion.
Note that while the array of objects in a paginated response is wrapped in an
envelope with a values
element, this prefix should not be included in the
query fields (so use /2.0/repositories/foo/bar/issues?q=state="new"
, not
/2.0/repositories/foo/bar/issues?q=values.state="new"
).
Fields that contain embedded instances of other object types (e.g. owner is an embedded user object, while parent is an embedded repository) can be traversed recursively. For instance:
1 2parent.owner.nickname = "bitbucket"
To find pull requests which merge into master, come from a fork of the repo rather than a branch inside the repo, and on which I am a reviewer:
1 2source.repository.full_name != "main/repo" AND state = "OPEN" AND reviewers.nickname = "evzijst" AND destination.branch.name = "master"
1 2/2.0/repositories/main/repo/pullrequests?q=source.repository.full_name+%21%3D+%22main%2Frepo%22+AND+state+%3D+%22OPEN%22+AND+reviewers.nickname+%3D+%22evzijst%22+AND+destination.branch.name+%3D+%22master%22
To find new or on-hold issues related to the UI, created or updated in the last day (SF local time), that have not yet been assigned to anyone:
1 2(state = "new" OR state = "on hold") AND assignee = null AND component = "UI" and updated_on > 2015-11-11T00:00:00-07:00
1 2/2.0/repositories/main/repo/issues?q=%28state+%3D+%22new%22+OR+state+%3D+%22on+hold%22%29+AND+assignee+%3D+null+AND+component+%3D+%22UI%22+and+updated_on+%3E+2015-11-11T00%3A00%3A00-07%3A00
To find all tags with the string "2015" in the name:
1 2name ~ "2015"
1 2/2.0/repositories/{username}/{slug}/refs/tags?q=name+%7E+%222015%22
Or all my branches:
1 2name ~ "erik/"
1 2/2.0/repositories/{username}/{slug}/refs/?q=name+%7E+%22erik%2F%22
You can sort result sets using the ?sort=
Endpoints that return collections of objects should always apply pagination. Paginated collections are always wrapped in the following wrapper object:
1 2{ "size": 5421, "page": 2, "pagelen": 10, "next": "https://api.bitbucket.org/2.0/repositories/pypy/pypy/commits?page=3", "previous": "https://api.bitbucket.org/2.0/repositories/pypy/pypy/commits?page=1", "values": [ ... ] }
Pagination is often page-bound, with a query parameter page indicating which page is to be returned.
However, clients are not expected to construct URLs themselves by manipulating the page number query parameter. Instead, the response contains a link to the next page. This link should be treated as an opaque location that is not to be constructed by clients or even assumed to be predictable. The only contract around the next link is that it will return the next chunk of results.
Lack of a next link in the response indicates the end of the collection.
The paginated response contains the following fields:
Field | Value |
---|---|
size | Total number of objects in the response. This is an optional element that is not provided in all responses, as it can be expensive to compute. |
page | Page number of the current results. This is an optional element that is not provided in all responses. |
pagelen | Current number of objects on the existing page. Globally, the minimum length is 10 and the maximum is 100. Some APIs may specify a different default. |
next | Link to the next page if it exists. The last page of a collection does not have this value. Use this link to navigate the result set and refrain from constructing your own URLs. |
previous | Link to previous page if it exists. A collections first page does not have this value. This is an optional element that is not provided in all responses. Some result sets strictly support forward navigation and never provide previous links. Clients must anticipate that backwards navigation is not always available. Use this link to navigate the result set and refrain from constructing your own URLs. |
values | The list of objects. This contains at most pagelen objects. |
The link to the next page is included such that you don't have to hardcode or construct any links. Only values and next are guaranteed (except the last page, which lacks next). This is because the previous and size values can be expensive for some data sets.
It is important to realize that Bitbucket support both list-based pagination and iterator-based pagination. List-based pa