Documentation menu

Ingest

Send events to ScryWatch over HTTP.

POST /api/ingest

Ingest a batch of events (up to 50 per request). Each event is canonicalized (message template, event ID, fingerprint) and enqueued to Cloudflare Queues; the response returns immediately and is decoupled from storage.

Auth: API key (Bearer) · Content-Type: application/json

Request body

fieldtyperequireddescription
eventsarrayyes1–50 event objects
events[].timestampnumberyesEpoch ms
events[].levelstringyeserror | warn | info | debug
events[].typestringyescrash | session | navigation | api_call | custom | cron | log
events[].messagestringyesEvent message
events[].user_idstringnoUser identifier
events[].session_idstringnoSession identifier
events[].environmentstringnoe.g. production
events[].servicestringnoService name
events[].device_typestringnoDevice type
events[].metadataobjectnoArbitrary JSON
events[].trace_idstringnoTrace correlation ID
events[].span_idstringnoSpan correlation ID

The log type is normally produced by the Supabase log drain (below), but is also accepted directly on this endpoint like any other type.

Response 202

{ "status": 202, "inserted": 3 }

inserted is the number of events accepted for processing.

Errors: 400 validation errors, shape { "status": 400, "error": "<message>" }:

  • "events array is required and must not be empty"
  • "batch size must not exceed 50 events"
  • "invalid level: <x>"
  • "invalid type: <x>"
  • "message is required"
  • "timestamp is required"

Common auth/limit responses (401, 402, 429) apply — see Authentication.

POST /api/ingest/supabase

Accepts a Supabase Generic HTTP log drain payload: a JSON array of Logflare events, optionally gzip-compressed (send Content-Encoding: gzip and the worker decompresses before parsing). Auth via Authorization: Bearer <project API key> set as a custom header on the drain (same key type as /api/ingest). Each event is mapped to a log-type event, with its source auto-detected (postgres | auth | api | storage | realtime | edge_functions | unknown) from the Logflare metadata shape, then filtered per the project’s Supabase drain config before being handed to the same ingest pipeline as /api/ingest.

Auth: API key (Bearer, set as a custom header on the drain) · Content-Type: application/json

Response 200

{ "received": 120, "kept": 43, "dropped": 77, "inserted": 43 }

If the project’s drain config is disabled, the endpoint still returns 200 with all events dropped (kept: 0, inserted: 0, dropped equal to received).

Errors:

  • 400"failed to read body (bad gzip?)" / "invalid JSON body" / "expected a JSON array of Supabase log events"
  • 413 — body too large: { "error": "body too large", "max_bytes": 8388608 } (decompressed body exceeds 8 MB)
  • 413 — batch too large: { "error": "batch too large", "max": 500 } (more than 500 events)

Common auth/limit responses (401, 402, 429) apply — see Authentication.