Tokenwise Python SDK
Metadata-only usage tracking for Anthropic and OpenAI. Swap one import line and every API call's token counts and latency flow to your Tokenwise dashboard — with zero access to your prompts or responses.
- from anthropic import Anthropic
+ from tokenwise import Anthropic
Your code is otherwise unchanged: the wrapper exposes the identical interface, forwards every call to the official SDK, and returns its response untouched.
Why it's safe
- Metadata only. The SDK reads exactly:
model,input_tokens,output_tokens,cache_read_input_tokens,cache_creation_input_tokens,latency_ms,timestamp,endpoint. It never reads or transmits prompt text, response text, system prompts, or tool definitions. (Contrast with proxy-based tools, which see all your traffic.) - Non-blocking. Events are queued and sent on a background daemon thread. If Tokenwise is slow or down, your AI calls complete normally.
- Fail-silent + bounded. Up to 1,000 events buffer when offline; the oldest drop silently if the buffer fills. Capture never raises, never waits.
Install
pip install tokenwise-sdk[anthropic] # if you use Anthropic
pip install tokenwise-sdk[openai] # if you use OpenAI
pip install tokenwise-sdk[anthropic,openai]
anthropic and openai are optional extras — install only what you use.
Configure
Set your Tokenwise key (from the dashboard, looks like tw_...):
export TOKENWISE_API_KEY=tw_your_key
# optional:
export TOKENWISE_API_URL=https://tokenwise-production-aa59.up.railway.app # default
export TOKENWISE_DISABLED=true # emergency kill switch
Precedence for every setting: constructor argument > environment variable > default. If no key is configured the SDK runs disabled and your AI calls behave exactly as the official SDK.
Usage
# Pattern 1 — key from environment
import os
os.environ["TOKENWISE_API_KEY"] = "tw_abc123"
from tokenwise import Anthropic
client = Anthropic(api_key="sk-ant-...")
msg = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=256,
messages=[{"role": "user", "content": "Hello"}],
)
# Pattern 2 — key passed explicitly
from tokenwise import Anthropic
client = Anthropic(api_key="sk-ant-...", tokenwise_key="tw_abc123")
# Pattern 3 — OpenAI
from tokenwise import OpenAI
client = OpenAI(api_key="sk-...", tokenwise_key="tw_abc123")
client.chat.completions.create(
model="gpt-5.4",
messages=[{"role": "user", "content": "Hello"}],
)
Streaming and async work the same way:
# Streaming (sync) — usage captured on stream completion
with client.messages.create(..., stream=True) as stream:
for event in stream:
...
# Async
from tokenwise import AsyncAnthropic
client = AsyncAnthropic(api_key="sk-ant-...", tokenwise_key="tw_abc123")
msg = await client.messages.create(...)
What's instrumented (v1)
| Provider | Method | Streaming |
|---|---|---|
| Anthropic | messages.create |
✅ usage read from the event stream (request unchanged) |
| OpenAI | chat.completions.create |
✅ see note below |
Other methods pass through and work, but aren't yet recorded. (OpenAI Responses API and legacy completions are planned.)
Note on OpenAI streaming
OpenAI only returns token usage on a streamed response when the request includes
stream_options={"include_usage": True}. When you stream without supplying
your own stream_options, Tokenwise injects it for you so usage can be captured.
This adds one final usage-only chunk (with an empty choices list) to the
stream. If you already pass stream_options, Tokenwise respects yours and does
not modify the request (in that case usage is captured only if you enabled it).
Latency semantics
For non-streaming calls, latency_ms is the wall-clock time of the call. For
streaming calls it is the total stream duration (until the last chunk is
consumed), which includes time your code spends between chunks — events from
streaming calls carry streamed: true so this is distinguishable.
License
MIT
Release files for tokenwise-sdk 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tokenwise_sdk-0.1.1.tar.gz | 17.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tokenwise_sdk-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 31.3 kB
Release files / tokenwise_sdk-0.1.1.tar.gz
| Download URL | tokenwise_sdk-0.1.1.tar.gz |
|---|---|
| Size | 17.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
32a4edc44f95d8c27c7daf89524861b1441e8cde51e156e2647a2dcb22d73307
|
|
BLAKE2b-256 checksum How to use checksums |
0387aa1e2cab44ac2f69276dd277488caef6bb376cd9c6c0ff89ac3e3c38c425
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.5
|
Release files / tokenwise_sdk-0.1.1-py3-none-any.whl
| Download URL | tokenwise_sdk-0.1.1-py3-none-any.whl |
|---|---|
| Size | 13.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1055960088bc6a2d26a79753affb2b1d35f67e137d2967a5f0aaa085b29e4509
|
|
BLAKE2b-256 checksum How to use checksums |
caefea1a74df04c1520b97ba73799da25463145a404bdb03dbd8cc0c3d3eb6d9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.5
|