Python SDK
Thread-safe event client with built-in batching, the public-key session handshake, and graceful shutdown. Zero required runtime dependencies (stdlib only).
Installation#
Requires Python 3.9+.
Quick start#
Or use it as a context manager (flushes on exit):
Which key do I use?#
| Where the code runs | Key | What to pass |
|---|---|---|
| Your server (Django, Flask, scripts) | sk_… secret | api_key only |
| A client you can't trust with a secret | pk_… public | api_key and get_user — the SDK runs the session handshake automatically |
Never put an sk_ key anywhere a user can read it. Python is primarily a
server-side language, so sk_ is the common case; pk_ is supported for parity.
When the key starts with pk_, the SDK calls /api/auth/session/ on first use,
caches the short-lived token, refreshes it 60s before expiry, and re-mints on a
401. If the key requires a signed user_id, produce the signature on your backend
with segops.sign_user_id and pass the fields through get_user.
Constructor#
| Argument | Default | Description |
|---|---|---|
api_url | — | Base URL of your SegOps deployment |
api_key | — | API key — sk_… (server) or pk_… (handshake) |
get_user | — | Required for pk_…: returns a UserContext at mint time |
batch | True | Buffer events and flush automatically; False sends each immediately |
batch_size | 20 | Max events before an automatic flush |
flush_interval | 5.0 | Periodic flush interval (seconds) |
on_error | log to stderr | Called when a background flush fails |
Methods#
track(event=None, *, user_id, event_type, occurred_at=None, payload=None)#
Enqueue an event. Accepts an Event (or dict) or keyword arguments. Non-blocking
and safe for concurrent use.
identify(context=None, *, user_id, traits=None)#
Record user traits as a context_identified event.
flush()#
Flush all buffered events immediately. Blocks until the HTTP request completes.
shutdown() / close()#
Stop the background thread and flush any remaining events. Always call this before
the process exits to avoid data loss. close() is an alias, and the client is a
context manager that flushes on exit.
reset_session()#
Drop the cached session token so the next event re-mints with the current
get_user() identity. Call after a login/logout. No-op for sk_ clients.
Using it with a web framework#
SegOpsClient is plain, framework-agnostic Python (zero runtime dependencies),
so it works anywhere — Django, FastAPI, Flask, Starlette, FastMCP, Celery
workers, or a one-off script. Create one client per process and reuse it.
The Claude Code skills wire it into common stacks for you (integrate-django,
integrate-fastapi, integrate-flask, integrate-node for Node) — see
Install with Claude Code.
Sync frameworks (Flask, Django, WSGI)#
Call the client directly and flush on shutdown:
Async frameworks (FastAPI, Starlette, async FastMCP tools)#
The client is synchronous with a background flush thread. track() is
normally just a queue append, but every batch_size-th call triggers an
inline flush, and flush()/shutdown() always block — so in an async def
handler, offload to a threadpool to keep the event loop free:
(Calling client.track(...) from a sync def endpoint is also fine —
FastAPI runs those in a threadpool for you.)
Types#
Signing a user id (backend only)#
Run this on your backend only — never ship the HMAC secret to a client.
See Server-side Signing for the full reference. Enable "require signed user_id" on the public key so the server rejects unsigned or forged identities.
Error handling#
The background flush thread reports errors via the on_error callback (default:
log to stderr). flush() and shutdown() raise on a non-2xx response so you can
handle them directly. Events are never dropped on shutdown — the client
guarantees a final flush.