Metadata-Version: 2.4
Name: crbonfree
Version: 0.2.0
Summary: Python SDK for the CrbonFree carbon-offset API
Project-URL: Homepage, https://crbonfree.com
Project-URL: Repository, https://github.com/Crbon-Labs-Inc/crbonfree-python-sdk
Project-URL: Issues, https://github.com/Crbon-Labs-Inc/crbonfree-python-sdk/issues
Author: Crbon Labs Inc.
Author-email: CrbonFree <support@crbonfree.com>
License: MIT
License-File: LICENSE
Keywords: ai,carbon,crbonfree,emissions,offset,sdk
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
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: Typing :: Typed
Requires-Python: >=3.8
Requires-Dist: httpx>=0.23
Requires-Dist: pydantic>=2
Requires-Dist: typing-extensions>=4.0.0
Provides-Extra: dev
Requires-Dist: pytest; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Description-Content-Type: text/markdown

<p align="center">
  <strong>crbonfree</strong>
</p>

<p align="center">
  Measure and offset the carbon footprint of your AI workloads.<br />
  One SDK. Every major provider. Verified retirement receipts.
</p>

<p align="center">
  <a href="https://pypi.org/project/crbonfree/"><img src="https://img.shields.io/pypi/v/crbonfree.svg?style=flat-square" alt="PyPI" /></a>
  <a href="https://github.com/Crbon-Labs-Inc/crbonfree-python-sdk/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg?style=flat-square" alt="MIT" /></a>
  <a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/Python-3.8+-3776ab.svg?style=flat-square&logo=python&logoColor=white" alt="Python" /></a>
  <a href="https://beta.crbonfree.com"><img src="https://img.shields.io/badge/CrbonFree-beta-047857.svg?style=flat-square" alt="CrbonFree" /></a>
</p>

<br />

```bash
pip install crbonfree
```

## Get started

### 1. Log in (one command — no dashboard needed)

```bash
crbonfree login
```

Opens your browser, creates an account (or signs in), generates an API key, and saves it locally.

### 2. Use the SDK

```python
from crbonfree import CrbonFree

crbon = CrbonFree()  # reads saved credentials automatically

summary = crbon.telemetry.get_summary()
print(f"{summary.data.total_co2_kg} kg CO₂ from your AI usage")
```

No API key to copy-paste. No env vars to set. Just `crbonfree login` and go.

---

## Works with

OpenAI &nbsp;·&nbsp; Anthropic &nbsp;·&nbsp; OpenRouter &nbsp;·&nbsp; AWS Bedrock &nbsp;·&nbsp; and growing

Connect your provider accounts. We meter the inference. You get the emissions data + signed retirement receipts.

---

## What you can do

| | Method | What it returns |
|---|---|---|
| **Measure** | `crbon.telemetry.get_summary()` | Total CO₂, per-model rollups, daily chart |
| **Analyze** | `crbon.usage.get_breakdown()` | Which models cost the most carbon |
| **Organize** | `crbon.projects.list()` | Track emissions by project / team |
| **Prove** | `crbon.billing.list_receipts()` | Signed carbon retirement receipts |
| **Audit** | `crbon.billing.list_audit_packs()` | CSRD-ready compliance artifacts |
| **Manage** | `crbon.apikeys.create()` | Programmatic API key management |

<details>
<summary>Full API surface (8 sub-clients, 40+ methods)</summary>

| Sub-client | What it does | Key methods |
|---|---|---|
| `crbon.auth` | Session + user metadata | `me()`, `register()`, `update_profile()`, `delete_account()` |
| `crbon.apikeys` | API key management | `list()`, `create()`, `revoke()` |
| `crbon.connections` | Provider connections | `list()`, `create()`, `get()`, `sync()`, `delete()` |
| `crbon.projects` | Workspace organization | `list()`, `create()`, `get()`, `update()`, `delete()` |
| `crbon.usage` | Aggregated analytics | `get_summary()`, `get_breakdown()`, `get_daily()`, `export_daily()` |
| `crbon.subscriptions` | Billing lifecycle | `get()`, `get_estimate()`, `update_cap()`, `save_payment_method()` |
| `crbon.telemetry` | Event-level emissions | `get_summary()`, `list_events()`, `list_models()` |
| `crbon.billing` | Receipts + compliance | `list_periods()`, `list_receipts()`, `list_audit_packs()`, `get_plan_tier()` |

Every sync method has an async twin on `AsyncCrbonFree`.

</details>

---

## Authentication

<details open>
<summary><strong>Auto-login</strong> (recommended — zero config after first run)</summary>

```bash
crbonfree login
```

Saves your API key to `~/.crbonfree/credentials` (the same file the MCP server and TS SDK use). The client reads it automatically — no constructor args needed:

```python
from crbonfree import CrbonFree

crbon = CrbonFree()
```

```bash
crbonfree logout   # remove saved credentials
crbonfree whoami   # check who you're logged in as
```
</details>

<details>
<summary><strong>Explicit API key</strong> (for CI / env-var workflows)</summary>

```python
import os
from crbonfree import CrbonFree

crbon = CrbonFree(api_key=os.environ["CRBONFREE_API_KEY"])
```

Or set the variable and let the client pick it up:

```bash
export CRBONFREE_API_KEY="ck_live_..."
```

```python
crbon = CrbonFree()
```
</details>

When you omit `api_key`, the client resolves it in order: the explicit `api_key=`
argument → the `CRBONFREE_API_KEY` environment variable → the
`~/.crbonfree/credentials` file written by `crbonfree login`. If none are found
it raises `MissingCredentialsError` (importable from `crbonfree.client`). The
resolved key is sent on every request as the `X-API-Key` header.

### Async

```python
import asyncio
from crbonfree import AsyncCrbonFree

async def main():
    crbon = AsyncCrbonFree()  # same credential resolution as the sync client
    summary = await crbon.telemetry.get_summary()
    print(f"{summary.data.total_co2_kg} kg CO₂ from your AI usage")

asyncio.run(main())
```

---

## Pagination

Listing endpoints accept `page` and `limit` directly, but the helpers drive the
page loop for you:

```python
from crbonfree.pagination import auto_paginate, collect_all

# Stream every item across all pages
for receipt in auto_paginate(crbon.billing.list_receipts, limit=100):
    print(receipt.serial_number)

# Or pull everything into a list at once
receipts = collect_all(crbon.billing.list_receipts, limit=100)
```

Async clients get `auto_paginate_async` and `collect_all_async`. These apply to
the paginated list endpoints — `billing.list_receipts`,
`billing.list_audit_packs`, `billing.list_overages`, `billing.list_periods`, and
`telemetry.list_events`. Capped-list endpoints (`connections.list`,
`projects.list`, `apikeys.list`, `telemetry.list_models`) return plain lists and
need no pagination.

---

## Error handling

Failed requests raise typed exceptions carrying the status code and parsed body:

```python
from crbonfree import CrbonFree, NotFoundError

crbon = CrbonFree()

try:
    crbon.projects.get(id="nope")
except NotFoundError as err:
    print(err.status_code, err.body)  # 404, with a typed ErrorResponse
```

<details>
<summary>All error types</summary>

| Error | Status |
|---|---|
| `BadRequestError` | 400 |
| `UnauthorizedError` | 401 |
| `PaymentRequiredError` | 402 |
| `ForbiddenError` | 403 |
| `NotFoundError` | 404 |
| `ConflictError` | 409 |
| `TooManyRequestsError` | 429 |
| `InternalServerError` | 500 |
| `ServiceUnavailableError` | 503 |

All are importable from `crbonfree` and extend `ApiError`
(`crbonfree.core.api_error`) with `status_code`, `headers`, and `body`. Missing
credentials raise `MissingCredentialsError`.
</details>

---

## Configuration

```python
from crbonfree import CrbonFree

crbon = CrbonFree(
    api_key="...",                 # explicit key (overrides env + saved credentials)
    timeout=30,                    # seconds
    max_retries=3,
    base_url="https://custom.api/",
)
```

---

## MCP server

Want to give AI agents direct access to your carbon data? Check out
[`@crbonfree/mcp`](https://www.npmjs.com/package/@crbonfree/mcp) — works with
Claude Desktop, Cursor, and any MCP-compatible client, and shares the same
`~/.crbonfree/credentials` login.

---

<p align="center">
  <a href="https://beta.crbonfree.com">Dashboard</a> &nbsp;·&nbsp;
  <a href="https://github.com/Crbon-Labs-Inc/crbonfree-python-sdk/issues">Issues</a> &nbsp;·&nbsp;
  <a href="https://crbonfree.com">Website</a>
</p>

<p align="center">
  <sub>MIT — Crbon Labs Inc.</sub>
</p>
