mesa-sdk) provides a typed Python client for interacting with the Depot API. It follows the same OpenAPI contract as the TypeScript SDK, with resource-based accessors, pagination support, retries, and structured errors.
Installation
Copy
pip install mesa-sdk
Quick Start
Copy
import os
from mesa_sdk import Mesa
client = Mesa(
api_key=os.environ["MESA_API_KEY"],
)
# Create a repository
repo = client.repos.create(
org="my-org",
body={"name": "my-repo"},
)
# List repositories
repos_page = client.repos.list(org="my-org")
print(repos_page)
Configuration
You can configure authentication, server URL, timeout, and retries when constructing the client.Copy
from mesa_sdk import Mesa
client = Mesa(
# Required: API key for authentication
api_key="your-api-key",
# Optional: Override base URL
server_url="https://depot.mesa.dev/api/v1",
# Optional: Global timeout in milliseconds
timeout_ms=30_000,
# Optional: Retry configuration
retry_config={
"strategy": "backoff",
"backoff": {
"initial_interval": 500,
"max_interval": 60_000,
"exponent": 1.5,
"max_elapsed_time": 300_000,
},
},
)
Environment Variables
The SDK can read credentials from environment variables when not explicitly configured:MESA_API_KEY- your API key
Resources
The SDK organizes methods into resource namespaces that mirror the API structure.Repositories
Copy
# Create a repository
repo = client.repos.create(
org="my-org",
body={
"name": "my-repo",
"default_branch": "main", # optional
},
)
# List repositories (paginated)
repos_page = client.repos.list(
org="my-org",
limit=50,
cursor="...", # optional
)
# Get a specific repository
repo = client.repos.get(
org="my-org",
repo="my-repo",
)
# Update a repository
updated = client.repos.update(
org="my-org",
repo="my-repo",
body={"name": "new-name"},
)
# Delete a repository
client.repos.delete(
org="my-org",
repo="my-repo",
)
Branches
Copy
# List branches
branches_page = client.branches.list(
org="my-org",
repo="my-repo",
)
# Create a branch
branch = client.branches.create(
org="my-org",
repo="my-repo",
body={
"name": "feature-branch",
"head_sha": "abc123...",
},
)
# Delete a branch
client.branches.delete(
org="my-org",
repo="my-repo",
branch="feature-branch",
)
Commits
Copy
# List commits
commits_page = client.commits.list(
org="my-org",
repo="my-repo",
ref="main", # optional
)
# Get a commit
commit = client.commits.get(
org="my-org",
repo="my-repo",
sha="abc123...",
)
# Create a commit
new_commit = client.commits.create(
org="my-org",
repo="my-repo",
body={
"branch": "main",
"message": "Add README",
"author": {
"name": "Bot",
"email": "bot@example.com",
},
"edits": [
{
"path": "README.md",
"action": "create",
"content": "# Hello from Mesa\n",
}
],
},
)
Content
Copy
# Get file content
content = client.content.get(
org="my-org",
repo="my-repo",
path="src/index.py",
ref="main", # optional
)
# Handle file vs directory responses
if getattr(content, "type", None) == "file":
print(content.content)
else:
print(content.entries)
Diffs
Copy
diff = client.diffs.get(
org="my-org",
repo="my-repo",
base="main",
head="feature-branch",
)
for file in diff.files:
print(f"{file.status}: {file.path}")
Merge
Copy
# Merge a branch into another (fast-forward when possible)
result = client.merge.perform(
org="my-org",
repo="my-repo",
base="main",
body={
"head": "feature-branch",
"author": {
"name": "Bot",
"email": "bot@example.com",
},
},
)
print(result.merge_type) # "fast_forward" or "merge_commit"
print(result.sha) # Resulting commit SHA
Copy
# Merge with a custom commit message
result = client.merge.perform(
org="my-org",
repo="my-repo",
base="main",
body={
"head": "feature-branch",
"message": "Ship feature X",
"author": {
"name": "Bot",
"email": "bot@example.com",
},
},
)
Copy
# Merge and delete the head branch afterward
result = client.merge.perform(
org="my-org",
repo="my-repo",
base="main",
body={
"head": "feature-branch",
"author": {
"name": "Bot",
"email": "bot@example.com",
},
"delete_branch": True,
},
)
print(result.branch_deleted) # True
The merge endpoint returns
409 MERGE_CONFLICT when the branches have conflicting changes that cannot be auto-resolved. Catch this error to handle conflicts in your workflow.Admin (API Keys)
Copy
# Create API key
new_key = client.admin.create_api_key(
org="my-org",
body={
"name": "CI Key",
"scopes": ["git:read", "git:write"],
},
)
print(new_key.key)
# List API keys
keys = client.admin.list_api_keys(org="my-org")
# Revoke API key
client.admin.revoke_api_key(
org="my-org",
id="key_123",
)
LFS (Large File Storage)
Copy
# Request upload URLs
upload = client.lfs.upload(
org="my-org",
repo="my-repo",
body={
"objects": [{"oid": "sha256-hash...", "size": 12_345_678}],
},
)
# Request download URLs
download = client.lfs.download(
org="my-org",
repo="my-repo",
body={
"objects": [{"oid": "sha256-hash...", "size": 12_345_678}],
},
)
Pagination
List endpoints support cursor-based pagination.Copy
cursor = None
while True:
page = client.repos.list(
org="my-org",
cursor=cursor,
limit=100,
)
for repo in page.result.repos:
print(repo.name)
cursor = page.result.next_cursor
if not cursor:
break
Error Handling
The SDK raises exceptions for request and response failures. Catch and branch on error type or status as needed by your application.Copy
try:
client.repos.get(org="my-org", repo="missing")
except Exception as exc:
# Handle SDK-specific errors in your application layer.
# Common categories: auth errors, validation errors, not found,
# conflict, and transport failures.
print(f"Request failed: {exc}")
raise
Error Shape
API errors follow a consistent shape:Copy
{
"error": {
"code": "NOT_FOUND",
"message": "Repository not found",
"details": {}
}
}
Per-Request Options
You can override client defaults for a single request (for example timeout, retries, or headers).Copy
repo = client.repos.get(
org="my-org",
repo="my-repo",
request_options={
"timeout_ms": 60_000,
"headers": {
"X-Custom-Header": "value",
},
},
)
Complete Example
Copy
import os
from mesa_sdk import Mesa
def main() -> None:
client = Mesa(api_key=os.environ["MESA_API_KEY"])
# Create repository
client.repos.create(
org="my-org",
body={"name": "example-repo"},
)
# Initial commit on main
client.commits.create(
org="my-org",
repo="example-repo",
body={
"branch": "main",
"message": "Initial commit",
"author": {
"name": "Bot",
"email": "bot@example.com",
},
"edits": [
{
"path": "README.md",
"action": "create",
"content": "# Example Repository\n",
}
],
},
)
# Create feature branch from latest main commit
commits_page = client.commits.list(
org="my-org",
repo="example-repo",
ref="main",
limit=1,
)
head_sha = commits_page.result.commits[0].sha
client.branches.create(
org="my-org",
repo="example-repo",
body={
"name": "feature",
"head_sha": head_sha,
},
)
# Commit feature change
client.commits.create(
org="my-org",
repo="example-repo",
body={
"branch": "feature",
"message": "Add feature",
"author": {
"name": "Bot",
"email": "bot@example.com",
},
"edits": [
{
"path": "feature.py",
"action": "create",
"content": "FEATURE_ENABLED = True\n",
}
],
},
)
# Diff feature against main
diff = client.diffs.get(
org="my-org",
repo="example-repo",
base="main",
head="feature",
)
print(f"Changes: {len(diff.files)} files")
# Merge feature branch into main and clean up
merge = client.merge.perform(
org="my-org",
repo="example-repo",
base="main",
body={
"head": "feature",
"author": {
"name": "Bot",
"email": "bot@example.com",
},
"delete_branch": True,
},
)
print(f"Merged via {merge.merge_type}: {merge.sha}")
if __name__ == "__main__":
main()
For endpoint behavior and payload details shared across all SDKs, see the HTTP API Reference.

