Skip to content

Authentication, tokens and scopes

The dashboard is the API’s first client and uses no private endpoints: what it does, you can do. The base URL is https://api.opdns.io, and the specification is served at /v1/openapi.yaml.

Method How Scopes
Session the opdns_session cookie, set by signing in (POST /v1/auth/login and the passkey ceremonies) all
API token Authorization: Bearer opdns_… the ones chosen at creation

Browsers use sessions. Scripts and integrations use tokens. A cookie-authenticated write from an origin other than the dashboard is rejected (csrf_rejected).

A session lasts at most 30 days from sign-in and ends after 7 days unused. The first request more than 24 hours after its token was issued gets a new token in Set-Cookie; the previous one keeps working for a few seconds, so requests already in flight do not fail. Password sign-in is slowed after failures (100 ms, doubling up to 5 s per address and per account); passkey sign-in is not.

In the dashboard: Account → Tokens → Create token. Name it, choose scopes, and optionally an expiry. The secret is shown once; store it like a password. Only a signed-in session can create or revoke tokens; a token cannot mint another token.

With the API (session only):

Terminal window
curl -X POST https://api.opdns.io/v1/tokens \
-H 'Content-Type: application/json' \
--cookie "opdns_session=…" \
-d '{"name":"home-assistant","scopes":["profiles:read","analytics:read"]}'

The response holds secret (opdns_ followed by 52 characters) once.

Scope Allows
profiles:read read profiles, rules, lists, linked IPs and nodes
profiles:write change them; create and revoke nodes; link addresses; read and rotate DDNS URLs (they let the holder move a linked address)
account:read list the account’s tokens; read the organisation’s audit log (/v1/auth/audit)
logs:read query logs (/v1/profiles/{id}/logs) and the live stream (/v1/profiles/{id}/logs/stream)
analytics:read analytics aggregates (/v1/profiles/{id}/analytics/{shape})

Operators also have the admin scope, for the /v1/admin/... routes. It is never granted through the API (Admin tools), and outside development it needs a stronger sign-in: a session that signed in with a password alone gets 403 mfa_required on every admin route, and cannot create a token with the admin scope. Sign in with a passkey, or with a password and an authenticator code, first.

Each operation in the reference states its scope. A token without it gets 403 insufficient_scope. Tokens see only the profiles of their own organisation; others are 404, not 403.

Terminal window
curl -H "Authorization: Bearer $OPDNS_TOKEN" https://api.opdns.io/v1/profiles

Revoke a token from the same dashboard page, or DELETE /v1/tokens/{id} with a session. The dashboard shows when each token was last used.

Every response carries X-Request-Id, the X-Opdns-Api-Version header, and security headers meant for browsers: Content-Security-Policy (default-src 'none'; frame-ancestors 'none' and more), X-Frame-Options: DENY, Referrer-Policy: no-referrer, X-Content-Type-Options: nosniff, and Strict-Transport-Security wherever the session cookie is marked Secure (every deployment but development).

Self-hosted nodes use a separate credential, the node token (opdnsnode_…), obtained by exchanging a one-time enrolment code at POST /v1/nodes/enrol. It is accepted only by the node endpoints and the link. See Enrol a node.