Official Boost.space API SDK (Python)
Project description
boostspace-sdk
Official Boost.space API SDK for Python — fully typed (pydantic v2 + httpx), generated from the OpenAPI spec. Sync and async.
Install
pip install boostspace-sdk
Requires Python ≥ 3.11.
Quickstart (sync)
from boostspace import BoostSpace
# Per-tenant base URL: https://<system>.boost.space/api
with BoostSpace(token="...", system="acme") as bs:
space = bs.spaces.get(1) # typed pydantic model
for s in bs.spaces.list(limit=50): # transparent pagination
print(s.name)
page = bs.spaces.list().page() # single page + total
print(page.found_records)
Quickstart (async)
import asyncio
from boostspace import AsyncBoostSpace
async def main() -> None:
async with AsyncBoostSpace(token="...", system="acme") as bs:
record = await bs.records.ref(1).get()
labels = await bs.records.ref(1).labels().all() # async pagination
async for r in bs.records.list(limit=50):
print(r.id)
asyncio.run(main())
OAuth2 / MCP tokens
Besides a static API token, the client accepts a callable token provider,
resolved per request. OAuth2Session implements the Boost.space OAuth2 flow
(MCP clients included — their tokens are ordinary OAuth2 access tokens) and is
itself callable, refreshing proactively before expiry:
from boostspace.runtime import OAuth2Session
session = OAuth2Session("client-id", "client-secret", system="acme",
refresh_token=stored_refresh_token)
# or bootstrap from an authorization code:
# session.exchange_code(code, redirect_uri="https://app.example.com/cb")
bs = BoostSpace(session, system="acme") # token stays fresh automatically
Relationship navigation
creator = bs.records.created_by(record) # belongsTo → related record (User)
for label in bs.records.labels(record.id): # hasMany → related collection
...
expanded = bs.records.expand(record, ["space", "created_by"]) # eager-load several at once
print(expanded.space.name if expanded.space else None)
Filtering
from boostspace import Filter
page = bs.spaces.list(
filter=str(
Filter.equals("color", "#4A90D9")
.and_(Filter.greater_than_or_equal("id", 3))
.and_(Filter.any_of(Filter.equals("name", "Acme"), Filter.equals("name", "Globex")))
)
).page()
# color=#4A90D9;id>=3;(name=Acme|name=Globex)
Operators: eq ne gt gte lt lte like not_like in_ is_null, combined with
and_/or_ (OR nested in AND is parenthesised automatically).
Upsert
Create-or-update by a match filter in a single call:
from boostspace import Filter, models
saved = bs.spaces.upsert(
Filter.equals("name", "VIP"),
models.Space(name="VIP", color="#ff0000"),
)
upsert lists by the filter, then updates the single match or creates one when
none exists. More than one match raises AmbiguousMatchError. Available on
resources that expose list + create + update over the same model.
Delta sync
Pull only the records changed since your last sync — pass updated_since (a Unix
timestamp) to list, and pair it with list_deleted to learn which records were
removed since the same point:
since = "1704067200" # Unix timestamp of your last sync
for record in bs.records.list(updated_since=since): # streams changed records
reindex(record)
for deleted_id in bs.records.list_deleted(updated_since=since):
drop(deleted_id)
Bulk with chunking
Split a large bulk update/delete into chunks and collect per-chunk failures instead of failing all-or-nothing:
report = bs.records.update_chunked(batch, chunk_size=100)
if not report.ok:
for f in report.failed: # BulkChunkError(index, size, error)
print(f.index, f.error)
print(len(report.results))
Resolve a boostId
Map a Boost.space boostId (e.g. "Space5") to its typed record across
entities, without knowing which resource it belongs to:
record = bs.resolve("Space5") # a typed model, or None
if record is not None:
print(record.boostId)
Returns None for an unknown prefix, a missing record, or a UUID-style id. The
result is verified against the input boostId, so it is never a wrong-type record.
Field values
Read a record's Boost.space field values keyed by field name (self-contained from the record — no extra request):
values = bs.records.field_values(record) # {"Rating": "5", "Tier": "gold"}
Available on resources whose model carries custom field values. Writing field values by name is planned for a later release.
Timeouts & observability
from boostspace import Hooks
bs = BoostSpace(
token="...", system="acme",
timeout=10.0, # per-request timeout in seconds (default 30)
hooks=Hooks(
on_request=lambda m, u, h: h.__setitem__("X-Trace-Id", trace_id),
on_response=lambda m, u, s, ms: metrics.record(s, ms),
),
)
Errors
from boostspace import NotFoundError
try:
bs.spaces.get(999)
except NotFoundError as err:
print(err.http_status, err.code) # internal Boost.space error code
Requests retry with jittered backoff on 429/5xx, only for idempotent methods.
Testing without a live API
Inject an httpx client backed by a mock transport to unit-test your code:
import httpx
from boostspace import BoostSpace
def handler(request: httpx.Request) -> httpx.Response:
return httpx.Response(200, json={"id": 1, "name": "Mock Inc"})
bs = BoostSpace("token", system="acme",
http_client=httpx.Client(transport=httpx.MockTransport(handler)))
assert bs.spaces.get(1).name == "Mock Inc" # no network
License
MIT
Guides
In-depth how-to guides live in docs/guides/:
filtering ·
ordering & pagination ·
authentication ·
record handles (ref) ·
relations & expand ·
delta sync & bulk ·
errors & retries ·
testing & mocking
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file boostspace_sdk-0.1.3.tar.gz.
File metadata
- Download URL: boostspace_sdk-0.1.3.tar.gz
- Upload date:
- Size: 93.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf984c4af7be9b9a5d6d8684b4cb385e691aa0e04b4ba48c83ec20d462803c9d
|
|
| MD5 |
5c6e10431df30d1cf2e85132a3c7c867
|
|
| BLAKE2b-256 |
c818b0589bba900ac1743cd81660e4cf84fa874782faaeb15ec521e1e12912b6
|
Provenance
The following attestation bundles were made for boostspace_sdk-0.1.3.tar.gz:
Publisher:
ci.yml on boostspace/sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
boostspace_sdk-0.1.3.tar.gz -
Subject digest:
bf984c4af7be9b9a5d6d8684b4cb385e691aa0e04b4ba48c83ec20d462803c9d - Sigstore transparency entry: 2225128022
- Sigstore integration time:
-
Permalink:
boostspace/sdk@b1526b5698858ec52954c172e5f0229c7d944ad2 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/boostspace
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@b1526b5698858ec52954c172e5f0229c7d944ad2 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file boostspace_sdk-0.1.3-py3-none-any.whl.
File metadata
- Download URL: boostspace_sdk-0.1.3-py3-none-any.whl
- Upload date:
- Size: 136.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da762f5201d04acb54d8e7a1d368f5d49fcf3e28a9753ab4f12bb900c96e6a68
|
|
| MD5 |
dd85410d5e69a919b3c18883870193fb
|
|
| BLAKE2b-256 |
01ac1ecd387aef833cee957210a834eb97ffa10719fb5db2f0d6438c6215d772
|
Provenance
The following attestation bundles were made for boostspace_sdk-0.1.3-py3-none-any.whl:
Publisher:
ci.yml on boostspace/sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
boostspace_sdk-0.1.3-py3-none-any.whl -
Subject digest:
da762f5201d04acb54d8e7a1d368f5d49fcf3e28a9753ab4f12bb900c96e6a68 - Sigstore transparency entry: 2225128487
- Sigstore integration time:
-
Permalink:
boostspace/sdk@b1526b5698858ec52954c172e5f0229c7d944ad2 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/boostspace
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@b1526b5698858ec52954c172e5f0229c7d944ad2 -
Trigger Event:
workflow_dispatch
-
Statement type: