Official Python client for the Dhanavega API — generated Pydantic models (datamodel-code-generator) over a thin httpx client core. See issue #41, ADR 0037.
Project description
dhanavega-sdk
Official Python client for the Dhanavega API. Generated Pydantic v2 models (via
datamodel-code-generator) over a thin httpx
client core — auth, Idempotency-Key autogeneration, RFC 9457 problem+json error parsing, If-Match
concurrency, and cursor pagination. See issue #41 and
ADR 0037 for the design
rationale.
Status: buildable and test-covered; not yet published to PyPI (issue #41 — publication is a manual step performed by the maintainers once the platform reaches its India-GA milestone). Everything below documents the eventual
pip install dhanavega-sdkexperience.
Install
pip install dhanavega-sdk
# or
uv add dhanavega-sdk
Quickstart
from dhanavega_sdk import DhanavegaClient
client = DhanavegaClient(base_url="https://api.dhanavega.example", token="…")
response = client.request("los", "GET", "/los/leads")
print(response.data)
Or with a token getter (refreshed per request):
client = DhanavegaClient(
base_url="https://api.dhanavega.example",
get_token=lambda: fetch_short_lived_token(),
)
An async client is available too:
from dhanavega_sdk import AsyncDhanavegaClient
async with AsyncDhanavegaClient(base_url="...", token="...") as client:
response = await client.request("los", "GET", "/los/leads")
Auth
tenant_id is never sent by the client — the API derives it server-side from the bearer JWT
(api-docs/02-auth-tenancy-scopes.md). Supply either a static token or a get_token callable; the
client sets the Authorization: Bearer <token> header on every request.
Idempotency
Every POST/PUT/PATCH/DELETE requires an Idempotency-Key header
(api-docs/04-idempotency-concurrency-webhooks.md §1). The client autogenerates a uuid4 for every
mutating request unless you pass your own (e.g. to deliberately replay an attempt):
client.request("los", "POST", "/los/applications", json=body, idempotency_key="my-own-key")
A stored replay comes back with response.idempotency_replayed is True.
Error handling
Every non-2xx response raises DhanavegaProblemError — never a bare httpx.HTTPStatusError — parsed
from the platform's RFC 9457 application/problem+json envelope
(api-docs/03-errors-pagination.md §1). Branch on error.code (a DhanavegaErrorCode), never on
error.detail text:
from dhanavega_sdk import DhanavegaProblemError
try:
client.request("los", "POST", "/los/applications", json=body)
except DhanavegaProblemError as error:
if error.code == "VALIDATION_FAILED":
for field_error in error.errors or []:
print(field_error.pointer, field_error.rule)
elif error.code == "RATE_LIMITED":
print("retry after", error.retry_after)
Concurrency (If-Match)
from dhanavega_sdk import with_if_match
client.request(
"los", "PATCH", f"/los/applications/{app_id}",
json=patch_body,
**with_if_match(etag),
)
Missing If-Match on a mutable-entity mutation → 428 PRECONDITION_REQUIRED; a stale one → 412 VERSION_CONFLICT.
Pagination
from dhanavega_sdk import paginate
for lead in paginate(lambda cursor: client.request(
"los", "GET", "/los/leads", params={"page[after]": cursor} if cursor else None,
).data):
print(lead)
paginate walks page.has_more / page.next_cursor until the stream ends — cursors are opaque; never
parse or construct them yourself.
Regenerating models
uv sync --group codegen
uv run --group codegen python scripts/generate_models.py
Regenerates every committed file under src/dhanavega_sdk/models/ from
planning/api-docs/openapi/**. Run this whenever a contract YAML changes — tests/test_models_drift.py
fails CI if the committed models fall out of sync with the contract.
Publish procedure (manual, first release)
Publication is intentionally not automated yet (issue #41). CI's sdk-release.yml carries a
publish-sdk-pypi job gated behind the PUBLISH_ENABLED repo variable, which is unset today. To publish
manually once the maintainers decide to:
cd packages/sdk-python
uv build
uv publish --token "$PYPI_TOKEN"
Development
uv sync
uv run ruff check .
uv run ruff format --check .
uv run mypy src
uv run pytest
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