Data Export

Download request logs, traces, anomaly snapshots, and security flags as CSV, JSONL, or JSON in one shot. CSV and JSONL stream out of a server-side database cursor, so a million-row export runs in ~30 MB of memory and finishes inside the function-execution window. Connect to Pandas, BigQuery, Redash, Metabase, or your own pipeline.

Endpoints

EndpointData
GET /api/v1/exports/requestsRequest logs, provider, model, tokens, cost, latency, etc.
GET /api/v1/exports/tracesTraces, span count, total cost, duration, etc.
GET /api/v1/exports/anomaliesAnomaly snapshots, daily history of buckets that exceeded 3σ
GET /api/v1/exports/securitySecurity flags, PII detections and prompt injection hits

All endpoints require JWT authentication (authJwt middleware). Include Authorization: Bearer <supabase_access_token> in the request header.

Common query parameters

ParameterDefaultDescription
formatcsvcsv · jsonl · json. CSV and JSONL stream; JSON materialises a wrapper object. See Formats below.
from,ISO 8601 start time (e.g. 2026-05-01T00:00:00Z). Defaults to 30 days ago if omitted.
to,ISO 8601 end time. Defaults to now if omitted.
limitformat-dependentCSV / JSONL: 1 to 1,000,000. JSON: 1 to 10,000./exports/requests only, other endpoints stay at 10,000.

Formats, when to pick each

FormatStreamed?Row capBest for
csvYes1,000,000BI tools, spreadsheets, ad-hoc analysis. Default.
jsonlYes1,000,000Pipelines that preserve typing (jq, pandas.read_json(lines=True), BigQuery, ClickHouse). One JSON object per line, newline-delimited.
jsonNo, buffered10,000Wrapper object { exported_at, count, data: [...] } for code that wants a single parseable response. Use jsonl for anything larger.

Streamed responses set Cache-Control: no-storeso intermediaries don't buffer the full body. One cursor batch (500 rows) is the only data held in memory at any point, so heap usage stays flat regardless of limit.

Additional parameters for requests

Extra filters available only on GET /api/v1/exports/requests.

ParameterDescription
projectIdExport only requests belonging to a specific project.
providerOne of openai / anthropic / gemini / azure.
modelPartial match, case-insensitive (e.g. mini).
providerKeyIdOnly requests that used a specific provider key.
statusok (2xx) / 4xx / 5xx.

File names

The response includes a Content-Disposition header with a date-stamped filename.

EndpointExample filename
/exports/requestsspanlens-requests-2026-05-15.csv
/exports/tracesspanlens-traces-2026-05-15.csv
/exports/anomaliesspanlens-anomalies-2026-05-15.csv
/exports/securityspanlens-security-2026-05-15.csv

CSV columns, requests

ColumnDescription
idUnique request ID
project_idProject this request belongs to
provideropenai / anthropic / gemini / azure
modelDated variant returned by the provider (e.g. gpt-4o-mini-2024-07-18)
prompt_tokensInput token count (gross, including cached portion)
completion_tokensOutput token count
total_tokensprompt + completion
cost_usdCalculated cost in USD. Empty if the model is not in the price table.
latency_msTime from proxy receiving the request to last byte sent (ms)
status_codeHTTP status code returned by the provider
error_messageError string. Empty for successful requests.
trace_idLinked trace ID. Empty if the call was not made inside an SDK observe().
created_atWhen the request arrived at the proxy (ISO 8601 UTC)

CSV columns, traces

ColumnDescription
idUnique trace ID
project_idProject this trace belongs to
nameTrace name (specified in the SDK)
statusok / error
error_messageError string. Empty for successful traces.
duration_msFirst span start to last span end (ms)
total_cost_usdSum of costs across all requests in the trace (USD)
total_tokensSum of tokens across all requests in the trace
span_countNumber of spans in the trace
started_atTrace start time (ISO 8601 UTC)
ended_atTrace end time (ISO 8601 UTC)
created_atWhen the row was saved to the database (ISO 8601 UTC)

curl examples

CSV download

bash
# Request logs, specific date range, GPT-4o only, CSV
curl "https://api.spanlens.io/api/v1/exports/requests?from=2026-05-01T00:00:00Z&to=2026-05-15T23:59:59Z&provider=openai&model=gpt-4o&format=csv" \
  -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \
  -o spanlens-requests.csv

# Traces, last 7 days, JSON
curl "https://api.spanlens.io/api/v1/exports/traces?from=2026-05-08T00:00:00Z&format=json" \
  -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \
  -o spanlens-traces.json

# Anomaly history, defaults (30 days, CSV)
curl "https://api.spanlens.io/api/v1/exports/anomalies" \
  -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \
  -o spanlens-anomalies.csv

# Security flags, from a specific date
curl "https://api.spanlens.io/api/v1/exports/security?from=2026-05-01T00:00:00Z" \
  -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \
  -o spanlens-security.csv

JSONL download (large exports)

bash
# One million rows, streamed. Pipe straight into jq for filtering.
curl "https://api.spanlens.io/api/v1/exports/requests?format=jsonl&from=2026-01-01T00:00:00Z&limit=1000000" \
  -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \
  | jq -c 'select(.cost_usd != null and (.cost_usd | tonumber) > 0.01)' \
  > expensive-requests.jsonl

# Each line is a self-contained JSON object:
# {"id":"req_xxx","provider":"openai","model":"gpt-4o-mini-2024-07-18",...}
# {"id":"req_yyy","provider":"anthropic","model":"claude-sonnet-4-5",...}

JSON download (small, wrapped)

bash
curl "https://api.spanlens.io/api/v1/exports/requests?format=json&limit=1000" \
  -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN"

# Response shape (buffered, capped at 10,000 rows):
# {
#   "exported_at": "2026-05-19T08:30:00.000Z",
#   "count": 1000,
#   "data": [
#     {
#       "id": "req_xxx",
#       "project_id": "proj_xxx",
#       "provider": "openai",
#       "model": "gpt-4o-mini-2024-07-18",
#       "prompt_tokens": 512,
#       "completion_tokens": 128,
#       "total_tokens": 640,
#       "cost_usd": 0.000096,
#       "latency_ms": 843,
#       "status_code": 200,
#       "error_message": null,
#       "trace_id": null,
#       "created_at": "2026-05-15T09:00:00.000Z"
#     },
#     ...
#   ]
# }

BI tool tips

Pandas (Python)

python
import pandas as pd

token = "YOUR_SUPABASE_ACCESS_TOKEN"

# Small / medium, CSV, single response.
url = "https://api.spanlens.io/api/v1/exports/requests?from=2026-05-01T00:00:00Z&format=csv"
df = pd.read_csv(url, storage_options={"Authorization": f"Bearer {token}"})

# Million-row pipeline, JSONL, streamed line-by-line. Pandas reads it in
# chunks so peak memory stays bounded.
url = "https://api.spanlens.io/api/v1/exports/requests?format=jsonl&limit=1000000"
chunks = pd.read_json(url, lines=True, chunksize=50_000,
                      storage_options={"Authorization": f"Bearer {token}"})
totals = pd.concat(chunk.groupby("model")["cost_usd"].sum() for chunk in chunks).groupby(level=0).sum()
print(totals)

Excel

Download the .csv file with curl, then import it into Excel via Data → From Text/CSV. The created_at column is an ISO 8601 string, convert it with DATEVALUE + TIMEVALUEor Power Query's date/time type conversion before using it in pivot tables.

Limitations

  • Row caps. /exports/requests goes up to 1,000,000 rows on the streamed formats (csv, jsonl) and 10,000 on json. The other endpoints (/traces, /security, /anomalies) stay at 10,000. For datasets above the cap, paginate by splitting the time range with from / to, or contact support, multi-GB exports with completion emails / S3 pre-signed URLs are on the roadmap.
  • request_body / response_body are not included. Body content is excluded for security and size reasons. View individual request bodies in the /requests detail view or via GET /api/v1/requests/:id.
  • Not real-time. Exports are a point-in-time snapshot. In-flight streaming requests or async logging delays may mean the most recent rows are not yet present.
  • Rate limit. Export endpoints are capped at 10 requests per minute. Space out calls in bulk batch pipelines.
  • Plan retention applies.The window of accessible rows is bounded by your plan's log retention (Free 14d / Pro 90d / Team 365d). Older rows are unavailable even via from.

Related: Requests, Traces, Anomalies, Security.