Data Export

Download request logs, traces, anomaly snapshots, and security flags as CSV, JSONL, or JSON in one shot. CSV and JSONL stream directly from ClickHouse, 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 – 1,000,000. JSON: 1 – 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. Each ClickHouse batch (~64 KB) is the only data held in memory at any point, 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

# Request logs, specific date range, GPT-4o only, CSV
curl "https://server.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://server.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://server.spanlens.io/api/v1/exports/anomalies" \
  -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \
  -o spanlens-anomalies.csv

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

JSONL download (large exports)

# One million rows, streamed. Pipe straight into jq for filtering.
curl "https://server.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",...}
bash

JSON download (small, wrapped)

curl "https://server.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"
#     },
#     ...
#   ]
# }
bash

BI tool tips

Pandas (Python)

import pandas as pd

token = "YOUR_SUPABASE_ACCESS_TOKEN"

# Small / medium, CSV, single response.
url = "https://server.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://server.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)
python

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.