Saved Filters

Save any filter combination set on the /requests page — provider, model, status, date range, and more — under a name, then restore the entire state in one click on future visits. Useful for recurring debug queries or shared team views.

How to use

  1. Go to /requests and configure your filters — provider, model, status, date range, etc.
  2. Click Save as filter on the right side of the filter bar.
  3. Enter a name (1–80 characters) and click Save.
  4. On future visits, select the saved name from the Saved filters dropdown in the filter bar to restore all filters at once.

Scope and isolation

Saved filters are per-user. Filters created by other members in the same organization are not visible, and only your own filters appear in the dropdown. This isolation is enforced at the database level via Row Level Security (RLS).

API

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

List

GET /api/v1/saved-filters

# Response: array sorted newest first
# [
#   {
#     "id": "sf_xxxxxxxx",
#     "name": "GPT-4o errors only",
#     "filters": { "provider": "openai", "model": "gpt-4o", "status": "5xx" },
#     "created_at": "2026-05-15T09:00:00.000Z"
#   },
#   ...
# ]
bash

Save

POST /api/v1/saved-filters
Content-Type: application/json

{
  "name": "GPT-4o errors only",
  "filters": {
    "provider": "openai",
    "model": "gpt-4o",
    "status": "5xx"
  }
}

# 201 Created
# {
#   "id": "sf_xxxxxxxx",
#   "name": "GPT-4o errors only",
#   "filters": { "provider": "openai", "model": "gpt-4o", "status": "5xx" },
#   "created_at": "2026-05-15T09:00:00.000Z"
# }
bash

Delete

DELETE /api/v1/saved-filters/:id

# 204 No Content
bash

Request / response schema

FieldTypeDescription
namestring1–80 characters. Must be unique per user — returns 409 on duplicate.
filtersobjectFree-form JSON object containing the filter values. Stored as JSONB without server-side parsing — the UI reads and writes it in its own format.
idstringServer-assigned identifier.
created_atstring (ISO 8601)Creation timestamp. The list is sorted by this value descending.

Error codes

HTTP statusCause
400name missing or too long, or filters is absent
401JWT token missing or expired
404Delete target ID does not exist or does not belong to the current user
409A filter with the same name already exists for this user

curl examples

# List saved filters
curl https://spanlens-server.vercel.app/api/v1/saved-filters \
  -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN"

# Save a filter
curl -X POST https://spanlens-server.vercel.app/api/v1/saved-filters \
  -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Anthropic 429 errors","filters":{"provider":"anthropic","status":"4xx"}}'

# Delete a filter
curl -X DELETE https://spanlens-server.vercel.app/api/v1/saved-filters/sf_xxxxxxxx \
  -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN"
bash

Limitations

  • No organization-wide sharing. Saved filters are private to the creating user. Shared team filters are on the roadmap.
  • No filter validation. The server stores the filters object as-is without validating keys or values. An invalid filter value will be saved without error but may be ignored when the /requests UI applies it.
  • 100 filters per user maximum. Delete old filters before creating new ones if you hit this limit.

Related: Requests (filter view), /requests dashboard.