Integrates with Bitbucket Cloud and Bitbucket Data Center REST APIs via
Scanned 9/4/2026
Install to Claude Code
npx -y skills add paulpas/agent-skill-router --skill bitbucket-api --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Bitbucket Api?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/paulpas-bitbucket-api)More formats (shields.io, HTML) on the badges page.
---
name: bitbucket-api
description: Integrates with Bitbucket Cloud and Bitbucket Data Center REST APIs via
atlassian-python-api to manage repositories, pull requests, pipelines, webhooks,
and workspace settings.
license: MIT
compatibility: opencode
metadata:
version: "1.0.0"
domain: coding
triggers: bitbucket api, atlassian-python-api, bitbucket cloud, bitbucket pipelines,
pull request bitbucket, bitbucket webhooks, manage bitbucket repos, bitbucket
data center
archetypes:
- tactical
- generation
anti_triggers:
- brainstorming
- vague ideation
- code golf
- over-engineering
response_profile:
verbosity: low
directive_strength: high
abstraction_level: operational
role: implementation
scope: implementation
output-format: code
content-types:
- code
- guidance
- do-dont
- examples
related-skills: coding-github-api, coding-gitlab-api, coding-jenkins-api
---
# Bitbucket API & atlassian-python-api Integration
Integrates with Bitbucket Cloud (API v2) and Bitbucket Server/Data Center REST APIs using the `atlassian-python-api` library to manage repositories, pull requests, pipelines, branch restrictions, webhooks, and workspace administration.
## TL;DR for Code Generation
- [ ] Use `Cloud(username, password)` for Bitbucket Cloud or `Bitbucket(url, username, password)` for Bitbucket Server/Data Center
- [ ] Bitbucket Cloud provides an object-oriented API (`cloud.workspaces.each()`, `workspace.repositories.each()`)
- [ ] Bitbucket Server uses a functional API (`bitbucket.project_list()`, `bitbucket.get_repo()`)
- [ ] Authenticate with app passwords for Cloud (not your main account password)
- [ ] Pass `sort="-created_on"` to pipeline list calls to get recent builds first
- [ ] Handle `HTTPError` from the `requests` library for API error responses
---
## When to Use
Use this skill when:
- Automating repository creation, project administration, or branch permission management
- Building pull request workflows with automatic merge, approval, or CI triggers
- Querying Bitbucket Pipelines status, logs, and deployment results
- Managing webhooks for repository events (push, PR, pipeline status)
- Administering workspace or project-level user permissions and group access
- Creating or updating branch restrictions and default reviewers
---
## When NOT to Use
Avoid this skill for:
- Git clone/push/fetch operations (use `gitpython` or raw `git` CLI)
- Full CI/CD pipeline YAML authoring (use the Bitbucket Pipelines editor or `bitbucket-pipelines.yml`)
- Jira or Confluence operations (use the same `atlassian-python-api` but with `Jira` or `Confluence` classes)
---
## Core Workflow
1. **Authenticate — Cloud vs. Server** — For Cloud, use `Cloud(url="https://api.bitbucket.org", username, password)` with an app password. For Server, use `Bitbucket(url, username, password)`. **Checkpoint:** List workspaces or projects to confirm connectivity.
2. **Resolve Workspace and Repository** — For Cloud: `workspace = cloud.workspaces.get(slug)` then `repo = workspace.repositories.get(slug)`. For Server: `bitbucket.get_repo(project_key, repo_slug)`. **Checkpoint:** Verify the repository name matches and the `uuid` or `id` is present.
3. **Execute Operation** — Call the appropriate method: create a pull request, trigger a pipeline, add a webhook, or modify branch restrictions. **Checkpoint:** Confirm the response includes the expected object ID or URL.
4. **Handle Pagination** — Methods returning generators (`.each()`) handle pagination automatically. For raw REST, pass `pagelen=100` and handle the `next` URL from responses. **Checkpoint:** Ensure all pages are consumed — Cloud defaults to 50 items per page.
5. **Error Handling** — Catch `requests.exceptions.HTTPError` and inspect the status code. 401=bad auth, 403=insufficient permissions, 404=not found. **Checkpoint:** Log the response body for 400-level errors to see validation messages.
---
## Implementation Patterns
### Pattern 1: Bitbucket Cloud — Pull Request Management
```python
import os
from atlassian.bitbucket import Cloud
from requests.exceptions import HTTPError
def create_pull_request(
workspace_slug: str,
repo_slug: str,
source_branch: str,
destination_branch: str,
title: str,
description: str = "",
close_source_branch: bool = True,
) -> dict:
"""Create a pull request in Bitbucket Cloud.
Args:
workspace_slug: Workspace identifier (e.g., "my-company").
repo_slug: Repository name (e.g., "backend-api").
source_branch: Feature branch to merge from.
destination_branch: Target branch to merge into.
title: Pull request title.
description: Pull request description in Markdown.
close_source_branch: Auto-close source branch after merge.
Returns:
Dict with PR ID, links, and state.
Raises:
RuntimeError: If authentication fails or the PR cannot be created.
"""
cloud = Cloud(
url="https://api.bitbucket.org",
username=os.environ["BITBUCKET_USERNAME"],
password=os.environ["BITBUCKET_APP_PASSWORD"],
)
try:
workspace = cloud.workspaces.get(workspace_slug)
repo = workspace.repositories.get(repo_slug)
except HTTPError as exc:
status = exc.response.status_code
if status == 404:
raise RuntimeError(
f"Repository '{workspace_slug}/{repo_slug}' not found."
) from exc
raise RuntimeError(
f"Failed to access Bitbucket resources: HTTP {status}"
) from exc
try:
pr = repo.pullrequests.create(
title=title,
description=description,
source={"branch": {"name": source_branch}},
destination={"branch": {"name": destination_branch}},
close_source_branch=close_source_branch,
)
except HTTPError as exc:
body = exc.response.text
raise RuntimeError(
f"Pull request creation failed: HTTP {exc.response.status_code} — {body}"
) from exc
return {
"id": pr.id,
"title": pr.title,
"state": pr.state,
"links": {"html": pr.links["html"]["href"]},
}
```
### Pattern 2: Bitbucket Pipelines — Trigger and Monitor
```python
import time
import os
from atlassian.bitbucket import Cloud
from requests.exceptions import HTTPError
def trigger_pipeline_and_get_result(
workspace_slug: str,
repo_slug: str,
branch: str = "main",
poll_interval: int = 15,
timeout: int = 900,
) -> dict:
"""Trigger a Bitbucket Pipeline and wait for completion.
Args:
workspace_slug: Workspace identifier.
repo_slug: Repository name.
branch: Branch to run the pipeline on.
poll_interval: Seconds between status checks.
timeout: Maximum seconds to wait.
Returns:
Dict with pipeline UUID, state, and result.
Raises:
TimeoutError: If the pipeline doesn't complete in time.
"""
cloud = Cloud(
url="https://api.bitbucket.org",
username=os.environ["BITBUCKET_USERNAME"],
password=os.environ["BITBUCKET_APP_PASSWORD"],
)
repo = cloud.workspaces.get(workspace_slug).repositories.get(repo_slug)
# Trigger the pipeline for the given branch
pipeline = repo.pipelines.create(
body={
"target": {
"type": "pipeline_ref_target",
"ref_type": "branch",
"ref_name": branch,
}
}
)
pipeline_uuid = pipeline.uuid
# Poll for completion
start = time.monotonic()
while True:
if time.monotonic() - start > timeout:
raise TimeoutError(
f"Pipeline {pipeline_uuid} did not complete within {timeout}s."
)
time.sleep(poll_interval)
# Re-fetch the pipeline object to get updated state
for p in repo.pipelines.each(sort="-created_on"):
if p.uuid == pipeline_uuid:
state = p.state
if state["type"] != "PIPELINE_STATE_IN_PROGRESS":
return {
"uuid": pipeline_uuid,
"state": state["type"],
"result": state.get("result", {}).get("type"),
"duration_seconds": p.duration_in_seconds,
}
break
```
### Pattern 3: Bitbucket Server — Project and Repository Admin
```python
from atlassian import Bitbucket
import os
def create_project_with_repo(
project_key: str,
project_name: str,
repo_name: str,
is_private: bool = True,
) -> dict:
"""Create a Bitbucket Server project and repository.
Args:
project_key: Short project key (e.g., "OPS").
project_name: Human-readable project name.
repo_name: Repository slug (kebab-case).
is_private: Whether the repo should be private.
Returns:
Dict with project and repository keys.
"""
bitbucket = Bitbucket(
url=os.environ["BITBUCKET_SERVER_URL"],
username=os.environ["BITBUCKET_USERNAME"],
password=os.environ["BITBUCKET_PASSWORD"],
)
# Create the project
try:
project = bitbucket.create_project(project_key, project_name)
except HTTPError as exc:
if exc.response.status_code == 409:
project = bitbucket.project(project_key)
else:
raise
# Create the repository within the project
try:
repo = bitbucket.create_repo(
project_key=project_key,
repo=repo_name,
is_private=is_private,
)
except HTTPError as exc:
if exc.response.status_code == 409:
repo = bitbucket.get_repo(project_key, repo_name)
else:
raise
return {
"project_key": project["key"],
"repo_name": repo["slug"],
"clone_url": repo["links"]["clone"][0]["href"],
}
```
### BAD vs GOOD: Pipeline Status Polling
```python
# ❌ BAD — no timeout, tight loop, no error handling
def poll_pipeline_bad(repo, uuid):
while True:
for p in repo.pipelines.each():
if p.uuid == uuid:
if p.state["type"] != "PIPELINE_STATE_IN_PROGRESS":
return p.state
time.sleep(1) # Too frequent, may hit rate limits
# ✅ GOOD — timeout, exponential backoff, error handling
import time
def poll_pipeline_good(
repo,
pipeline_uuid: str,
timeout: int = 600,
) -> dict:
"""Poll a Bitbucket pipeline until completion with timeout.
Uses exponential backoff to avoid rate limiting.
"""
start = time.monotonic()
backoff = 5
while time.monotonic() - start < timeout:
try:
for p in repo.pipelines.each(sort="-created_on"):
if p.uuid == pipeline_uuid:
state_type = p.state["type"]
if state_type != "PIPELINE_STATE_IN_PROGRESS":
return {
"uuid": pipeline_uuid,
"state": state_type,
"result": p.state.get("result", {}).get("type"),
"duration": p.duration_in_seconds,
}
break
except HTTPError as exc:
if exc.response.status_code == 429:
time.sleep(backoff)
backoff = min(backoff * 2, 60)
continue
raise
time.sleep(10) # Normal poll interval
raise TimeoutError(f"Pipeline {pipeline_uuid} did not complete in {timeout}s.")
```
## MUST DO
- Use app passwords for Bitbucket Cloud authentication (Settings → Access Management → App Passwords)
- Grant app passwords only the scopes needed (repo, pull request, pipeline)
- Use the object-oriented Cloud API (`Cloud` class) for Bitbucket Cloud and the functional API (`Bitbucket` class) for Server/DC
- Pass `sort="-created_on"` when listing pipelines to get the most recent first
- Set a reasonable timeout (>= 600s) when polling pipeline results
- Check 409 Conflict responses to handle idempotent resource creation
## MUST NOT DO
- Never use your main Bitbucket password for API access — always use app passwords
- Do not hardcode workspace or repository slugs in application code
- Avoid polling pipelines without backoff — Bitbucket rate-limits at 1000 requests/hour
- Never log or print pipeline variables or authentication tokens
- Do not assume pagination is complete without checking the `next` page link
---
## Constraints
### MUST DO
- Implement structured error responses with consistent format: {error_code, message, details, request_id}
- Add rate limiting per client/API key with configurable burst and sustained limits using a token bucket algorithm
- Validate all incoming requests against a schema before processing — reject malformed input with clear error messages
- Include correlation/request IDs in all log entries for end-to-end request tracing across service boundaries
### MUST NOT DO
- Do not expose internal implementation details, stack traces, or database queries in error responses
- Avoid accepting unbounded request bodies — set maximum payload sizes and timeout limits
- Never trust client-supplied authentication tokens without validation (signature verification, expiration check)
- Do not log request/response bodies containing PII, API keys, or other sensitive data
## Live References
- [atlassian-python-api Documentation](https://atlassian-python-api.readthedocs.io/)
- [atlassian-python-api GitHub Repository](https://github.com/atlassian-api/atlassian-python-api)
- [Bitbucket Cloud REST API v2](https://developer.atlassian.com/cloud/bitbucket/rest/api-group-repositories/)
- [Bitbucket Server/Data Center REST API](https://developer.atlassian.com/server/bitbucket/rest/)
- [Bitbucket Cloud Pipelines API](https://developer.atlassian.com/cloud/bitbucket/rest/api-group-pipelines/)
- [Bitbucket App Passwords Documentation](https://support.atlassian.com/bitbucket-cloud/docs/app-passwords/)
- [Bitbucket Webhook Events Reference](https://developer.atlassian.com/cloud/bitbucket/rest/api-group-webhooks/)
## Related Skills
| Skill | Purpose |
|---|---|
| `coding-github-api` | GitHub API with PyGithub for repository and PR automation |
| `coding-gitlab-api` | GitLab API with python-gitlab for CI/CD and MR management |
| `coding-jenkins-api` | Jenkins automation for cross-platform CI/CD orchestration |
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!