Metadata-Version: 2.5
Name: costfluent
Version: 1.0.0
Summary: Python client for the Costfluent Public API
Project-URL: Homepage, https://costfluent.com
Project-URL: Documentation, https://docs.costfluent.com/developers/sdks
Project-URL: Source, https://github.com/costfluent/costfluent-python
Author: Costfluent
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: api-client,cloud-costs,costfluent,finops
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: attrs>=22.2.0
Requires-Dist: httpx<0.29.0,>=0.23.1
Description-Content-Type: text/markdown

# costfluent

Python client for the [Costfluent](https://costfluent.com) Public API: every operation with typed
models, sync and async, plus retries, idempotency keys, pagination and errors handled for you.

```bash
pip install costfluent
```

It needs Python 3.11 or later and an API token, created under **Settings**, **API tokens**, on a
plan that includes API access. Give the token only the capabilities your script needs.

## Quick start

```python
import os

from costfluent import create_client, paginate
from costfluent.api.workspaces import list_workspaces

client = create_client(os.environ["COSTFLUENT_API_TOKEN"])

for workspace in paginate(list_workspaces.sync, client=client, limit=100):
    print(workspace.id, workspace.name)
```

Each operation is a module under `costfluent.api.<tag>` named after the operation, with four
functions: `sync` returns the parsed model, `sync_detailed` the status, headers and model, and
`asyncio` and `asyncio_detailed` are their async twins. Request and response models are under
`costfluent.models`. `create_client` takes `base_url`, `timeout` (seconds, per request) and
`max_retries`.

```python
from costfluent.api.folders import create_folder
from costfluent.models.create_folder_request import CreateFolderRequest

folder = create_folder.sync(client=client, body=CreateFolderRequest(workspace_id="wsp_...", title="Finance"))
```

## Pagination

A list answers one page with `links` and `data`. `paginate` (and `apaginate` for the async
functions) yields every item, following `links.next` until it is empty. The next page is always
requested from the client's own base URL, so the token goes nowhere else.

## Money

Amounts are strings holding the exact decimal the API computed, such as `"1234.56789012"`, never
floats. Convert with `decimal.Decimal(amount)` to calculate with them.

## Errors and retries

Any error status raises `CostfluentError` once retries are spent. It carries `status`, the API's
`code` (`not_found`, `validation_failed`, `idempotency_key_reused` and so on), `detail`,
`field_errors`, `trace_id` and the `request_id` to quote to support, with `is_not_found`,
`is_rate_limited` and `is_idempotency_key_reused` for the common checks.

- A 429 is retried for every method, after the `Retry-After` or `RateLimit-Reset` the API sends.
- A 5xx, a connection error, or a 404 that is not the API's own problem details (a proxy's) is
  retried for GET, HEAD, PUT, DELETE and creates, but not for other POSTs, which trigger work, nor
  for a request with `If-Match`.
- Retries back off exponentially from one second with jitter, at most three times. A wait over 60
  seconds is not waited out: the error is raised at once. A timeout is not retried.

Every create sends a fresh `Idempotency-Key` and resends it on each retry, so a retried create is
answered with the first response instead of creating twice. Pass `idempotency_key=` to choose the
key yourself, for example to make a scheduled job's create safe to run again.

## Versions

Releases are `1.MINOR.PATCH`, numbered with the Costfluent Go and TypeScript clients. The major is
the API's path version, `v1`, which only grows; the minor rises with each release that carries a
newer API contract, the patch is a fix to the client alone. `costfluent.CONTRACT_SHA256` is the
SHA-256 of the API document a release was generated from.

## Development

The modules under `costfluent/api` and `costfluent/models`, `client.py`, `errors.py`, `types.py`
and `_contract.py` are generated by `openapi-python-client` with `openapi-python-client.yaml`;
the rest is written by hand.

```bash
python3 -m venv .venv
.venv/bin/pip install --require-hashes -r requirements-dev.txt
PYTHONPATH=src .venv/bin/python -m unittest discover -s tests -t .
.venv/bin/ruff check . && .venv/bin/ruff format --check .
```

## License

Apache-2.0, see `LICENSE`.
