Busabase

Python SDK

Install the official Python SDK with pip and read your first Bases and records from Busabase Cloud or a self-hosted server.

busabase is the official Python client for the Busabase REST API. Use it from scripts, notebooks, data pipelines, and Python backends. One client works against Busabase Cloud and any self-hosted Busabase server, and it uses the same base URL, API key, and workspace settings as the CLI and the TypeScript SDK.

Every endpoint has a typed model, generated from the Busabase OpenAPI document. A small hand-written layer on top adds configuration from environment variables, bb.<group>.<operation>(...) calls, and a BusabaseError for every failed request.

Install

pip install busabase

Or use uv add busabase in a uv project.

Quick start

from busabase import Busabase

bb = Busabase(api_key="bb_...")  # or set BUSABASE_API_KEY
for base in bb.bases.list():
    print(base.slug, base.name)
record = bb.records.get(record_id="rec_...")
print(record.head_commit.payload.to_dict())  # the record's field values

Create an API key in API keys (a read key is enough for this example), and replace rec_... with the id of a record you can see. The script prints the slug and name of each Base visible to your key, then that record's field values. It only reads data.

Busabase Cloud or self-hosted

Busabase CloudSelf-hosted server
base_url / BUSABASE_BASE_URLhttps://busabase.com (the default)Your server, e.g. http://localhost:15419
api_key / BUSABASE_API_KEYRequired. Create one in API keysNot needed for a local server
space / BUSABASE_SPACE_IDNeeded when your key can reach more than one workspaceUsually not needed
bb = Busabase()  # everything from the environment
bb = Busabase(base_url="http://localhost:15419")  # a local `busabase server`
bb = Busabase(api_key="bb_...", space="spc_...")  # a specific Cloud workspace

base_url works with or without a trailing /api/v1.

The SDK reads environment variables, but does not load ~/.busabase/.env by itself. To reuse the connection you saved with busabase-cli login and busabase-cli space use, export that file before running Python:

set -a; . "$HOME/.busabase/.env"; set +a
python quickstart.py

Cloud-only endpoints. The SDK covers the full public API. A few groups exist only on Busabase Cloud and return 404 from a self-hosted server: system (health, meta), users.me, and agent_tasks.

Writing: Change Requests

Every write in Busabase is a Change Request. When your key has write access, it merges in the same call and you get the saved object back. Otherwise it waits in the inbox for a person to review. Check which one you got:

from busabase.generated.models import MaterializedRecord, PendingChangeRequest

result = bb.bases.create_change_request(
    base_id="bas_...",
    body={"fields": {"company": "Acme", "score": 7}, "message": "Add Acme — inbound lead"},
)
if isinstance(result, MaterializedRecord):
    print("merged:", result.id)
elif isinstance(result, PendingChangeRequest):
    print("waiting for review:", result.id)

Don't pass autoMerge. Let the server decide from your key's permissions.

Calling operations

Operations are grouped the way the API is (bases, records, nodes, docs, file_trees, change_requests, search, grep, …), with snake_case names. dir(bb) and dir(bb.records) list them.

bb.records.list(base_id="bas_...", limit=20)
bb.nodes.get("nod_...")  # path parameters can be positional
bb.grep(body={"pattern": "acme", "sources": ["records", "nodes"]})
await bb.records.get.asyncio(record_id="rec_...")  # async

A request body can be a plain dict or the generated model. Request and response shapes are listed in the API reference.

Errors

Any HTTP status of 400 or above raises BusabaseError, carrying the server's error envelope:

from busabase import BusabaseError

try:
    bb.records.get(record_id="rec_missing")
except BusabaseError as error:
    print(error.status, error.code, error.message)  # 404 NOT_FOUND Record not found: rec_missing

code is the server's outcome (NOT_FOUND, FORBIDDEN, BAD_REQUEST, CONFLICT, …). For a validation failure, message names each field and data holds the raw issues.

Keep API keys in your server environment, not in notebooks you share or commit. More options, including async usage, timeouts, and proxies, are in the SDK README.

Other ways to connect: Integration overview · CLI · SDK · Python SDK · MCP · OpenAPI / REST · Agent Skills · Webhooks

On this page