> ## Documentation Index
> Fetch the complete documentation index at: https://recipe.uselettuce.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Bitbucket

> Connect your Bitbucket Cloud repos to Lettuce — authorize via OAuth, pick repos across workspaces, push webhooks wired automatically.

Lettuce pulls repos directly from **Bitbucket Cloud** through OAuth2. As
the admin connecting your team to Lettuce, you click *Connect Bitbucket*,
grant Lettuce access on Bitbucket, pick the repos you want indexed across
any workspaces you're a member of, and Lettuce takes care of cloning them
plus wiring up push-event webhooks so future commits trigger a re-index.

The manual "paste a git URL" flow keeps working alongside this — use it for
public repos hosted anywhere git speaks.

<Note>
  **This page is for the admin connecting your team's Bitbucket repos to
  Lettuce Cloud.** If you're standing up a self-hosted Lettuce install,
  the one-time Bitbucket OAuth-consumer registration that backs this flow
  is documented in [Self-hosted install](/self-hosted/install). Bitbucket
  Data Center (the self-hosted Atlassian product) isn't supported in v1 —
  self-hosted Lettuce only connects to Bitbucket Cloud today.
</Note>

## Connect Bitbucket and add repos

<Steps>
  <Step title="Open the Repos page">
    Sign in to Lettuce, go to **Repos**, click **+ Add repo**.
  </Step>

  <Step title="Connect Bitbucket">
    On the **Bitbucket** tab, click **Connect Bitbucket →**. You're
    redirected to bitbucket.org.

    Bitbucket shows the permissions Lettuce is requesting (Account: Read,
    Workspace membership: Read, Projects: Read, Repositories: Read+Write,
    Webhooks: Read+Write — see below for why). Click **Grant access**.

    Bitbucket redirects you back to Lettuce.
  </Step>

  <Step title="Pick a repo">
    You land back on **Repos** with a green toast — "Bitbucket connected".
    The Add-repo dialog now lists every repo you have **contributor or
    higher** access to, across every workspace you're a member of. Filter
    by `workspace/repo` substring, then click one.

    Lettuce:

    1. Registers the repo against your account.
    2. Auto-creates a webhook on it (`repo:push` event) so future commits
       trigger a re-index.
    3. Queues a clone + index job. Status moves from *pending* to
       *indexing* to *ready* — usually in a few seconds for small repos.

    No copy-pasting URLs, no fiddling with webhook secrets.
  </Step>

  <Step title="(Optional) Add more later">
    The dialog remembers your connection — re-open it any time to add
    another repo. Tokens refresh automatically; you only need to come
    back here if you revoke Lettuce on Bitbucket or otherwise invalidate
    the connection. In that case the Bitbucket tab shows
    **Re-connect Bitbucket** instead of the picker.
  </Step>
</Steps>

## What Lettuce asks for, and why

The Lettuce Bitbucket OAuth grant requests least-privilege scopes for
"list workspaces + list repos + clone + manage webhooks":

| Scope                      | Why                                                                       |
| -------------------------- | ------------------------------------------------------------------------- |
| Account: Read              | Identify your Bitbucket user.                                             |
| Workspace membership: Read | List the workspaces you belong to.                                        |
| Projects: Read             | List the projects in those workspaces.                                    |
| Repositories: Read         | Clone repos over HTTPS.                                                   |
| Repositories: Write        | Register the per-account push webhook on each repo you add.               |
| Webhooks: Read & write     | Same — webhook management is gated on this scope on some Bitbucket plans. |

Lettuce never asks for write access to your code. The *Repositories:
Write* scope is required only because Bitbucket gates the webhook-
registration API behind it. We do not push commits.

## How the security model works

* Per-account access + refresh tokens are stored against your Lettuce
  account. The access token is short-lived (\~2h); Lettuce refreshes
  on demand whenever it needs to call the Bitbucket API. If refresh
  ever fails (you revoked Lettuce on Bitbucket, your workspace admin
  removed third-party-OAuth permission, etc.) the UI surfaces a
  **Reconnect Bitbucket** prompt instead of failing the whole flow.
* The OAuth-style **`state`** param on the install callback is
  HMAC-signed and bound to the Lettuce account that started the
  connect flow, so a redirect can't be replayed against a different
  account.
* The **webhook secret** is per-account, generated automatically the
  first time you add a repo, and reused across every repo. Bitbucket
  signs each webhook payload with HMAC-SHA256 in the `X-Hub-Signature`
  header (same format as GitHub: `sha256=<hex>`), and Lettuce rejects
  any delivery whose signature doesn't match. You can rotate the
  secret from **Settings → Webhook** in the Lettuce dashboard;
  rotation invalidates every existing Bitbucket webhook for your
  account and re-registers them with the new secret.

## Disconnecting

Owners can disconnect the Bitbucket integration from the Lettuce side
under **Settings → Connected integrations** (or via the `DELETE
/v1/integrations/bitbucket` API). Disconnecting:

* Discards the stored access and refresh tokens.
* Leaves all your existing repos in place — they keep working as long as
  they're public. Private repos will fail their next re-clone until you
  reconnect or switch them to a paste-URL with credentials.

To fully revoke access on the Bitbucket side, go to **Your profile and
settings → Personal settings → Access management → OAuth** and revoke the
Lettuce consumer.

## Troubleshooting

<AccordionGroup>
  <Accordion title="The 'Connect Bitbucket' button is greyed out / missing">
    On Lettuce Cloud the Bitbucket integration is always available — if
    you see this state, refresh the page and re-open the Add-repo
    dialog. On a self-hosted Lettuce install, this means your admin
    hasn't finished the OAuth-consumer registration; see the self-hosted
    admin note below.
  </Accordion>

  <Accordion title="Bitbucket redirects me back with 'invalid or expired install state'">
    The signed `state` param is older than 15 minutes. Restart the
    install from the Add-repo dialog.
  </Accordion>

  <Accordion title="I see 'Bitbucket access was denied'">
    You clicked **Cancel** on Bitbucket's authorization screen, or your
    workspace admin has restricted third-party OAuth consumers. Ask your
    Bitbucket workspace admin to allow the Lettuce consumer, then retry.
  </Accordion>

  <Accordion title="The picker says 'No repos visible in any of your workspaces'">
    Lettuce only lists repos you have at least *contributor* access to.
    If you only have *read* access to a repo, ask the owner to bump your
    permission, or have an admin on that workspace connect Lettuce
    themselves and add the repo on the workspace's behalf.
  </Accordion>

  <Accordion title="My private repo clones but later pushes don't trigger a refresh">
    The auto-webhook step may have failed if Bitbucket rejected the
    `Webhooks: Read and write` scope at authorize time. Click
    **Re-connect Bitbucket** in the Add-repo dialog and make sure all
    requested scopes are granted on the Bitbucket consent screen.
  </Accordion>
</AccordionGroup>

<Note>
  **Self-hosted admin note.** The end-user flow above only works once
  the Lettuce Bitbucket OAuth consumer has been registered against
  Bitbucket. On Lettuce Cloud, the Lettuce team has done this for you. On
  a self-hosted install, your admin registers the consumer once and
  points the worker / api pods at it via `BITBUCKET_APP_CLIENT_ID` and
  `BITBUCKET_APP_CLIENT_SECRET` — see
  [Self-hosted install](/self-hosted/install). Bitbucket Data Center is
  not yet supported in v1.
</Note>
