Skip to content

The Logs endpoints let you search, aggregate, and live-tail the centralized request, response, and event logs captured by the proxy. Use these when you need to investigate traffic, build dashboards, or stream new entries into an external system.

Search and filter the stored request/response and event logs. Supports pagination, level filtering, cross-tenant fanout (admin only), and row-cursor streaming.

GET /api/proxy-logs/_logs

NameInTypeRequiredDescription
limitqueryintegerNoMax entries to return (default: 200)
offsetqueryintegerNoEntries to skip (default: 0)
projectIdquerystringNoRestrict to a single project
containerIdquerystringNoRestrict to a single container
serviceNamequerystringNoRestrict to a single service name
levelquerystringNoComma-separated levels (debug,info,warn,error)
includeRequestBodyquerybooleanNoInclude captured request bodies (default: false)
includeResponseBodyquerybooleanNoInclude captured response bodies (default: false)
lastqueryintegerNoReturn only the last N entries
afterIdqueryintegerNoReturn entries with SQLite row ID greater than this (ASC cursor)
cursorquerystringNov8 §5.2 — cross-tenant fanout pagination cursor (signed opaque base64). Only honored when LOGS_ADMIN_FANOUT=true
kindquerystringNoOne of: request, response, event
methodquerystringNoHTTP method filter (e.g. GET, POST)
sourcequerystringNoOne of: backend, edge
{
"entries": [
{
"id": 84321,
"traceId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"tsMs": 1718201234000,
"tsIso": "2024-06-12T14:33:54.000Z",
"kind": "request",
"level": "info",
"projectId": "proj_a1b2c3d4",
"containerId": "cnt_x9y8z7w6",
"serviceName": "user-api",
"method": "POST",
"url": "/v1/users",
"clientIp": "203.0.113.42",
"status": 201,
"data": {"bytesIn": 412, "userAgent": "Hoody-CLI/1.4.2"},
"source": "backend"
},
{
"id": 84322,
"traceId": "f47ac10b-58cc-4372-a567-0e02b2c3d480",
"tsMs": 1718201234102,
"tsIso": "2024-06-12T14:33:54.102Z",
"kind": "response",
"level": "info",
"projectId": "proj_a1b2c3d4",
"containerId": "cnt_x9y8z7w6",
"serviceName": "user-api",
"method": "POST",
"url": "/v1/users",
"clientIp": "203.0.113.42",
"status": 201,
"data": {"bytesOut": 318, "durationMs": 102},
"source": "backend"
}
],
"total": 1284,
"limit": 200,
"offset": 0
}
const page = await client.proxyLogs.logs.listIterator({
projectId: "proj_a1b2c3d4",
level: "warn,error",
limit: 100,
});
for await (const entry of page) {
console.log(entry.traceId, entry.level, entry.url);
}

Returns aggregate counts across level, project, container, and service dimensions. Useful for building dashboards or sizing retention.

GET /api/proxy-logs/_logs/stats

This endpoint takes no parameters.

{
"total": 8421,
"byLevel": {"info": 6200, "warn": 1500, "error": 521, "debug": 200},
"byProject": {"proj_a1b2c3d4": 5000, "proj_e5f6g7h8": 3421},
"byContainer": {"cnt_x9y8z7w6": 3000, "cnt_m5n6o7p8": 5421},
"byService": {"user-api": 4200, "billing-api": 2100, "webhook-svc": 2121}
}
const stats = await client.proxyLogs.logs.getStats();
console.log("Total entries:", stats.total);
console.log("Errors:", stats.byLevel.error);

Opens a persistent Server-Sent Events connection streaming new log entries as they are written. Each frame carries an id: <ringSeq> line for resumable reconnect.

GET /api/proxy-logs/_logs/stream

v8 §6.4 framing — every frame carries an id: <ringSeq> line:

id: 12345
data: {"id":84321,"kind":"request","level":"info",...}

Reconnect resume — clients MAY send Last-Event-ID: <ringSeq> on reconnect; the server skips any frame with ringSeq <= Last-Event-ID from the ring buffer (5000 entries / ~50 s replay window at 100 entries/s).

Named events (v8):

  • event: scope-destroyed — container destroyed; stream closes immediately after. Clients should exit cleanly.
  • event: reset — server restart; ringSeq counter reset with a ≥10 000 safety margin. Clients MUST discard their lastSeenId and reconnect fresh.

Periodic :\n\n heartbeats every 15s keep the connection alive.

NameInTypeRequiredDescription
projectIdquerystringNoFilter to a single project (admin-port only; SNI clients are auto-scoped)
containerIdquerystringNoFilter to a single container
kindquerystringNoOne of: request, response, event
levelquerystringNoOne of: debug, info, warn, error
Last-Event-IDheaderstringNov8 §6.4 — numeric ringSeq of the last event received. Server skips entries ≤ this value from the ring buffer on reconnect.
HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
id: 12345
data: {"id":84321,"traceId":"f47ac10b-58cc-4372-a567-0e02b2c3d479","tsMs":1718201234000,"kind":"request","level":"info","method":"POST","url":"/v1/users","status":201,"source":"backend"}
id: 12346
data: {"id":84322,"traceId":"f47ac10b-58cc-4372-a567-0e02b2c3d480","tsMs":1718201234102,"kind":"response","level":"info","method":"POST","url":"/v1/users","status":201,"source":"backend"}
:
const stream = await client.proxyLogs.logs.streamLogs({
projectId: "proj_a1b2c3d4",
level: "error",
});
for await (const frame of stream) {
if (frame.event === "scope-destroyed") break;
if (frame.event === "reset") {
// discard lastSeenId and reconnect fresh
continue;
}
console.log(frame.id, frame.data);
}