Skip to content

Bitbucket Source

What it ingests

Repository activity from Bitbucket Cloud — pull requests, issues, commits, and review verdicts (approvals and change requests) — across a whole workspace or an explicit list of repositories.

It is the Bitbucket-side peer of the GitHub source and feeds the same graph entity types (Repository, PullRequest, Issue, Commit), so an org split across both forges gets one graph rather than two.

Bitbucket Cloud only

This source does not support Bitbucket Data Center / Server. That product speaks /rest/api/1.0, which is a different API rather than a different base URL for this one — different pagination, different response envelopes, different user and link shapes, and no workspace concept (it has projects instead). There is no base_url setting that would reach it.

Credential

The Bitbucket source references a bitbucket_access_token credential by id. Store only the secret — never a username:secret pair, even though Bitbucket's own curl examples show them joined by a colon. The username, when one is needed at all, goes in the source's username config field.

Three kinds of secret work, and which one you have decides whether you set username:

SecretSet username?How it is sent
Access token (workspace, project, or repository)No — leave it emptyAuthorization: Bearer <token>
App passwordYes — the Bitbucket usernameHTTP Basic
Atlassian API tokenYes — the account emailHTTP Basic

An access token is the recommended choice: it is scoped to exactly the workspace, project, or repository you point it at, and it needs no user account behind it. Atlassian has put app passwords on a deprecation path, so prefer an access token for a new install.

bash
curl -sS -X POST https://your-corveil-host/api/credentials \
  -H "Authorization: Bearer <admin>" -H "Content-Type: application/json" \
  -d '{"type":"bitbucket_access_token","name":"acme-bitbucket-ro","secret":"ATCTT..."}'

Copy the returned credential id.

Required scopes

Grant read access to repositories, pull requests, and issues:

  • Access tokenrepository, pullrequest, and issue.
  • App passwordRepositories: Read, Pull requests: Read, and Issues: Read.

A missing scope surfaces as a 403 that names what to grant, rather than a bare status code.

Config fields

KeyRequiredNotes
workspaceone of workspace / reposWorkspace slug, e.g. acme. Use the slug from the workspace URL, not its display name.
reposone of workspace / reposComma-separated workspace/repo-slug list, e.g. acme/api, acme/web.
usernamenoThe account username or email, for an app password or Atlassian API token. Leave empty for an access token — see the table above.

Provide either a workspace or an explicit repo list. Setting workspace polls every repository in it; setting repos polls exactly those.

Provider-side setup

  1. Create the credential in Bitbucket:
    • Access tokenWorkspace settings → Access tokens (or a project's or repository's own settings, for a narrower scope).
    • App passwordPersonal settings → App passwords.
  2. Grant the scopes listed above.
  3. Copy the secret. Bitbucket shows it exactly once.

Wire-up

POST /api/sensors

json
{
  "sensor_type": "bitbucket",
  "name": "Acme Bitbucket",
  "config": { "workspace": "acme" },
  "credentials": { "token": "<bitbucket_access_token credential id>" }
}

To scope to specific repos instead:

json
{
  "sensor_type": "bitbucket",
  "name": "Acme API + Web",
  "config": { "repos": "acme/api, acme/web" },
  "credentials": { "token": "<bitbucket_access_token credential id>" }
}

With an app password, add the username:

json
{
  "sensor_type": "bitbucket",
  "name": "Acme Bitbucket",
  "config": { "workspace": "acme", "username": "jane@acme.com" },
  "credentials": { "token": "<bitbucket_access_token credential id>" }
}

Verify

Use Test connection on the source. It probes the workspace's repository listing — the same call the poller makes — so a pass means the credential can read what the source is configured to ingest. A bad or under-scoped credential comes back as a named auth failure quoting Bitbucket's own message, not a generic error.

After the first poll, the source's event count climbs and sensor_events carry source = "bitbucket".

What to expect

  • Backfill then poll. A new source first backfills the configured history window, then polls for what changed since a timestamp watermark. The watermark only advances when every repository succeeded, so a transient failure re-fetches its window rather than skipping it.
  • Lifecycle transitions are separate events. A pull request that opens and later merges produces two events, not one — which is what lets the graph record who merged it.
  • Repos with no issue tracker are fine. The tracker is opt-in per repository on Bitbucket Cloud; a repo without one contributes pull requests and commits as normal.
  • No author emails on pull requests or issues. Bitbucket Cloud stopped exposing user email addresses on its API in 2018, so those actors resolve by display name. Commits are the exception — their git identity includes an address, so commit authors resolve by email like any other source.
  • Review activity is polled, not backfilled. Approvals and change requests cost one request per pull request, so they are collected on the ongoing poll (capped per repository per tick) and skipped during the initial backfill. The pull-request lifecycle events covering the same people and PRs are backfilled as normal.