API Lens Python SDK with OpenTelemetry-based ingest forwarding
Project description
API Lens Python SDK
Production-ready Python ingest client for API Lens with OpenTelemetry integration.
⚠️ Breaking Change in v0.1.6: Both
project_slugandapp_idare now required for all ingest paths. Make sure both match the same project in your dashboard.
Framework support matrix
| Framework | Integration Module | Integration Type | Client Type |
|---|---|---|---|
| FastAPI | apilens.fastapi |
ASGI Middleware | AsyncIO |
| Starlette | apilens.starlette |
ASGI Middleware | AsyncIO |
| Django REST Framework | apilens.django |
Django Middleware | Threading |
| Django Ninja | apilens.django |
Django Middleware | Threading |
| Flask | apilens.flask |
WSGI Wrapper | Threading |
| Litestar | apilens.litestar |
Plugin Protocol | AsyncIO |
| BlackSheep | apilens.blacksheep |
ASGI Middleware | AsyncIO |
What this SDK includes
- batched + retrying ingest client (
ApiLensClient) - OpenTelemetry span exporter (
apilens.otel) for teams already on OTel - first-class framework integrations listed above
- automatic request/response payload sampling (size-limited)
Install
pip install apilenss
With framework support:
pip install 'apilenss[all]'
# or only one
pip install 'apilenss[fastapi]'
pip install 'apilenss[flask]'
Local development install (from repo):
pip install ./packages/sdk-python
pip install './packages/sdk-python[all]'
Quick start (manual capture)
from apilens import ApiLensClient, ApiLensConfig
client = ApiLensClient(
ApiLensConfig(
api_key="your_app_api_key",
project_slug="your-project-slug",
base_url="https://ingest.apilens.ai/v1",
environment="production",
)
)
client.capture(
app_id="my-api-service", # Required: App slug inside that project
method="GET",
path="/health",
status_code=200,
response_time_ms=12.4,
)
client.shutdown(flush=True)
Getting your Project Slug and App ID
You now need both:
project_slug = "astra"
app_id = "sidecar"
Use the project slug from the project page, and the app slug from the app page in that same project.
FastAPI
No OpenTelemetry instrumentation is required for endpoint + payload monitoring.
from fastapi import FastAPI
from typing import Annotated
from fastapi import Depends, Request
from apilens.fastapi import ApiLensMiddleware, set_consumer
app = FastAPI()
app.add_middleware(
ApiLensMiddleware,
api_key="your_app_api_key", # Required: Your API key
project_slug="your-project-slug", # Required: Project slug from dashboard
app_id="my-api-service", # Required: App slug inside that project
base_url="https://ingest.apilens.ai/v1",
env="production",
enable_request_logging=True,
log_request_body=True,
log_response_body=True,
)
def identify_consumer(request: Request, user_id: Annotated[str, Depends(lambda: "user_123")]):
set_consumer(request, identifier=user_id, name="Demo User", group="starter")
app.router.dependencies.append(Depends(identify_consumer))
@app.get("/v1/orders")
def list_orders():
return {"ok": True}
Environment Variables (Recommended):
import os
from fastapi import FastAPI
from apilens.fastapi import ApiLensMiddleware
app = FastAPI()
app.add_middleware(
ApiLensMiddleware,
api_key=os.getenv("APILENS_API_KEY"),
project_slug=os.getenv("APILENS_PROJECT_SLUG"),
app_id=os.getenv("APILENS_APP_ID"),
base_url=os.getenv("APILENS_BASE_URL", "https://ingest.apilens.ai/v1"),
env=os.getenv("APILENS_ENVIRONMENT", "production"),
enable_request_logging=True,
log_request_body=True,
log_response_body=True,
)
Starlette
from starlette.applications import Starlette
from apilens import ApiLensClient, ApiLensConfig
from apilens.starlette import instrument_app
app = Starlette()
client = ApiLensClient(
ApiLensConfig(
api_key="your_app_api_key",
project_slug="your-project-slug",
base_url="https://ingest.apilens.ai/v1",
environment="production",
)
)
instrument_app(
app,
client,
project_slug="your-project-slug",
app_id="your_app_id"
)
Flask
from flask import Flask
from apilens import ApiLensClient, ApiLensConfig
from apilens.flask import instrument_app
app = Flask(__name__)
client = ApiLensClient(
ApiLensConfig(
api_key="your_app_api_key",
project_slug="your-project-slug",
base_url="https://ingest.apilens.ai/v1",
environment="production",
)
)
instrument_app(
app,
client,
project_slug="your-project-slug",
app_id="your_app_id"
)
@app.get("/v1/invoices")
def invoices():
return {"ok": True}
Django (DRF + Django Ninja)
Add middleware in Django settings:
MIDDLEWARE = [
# ...
"apilens.django.ApiLensDjangoMiddleware",
]
# Required configuration
APILENS_API_KEY = "your_app_api_key"
APILENS_PROJECT_SLUG = "your-project-slug"
APILENS_APP_ID = "your_app_id"
APILENS_BASE_URL = "https://ingest.apilens.ai/v1"
APILENS_ENVIRONMENT = "production"
Litestar
from litestar import Litestar
from apilens import ApiLensClient, ApiLensConfig
from apilens.litestar import ApiLensPlugin
client = ApiLensClient(
ApiLensConfig(
api_key="your_app_api_key",
base_url="https://ingest.apilens.ai/v1",
environment="production",
)
)
app = Litestar(
route_handlers=[],
plugins=[ApiLensPlugin(
client=client,
app_id="your_app_id" # Required: Your app ID from dashboard
)]
)
BlackSheep
from blacksheep import Application
from apilens import ApiLensClient, ApiLensConfig
from apilens.blacksheep import instrument_app
app = Application()
client = ApiLensClient(
ApiLensConfig(
api_key="your_app_api_key",
base_url="https://ingest.apilens.ai/v1",
environment="production",
)
)
instrument_app(
app,
client,
app_id="your_app_id" # Required: Your app ID from dashboard
)
Configuration Options
| Parameter | Required | Default | Description |
|---|---|---|---|
api_key |
Yes | - | Your API key from API Lens dashboard |
project_slug |
Yes | - | Your project slug from API Lens dashboard |
app_id |
Yes | - | Your app slug inside that project |
base_url |
No | https://ingest.apilens.ai/v1 |
API Lens ingest endpoint |
environment |
No | production |
Environment name (e.g., production, staging, dev) |
enable_request_logging |
No | True |
Enable request/response logging |
log_request_body |
No | False |
Log request body (up to max size) |
log_response_body |
No | False |
Log response body (up to max size) |
Notes
- Default flush interval:
3s - Default batch size:
200 - Max ingest batch payload sent per request: follows backend limit (
<= 1000) - Call
client.shutdown(flush=True)on graceful shutdown
Troubleshooting
422 Unprocessable Entity Error
If you're getting 422 errors, make sure you've included both project_slug and app_id:
# ❌ Old way (will fail)
app.add_middleware(
ApiLensMiddleware,
api_key="your_key",
)
# ✅ New way (required since v0.1.6)
app.add_middleware(
ApiLensMiddleware,
api_key="your_key",
project_slug="your-project-slug",
app_id="your_app_id",
)
Finding Your Project Slug and App ID
- Log in to API Lens Dashboard
- Open your project and copy the project slug
- Open the app inside that project and copy the app slug
Data Not Appearing in Dashboard
- Verify
project_slugis correct - Verify
app_idis correct for that project - Check that
api_keyis valid - Ensure
base_urlpoints to the correct endpoint - Check application logs for SDK errors
- Wait up to 30 seconds for data to appear (batching delay)
Migration from v0.1.5 to v0.1.6
Breaking change: project_slug is now required alongside app_id.
Update all middleware/client configurations to include project_slug and app_id:
# Before (v0.1.5)
client = ApiLensClient(ApiLensConfig(
api_key="...",
))
# After (v0.1.6)
client = ApiLensClient(ApiLensConfig(
api_key="...",
project_slug="your-project-slug",
))
client.capture(
app_id="your_app_id",
method="GET",
path="/health",
# ...
)
Support
- 📧 Email: hello@apilens.ai
- 📖 Documentation: https://apilens.ai/docs
- 🐛 Issues: https://github.com/apilens/apilens/issues
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 apilenss-0.1.7.tar.gz.
File metadata
- Download URL: apilenss-0.1.7.tar.gz
- Upload date:
- Size: 76.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4ebda541e20d0c31ee60b87bb3b6b8a7c14ca942f1bf9a2852edec177d3913f9
|
|
| MD5 |
dc0f97c6d286698b9cbca9de78a32ec5
|
|
| BLAKE2b-256 |
823cbe996e38a9f2781cd98eb52bce8ab90758c0c722744995b4eb673bef83f1
|
Provenance
The following attestation bundles were made for apilenss-0.1.7.tar.gz:
Publisher:
workflow.yml on apilens/apilens
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
apilenss-0.1.7.tar.gz -
Subject digest:
4ebda541e20d0c31ee60b87bb3b6b8a7c14ca942f1bf9a2852edec177d3913f9 - Sigstore transparency entry: 1708531798
- Sigstore integration time:
-
Permalink:
apilens/apilens@540163ebd21efa4a37abf54a517295d9d1c34df6 -
Branch / Tag:
refs/tags/apilens-sdk-v0.1.7 - Owner: https://github.com/apilens
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@540163ebd21efa4a37abf54a517295d9d1c34df6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file apilenss-0.1.7-py3-none-any.whl.
File metadata
- Download URL: apilenss-0.1.7-py3-none-any.whl
- Upload date:
- Size: 19.5 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 |
7b8e2091f9db48873f5a72444e5958dcce530bdfdb918935d7814a8354688a3c
|
|
| MD5 |
fc859290bc537b7ae1b2dc21df577778
|
|
| BLAKE2b-256 |
e0b27f41601b93729eb13b619989fd099b08d2694ef2af2afc4115153e83e453
|
Provenance
The following attestation bundles were made for apilenss-0.1.7-py3-none-any.whl:
Publisher:
workflow.yml on apilens/apilens
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
apilenss-0.1.7-py3-none-any.whl -
Subject digest:
7b8e2091f9db48873f5a72444e5958dcce530bdfdb918935d7814a8354688a3c - Sigstore transparency entry: 1708531810
- Sigstore integration time:
-
Permalink:
apilens/apilens@540163ebd21efa4a37abf54a517295d9d1c34df6 -
Branch / Tag:
refs/tags/apilens-sdk-v0.1.7 - Owner: https://github.com/apilens
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@540163ebd21efa4a37abf54a517295d9d1c34df6 -
Trigger Event:
push
-
Statement type: