apidepth-python
Track outbound API latency, error rates, and rate limit quota across your third-party vendors — Stripe, OpenAI, Anthropic, Twilio, GitHub, and more.
Zero config for supported vendors. No code changes to your existing HTTP calls.
Installation
pip install apidepth
For requests instrumentation (most common):
pip install "apidepth[requests]"
For httpx instrumentation:
pip install "apidepth[httpx]"
Quick start
Django
Add to INSTALLED_APPS and configure in settings.py:
INSTALLED_APPS = [
...
"apidepth.integrations.django",
]
APIDEPTH = {
"api_key": env("APIDEPTH_API_KEY"),
"environment": env("DJANGO_ENV", default="development"),
}
Flask
from flask import Flask
from apidepth.integrations.flask import Apidepth
app = Flask(__name__)
app.config["APIDEPTH_API_KEY"] = os.environ["APIDEPTH_API_KEY"]
app.config["APIDEPTH_ENVIRONMENT"] = "production"
Apidepth(app)
Standalone / scripts
import apidepth
from apidepth import registry_loader
apidepth.configure(
api_key=os.environ["APIDEPTH_API_KEY"],
environment="production",
)
apidepth.instrument() # call before any outbound HTTP
registry_loader.load_and_start() # loads remote vendor registry + starts refresh thread
import requests
resp = requests.get("https://api.stripe.com/v1/charges/ch_abc123", ...)
load_and_start() fetches the latest vendor registry from the network (with a local disk cache fallback) and starts a background refresh thread. Without it, only the six bundled vendors are recognised. Django and Flask integrations call this automatically.
For Gunicorn / uWSGI, call Collector.register_fork_safety() once before the server forks so each worker gets its own flush thread:
from apidepth.collector import Collector
Collector.register_fork_safety()
Configuration
| Option | Default | Description |
|---|---|---|
api_key |
None |
Required. Your Apidepth API key. |
environment |
None |
Deployment environment tag, e.g. "production". |
enabled |
True |
Set False to disable all instrumentation. |
sample_rate |
1.0 |
Float 0.0–1.0. Fraction of requests to capture. |
ignored_hosts |
[] |
List of hostnames to never record. |
extra_vendors |
{} |
Map {"vendor-name": "host"} for in-house APIs. |
flush_interval |
20 |
Background flush interval in seconds. |
registry_cache_path |
/tmp/apidepth_registry.json |
Disk cache for the vendor registry. |
registry_refresh_interval |
21600 |
Registry refresh interval in seconds (6 h). |
on_flush_error |
None |
Callable(exc, ctx) for routing errors to Sentry etc. |
collector_url |
production endpoint | Override for self-hosted collectors. |
What gets captured
Every outbound HTTP request to a recognised vendor produces one event:
| Field | Example |
|---|---|
vendor |
"stripe" |
endpoint |
"/v1/charges/:id" |
method |
"POST" |
status |
200 |
outcome |
"success" / "client_error" / "server_error" / "timeout" |
duration_ms |
234 |
cold_start |
false (always — see Known differences) |
env |
"production" |
ts |
1747008000000 (epoch ms) |
rl_remaining |
4999 (when rate limit headers present) |
rl_limit |
5000 |
rl_reset_at |
1747008060000 (epoch ms) |
Never captured: request/response bodies, headers, query parameters, credentials.
Supported vendors
| Vendor | Host |
|---|---|
| Stripe | api.stripe.com |
| OpenAI | api.openai.com |
| Anthropic | api.anthropic.com |
| Twilio | api.twilio.com |
| Resend | api.resend.com |
| GitHub | api.github.com |
Additional vendors are loaded from the remote registry every 6 hours.
Custom vendors
apidepth.configure(
extra_vendors={"payments-api": "api.payments.internal"},
)
Rate limit tracking
The SDK extracts quota state from response headers and includes it in every event. Supported header families (checked in priority order):
- OpenAI / Anthropic:
x-ratelimit-remaining-requests,x-ratelimit-limit-requests,x-ratelimit-reset-requests - GitHub:
x-ratelimit-remaining,x-ratelimit-limit,x-ratelimit-reset - IETF draft / HubSpot:
ratelimit-remaining,ratelimit-limit,ratelimit-reset - Stripe / generic 429:
retry-after
Reset values are normalised to epoch milliseconds regardless of the source format (Unix timestamp, seconds-from-now, OpenAI duration strings like "1m30s").
Debugging
from apidepth.collector import Collector
print(Collector.instance().stats())
# {
# 'queue_size': 0,
# 'consecutive_failures': 0,
# 'total_dropped': 0,
# 'last_flush_at': 1747008000.123,
# }
Framework compatibility
| Framework | Version | Integration |
|---|---|---|
| Django | 3.2+ | apidepth.integrations.django in INSTALLED_APPS |
| Flask | 2.0+ | Apidepth(app) |
| FastAPI / Starlette | any | Call apidepth.instrument() at startup |
| Scripts / workers | — | Call apidepth.instrument() at startup |
Python compatibility
Python 3.9–3.13. No required runtime dependencies (stdlib only). requests and httpx are optional instrumentation targets detected at runtime.
Known differences from the Ruby gem
cold_start is always false
The Ruby gem tags the first outbound request on each TCP connection with cold_start: true using Net::HTTP#started?. The Apidepth collector uses this flag to exclude DNS + TCP + TLS handshake overhead from latency percentile calculations (p50/p95/p99), keeping those metrics representative of steady-state vendor performance.
Neither requests (backed by urllib3) nor httpx exposes a public API for detecting whether the underlying socket is a keep-alive reuse. The Python SDK therefore always sends cold_start: false.
Practical impact depends on your traffic pattern:
| Traffic pattern | Impact |
|---|---|
| High-throughput web service | Negligible — cold starts are a tiny fraction of total requests; percentile inflation is unmeasurable |
| Low-throughput service / cron job | Noticeable — the first request per run pays ~50–200 ms of connection overhead that isn't excluded from percentiles; p95/p99 may read slightly higher than in Ruby |
| Serverless / short-lived worker | Material — every invocation starts cold; all latency data includes connection overhead; comparisons against Ruby-instrumented services will show the Python side as systematically higher |
The raw duration values are accurate — only the percentile statistics are affected. If cold-start exclusion matters for your environment, filter those events manually in your dashboard (e.g. a warm-up request flag in thread-local state) until the underlying libraries expose the required connection-state API.
Metadata
Release files for apidepth 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| apidepth-0.2.0.tar.gz | 94.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| apidepth-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 136.4 kB
Release files / apidepth-0.2.0.tar.gz
| Download URL | apidepth-0.2.0.tar.gz |
|---|---|
| Size | 94.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a08b471176c4f0214c3141805f7eebd6359aae2ad37d4cf6aab9a1322a1ba821
|
|
BLAKE2b-256 checksum How to use checksums |
cbfa71b8753ff5f6f227202e7a6970cb9ddf18d359c86c76af33cce18bd3000e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 27, 2026.
Transparency logRelease files / apidepth-0.2.0-py3-none-any.whl
| Download URL | apidepth-0.2.0-py3-none-any.whl |
|---|---|
| Size | 41.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7d2f11a88e6cc08cfc4e7de25590fefe593efc8ecf3a96a2a98c756b6673c2cf
|
|
BLAKE2b-256 checksum How to use checksums |
e7324141da99133dbec48ef4f4489b0f65cfa00b39c0568bc59e45cd4a7f741e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 27, 2026.
Transparency log