Documentation menu

Authentication

Authenticate ScryWatch API requests with a per-project API key.

Base URL

https://api.scrywatch.com

API keys

Create an API key from the dashboard: Settings → API Keys. Keys are scoped to a single project — every request made with a key is automatically limited to that project’s data, so there’s no need to put an org or project identifier in the URL.

Send the key as a Bearer token on every request:

Authorization: Bearer <your-api-key>

Two different auth middlewares are used across the API, and they behave slightly differently on failure:

  • Ingest-style endpoints (POST /api/ingest, POST /api/ingest/supabase, POST /api/traces, POST /api/traces/otlp, POST /api/deploys) require a valid Bearer API key and nothing else (requireApiKey). See the exact 401 shapes below.
  • Query endpoints (/api/logs, /api/stats, /api/facets, /api/sessions, /api/services, /api/environments, /api/device-types, and their /api/orgs/:orgSlug/projects/:projectSlug/... equivalents) accept either a Bearer API key or a dashboard session cookie (requireSession). These are documented on the Logs & Search and Sessions pages.

POST /mcp uses its own OAuth bearer token middleware, not requireApiKey — see the MCP reference for its authentication model and error shapes.

Common responses

Most authenticated endpoints share one of the responses below, from shared middleware. Endpoint pages link back here instead of repeating them.

401 Unauthorized

On endpoints protected by requireApiKey (ingest-style, listed above):

{ "error": "Missing API key" }

No Authorization: Bearer <key> header was sent.

{ "error": "Invalid API key" }

The key doesn’t match any active API key.

On endpoints protected by requireSession (query endpoints) — an invalid or missing Bearer key falls through to checking for a session cookie, so the failure response is generic rather than key-specific:

{ "error": "Unauthorized" }

402 Payment Required

Ingest endpoints only (POST /api/ingest, POST /api/ingest/supabase), when the org’s monthly log limit has been reached and enforcement is active (free plan, or a paid plan with the hard cap enabled):

{ "error": "usage_limit_exceeded", "message": "Monthly log limit reached. Upgrade your plan or enable overage billing." }

Query endpoints never return 402, with one exception: POST /api/orgs/:orgSlug/projects/:projectSlug/insights/summary returns 402 when the org has hit its monthly AI-summary quota:

{ "error": "usage_limit_exceeded", "message": "Monthly AI summary limit reached. Upgrade your plan." }

See Insights for details. Outside of that endpoint, usage limits are only enforced on the ingest path.

429 Too Many Requests

Ingest endpoints only (POST /api/ingest, POST /api/ingest/supabase), enforced per source IP at the edge:

{ "error": "Rate limit exceeded. Please slow down." }

Query endpoints are not rate-limited by this middleware.