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.
Two ways in
Section titled “Two ways in”| 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.
Create a token
Section titled “Create a token”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):
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.
Scopes
Section titled “Scopes”| 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.
Use a token
Section titled “Use a token”curl -H "Authorization: Bearer $OPDNS_TOKEN" https://api.opdns.io/v1/profilesRevoke a token from the same dashboard page, or DELETE /v1/tokens/{id}
with a session. The dashboard shows when each token was last used.
Response headers
Section titled “Response headers”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).
Node tokens
Section titled “Node tokens”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.