Skip to main content

campai-client

A Python SDK for campai.com, generated from campai's OpenAPI spec, with pydantic v2 models, sync + async clients, and a durable patch layer for spec-vs-reality fixes.

Status: early / alpha. See docs/DESIGN.md for the full architecture and docs/adr/ for key decisions.

Install

pip install campai-client

Requires Python ≥ 3.13. Runtime deps: httpx, pydantic>=2, pydantic-settings.

Quickstart

from campai_client import CampaiClient
from campai_client import models

client = CampaiClient(
    api_key="...",  # or env CAMPAI_API_KEY
    organization_id="...",  # or env CAMPAI_ORGANIZATION_ID
    mandate_id="...",  # optional default; overridable per call
    # base_url defaults to https://cloud.campai.com/api
)

# Ergonomic namespaces mirror campai's tag hierarchy. List bodies (pagination +
# filters) are typed via the generated request model:
page = client.crm.applications.forms.list(
    body=models.CrmApplicationsFormsListFormsRequest(limit=50)
)
print(page.count, len(page.items))

form = client.crm.applications.forms.get(application_form_id="...")

# Walk every page transparently:
for form in client.crm.applications.forms.iterate():
    ...

client.close()

Async mirror:

from campai_client import AsyncCampaiClient

async with AsyncCampaiClient(api_key="...", organization_id="...") as client:
    form = await client.crm.applications.forms.get(application_form_id="...")
    async for f in client.crm.applications.forms.aiterate():
        ...

Configuration is resolved from constructor args or CAMPAI_* env vars (CAMPAI_API_KEY, CAMPAI_ORGANIZATION_ID, CAMPAI_MANDATE_ID, CAMPAI_BASE_URL).

Errors

HTTP status + campai's error envelope map to a typed hierarchy: CampaiAPIError (BadRequestError/AuthenticationError/PermissionError/NotFoundError/ServerError), plus CampaiValidationError (response didn't match the models) and CampaiConfigError.

How it's built (three layers)

  1. Spec pipeline (spec/, scripts/): download → normalize/overlay → committed spec.
  2. Generated layer (src/campai_client/_generated/, never hand-edited): 2 200+ pydantic v2 models via openapi-generator (models-only), plus the operations manifest (operations.py) built from the spec.
  3. Facade + patch layer (src/campai_client/, durable): clients, resource namespaces, the patch pipeline, pagination, errors.

See docs/adr/0002 for how the runtime call path and resource tree are driven by the manifest.

The agent maintenance loop

When campai's spec changes, regenerate and let the tests triage the drift:

pixi run regen          # fetch + normalize + generate + manifest + format
pixi run test           # replay (VCR) tests

Triage failures:

  • CampaiValidationError / import error → schema drift. Fix spec/overlay.yaml (schema-level, JSON-Pointer keyed), then pixi run regen.
  • Behavioural mismatch (id-only response, aliasing, follow-up needed) → add or adjust a patch in src/campai_client/patches/ plus a test. Patches without tests are not allowed.
  • New/removed operations → the manifest + resource namespaces regenerate automatically; add smoke tests for important new resources.

Cassettes are re-recorded (CAMPAI_RECORD=1 pixi run test-record) only when the real API behaviour changed.

Development

pixi manages the dev environment (the shipped package uses standard pyproject.toml deps).

pixi run check       # lint + typecheck + test  (CI aggregate)
pixi run lint        # ruff check
pixi run format      # ruff format
pixi run typecheck   # ty check
pixi run test        # pytest (VCR replay)
pixi run regen       # full regeneration (openapi-generator via pixi's JVM)

lefthook runs format/lint/typecheck on staged files and guards against hand-edits to _generated/**.

Regeneration (pixi run regen/generate) runs the openapi-generator JAR with a JVM supplied by pixi (openjdk) — no Docker required (it runs fine inside containers). The JAR is pinned by version + SHA-256 and cached under .cache/. Using or testing the shipped client needs neither Java nor the JAR.

Integration tests (real campai org)

Most tests use a mock transport. The integration tests (tests/resources/test_live.py) hit the real API and are recorded with VCR, then replayed from committed cassettes (no credentials on replay). Provide credentials via env vars to record:

CAMPAI_RECORD=1 CAMPAI_API_KEY=... CAMPAI_ORGANIZATION_ID=... \
  CAMPAI_MANDATE_ID=... pixi run test-record

Credentials are scrubbed from cassettes. See tests/README.md for the full flow and scrubbing tradeoffs.

License

Apache-2.0.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

campai_client-2026.8.4.tar.gz (854.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

campai_client-2026.8.4-py3-none-any.whl (3.7 MB view details)

Uploaded Python 3

File details

Details for the file campai_client-2026.8.4.tar.gz.

File metadata

  • Download URL: campai_client-2026.8.4.tar.gz
  • Upload date:
  • Size: 854.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for campai_client-2026.8.4.tar.gz
Algorithm Hash digest
SHA256 25c979e5950d9198ed21559e03d94e2fa7eaff48880ec677ff8dc0c8db8cfe87
MD5 fbec2255de5f0fc3ad7957e631f1768d
BLAKE2b-256 f7d533e6fe13e16446a585bdbd8b42621c6ab473b3dc3251d1d28dcbc34d2ef1

See more details on using hashes here.

Provenance

The following attestation bundles were made for campai_client-2026.8.4.tar.gz:

Publisher: release.yml on janjagusch/campai-client

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file campai_client-2026.8.4-py3-none-any.whl.

File metadata

File hashes

Hashes for campai_client-2026.8.4-py3-none-any.whl
Algorithm Hash digest
SHA256 720ffff7c4bab36f997cffa9ec99794a7bb08b82dc8da81ef2838c53df5d6f39
MD5 eeb17e86eef9dcda6088bca91de0bbaf
BLAKE2b-256 549e6223e62e7f31336d10b2f2ad3ab4f087be5a4b7f8440876def50fab09fbb

See more details on using hashes here.

Provenance

The following attestation bundles were made for campai_client-2026.8.4-py3-none-any.whl:

Publisher: release.yml on janjagusch/campai-client

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page