Live log tail as server-sent events.
const url = 'https://api.opdns.io/v1/profiles/example/logs/stream?limit=100';const options = {method: 'GET', headers: {cookie: 'opdns_session=<opdns_session>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://api.opdns.io/v1/profiles/example/logs/stream?limit=100' \ --cookie opdns_session=<opdns_session>Token scope: logs:read. A text/event-stream of the profile’s new log rows,
with the filters of the tail query. The server polls the log destination
every second with the tail cursor: ClickHouse for cloud and both, the
node over the link for self-hosted; none sends only heartbeats. Errors
known before the stream starts (501 not_implemented, 503 node_offline,
400 invalid cursor, 429 too_many_streams when the account already holds
the maximum number of open streams) are problem responses.
Events:
event: rows,id: <cursor>,data:aQueryResultJSON (shapetail) holding the new rows. The first event carries the latest rows (up tolimit) unless the stream resumes. Sent only when there are rows.event: partial,data: {"partial": true, "partial_reason": "node_reconnecting"}: a poll answered partially with no rows (aself-hostedprofile’s node is between link sessions). Sent once until a complete poll;rowsevents carry the result’s ownpartialflag.event: error,data: {"status", "code", "detail"}: a failure while streaming. Transient ones (node_offline,node_timeout, 5xx) are followed by further polls; after any other the stream ends.- A comment line
: heartbeatevery 15 s. Each heartbeat re-checks the session or token and the profile: a revoked credential or a deleted profile ends the stream (after anerrorevent).
The event id is the tail cursor after that event’s rows. Reconnecting with
Last-Event-ID (EventSource does so by itself) or ?cursor= resumes after
it, without gaps or repeats. The server ends a stream after an hour; clients
reconnect.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Public 6-character id; never 000000.
Query Parameters
Section titled “Query Parameters”Device id; repeat for several.
Repeat for several.
Substring match for search, exact name otherwise.
Numeric DNS type; repeat for several.
Blocking list id; repeat for several.
Opaque, from a previous result’s next_cursor.
Header Parameters
Section titled “Header Parameters”The id of the last rows event received; resumes after it.
Responses
Section titled “Responses”The event stream.
Server-sent events, e.g.
retry: 2000
id: dDE3Mjc2MDQ4MDAwMDAwMDA6MTcyNzYwNDc5OTk5OTAwMDAwMDo0Mg
event: rows
data: {"shape":"tail","source":"clickhouse","columns":[...],"rows":[[...]],"next_cursor":"dDE3..."}
: heartbeat
Examples
id: dDE3Mjc2MDQ4MDAwMDAwMDA6MTcyNzYwNDc5OTk5OTAwMDAwMDo0Mgevent: rowsdata: {"shape":"tail","source":"clickhouse","columns":[{"name":"ts","type":"time"}],"rows":[["2026-09-29T10:00:00Z"]],"next_cursor":"dDE3Mjc2MDQ4MDAwMDAwMDA6MTcyNzYwNDc5OTk5OTAwMDAwMDo0Mg"}Malformed request.
object
Stable machine code.
object
Seconds, repeating the Retry-After header (rate limits, offline nodes).
Example
{ "type": "https://opdns.io/problems/bad_request", "title": "Bad Request", "status": 400, "code": "bad_request", "detail": "invalid JSON body", "request_id": "5f2c9a0e7b1d4c38"}Not authenticated.
object
Stable machine code.
object
Seconds, repeating the Retry-After header (rate limits, offline nodes).
Example
{ "type": "https://opdns.io/problems/unauthenticated", "title": "Unauthorized", "status": 401, "code": "unauthenticated", "detail": "authentication required", "request_id": "5f2c9a0e7b1d4c38"}Authenticated but not allowed: insufficient_scope, session_required, csrf_rejected, mfa_enrolment_required (restricted session), mfa_required (an operator action, or an admin-scoped token, from a session signed in with the password alone; not in dev), reauth_required (sign in again within five minutes), account_pending_deletion (the account is in its deletion cooling-off).
object
Stable machine code.
object
Seconds, repeating the Retry-After header (rate limits, offline nodes).
Example
{ "type": "https://opdns.io/problems/insufficient_scope", "title": "Forbidden", "status": 403, "code": "insufficient_scope", "detail": "the token lacks the profiles:write scope", "request_id": "5f2c9a0e7b1d4c38"}Not found (also for resources of another organisation).
object
Stable machine code.
object
Seconds, repeating the Retry-After header (rate limits, offline nodes).
Example
{ "type": "https://opdns.io/problems/not_found", "title": "Not Found", "status": 404, "code": "not_found", "detail": "resource not found", "request_id": "5f2c9a0e7b1d4c38"}Field validation failed (validation_failed, unknown_list).
object
Stable machine code.
object
Seconds, repeating the Retry-After header (rate limits, offline nodes).
Example
{ "type": "https://opdns.io/problems/validation_failed", "title": "Unprocessable Content", "status": 422, "code": "validation_failed", "detail": "the request has invalid fields", "errors": [ { "field": "settings.block_mode", "message": "one of nxdomain, refused, null, block-page" } ], "request_id": "5f2c9a0e7b1d4c38"}Rate limited (rate_limited).
object
Stable machine code.
object
Seconds, repeating the Retry-After header (rate limits, offline nodes).
Example
{ "type": "https://opdns.io/problems/rate_limited", "title": "Too Many Requests", "status": 429, "code": "rate_limited", "detail": "too many requests", "request_id": "5f2c9a0e7b1d4c38", "retry_after": 6}Headers
Section titled “Headers”not_implemented (cloud log queries not configured on this server) or shape_unsupported (node too old).
object
Stable machine code.
object
Seconds, repeating the Retry-After header (rate limits, offline nodes).
Example
{ "type": "https://opdns.io/problems/not_implemented", "title": "Not Implemented", "status": 501, "code": "not_implemented", "detail": "cloud log queries are not configured on this server", "request_id": "5f2c9a0e7b1d4c38"}node_offline: the profile’s logs live on a self-hosted node and no node is
connected; node_busy: the node has too many queries in flight;
relay_unavailable. Retry after Retry-After (also retry_after in the body).
object
Stable machine code.
object
Seconds, repeating the Retry-After header (rate limits, offline nodes).
Example
{ "type": "https://opdns.io/problems/node_offline", "title": "Service Unavailable", "status": 503, "code": "node_offline", "detail": "no node of this profile is connected", "request_id": "5f2c9a0e7b1d4c38", "retry_after": 30}