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 byhttpx - 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 ofAPIError CRUXPASS_API_KEYandCRUXPASS_BASE_URLenvironment 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e1171f68cc8500d652e33ae5f15542d2b9eab2f0a0fd6841dc4325a28c5344d4
|
|
| MD5 |
57e5eb8691c7fabcf214c26c616c90f9
|
|
| BLAKE2b-256 |
f0f90e0487f17b3de7e371f6e43a48f5d4cfb84128e2633835769135e7b70f00
|
Provenance
The following attestation bundles were made for cruxpass-0.0.4.tar.gz:
Publisher:
workflow.yml on cruxpass/cruxpass.py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cruxpass-0.0.4.tar.gz -
Subject digest:
e1171f68cc8500d652e33ae5f15542d2b9eab2f0a0fd6841dc4325a28c5344d4 - Sigstore transparency entry: 2095257388
- Sigstore integration time:
-
Permalink:
cruxpass/cruxpass.py@22dc9a40825c84cc5793854529e4533fcad9fd93 -
Branch / Tag:
refs/tags/v0.0.4 - Owner: https://github.com/cruxpass
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@22dc9a40825c84cc5793854529e4533fcad9fd93 -
Trigger Event:
push
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
33f4a3bf11270a16782510d702f7e48a2c4d5c45a953146e59f3cff777799ff8
|
|
| MD5 |
be3486726e17da57488cdfbc2371ee69
|
|
| BLAKE2b-256 |
e0e74a52c8e05c569a2c34979552e555354c74969bc1f1b361a93b16c76620a5
|
Provenance
The following attestation bundles were made for cruxpass-0.0.4-py3-none-any.whl:
Publisher:
workflow.yml on cruxpass/cruxpass.py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cruxpass-0.0.4-py3-none-any.whl -
Subject digest:
33f4a3bf11270a16782510d702f7e48a2c4d5c45a953146e59f3cff777799ff8 - Sigstore transparency entry: 2095257722
- Sigstore integration time:
-
Permalink:
cruxpass/cruxpass.py@22dc9a40825c84cc5793854529e4533fcad9fd93 -
Branch / Tag:
refs/tags/v0.0.4 - Owner: https://github.com/cruxpass
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@22dc9a40825c84cc5793854529e4533fcad9fd93 -
Trigger Event:
push
-
Statement type: