Metadata-Version: 2.4
Name: cruxpass
Version: 0.0.3
Summary: Python client for the CruxPass API
Project-URL: Homepage, https://cruxpass.com
Project-URL: Repository, https://github.com/cruxpass/cruxpass.py
Project-URL: Issues, https://github.com/cruxpass/cruxpass.py/issues
Project-URL: Changelog, https://github.com/cruxpass/cruxpass.py/blob/main/CHANGELOG.md
Author-email: CruxPass <admin@cruxpass.com>
License: MIT
License-File: LICENSE
Keywords: calendar,cruxpass,feeds,ics
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: requests>=2.31
Description-Content-Type: text/markdown

# cruxpass

Python client for the CruxPass API.

This package is intentionally small while the public API settles. It provides a
thin `requests`-based wrapper around CruxPass publisher endpoints for creating
groups, feeds, subscribers, one-off events, and recurring schedules.

## Install

```bash
pip install cruxpass
```

## Usage

```python
from cruxpass import CruxPass

client = CruxPass(api_key="pk_...")

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"])
```

## Feed reads

```python
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

```python
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",
    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,
)
```

## Helpers

The client exposes the documented REST surface:

- `get_project()` / `update_project(feed_domain=...)`
- `list_groups()` / `create_group(...)`
- `list_feeds()` / `create_feed(...)`
- `list_subscribers()` / `create_subscriber(...)`
- `deactivate_subscriber(token)` / `rotate_subscriber_token(token)` / `refresh_subscriber_artifact(token)`
- `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=...)`.

## Status

Pre-1.0 package. Releases are coordinated with the matching CruxPass server
contract; see `CHANGELOG.md` for endpoint, client method, and migration notes.
