> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.basement.chat/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.basement.chat/_mcp/server.

# Python SDK

The package is [`basement-gateway`](https://pypi.org/project/basement-gateway/). The source is on [GitHub](https://github.com/Get-Basement/gateway-python).

## Install

```bash
pip install basement-gateway
```

## Create the client

```python
import os
from basement_gateway import BasementGateway

basement = BasementGateway(api_key=os.environ["BASEMENT_API_KEY"])
```

When you do not give `api_key`, the client reads the `BASEMENT_API_KEY` environment variable.

## Call the Gateway

Each tool is a method. Arguments are keyword arguments, and answers are typed objects.

```python
# Documents
docs = basement.docs.list().docs
doc = basement.docs.read(doc_id=docs[0].id)

basement.docs.edit(
    doc_id=doc.id,
    old_text="Prices are in USD",
    new_text="Prices are in BRL",
    change_summary="Currency",
)

# Search, and read a part of a text
results = basement.search(query="pricing").results
found = basement.text.find(doc_id=doc.id, query="discount")

# Tasks
task = basement.tasks.create(title="Review the Q4 pricing")
basement.tasks.update(task_id=task.task_id, status="done")

# Connected services
connected = basement.services.list().connected
issue = basement.services.execute(
    tool_slug="jira__getJiraIssue",
    arguments={"issueIdOrKey": "OPS-12"},
)
```

## Async

`AsyncBasementGateway` has the same methods, with `await`:

```python
import asyncio
from basement_gateway import AsyncBasementGateway

basement = AsyncBasementGateway()

async def main():
    docs = (await basement.docs.list()).docs
    print(len(docs))

asyncio.run(main())
```

## Handle errors

A call that the Gateway refuses raises an `ApiError` with the HTTP status and the error body.

```python
from basement_gateway.core.api_error import ApiError

try:
    basement.tasks.create(title="Review the Q4 pricing")
except ApiError as error:
    print(error.status_code)         # 403
    print(error.body.error.code)     # "forbidden"
    print(error.body.error.message)  # "Role lacks write access"
```

See [Errors and limits](/sdks/errors-and-limits) for each status.

## Timeouts and retries

A call times out after 60 seconds. The client tries a call again, up to 2 more times, when it gets `408`, `429` or a `5xx` status. Change both for the client or for one call:

```python
basement = BasementGateway(timeout=30)

basement.docs.list(request_options={"timeout_in_seconds": 10, "max_retries": 3})
```

## Another address

The client talks to `https://mcp.basement.chat`. To use another deployment, give `base_url`:

```python
basement = BasementGateway(base_url="http://127.0.0.1:3214")
```