EnfinitOSEnfinitOS
DevelopersOperator & brand
Production-ready scaffold

Brand SDK — Python

Async REST client — the same brand-side surface as the TS SDK, for data-science and audit-pipeline integration.

enfinitos-sdk-brandSubstrate ALLPython
Install

Get the SDK

pip install enfinitos-sdk-brand

About this status badge

Typed, tested, documented, and grounded in the 2026 platform reality. Awaiting first customer-integration validation.

README

The developer-facing documentation in full

Rendered from packages/sdks/brand-py/README.md at build time — the same source the package ships with.

enfinitos-sdk-brand (Python)

EnfinitOS Brand/Advertiser SDK — a lightweight async REST client that lets a brand (advertiser) query its own delivery proof, metering, and settlement records directly, without going through the operator's reporting plane. Read-only by design and scoped to campaigns the brand owns.

Python counterpart of @enfinitos/sdk-brand (TypeScript). Same shape, idiomatic Python: async-first via httpx.AsyncClient, pydantic v2 models.

Who should use this

You are a brand (advertiser) and:

  • you want to reconcile EnfinitOS invoices against your own impression logs or auditor analysis;
  • you need to file disputes backed by signed counter-evidence the operator is contractually bound to respond to;
  • your data pipeline is async (FastAPI / Prefect / Airflow with async tasks / Temporal).

If you are an operator, you want the operator-web SDK instead. If you are an auditor verifying signatures, you want enfinitos-sdk-auditor for the cryptographic primitives.

Authentication

Authorization: Bearer brk_…
X-Enfinitos-Brand: brand_acme

Brand API keys are issued by EnfinitOS to the brand's tenant admin via the brand portal. They are scoped read-only to records the brand owns. Disputes are the only write surface and are bound to the brand's own auditor-key signature, not the API key.

Installation

pip install enfinitos-sdk-brand
# or, for tests:
pip install 'enfinitos-sdk-brand[dev]'

Requires Python 3.10+ (pattern matching, structural typing).

Getting started

import asyncio
import os

from enfinitos_brand import EnfinitOSAPIError, EnfinitOSBrandClient


async def main() -> None:
    async with EnfinitOSBrandClient(
        api_base_url="https://api.enfinitos.com",
        brand_id=os.environ["ENFINITOS_BRAND_ID"],
        api_key=os.environ["ENFINITOS_BRAND_API_KEY"],
    ) as client:
        # 1. List active campaigns.
        page = await client.campaigns.list(status="ACTIVE")
        print(f"Brand has {len(page.items)} active campaigns")

        for cmp in page.items:
            # 2. Pull the signed proof pack + metering summary.
            pack = await client.proof.pack(cmp.campaign_id)
            summary = await client.metering.summary(cmp.campaign_id)
            print(cmp.name, summary.totals)

            # 3. Hand the pack to the Auditor SDK to verify the
            #    signature + Merkle structure.
            #
            # from enfinitos_auditor import verify_pack
            # verdict = await verify_pack(pack)
            # if not verdict.ok:
            #     ...  # dispute

        # 4. On any 4xx/5xx, the SDK raises a typed error.
        try:
            await client.campaigns.get("does-not-exist")
        except EnfinitOSAPIError as e:
            print("API error", e.code, e.correlation_id)


asyncio.run(main())

Module reference

NamespaceMethodsPurpose
client.campaignslist, getBrand-owned campaigns. Read-only.
client.proofsummary, pack, chainSigned evidence. Verify with the Auditor SDK.
client.meteringsummary, breakdownBillable-unit rollups per campaign.
client.settlementinvoices, invoice, lineInvoices issued to the brand, with per-line proof slices.
client.disputesopen, list, getBrand-raised disputes. The SDK's only write surface.

All methods are async coroutines.

Error model

class EnfinitOSAPIError(Exception):
    code: str               # "UNAUTHORIZED", "CAMPAIGN_NOT_FOUND", …
    http_status: int
    correlation_id: str
    details: dict | None
    is_client_error: bool   # @property
    is_retryable: bool      # @property


class EnfinitOSTransportError(Exception):
    cause: BaseException | None

Connection-level failures surface as EnfinitOSTransportError — those never reached the platform and are always safe to retry. The SDK does not retry automatically. Use EnfinitOSAPIError.is_retryable to opt in.

Cross-reference: Auditor SDK

The brand SDK retrieves evidence; the Auditor SDK verifies it. They are deliberately separate packages so the verifier can ship into an air-gapped environment without the HTTP client.

Brand SDK outputAuditor SDK function
SignedProofPackverify_pack(pack)
ProofRecord + Merkle pathverify_leaf_inclusion(record, path, root)
InvoiceLine.proof_slice_rootverify_slice(slice, root)
SignedEvidence (dispute)verify_evidence(evidence, public_key)

Status

Initial release. Contract version 1.

API reference

Hit the HTTP surface directly

The Brand SDK — Python is a thin client over the same governed HTTP API every other SDK calls. The full OpenAPI 3.1 reference lives on the docs site.

Sandbox

Run this SDK against a real tenant

The hosted sandbox is the fastest way to verify Brand SDK — Python against a real EnfinitOS tenant before committing to a pilot. Launching Q4 2026.