Skip to main content

Python SDK

The zeridion-flare package is published on PyPI and follows the same wire contract as every other Flare SDK.

pip install zeridion-flare

Requires: Python 3.10+ · httpx>=0.27 (declared as a dependency; pip installs it for you).

Quick start

The client exposes flat methods (one per endpoint) rather than nested namespaces, and returns plain dict payloads matching the wire format.

from zeridion_flare import FlareClient

flare = FlareClient(api_key="zf_live_sk_...")

# Enqueue a job. create_job takes the request body as a dict (the same shape
# as POST /jobs) — including optional fields like "tags".
# Optional keyword-only request_id / idempotency_key are accepted per call:
# - idempotency_key dedupes a replayed write (same key + same body → original response).
# - request_id is a log-correlation hint (your trace ID flows into Zeridion's logs);
# omit it and the server returns a generated ULID in the response X-Request-Id header.
job = flare.create_job(
{
"job_type": "SendWelcomeEmail",
"payload": {"email": "alice@example.com", "name": "Alice"},
"queue": "default",
"max_attempts": 3,
"tags": {"env": "dev"},
},
idempotency_key="welcome-email-alice",
)
print(job["id"], job["state"]) # "job_abc123", "pending"

# Get job status
detail = flare.get_job(job["id"])

# List jobs (returns a dict with "jobs" + "has_more" + "next_cursor")
page = flare.list_jobs(state="failed", limit=25)
for j in page["jobs"]:
print(j["id"], j["state"])

# Cancel / retry
flare.cancel_job(job["id"])
flare.retry_job(job["id"])

Client construction

KeywordDefaultDescription
api_keyos.environ["FLARE_API_KEY"]Required — pass directly or via env var.
base_urlhttps://api.zeridion.com/flare/v1Override for dev / staging. Unlike most other Flare SDKs, the default includes the /flare/v1 path — an override must include it too.
max_retries3Maximum retry attempts on 429 / 5xx / network errors. Set 0 to disable.
retry_base_delay_ms500Base for the exponential backoff schedule.
retry_max_delay_ms30000Cap on a single backoff wait (and on Retry-After).
max_response_bytes10 * 1024 * 1024 (10 MiB)Hard cap on response body size; protects against an unbounded body. Set 0 to disable.

Type hints

The SDK is fully typed using Python 3.10+ union syntax (str | None, dict[str, Any]) — no Optional[...] / Union[...] imports needed. Method signatures, dataclass fields, and exception attributes all carry runtime-checkable annotations, so mypy / pyright / your IDE will flag drift without you re-typing anything.

Typed error hierarchy

The following are importable from zeridion_flare:

ClassHTTPWhen it fires
FlareErrorBase class for every SDK exception
AuthError401Missing / invalid / revoked API key
QuotaError402Billing state blocked — subscription past_due / unpaid / cancelled
NotFoundError404Resource doesn't exist (or returns None on GETs)
ConflictError409Idempotency or invalid-state conflict
RateLimitError429Rate-limited; inspect .retry_after, .limit, .remaining

Webhook verification

verify_webhook(payload, signature_header, secret, *, tolerance_seconds=None) verifies the X-Zeridion-Signature header on a delivery. Pass the raw request body bytes — parsing and re-serializing the JSON invalidates the signature.

from zeridion_flare import verify_webhook

@app.post("/hooks/zeridion")
async def receive(request):
raw = await request.body()
header = request.headers.get("x-zeridion-signature", "")
if not verify_webhook(raw, header, WEBHOOK_SECRET, tolerance_seconds=300):
return Response(status_code=400)
...

Set tolerance_seconds (recommended: 300) to reject replayed deliveries whose signature timestamp is too old. The helper is rotation-safe — it accepts any matching v1= digest in the header.

Tags and progress

Because create_job takes the raw request body, tags work today — pass them as a key in the body dict (see the example above). Job progress is reported by workers, so reading it is available now via get_job (the response includes progress when set); reporting it from Python arrives with the worker loop below.

Planned features

  • Built-in worker loop (def execute(payload: dict) handlers, sync today; async variant tracked separately if there is demand) — including progress reporting from Python workers
  • Recurring job support

The synchronous client is what ships today. There is no AsyncFlareClient on the immediate roadmap — if asyncio support is a hard requirement for your stack, wrap FlareClient calls in asyncio.to_thread() for now and tell us via GitHub issues, which will prioritise a native async client.

See also