Skip to content

Python SDK

Server-side capture for Python — events, identity, super properties and feature flags with zero dependencies.

azfive-capture is the Python server SDK — events, identity, super properties, and feature flags / experiments, implemented on the stdlib only (zero dependencies). It follows the same behavioral spec as every other AZ-Five SDK.

Install

pip install azfive-capture

The import name is azfive_capture. Use a secret API key with the events:write scope (Settings → API Keys) — server SDKs post to /api/v1/events, where public tokens are rejected. Secret keys are also valid on /v1/decide, so server-side flag evaluation needs no extra setup.

Initialize

from azfive_capture import Client

azfive = Client("azfive_…", host="https://app.az-five.com", project="backend")

host is required (keyword-only); a missing api_key or host raises at construction — the only place this SDK raises. Delivery and flag failures are always silent.

Capture events

Server processes handle many users at once, so pass distinct_id per call:

azfive.capture("invoice_paid", {"amount": 99}, distinct_id="user-42")

# Super properties — merged into every subsequent event
azfive.register({"deployment": "eu-1"})
azfive.register_once({"first_seen_version": "2.3"})
azfive.unregister("deployment")

Events without a distinct_id are attributed to the client’s own anonymous id.

Identify & person properties

azfive.identify("user-42", set={"plan": "pro"})
azfive.alias("legacy-77")
azfive.people.set({"plan": "enterprise"}, distinct_id="user-42")
azfive.people.set_once({"signup_date": "2026-08-01"}, distinct_id="user-42")

identify with a new id emits az.identify (carrying the previous id as $anonymous_id) and reloads flags; repeating it with the same id only emits an az.set update. reset() mints a fresh anonymous id and clears super properties — reset(reset_device_id=True) also re-mints the device id. Opt-out (opt_out_capturing() / opt_in_capturing() / has_opted_out_capturing()) drops events at capture time and survives reset().

Feature flags

Flag methods take the distinct_id first; each decide response is cached per id for 60 seconds:

variant = azfive.get_flag("user-42", "exp-checkout")          # 'control' | 'test' | True | False | None
if azfive.is_flag_enabled("user-42", "new-onboarding"):
    payload = azfive.get_flag_payload("user-42", "new-onboarding")  # no exposure event

azfive.reload_flags("user-42")   # bust one id's cache

get_flag and is_flag_enabled capture an az.flag_called exposure automatically, deduped per (distinct_id, flag, value). get_flag_payload never fires an exposure. Optional person_properties on each call are sent to /v1/decide for property-based targeting.

Flush & shutdown

Events queue in memory and are delivered by a daemon thread (batch 10 / 5 s / max 1,000, oldest dropped). Failed batches — 429 included — retry on the next tick.

azfive.flush()   # force delivery now
azfive.close()   # drain the queue and stop the worker

close() is also registered via atexit, so short-lived scripts don’t lose their tail of events.

Reference

Client constructor

ParameterDefaultNotes
api_keyrequiredSecret key (azfive_…) with events:write
hostrequiredAZ-Five deployment base URL (keyword-only)
project"default"Target project slug
batch_size10Queue length that triggers a flush
flush_interval_s5.0Background flush period (seconds)
max_queue_size1000Queue bound; oldest events dropped on overflow
gzipFalseContent-Encoding: gzip on event POSTs
opt_outFalseStart opted out of capturing
disable_decideFalseDisable the /v1/decide flag client
extra_static_propsNoneExtra static properties merged into every event
start_flush_threadTrueDisable the background thread (tests)

API

capture · identify · alias · reset · get_distinct_id · get_session_id · register / register_once / unregister · people.set / people.set_once · opt_in_capturing / opt_out_capturing / has_opted_out_capturing · get_flag / is_flag_enabled / get_flag_payload / reload_flags · flush · close.

Behavior notes

  • Server runtime: identity is in-memory only, there are no sessions (get_session_id() returns ""), and events are stamped with $device_type: "Server".
  • Custom event names: anything except the reserved az. prefix, ≤ 200 characters; properties ≤ 64 KiB serialized.
  • The decide cache is a bounded LRU (per-distinct_id, 60 s TTL); exposure dedup uses a bounded LRU as well, so long-running processes don’t grow without bound.