Skip to main content

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.

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)

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() raises WeckrCapError and the LLM call is never made.
  • action: "downgrade" — the SDK silently swaps the model for a cheaper one in the same provider (gpt-4ogpt-4o-mini, claude-opus-4claude-sonnet-4, etc.) and emits a one-time WeckrDowngradeWarning per (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

  • OpenAIgpt-4o, gpt-4o-mini, gpt-4-turbo, gpt-4, gpt-3.5-turbo, o1-preview, o1-mini
  • Anthropicclaude-opus-4, claude-sonnet-4, claude-haiku-4-5, claude-3-5-sonnet, claude-3-5-haiku, claude-3-opus
  • Geminigemini-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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

weckr_sdk-0.1.1.tar.gz (13.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

weckr_sdk-0.1.1-py3-none-any.whl (17.6 kB view details)

Uploaded Python 3

File details

Details for the file weckr_sdk-0.1.1.tar.gz.

File metadata

  • Download URL: weckr_sdk-0.1.1.tar.gz
  • Upload date:
  • Size: 13.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for weckr_sdk-0.1.1.tar.gz
Algorithm Hash digest
SHA256 8191ab1b78b5fb196a6adda4e983d27c94624c977556b070ff713f0c2cee3b9c
MD5 7458d8674255b5334147528a3d868c05
BLAKE2b-256 d946345cea6d1aab27b53f22b34149d283749999a84b00820f8fcd6dae4f8a9a

See more details on using hashes here.

File details

Details for the file weckr_sdk-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: weckr_sdk-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 17.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for weckr_sdk-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1764b576808f59a430934c8a21107b3e28e2f1fd8e8113d869c8705daa4c6e24
MD5 a029ff5a314fa5df760a6fef40979a8a
BLAKE2b-256 711f846e241a1e8b867d3246383a1938735344074fa11c06d936fa3c5dc0c419

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page