Python async API client wrapper for the Cinder API.
- Async/await support
- Type-safe request/response models using Pydantic
- Automatic request/response validation
- Authentication handling
# Using pip
pip install git+https://github.com/roverdotcom/cinder.git
# Using uv
uv pip install git+https://github.com/roverdotcom/cinder.git# Using pip
pip install -e /path/to/cinder
# Using uv
uv pip install -e /path/to/cinderAdd to your requirements.txt:
cinder @ git+https://github.com/roverdotcom/cinder.git@masterOr with uv in pyproject.toml:
[project]
dependencies = [
"cinder @ git+https://github.com/roverdotcom/cinder.git",
]The client can be configured using environment variables:
export CINDER_API_BASE_URL="https://rover-staging.cinderapp.com"
export CINDER_API_TOKEN="XXXXXXXXXXXXXX"Add to settings:
# Cinder API Configuration
CINDER_API_BASE_URL = os.environ.get("CINDER_API_BASE_URL")
CINDER_API_TOKEN = os.environ.get("CINDER_API_TOKEN")Note: Sync vs Async
For its first few steps into the real world, this library offers both sync and async variants. Some of the sync code is the LLM-generated version of the other, and vice versa, as the code is quite boilerplate-ish.
However, as we move forward with this, keep in mind that some day one of them might be dropped (and probably should, to reduce overhead), while the other will get more updates and new features.
from cinder import SyncCinderClient
# Basic usage
with SyncCinderClient(
base_url="https://rover-staging.cinderapp.com/",
token="XXXXXXXXX"
) as client:
# Get graph schema
schema = client.get_graph_schema()
print(f"Found {len(schema.entity_schemas)} entity schemas")
# List decisions
decisions = client.list_decisions(limit=10)
print(f"Found {decisions.total} decisions")
# Get specific decision
decision = client.get_decision("decision-id")
print(f"Decision: {decision.id}")from cinder import get_sync_client
# Reads from CINDER_API_BASE_URL and CINDER_API_TOKEN env vars
client = get_sync_client()
with client:
schema = client.get_graph_schema()
print(schema.model_dump_json(indent=2))import asyncio
from cinder import CinderClient
async def main():
async with CinderClient(
base_url="https://rover-staging.cinderapp.com/",
token="XXXXXXXXX"
) as client:
# Get graph schema
schema = await client.get_graph_schema()
print(f"Found {len(schema.entity_schemas)} entity schemas")
# List decisions
decisions = await client.list_decisions(limit=10)
print(f"Found {decisions.total} decisions")
asyncio.run(main())create_report(report: CreateReportSchema) -> Reportlist_reports(limit, offset, **filters) -> PagedReport
get_graph_schema() -> SchemaResponse
request(method: str, path: str, **kwargs) -> httpx.Response
This covers the uv setup, alternatively you can use requirements.txt and
the environment manager of your choice.
# Clone the repository
git clone https://github.com/roverdotcom/cinder.git
cd cinder
uv sync --frozen# Run all tests
make test
# Run with verbose output
make test-verbose
# Run with coverage report
make test-coverageWhen the OpenAPI spec changes:
# Update openapi.json with the new spec
# Then regenerate models
make regenerate-models# Generate requirements.txt from uv.lock
make requirements