Skip to main content

Python client for the CruxPass API

Project description

cruxpass

Python client for the CruxPass API.

CruxPass publishes subscribable, per-user calendar feeds on behalf of SaaS platforms. This package is a nimble, fully typed client for the CruxPass publisher REST surface: projects, groups, feeds, subscribers, one-off events, recurring schedules, and public ICS feed reads.

  • Python 3.13+
  • Sync (CruxPass) and async (AsyncCruxPass) clients backed by httpx
  • Automatic retries with backoff for connect errors, 429, and transient 5xx responses (safe because CruxPass writes are idempotent upserts keyed by external_id)
  • Typed exceptions: AuthenticationError, NotFoundError, RateLimitError, ServerError, all subclasses of APIError
  • CRUXPASS_API_KEY and CRUXPASS_BASE_URL environment fallbacks, matching the CruxPass server tooling

Install

uv add cruxpass
# or
pip install cruxpass

Usage

from cruxpass import CruxPass

client = CruxPass(api_key="pk_...")  # or set CRUXPASS_API_KEY

client.update_project(feed_domain="feeds.example.com")

client.create_feed(name="Events", slug="events")

client.upsert_event(
    feed_slug="events",
    external_id="event-123",
    summary="Demo Event",
    start="2026-07-20T23:00:00Z",
    end="2026-07-21T00:30:00Z",
)

subscriber = client.create_subscriber(
    label="Demo subscriber",
    feeds=["events"],
)

print(subscriber["subscribe_url"])

start, end, and other temporal fields accept ISO 8601 strings or datetime.date / datetime.datetime objects; timezone-aware UTC datetimes serialize with a Z suffix.

list_groups(), list_feeds(), list_events(), and list_subscribers() return plain Python lists. When the server returns a paginated REST envelope, the helpers follow next links and collect every page for you.

Detail helpers are available for mutable resources: get_*, update_*, and delete_* for groups and feeds, plus get_subscriber() and update_subscriber(). Feed and group slugs are immutable server-side; subscriber tokens and active state are managed through explicit lifecycle helpers.

Recurring schedules accept an optional IANA timezone. Omit it to preserve UTC recurrence behavior. All-day event and schedule writes must use UTC-midnight datetimes.

Async

Every helper is also available on AsyncCruxPass with the same signatures:

import asyncio

from cruxpass import AsyncCruxPass


async def main() -> None:
    async with AsyncCruxPass(api_key="pk_...") as client:
        feeds = await client.list_feeds()
        print(feeds)


asyncio.run(main())

Feed reads

Public subscriber feeds are fetched without auth and support conditional requests via ETag and Last-Modified validators:

feed = client.get_subscriber_feed(subscriber["token"])

print(feed.status_code)
print(feed.etag)
print(feed.text)

not_modified = client.get_subscriber_feed(
    subscriber["token"],
    etag=feed.etag,
)

assert not_modified.status_code == 304

Recurring schedules

client.upsert_recurring_schedule(
    feed_slug="events",
    external_id="weekly-meeting",
    summary="Weekly Meeting",
    first_start="2026-07-20T23:00:00Z",
    first_end="2026-07-21T00:00:00Z",
    frequency="weekly",
    timezone="America/Denver",
    count=12,
)

client.move_recurring_occurrence(
    feed_slug="events",
    schedule_external_id="weekly-meeting",
    occurrence_number=2,
    start="2026-07-28T01:00:00Z",
    end="2026-07-28T02:00:00Z",
)

client.cancel_recurring_occurrence(
    feed_slug="events",
    schedule_external_id="weekly-meeting",
    occurrence_number=3,
)

Errors and retries

API failures raise typed exceptions carrying status_code, message, and the underlying httpx.Response:

from cruxpass import AuthenticationError, NotFoundError

try:
    client.get_project()
except AuthenticationError:
    ...  # bad or revoked API key
except NotFoundError:
    ...

Connect errors and 429/502/503/504 responses are retried with exponential backoff (honoring Retry-After). Tune or disable with CruxPass(..., max_retries=0).

Configuration

Option Constructor Environment Default
API key api_key CRUXPASS_API_KEY required
Base URL base_url CRUXPASS_BASE_URL https://cruxpass.com
Timeout timeout 10.0 seconds
Retries max_retries 2
HTTP client http_client owned httpx.Client

Helpers

The client exposes the documented REST surface:

  • get_project() / update_project(feed_domain=...)
  • list_groups() / create_group(...) / get_group(...) / update_group(...) / delete_group(...)
  • list_feeds() / create_feed(...) / get_feed(...) / update_feed(...) / delete_feed(...)
  • list_subscribers() / create_subscriber(...) / get_subscriber(...) / update_subscriber(...)
  • deactivate_subscriber(token) / rotate_subscriber_token(token) / refresh_subscriber_artifact(token)
  • list_events(feed_slug=...) / upsert_event(...) / cancel_event(...)
  • upsert_recurring_schedule(...)
  • upsert_recurring_exception(...)
  • move_recurring_occurrence(...)
  • skip_recurring_occurrence(...)
  • cancel_recurring_occurrence(...)
  • get_subscriber_feed(token, etag=..., modified_since=...)
  • get_subscriber_feed_ics(token)

For API paths that do not have a named helper yet, use client.request(method, path, json=..., params=...).

Development

The project is managed with uv end to end:

uv sync --group dev
uv run python -m unittest discover -s tests
uv run --group dev ruff check .
uv run --group dev ruff format --check .
uv run --group dev ty check src tests
uv build

Status

Pre-1.0 package. Releases are coordinated with the matching CruxPass server contract; see CHANGELOG.md for endpoint, client method, and migration notes. PyPI publishing is GitHub-only; see RELEASE.md.

Project details


Download files

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

Source Distribution

cruxpass-0.0.4.tar.gz (9.4 kB view details)

Uploaded Source

Built Distribution

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

cruxpass-0.0.4-py3-none-any.whl (13.5 kB view details)

Uploaded Python 3

File details

Details for the file cruxpass-0.0.4.tar.gz.

File metadata

  • Download URL: cruxpass-0.0.4.tar.gz
  • Upload date:
  • Size: 9.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cruxpass-0.0.4.tar.gz
Algorithm Hash digest
SHA256 e1171f68cc8500d652e33ae5f15542d2b9eab2f0a0fd6841dc4325a28c5344d4
MD5 57e5eb8691c7fabcf214c26c616c90f9
BLAKE2b-256 f0f90e0487f17b3de7e371f6e43a48f5d4cfb84128e2633835769135e7b70f00

See more details on using hashes here.

Provenance

The following attestation bundles were made for cruxpass-0.0.4.tar.gz:

Publisher: workflow.yml on cruxpass/cruxpass.py

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

File details

Details for the file cruxpass-0.0.4-py3-none-any.whl.

File metadata

  • Download URL: cruxpass-0.0.4-py3-none-any.whl
  • Upload date:
  • Size: 13.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cruxpass-0.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 33f4a3bf11270a16782510d702f7e48a2c4d5c45a953146e59f3cff777799ff8
MD5 be3486726e17da57488cdfbc2371ee69
BLAKE2b-256 e0e74a52c8e05c569a2c34979552e555354c74969bc1f1b361a93b16c76620a5

See more details on using hashes here.

Provenance

The following attestation bundles were made for cruxpass-0.0.4-py3-none-any.whl:

Publisher: workflow.yml on cruxpass/cruxpass.py

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