Python API
Python 3.12 and 3.13 are supported. Install the Postgres backend with:
pip install "bursar[postgres]"
Constructing the facade
Bursar wires a store, the optional billing/commerce capabilities, and
an optional event emitter into one application-facing facade:
from bursar import Bursar, PostgresStore
store = PostgresStore(
database_url,
tenant_id=tenant_id,
provider_environment="test",
)
bursar = Bursar(credit_store=store)
credit_storeis the only required argument.PostgresStoreis the bundled implementation;CreditStoreis the abstract base for custom backends.tenant_idscopes every store operation to a single tenant.billing_storepluscommerce_optionsenable the billing and commerce capabilities (ingest_billing_event, checkouts, subscriptions, auto-recharge).emitterreceives credit lifecycle events (CreditEventEmitter).
Apply the database schema with bursar migrate before constructing a store —
the package never runs migrations from the store itself.
Errors, deadlines, and retries
All Bursar-classified failures extend BursarError and expose stable code,
category, and retryable fields. to_dict() returns the safe logging shape
without exposing the underlying driver exception.
Use the Tenacity-backed retry helper only for reads or mutations protected by a stable idempotency key:
from bursar import BursarRetryOptions, is_bursar_error, retry_bursar_operation
try:
balance = retry_bursar_operation(
bursar.credits.get_balance,
user_id,
retry_options=BursarRetryOptions(max_attempts=3),
)
except Exception as error:
if is_bursar_error(error):
logger.error("Bursar request failed", extra={"bursar": error.to_dict()})
raise
StoreError.indeterminate means a transport failure occurred after a mutation
may have reached PostgreSQL. Retry only with the same idempotency key. Custom
stores should use StoreUnavailableError or StoreTimeoutError for classified
transient failures rather than matching error-message text.
Package layout
The bursar top level exposes the application-facing facade, stores, pricing
engine, common inputs, errors, and retry helpers. Domain-specific result and
provider types remain grouped under focused modules such as
bursar.credits.types and bursar.providers.
| Export | Purpose |
|---|---|
Bursar | The facade: credits, catalog, accounts, plus optional billing/commerce |
PostgresStore | Production, tenant-scoped credit store (requires the [postgres] extra) |
PostgresBillingStore | Billing store for payment-provider lifecycle (requires the [postgres] extra) |
PricingEngine | Database-free operation-pricing core |
CreditStore | Abstract base class for custom credit backends |
BillingStore | Abstract base class for custom billing backends |
UsageMetrics | One billable operation (measures + dimensions) |
load_config_from_dict | Validate and canonicalize a config document |
| errors | BursarError, CreditError, ConfigError, StoreError, CapabilityNotSupportedError, … |
| retry helpers | BursarRetryOptions, retry_bursar_operation, and its async counterpart |
PostgresStore and PostgresBillingStore are lazy-imported: they are only
available when the optional psycopg2 extra is installed.
Where to go next
- Credits service — balances, metered charging, leases, plans, ledger, analytics, teams
- PricingEngine — pricing without a database
- Stores —
PostgresStore,PostgresBillingStore, and theCreditStorecontract - API reference — generated symbol reference
- Concepts and configuration — the canonical config document