HTTP API: logs and traces
Request logs and traces, recorded errors, and the observability summaries behind the console's charts.
Read the project's request logs and traces, and forward logs to your own tools. Guides: Logs and log drains, Request traces: why did this request fail?.
| Base URL | https://<project-ref>.sovarias.in — your project URL from Connect. |
| Keys | Send the project's key as apikey. Calls made for a signed-in user also send Authorization: Bearer <access token>. |
| Errors | A status code and {"detail": …} — a sentence, or {code, message} for errors your code may branch on (HTTP API). |
Logs and request traces
GET/api/v1/observability/logs
The project's recent requests, newest first, one page at a time.
For a live tail, poll with after = the newest time you have; to load older ones pass before = the oldest. How far back depends on the plan (Logs and log drains).
- Who
- The project team (not app users or the anon key).
Query parameters
limitintegeroptionaldefault50- Rows per page (1–200).
- 1–200
servicestring | nulloptional- One service (
rest,auth,storage,functions…). - 0–32 characters
statusstring | nulloptional2xx,3xx,4xx,5xxorerrors.- pattern `^(2xx|3xx|4xx|5xx|errors)
HTTP API: logs and traces | Sovaria Docs qstring | nulloptional- Text in the path or method.
- 0–200 characters
afternumber | nulloptional- Only newer than this Unix time (live tail).
beforenumber | nulloptional- Only older than this Unix time.
sourcestringoptionaldefaultappapp(your app's traffic, default),console(the team's activity) orall.- pattern `^(app|console|all)
HTTP API: logs and traces | Sovaria Docs Returns
logs[].timenumber- Unix seconds.
has_moreboolean- Older rows exist: page with
before. retention_minutesinteger- How far back the plan keeps logs.
Responses
- 200Success.
- 401No valid session or key.
curl -s "$URL/api/v1/observability/logs?status=errors&limit=50" \ -H "apikey: $ANON_KEY" \ -H "Authorization: Bearer $ACCESS_TOKEN"Response
{ "project_id": "f0c3e9a2-1b4d-4e7f-8a6c-2d9b5e3f1a07", "logs": [ { "time": 1792396800.412, "method": "GET", "path": "/rest/v1/orders", "status": 403, "duration_ms": 12.4, "service": "rest", "source": "app" } ], "has_more": true, "retention_minutes": 1440 }GET
/api/v1/request-tracesRecent refused (4xx) and failed (5xx) requests, each with why.
The trace id is the W3C
traceparentid the SDKs send, also returned asX-Request-IDon every response. Kept for the plan'sobs.trace_days(Request traces: why did this request fail?).- Who
- The project team (not app users or the anon key).
Query parameters
kindstringoptionaldefaultalldenied,failedorall.- One of
denied,failed,all beforestring | nulloptional- Older than this time (paging).
- 0–40 characters
limitintegeroptionaldefault50- How many (1–100).
- 1–100
Returns
explanation.verdictstringdenied,failedorallowed.explanation.by, step, reason, hintstring- What decided, in which step, why, and what to do.
Responses
- 200Success.
- 401No valid session or key.
curl -s "$URL/api/v1/request-traces?kind=denied" \ -H "apikey: $ANON_KEY" \ -H "Authorization: Bearer $ACCESS_TOKEN"Response
{ "traces": [ { "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736", "occurred_at": "2026-10-18T10:40:00.412+00:00", "method": "GET", "path": "/rest/v1/orders", "final_status": 403, "duration_ms": 12, "actor_id": null, "env_id": "", "explanation": { "verdict": "denied", "by": "policy", "service": "gateway", "step": "policy", "status": 403, "reason": "No access policy allows sql:select on orders for visitors who aren't signed in.", "detail": "NO_POLICY_DEFINED", "hint": "Add a policy for orders, or sign the user in first." } } ], "days": 7 }GET
/api/v1/request-traces/{trace_id}One request, hop by hop (gateway checks, engine, SQL), with the explanation.
- Who
- The project team (not app users or the anon key).
Path parameters
trace_idstringrequired- 32 hex characters (dashes ignored).
Responses
- 200Success.
- 404No such trace in this project, or older than the plan keeps.
- 403App users and the anon key can't read traces.
- 401No valid session or key.
curl -s "$URL/api/v1/request-traces/4bf92f3577b34da6a3ce929d0e0e4736" \ -H "apikey: $ANON_KEY" \ -H "Authorization: Bearer $ACCESS_TOKEN"Response
{ "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736", "occurred_at": "2026-10-18T10:40:00.412+00:00", "method": "GET", "path": "/rest/v1/orders", "final_status": 403, "duration_ms": 12, "actor_id": null, "env_id": "", "explanation": { "verdict": "denied", "by": "policy", "service": "gateway", "step": "policy", "status": 403, "reason": "No access policy allows sql:select on orders for visitors who aren't signed in.", "detail": "NO_POLICY_DEFINED", "hint": "Add a policy for orders, or sign the user in first." }, "hops": [ { "seq": 1, "service": "gateway", "hop_kind": "gateway_denied", "status_code": 403, "error_class": "PolicyDenied", "error_detail": "NO_POLICY_DEFINED", "duration_ms": 6, "at": "2026-10-18T10:40:00.420+00:00" } ] }Log drains
GET
/api/v1/observability/drainsLog drains: where the project's request logs are forwarded.
- Who
- The project team (not app users or the anon key).
Returns
drains[].activeboolean- Running (the oldest enabled drains up to the plan's
obs.log_drainsrun; the rest wait). sent, failed, last_delivery_at, last_errormixed- Delivery stats.
Responses
- 200Success.
- 401No valid session or key.
curl -s "$URL/api/v1/observability/drains" \ -H "apikey: $ANON_KEY" \ -H "Authorization: Bearer $ACCESS_TOKEN"Response
{ "drains": [ { "id": "drn_3f9a1c0b7e2d4a6f", "name": "Datadog prod", "kind": "datadog", "config": { "site": "datadoghq.eu" }, "has_secret": true, "enabled": true, "disabled_reason": null, "active": true, "created_at": 1792310000.0, "sent": 18234, "failed": 2, "last_delivery_at": 1792396800.4, "last_error": null } ], "limit": 1, "used": 1 }POST
/api/v1/observability/drainsForward request logs to Datadog, Grafana Loki or any HTTPS endpoint.
HTTPS drains receive batches of JSON signed with
X-Sovaria-Signature; the signing secret is in this answer only. The plan limits how many drains run (obs.log_drains) (Logs and log drains).- Who
- A project owner or admin, or the service-role key.
Body
kindstringrequired- One of
http,datadog,loki namestringoptionalconfigobjectoptionalhttp:url,header_name;datadog:site(datadoghq.com,us3.datadoghq.com,us5.datadoghq.com,datadoghq.eu,ap1.datadoghq.com,ddog-gov.com);loki:url,username.secretstringoptionalhttp: the auth header's value;datadog: the API key (required);loki: password or token. Stored encrypted.
Responses
- 201Created.
- 403Not an owner/admin.
- 422Unknown kind, invalid URL, no Datadog site or key, or a bad header name.
- 401No valid session or key.
curl -s -X POST "$URL/api/v1/observability/drains" \ -H "apikey: $ANON_KEY" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H 'Content-Type: application/json' \ -d '{"kind": "http", "name": "Our collector", "config": {"url": "https://logs.acme.com/ingest", "header_name": "X-Api-Key"}, "secret": "<collector key>"}'Response
{ "id": "drn_7c2e…", "name": "Our collector", "kind": "http", "config": { "url": "https://logs.acme.com/ingest", "header_name": "X-Api-Key" }, "has_secret": true, "enabled": true, "disabled_reason": null, "active": true, "created_at": 1792310000.0, "sent": 0, "failed": 0, "last_delivery_at": null, "last_error": null, "signing_secret": "whsec_…(shown once)" }PATCH
/api/v1/observability/drains/{drain_id}Rename, re-configure, change the secret, or pause a drain.
- Who
- A project owner or admin, or the service-role key.
Path parameters
drain_idstringrequired- The drain.
Body
namestring | nulloptional- Name.
- 0–80 characters
enabledboolean | nulloptional- On or off.
configobject | nulloptional- New settings.
secretstring | nulloptional- New secret.
- 0–4,000 characters
Responses
- 200Success.
- 404No such drain.
- 422Invalid settings.
- 401No valid session or key.
curl -s -X PATCH "$URL/api/v1/observability/drains/drn_3f9a1c0b7e2d4a6f" \ -H "apikey: $ANON_KEY" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H 'Content-Type: application/json' \ -d '{"enabled": false}'Response
{ "id": "drn_3f9a1c0b7e2d4a6f", "name": "Datadog prod", "kind": "datadog", "config": { "site": "datadoghq.eu" }, "has_secret": true, "enabled": false, "disabled_reason": null, "active": false, "created_at": 1792310000.0, "sent": 18234, "failed": 2, "last_delivery_at": 1792396800.4, "last_error": null }DELETE
/api/v1/observability/drains/{drain_id}Delete a drain.
- Who
- A project owner or admin, or the service-role key.
Path parameters
drain_idstringrequired- The drain.
Responses
- 200Success.
- 401No valid session or key.
curl -s -X DELETE "$URL/api/v1/observability/drains/drn_3f9a1c0b7e2d4a6f" \ -H "apikey: $ANON_KEY" \ -H "Authorization: Bearer $ACCESS_TOKEN"Response
{ "deleted": "drn_3f9a1c0b7e2d4a6f" }POST
/api/v1/observability/drains/{drain_id}/testSend a test batch to a drain now.
- Who
- A project owner or admin, or the service-role key.
Path parameters
drain_idstringrequired- The drain.
Responses
- 200Success.
- 401No valid session or key.
curl -s -X POST "$URL/api/v1/observability/drains/drn_3f9a1c0b7e2d4a6f/test" \ -H "apikey: $ANON_KEY" \ -H "Authorization: Bearer $ACCESS_TOKEN"Response
{ "ok": true, "error": null }