Recost middleware for Python — API cost intelligence
Project description
recost
Python SDK for Recost — automatically tracks outbound HTTP API calls from your application and reports cost, latency, and usage patterns to the Recost dashboard or your local VS Code extension.
Requires Python 3.9+. No core dependencies.
How it works
The SDK patches urllib3, httpx, and aiohttp to intercept outbound requests at runtime. It captures metadata only (URL, method, status, latency, byte sizes — never headers or bodies), matches each request against a built-in provider registry, aggregates events into time-windowed summaries, and ships those summaries to the Recost cloud API or the Recost VS Code extension running locally.
Your app
└─ requests.get("https://api.openai.com/v1/chat/completions", ...)
│
▼
Interceptor ← patches urllib3, httpx, aiohttp
│ RawEvent { host, path, method, status_code, latency_ms, ... }
▼
ProviderRegistry ← matches host/path → provider + endpoint_category + cost
│
▼
Aggregator ← buffers events, flushes WindowSummary every 30s
│
▼
Transport
├─ local mode → WebSocket → VS Code extension (port 9847)
└─ cloud mode → HTTPS POST → api.recost.dev
Installation
pip install recost
With optional framework and local mode extras:
pip install recost[fastapi] # FastAPI/Starlette middleware
pip install recost[flask] # Flask extension
pip install recost[local] # WebSocket transport for VS Code extension
pip install recost[all] # Everything
Quick start
Local mode (VS Code extension)
No API key needed. Telemetry goes to the Recost VS Code extension over localhost.
from recost import init
init() # defaults — local mode on port 9847
Cloud mode
import os
from recost import init, RecostConfig
init(RecostConfig(
api_key=os.environ["RECOST_API_KEY"],
project_id=os.environ["RECOST_PROJECT_ID"],
environment=os.environ.get("PYTHON_ENV", "development"),
))
FastAPI
from fastapi import FastAPI
from recost.frameworks.fastapi import RecostMiddleware
app = FastAPI()
app.add_middleware(RecostMiddleware, api_key="...", project_id="...")
Flask
from flask import Flask
from recost.frameworks.flask import ReCost
app = Flask(__name__)
ReCost(app, api_key="...", project_id="...")
Or using the init_app pattern:
recost = ReCost()
recost.init_app(app, api_key="...", project_id="...")
Configuration
All fields are optional. Pass them as keyword arguments or via a RecostConfig instance.
| Option | Type | Default | Description |
|---|---|---|---|
api_key |
str |
— | Recost API key (rc-...). If omitted, runs in local mode. |
project_id |
str |
— | Recost project ID. Required in cloud mode. |
environment |
str |
"development" |
Environment tag attached to all telemetry. |
flush_interval |
float |
30.0 |
Seconds between automatic flushes. |
max_batch_size |
int |
100 |
Early-flush threshold (number of events). |
local_port |
int |
9847 |
WebSocket port for the VS Code extension. |
debug |
bool |
False |
Log telemetry activity to stderr. |
enabled |
bool |
True |
Master kill switch — set False to disable entirely. |
custom_providers |
list[ProviderDef] |
[] |
Extra provider rules with higher priority than built-ins. |
exclude_patterns |
list[str] |
[] |
URL substrings — matching requests are silently dropped. |
base_url |
str |
"https://api.recost.dev" |
Override for self-hosted deployments. |
max_retries |
int |
3 |
Retry attempts for failed cloud flushes. |
on_error |
Callable |
— | Called on internal SDK errors. |
Custom providers
from recost import init, RecostConfig, ProviderDef
init(RecostConfig(
custom_providers=[
ProviderDef(
host_pattern="api.internal.acme.com",
path_prefix="/payments",
provider="acme-payments",
endpoint_category="charge",
cost_per_request_cents=0.5,
),
],
))
Cleanup / teardown
init() returns a handle with a dispose() method that stops the interceptor, cancels the flush timer, and closes the transport connection.
handle = init(RecostConfig(api_key="..."))
# In a test teardown or shutdown handler:
handle.dispose()
Disabling in tests
import os
from recost import init, RecostConfig
init(RecostConfig(enabled=os.environ.get("PYTHON_ENV") != "test"))
Supported providers
Built-in rules ship for the providers below. Cost estimates are rough per-request averages for relative comparison — actual costs vary by model, token count, and region.
| Provider | Host | Tracked endpoints | Cost estimate |
|---|---|---|---|
| OpenAI | api.openai.com |
chat completions, embeddings, image generation, audio transcription, TTS | 0.01–4.0¢/req |
| Anthropic | api.anthropic.com |
messages | 1.5¢/req |
| Stripe | api.stripe.com |
charges, payment intents, customers, subscriptions | 0¢ (% billing) |
| Twilio | api.twilio.com |
SMS, voice calls | 0.79–1.3¢/req |
| SendGrid | api.sendgrid.com |
mail send | 0.1¢/req |
| Pinecone | *.pinecone.io |
vector upsert, query | 0.08¢/req |
| AWS | *.amazonaws.com |
all services (wildcard) | 0¢ (complex pricing) |
| Google Cloud | *.googleapis.com |
all services (wildcard) | 0¢ (complex pricing) |
Unrecognized hosts still appear in telemetry, grouped under "unknown".
What is captured (and what is not)
Captured:
- Request timestamp, method, URL (query params stripped), host, path
- Response status code
- Round-trip latency (ms)
- Request and response body size (bytes)
- Matched provider, endpoint category, and estimated cost
Never captured:
- Request or response headers (may contain API keys)
- Request or response body content (may contain user data or PII)
Core types
from recost import (
RawEvent, # A single intercepted HTTP request
MetricEntry, # Aggregated stats for one provider + endpoint + method
WindowSummary, # Flush payload sent to the API or VS Code extension
RecostConfig, # SDK configuration
ProviderDef, # A custom provider matching rule
TransportMode, # Literal["local", "cloud"]
)
Development
pip install -e ".[dev]"
pytest # run all tests
ruff check . # lint
mypy recost/ # type check
API reference
All requests go to https://api.recost.dev. Authentication uses a rc- prefixed API key as Authorization: Bearer {api_key}.
Send telemetry (what the SDK does on flush)
curl -s -X POST https://api.recost.dev/projects/{project_id}/telemetry \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {api_key}" \
-d @payload.json | jq .
View recent telemetry windows
curl -s "https://api.recost.dev/projects/{project_id}/telemetry/recent?limit=10" \
-H "Authorization: Bearer {api_key}" | jq .
View analytics
curl -s "https://api.recost.dev/projects/{project_id}/analytics?from=2026-01-01T00:00:00Z&to=2026-12-31T23:59:59Z" \
-H "Authorization: Bearer {api_key}" | jq .
License
Licensed under the Business Source License 1.1 © 2026 Andres Lopez, Aslan Wang, Donggyu Yoon. Converts to Apache 2.0 on 2030-04-02.
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 recost-0.1.1.tar.gz.
File metadata
- Download URL: recost-0.1.1.tar.gz
- Upload date:
- Size: 30.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fcdd7b4aa50f337d832450b92d8e52e29179cd9f622693aeade3eeb13cb2b681
|
|
| MD5 |
bedec83ef15dc099b63df5624cbeece4
|
|
| BLAKE2b-256 |
009d1fe668ef00051a1e6a937aa06c9ba0c0a8ee684f823e364eb862c7074150
|
Provenance
The following attestation bundles were made for recost-0.1.1.tar.gz:
Publisher:
pypi-publish.yml on recost-dev/middleware-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
recost-0.1.1.tar.gz -
Subject digest:
fcdd7b4aa50f337d832450b92d8e52e29179cd9f622693aeade3eeb13cb2b681 - Sigstore transparency entry: 1355950298
- Sigstore integration time:
-
Permalink:
recost-dev/middleware-python@133114d7fabcf3137268eb77c61ed03b6e892412 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/recost-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@133114d7fabcf3137268eb77c61ed03b6e892412 -
Trigger Event:
push
-
Statement type:
File details
Details for the file recost-0.1.1-py3-none-any.whl.
File metadata
- Download URL: recost-0.1.1-py3-none-any.whl
- Upload date:
- Size: 25.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1ef5f4ea2356fd77518fd56206f5b8af237361cfdd436ce333cfc58f2997fb32
|
|
| MD5 |
0f77b1e712b687ce216273aa532ed4ab
|
|
| BLAKE2b-256 |
a114579d8afe377e7ddf44ed23fb6cc7c231e90942cc9a1aa3d91a275f026ba9
|
Provenance
The following attestation bundles were made for recost-0.1.1-py3-none-any.whl:
Publisher:
pypi-publish.yml on recost-dev/middleware-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
recost-0.1.1-py3-none-any.whl -
Subject digest:
1ef5f4ea2356fd77518fd56206f5b8af237361cfdd436ce333cfc58f2997fb32 - Sigstore transparency entry: 1355950327
- Sigstore integration time:
-
Permalink:
recost-dev/middleware-python@133114d7fabcf3137268eb77c61ed03b6e892412 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/recost-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@133114d7fabcf3137268eb77c61ed03b6e892412 -
Trigger Event:
push
-
Statement type: