# AffixIO from Python Canonical page: https://www.affix-io.com/sdk-python/ API base: https://api.affix-io.com OpenAPI: https://api.affix-io.com/v1/openapi.json Connection surfaces index: https://www.affix-io.com/connections/ Site brief: https://www.affix-io.com/llms.txt There is an official Python package, `affix-io`. It is Apache-2.0, requires Python 3.10+, and has no runtime dependencies. It is distributed as source by AffixIO and is NOT published on public PyPI, so `pip install affix-io` from the public index will not fetch it. On the AffixIO host the source tree is at `/var/www/vhosts/api.affix-io.com/packages/python-sdk/`; customers receive the same tree on request from hello@affix-io.com. ## Install Editable install from the source tree: python3 -m pip install -e "/var/www/vhosts/api.affix-io.com/packages/python-sdk[dev]" Or from inside a copy of the tree: `python3 -m pip install -e ".[dev]"`. ## What the package gives you - `AffixClient`: remote prove, verify, attest, gate, Merkle audit and inclusion, spent state, evidence export, webhook management. Handles `Idempotency-Key` and rate limit headers. - `AffixLight`: local Affix Light prove and verify, HMAC-SHA256, scheme `affix-light-v1`, matching `@affix-io/sdk-light`. Light proofs are HMAC-bound decisions, not SNARKs. - `verify_webhook_signature` and `sign_webhook_payload`: webhook receiver checks. - Not included: local UltraHonk zero-knowledge proving, offline queue and auto-flush, QR or barcode rendering. AffixIO also publishes `@affix-io/sdk` and `@affix-io/sdk-light` on npm, both Node.js 18+. Everything the Python package does is also reachable over the raw HTTP API with one HTTP client (`httpx` or `requests`) plus the standard library. The sections below describe that raw contract. ## Client basics - Base URL `https://api.affix-io.com`. - Auth: `Authorization: Bearer ` or `X-API-Key: `. - Send `Idempotency-Key` on prove and verify POSTs. A replay inside 24 hours returns the original 2xx body with `Idempotency-Replayed: true`. - Rate limit: 10 requests per second per key by default. `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` on every response, `Retry-After` on 429. - `X-Request-Id` on every response. Log it alongside your own correlation id. - Reuse one client instance and its connection pool. ## Statuses that carry meaning - `409 double_spend_detected` with reason code `DOUBLE_SPEND`: the digest was already spent. This is a decision, not a transport failure. Do not retry. - `429`: rate limited. Sleep for `Retry-After` and retry with the same idempotency key. Reason codes: ADMITTED, VALID_CHECK, VALID_ALREADY_SPENT, INVALID_PROOF, DOUBLE_SPEND, EXPIRED, WRONG_GATE, POLICY_MISMATCH, DEVICE_UNKNOWN, DEVICE_REVOKED, REGION_MISMATCH, FACTOR_INCOMPLETE, QUORUM_INCOMPLETE, DELEGATE_OK, DELEGATE_EXPIRED, DELEGATE_UNKNOWN. Live list: `GET /v1/verify/reason-codes`. ## Webhook verification in Python Read the raw request bytes before parsing. Reject when `X-Affix-Timestamp` is more than 300 seconds from now. Compute `hmac.new(secret, f"{ts}.".encode() + raw_body, hashlib.sha256).hexdigest()` and compare with `hmac.compare_digest` against the hex value after `hmac-sha256=` in `X-Affix-Signature`. Deduplicate on `X-Affix-Delivery-Id`. Respond 2xx within eight seconds. Details: https://www.affix-io.com/webhooks/ ## Merkle inclusion in Python Interior node hash: `sha256(b"affix:node:" + lo + hi)` where `lo` and `hi` are the two hex hashes sorted lexicographically. Fold `leaf_hash` with each `sibling` from `GET /v1/merkle/proof/{digest}` and compare the result with `root`. Cross-check against the public root at `GET /v1/merkle/root`, which needs no key. Because the node hash sorts its inputs, the `side` field does not change the outcome. Server-side alternative: `POST /v1/merkle/verify-proof`. ## Evidence export in Python Stream `GET /api/export/siem?since=&until=` and parse one JSON object per line. Check `X-Affix-Export-Truncated`; `1` means the window exceeded the 10000 event ceiling. Details: https://www.affix-io.com/siem/ ## Not available in Python - Local UltraHonk zero-knowledge proving (Barretenberg, Node only). Call `POST /v1/prove` or run the Node package as a worker. - A public PyPI listing. The package is real but ships as source; upgrades come from pulling a new tree. - Offline queue and auto-flush. Build your own queue and anchor with `POST /v1/merkle/audit/batch` (up to 1000 leaves). - QR and barcode rendering from a proof. Issue carriers through the API instead, for example `POST /v1/token/issue` or `POST /v1/link/issue`. The Affix Light HMAC prove and verify path IS available in Python through `AffixLight`. Contact hello@affix-io.com for the source tree, or if a published PyPI release would change how you deploy. Last updated: 2026-08-14