Metadata-Version: 2.4
Name: codelet
Version: 0.2.0
Summary: Official Python SDK for the Codelet public API
Author: Codelet
License: MIT
Project-URL: Homepage, https://codelet.co
Keywords: codelet,billing,usage,sdk
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: urllib3<3.0.0,>=2.1.0
Requires-Dist: python-dateutil>=2.8.2
Requires-Dist: pydantic>=2
Requires-Dist: typing-extensions>=4.7.1

# Codelet Python SDK

Official Python client for the [Codelet](https://codelet.co) public API.

## Install

```bash
pip install codelet
```

For local development from this monorepo:

```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
```

## Usage

```python
from codelet import Codelet, CodeletError
from codelet.models import CancelSubscriptionRequest

codelet = Codelet(api_key="cl_test_…")  # or cl_live_…

# Ingest (auto idempotency_key when omitted)
codelet.ingest({
    "customer_id": "org_42",
    "metric": "api_call",
    "quantity": "1",
})

me = codelet.account.get_me()
customers = codelet.customers.list_customers()
codelet.subscriptions.cancel_subscription(
    "subs_…",
    CancelSubscriptionRequest(mode="at_period_end"),
)
```

Optional client options: `base_url`, `retries`, `headers`.

## Examples

Create metrics before plans, credit packs, or ingest. Unknown metric names return 400.

### Create a metric

```python
from codelet.models import CreateMetricRequest

metric = codelet.metrics.create_metric(
    CreateMetricRequest(
        name="api_request",
        display_name="API Request",
        aggregation="sum",
    )
)
```

### Create a credit pack

```python
from codelet.models import CreateCreditPackRequest

pack = codelet.credit_packs.create_credit_pack(
    CreateCreditPackRequest(
        metric="api_request",
        name="500 API requests",
        price_amount="25.00",
        currency="USD",
        quantity_granted="500",
    )
)
```

### Create and publish a plan

```python
from codelet.models import CreatePlanRequest

plan = codelet.plans.create_plan(
    CreatePlanRequest(
        name="Pro",
        description="Usage-based Pro plan",
        version={
            "currency": "USD",
            "billing_period": "monthly",
            "billing_mode": "postpaid",
            "fixed_fees": [
                {
                    "fee_type": "period_charge",
                    "name": "Platform fee",
                    "amount": "29.00",
                },
            ],
            "usage_fees": [
                {
                    "pricing_model": "unit",
                    "billing_timing": "in_arrears",
                    "included_quantity": "1000",
                    "unit_price": "0.002",
                    "metric": "api_request",
                },
            ],
        },
    )
)

# Drafts are not checkout-ready until published
codelet.plans.publish_plan(plan.id)
```

### Create checkout

Credit pack (one-time purchase):

```python
from codelet.models import CreateCheckoutRequest

pack_checkout = codelet.checkout.create_checkout(
    CreateCheckoutRequest(
        customer_id="org_42",
        pack_id="pack_…",
        success_url="https://yourapp.com/billing/success",
        cancel_url="https://yourapp.com/billing/cancel",
        idempotency_key="purchase:order-123",
    )
)
# Redirect the browser to pack_checkout.checkout_url
```

Subscription (plan):

```python
plan_checkout = codelet.checkout.create_checkout(
    CreateCheckoutRequest(
        customer_id="org_42",
        plan_id="plan_…",
        success_url="https://yourapp.com/welcome",
    )
)
# Redirect the browser to plan_checkout.checkout_url
```

Pass either `customer_id` or `customer_email`, not both. Exactly one of
`pack_id` or `plan_id` is required.

## API reference

All generated methods are available on the `Codelet` instance (for example
`codelet.customers.list_customers`). Prefer `codelet.ingest(…)` over
`codelet.usage.ingest_event(…)` when recording usage; the helper fills
`idempotency_key` when omitted.

### `codelet.ingest(body)`

Ingest a usage event. Same as `usage.ingest_event`, but generates
`idempotency_key` when omitted. Accepts a dict or `IngestEventRequest`.

| Method         | Description       |
| -------------- | ----------------- |
| `ingest(body)` | `POST /v1/ingest` |

### Account (`codelet.account`)

| Method     | Description                             |
| ---------- | --------------------------------------- |
| `get_me()` | API key context (project + environment) |

### Checkout (`codelet.checkout`)

| Method                                     | Description                                   |
| ------------------------------------------ | --------------------------------------------- |
| `create_checkout(create_checkout_request)` | Create a credit pack or subscription checkout |

### Credit packs (`codelet.credit_packs`)

| Method                                                                       | Description                             |
| ---------------------------------------------------------------------------- | --------------------------------------- |
| `list_credit_packs(metric=None, active="true", page_size=None, cursor=None)` | List packs (default: active only)       |
| `create_credit_pack(create_credit_pack_request)`                             | Create a pack                           |
| `get_credit_pack(pack_id)`                                                   | Get a pack by ID                        |
| `update_credit_pack(pack_id, update_credit_pack_request)`                    | Update name, description, and/or active |

### Customers (`codelet.customers`)

| Method                                                  | Description                           |
| ------------------------------------------------------- | ------------------------------------- |
| `list_customers(page_size=None, cursor=None)`           | List customers                        |
| `create_customer(create_customer_request)`              | Create a customer                     |
| `get_customer(customer_id)`                             | Get a customer                        |
| `update_customer(customer_id, update_customer_request)` | Update editable fields                |
| `get_customer_balance(customer_id, metric=None)`        | Credit balances (all metrics, or one) |

### Metrics (`codelet.metrics`)

| Method                                       | Description                            |
| -------------------------------------------- | -------------------------------------- |
| `list_metrics(page_size=None, cursor=None)`  | List metrics                           |
| `create_metric(create_metric_request)`       | Create a metric                        |
| `get_metric(name)`                           | Get a metric by name                   |
| `update_metric(name, update_metric_request)` | Partial update (today: `display_name`) |

### Plans (`codelet.plans`)

| Method                                                        | Description                     |
| ------------------------------------------------------------- | ------------------------------- |
| `list_plans(status="published", page_size=None, cursor=None)` | List plans (default: published) |
| `create_plan(create_plan_request)`                            | Create a draft plan             |
| `get_plan(plan_id, include_pricing_details=False)`            | Get a plan                      |
| `publish_plan(plan_id)`                                       | Publish the draft version       |

### Subscriptions (`codelet.subscriptions`)

| Method                                                                        | Description                             |
| ----------------------------------------------------------------------------- | --------------------------------------- |
| `list_subscriptions(customer=None, status=None, page_size=None, cursor=None)` | List subscriptions                      |
| `get_subscription(subscription_id)`                                           | Get a subscription                      |
| `cancel_subscription(subscription_id, cancel_subscription_request)`           | Cancel (`at_period_end` or `immediate`) |
| `resume_subscription(subscription_id)`                                        | Clear a scheduled cancellation          |

### Usage (`codelet.usage`)

| Method                               | Description                                    |
| ------------------------------------ | ---------------------------------------------- |
| `ingest_event(ingest_event_request)` | Ingest a usage event (no auto idempotency key) |

Request and response models live under `codelet.models`.

Request and response shapes match the [OpenAPI spec](https://codelet.co/openapi.json).
See also [codelet.co/SKILL.md](https://codelet.co/SKILL.md) for merchant integration guidance.

## Errors

```python
from codelet import CodeletError, CodeletRateLimitError

try:
    codelet.ingest({...})
except CodeletRateLimitError:
    # 429
    pass
except CodeletError:
    # other API errors (status + body)
    pass
```

Generated APIs raise `ApiException` from the OpenAPI client. The top-level
`ingest` helper maps those to `CodeletError` / `CodeletRateLimitError`.

## Development

```bash
# from repo root
make sdk-generate
cd sdks/python && python3 -m venv .venv && source .venv/bin/activate && pip install -e .
```

Hand-written surface (`src/codelet/`) stays stable. Generated code under
`src/codelet_generated/` is overwritten by `make sdk-generate`, which also
refreshes `src/codelet/models.py` public re-exports.
