marginal-sdk
Marginal SDK for Python — send AI cost events and see where your AI spend goes, sliced by customer, feature, environment, model, or any field you define.
pip install marginal-sdk
Python 3.9+, stdlib only (zero dependencies).
Quickstart
One call per LLM request: name the provider, paste the response's model and
usage — Marginal detects the provider's usage shape and computes the cost
server-side against its model price catalog.
import os
from marginal import Marginal
marginal = Marginal(api_key=os.environ["MARGINAL_API_KEY"])
response = client.chat.completions.create(...)
marginal.track(
provider="openai",
model=response.model,
usage=response.usage.model_dump(),
fields={"customer": "acme-corp", "feature": "support-bot"},
)
For non-LLM spend (voice, images, pre-computed costs), send dollars directly:
marginal.track(cost=0.05, fields={"customer": "acme-corp"})
track() is synchronous and never raises: events are buffered and flushed by
a daemon worker thread (every 5 s or at 100 events), with retries on network
errors, 429s, and 5xx. Errors are reported to an on_error callback (a
warning print by default). Buffered events are flushed automatically at
interpreter exit; call marginal.flush() to force one earlier. Fork-safe:
the worker restarts in the child after os.fork().
Delivery guarantees
Best-effort, at-most-once. Events are buffered in memory (no disk
persistence), so a hard crash — kill -9, OOM, an unhandled exception —
loses what's still buffered: at most ~5 seconds or 100 events with the
defaults. On a clean interpreter exit the remaining events are flushed via
atexit (disable with flush_on_exit=False). Note that atexit does not
run on an unhandled SIGTERM — call marginal.shutdown() from your own
signal handler if you need that. A batch whose retries are exhausted is
dropped and reported through on_error — the SDK never blocks or crashes
your app to save an event. Retries carry no idempotency keys yet, so a batch
whose response was lost after the server accepted it can, rarely, land
twice.
Options
Marginal(
api_key="mgl_...", # required — server-side only
on_error=lambda err: ..., # delivery/validation errors (never raised)
flush_on_exit=True, # default; False disables the atexit flush
base_url="https://api.marginalhq.com", # default
)
Docs
- Quickstart
- Event shape & API
- Integrations cookbook — OpenAI, Anthropic, Gemini, Bedrock, streaming
- llms.txt — paste into your coding assistant to instrument a codebase automatically
Metadata
Release files for marginal-sdk 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| marginal_sdk-0.1.2.tar.gz | 17.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| marginal_sdk-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.4 kB
Release files / marginal_sdk-0.1.2.tar.gz
| Download URL | marginal_sdk-0.1.2.tar.gz |
|---|---|
| Size | 17.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
92e8ca8807f4e1d3587a900c499787b395c0c3e443678822325e14cd6b561193
|
|
BLAKE2b-256 checksum How to use checksums |
0a156daa149c061343e0922e9bafbd334523e8501e604089f58ecb95c4d9e5b2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.15
|
Release files / marginal_sdk-0.1.2-py3-none-any.whl
| Download URL | marginal_sdk-0.1.2-py3-none-any.whl |
|---|---|
| Size | 9.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9f8d861be65826cac41a54706982f3eaa9a4ea1e0805dfcc7db063a9969aa336
|
|
BLAKE2b-256 checksum How to use checksums |
de0f2e68e5456777ec19db0c5408416f647a2ef3a4a1666cce767e449f0548ed
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.15
|