AI cost and margin intelligence for SaaS founders
Project description
weckr-sdk
AI cost and margin intelligence for SaaS founders. See exactly which users
cost more than they pay — per LLM call, zero added latency. The Python
counterpart of the TypeScript @weckr/sdk.
Try it live
See the dashboard with real data — no signup needed. 👉 https://app.useweckr.com/demo
Install
pip install weckr-sdk
Zero runtime dependencies. Bring your own LLM SDK:
pip install weckr-sdk openai # for OpenAI
pip install weckr-sdk anthropic # for Anthropic
pip install weckr-sdk google-genai # for Gemini (new SDK)
# or all at once:
pip install "weckr-sdk[all]"
Quick start
import os
from openai import OpenAI
from weckr import Weckr
openai_client = OpenAI() # reads OPENAI_API_KEY from env
wk = Weckr(
api_key=os.environ["WK_API_KEY"],
plans={"free": 0, "pro": 29, "business": 99},
)
result = wk.chat(
openai_client,
{
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "Summarize this."}],
"user_id": user.id,
"feature": "ai-summary",
"plan": user.plan,
},
)
print(result.choices[0].message.content)
See your own data in the dashboard: https://app.useweckr.com/dashboard Try the demo without signing up: https://app.useweckr.com/demo
The original LLM call runs unchanged and returns the original result. After it resolves, Weckr fires an async log POST to the Weckr API on a background thread — fire-and-forget, never blocks your request path.
Anthropic
from anthropic import Anthropic
from weckr import Weckr
anthropic_client = Anthropic()
wk = Weckr(api_key=os.environ["WK_API_KEY"], plans={"pro": 29})
msg = wk.chat(
anthropic_client,
{
"model": "claude-sonnet-4",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Hello!"}],
"user_id": user.id,
"plan": "pro",
},
)
Gemini
from google import genai
from weckr import Weckr
genai_client = genai.Client()
wk = Weckr(api_key=os.environ["WK_API_KEY"], plans={"pro": 29})
resp = wk.chat(
genai_client,
{
"model": "gemini-2.5-flash",
"messages": [{"role": "user", "content": "Hello!"}],
"user_id": user.id,
"plan": "pro",
},
)
Caps + downgrades
Set per-plan spending caps in the dashboard. When a user crosses their cap:
action: "block"—wk.chat()raisesWeckrCapErrorand the LLM call is never made.action: "downgrade"— the SDK silently swaps the model for a cheaper one in the same provider (gpt-4o→gpt-4o-mini,claude-opus-4→claude-sonnet-4, etc.) and emits a one-timeWeckrDowngradeWarningper (user, model) pair.
from weckr import Weckr, WeckrCapError, WeckrConfigError
try:
wk.chat(openai_client, {...})
except WeckrCapError as e:
show_upgrade_prompt(e.user_id, e.cap)
except WeckrConfigError as e:
# Typo'd api key, revoked key, or `plan` not in the plans dict —
# fail-CLOSED so cap enforcement isn't silently disabled.
alert_backend_team(e.code, str(e))
Short-lived processes (Lambda, cron, CLI)
wk.chat() returns as soon as the LLM call resolves; the log POST runs on a
daemon thread. In short-lived processes — Lambda, cron jobs, CLI scripts —
call wk.flush() before exit so the daemon thread isn't torn down mid-POST:
wk.chat(openai_client, {...})
wk.flush() # default 5s timeout
What gets logged
Every successful call (and every failed LLM call) lands in the dashboard:
{
"userId": "u_42",
"feature": "ai-summary",
"model": "gpt-4o-mini",
"provider": "openai",
"inputTokens": 12,
"outputTokens": 2,
"costUsd": 0.000003,
"latencyMs": 1218,
"planName": "pro",
"planRevenueUsd": 29.0,
"timestamp": "2026-06-15T07:52:18.086515+00:00",
}
Cost is recomputed server-side from (model, input_tokens, output_tokens) —
clients cannot forge cost values. Margin is planRevenueUsd - costUsd
(negative means you're losing money on that user); the dashboard derives it
on read from SUM(revenue) - SUM(cost) for full precision.
Supported models
- OpenAI —
gpt-4o,gpt-4o-mini,gpt-4-turbo,gpt-4,gpt-3.5-turbo,o1-preview,o1-mini - Anthropic —
claude-opus-4,claude-sonnet-4,claude-haiku-4-5,claude-3-5-sonnet,claude-3-5-haiku,claude-3-opus - Gemini —
gemini-2.5-pro,gemini-2.5-flash,gemini-1.5-pro,gemini-1.5-flash
Dated variants (gpt-4o-2024-08-06, claude-3-5-sonnet-latest, …) resolve
to the matching family by longest-prefix lookup.
Dashboard
View cost / margin / per-user / per-feature breakdowns at https://app.useweckr.com/dashboard.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file weckr_sdk-0.1.5.tar.gz.
File metadata
- Download URL: weckr_sdk-0.1.5.tar.gz
- Upload date:
- Size: 15.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ac8e891c805470d82d969886265f49a13c1ee73dcade4e22df54cd4b7422cf6d
|
|
| MD5 |
8856c4f6f9d8ebe5c17c0a652b55c016
|
|
| BLAKE2b-256 |
e972ef30b5999b1beca862379cc4f908e7bdcc6c3d4073def298ba329fd80b0a
|
File details
Details for the file weckr_sdk-0.1.5-py3-none-any.whl.
File metadata
- Download URL: weckr_sdk-0.1.5-py3-none-any.whl
- Upload date:
- Size: 19.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
14afc3f753e9460f189adccdd3742dc7f4356e381e789a0c8593c3ec02994dc3
|
|
| MD5 |
d16bc80ae1ee84860eb611651255d7d9
|
|
| BLAKE2b-256 |
93828eefad53c50caa1158f1eb20426584c6999850f47f67ba8232d646dfe84d
|