Metadata-Version: 2.5
Name: tolla
Version: 0.1.1
Summary: Free-tier economics for AI and usage-based SaaS: see what each free user costs and which ones convert.
Project-URL: Homepage, https://gettolla.com
License-Expression: MIT
License-File: LICENSE
Keywords: ai,anthropic,cost,free tier,llm,openai,saas,stripe,usage
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# tolla

See what each free user of your AI product costs, which ones convert, and which accounts are the same person. This is the Python server SDK for [Tolla](https://gettolla.com). Python 3.9+, no dependencies.

```bash
pip install tolla
```

```python
from openai import OpenAI
from tolla import Tolla, with_user, wrap_openai

tolla = Tolla()  # reads TOLLA_SECRET_KEY
openai = wrap_openai(OpenAI(), tolla)

# 1. When someone signs up
tolla.identify(user.id, created_at=user.created_at, identity={"email": user.email, "ip": request.remote_addr})

# 2. Every AI call: cost is recorded per user automatically
with with_user(user.id, feature="chat"):
    openai.chat.completions.create(model="gpt-4o", messages=messages)
```

Payments come from Stripe: connect it with a read-only key on your Tolla Connect page. No code needed.

## Safe by design

- **Never blocks, never raises.** Calls return immediately; a background thread sends events in batches.
- **Survives outages.** Retries with backoff and a timeout; if Tolla stays unreachable, events are dropped with a warning (bounded queue), and your product carries on.
- **Retry-safe.** Every event gets an id, so a resend is never counted twice.
- **Fork-safe.** Works under gunicorn, uWSGI and multiprocessing.
- **No prompts, no outputs.** The AI wrappers read only `model` and `usage`.
- **No dependencies.** Standard library only.

## AI cost

`wrap_openai` and `wrap_anthropic` work with sync and async clients (`OpenAI`, `AsyncOpenAI`, `Anthropic`, `AsyncAnthropic`) and record model and tokens for chat, responses, embeddings and messages, streaming included. Tolla prices the tokens server-side from a maintained price list (cached-input and cache-write rates included), so new prices never need an SDK update. Any model's price can be overridden in your workspace.

Attach the user with `with with_user(user_id, feature="chat"):` (works across threads and asyncio), or per client: `wrap_openai(client, tolla, user_id=user.id)`.

OpenAI Chat Completions streams only include usage when you pass `stream_options={"include_usage": True}`. The Responses API and Anthropic always include it.

Other providers: send the tokens yourself.

```python
tolla.cost(user.id, "chat", model="gemini-2.5-pro", input_tokens=812, output_tokens=230)
tolla.cost(user.id, "render", cost_usd=0.04)  # or a cost you computed
```

## Serverless

Background sending needs the process to stay alive. In AWS Lambda, Cloud Functions and similar, call `tolla.flush()` before returning.

## Options

`Tolla(api_key=None, base_url=None, batch_size=100, flush_interval=1.0, max_queue_size=10_000, timeout=10.0, max_retries=5, disabled=False, on_error=None)`

`on_error` receives every problem, including events Tolla rejected and why; by default a warning is logged at most once a minute. The Connect page in Tolla has a live event debugger showing every event received.

MIT licensed.
