Send feedback from the dashboard.
const url = 'https://api.opdns.io/v1/feedback';const options = { method: 'POST', headers: { cookie: 'opdns_session=<opdns_session>', 'Content-Type': 'application/json' }, body: '{"category":"bug","message":"example","page":"example","dashboard_version":"example","reply_ok":true}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.opdns.io/v1/feedback \ --header 'Content-Type: application/json' \ --cookie opdns_session=<opdns_session> \ --data '{ "category": "bug", "message": "example", "page": "example", "dashboard_version": "example", "reply_ok": true }'A session, or an API token with account:read. The dashboard’s
Help form posts here: a category and free text, the dashboard route it was
sent from (ids replaced, /p/:id/logs) and the dashboard version. It is
stored in our database only (no third party) and read by the operator
(GET /v1/admin/feedback), who answers by email to the account’s address
when reply_ok is true (the default). Limited to 5 messages at once and one
every 2 minutes after that per account, and to 20 a day
(429 rate_limited). Messages are deleted with the account.
Authorizations
Section titled “Authorizations”Request Bodyrequired
Section titled “Request Bodyrequired”object
Free text, at most 4000 characters after trimming.
The dashboard route it was sent from, ids replaced (/p/:id/logs); starts with /.
The operator may answer by email.
Responses
Section titled “Responses”Stored.
object
Example
{ "id": 42, "created_at": "2026-09-30T14:02:11Z"}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"}Body over 16 KiB (body_too_large).
object
Stable machine code.
object
Seconds, repeating the Retry-After header (rate limits, offline nodes).
Example
{ "type": "https://opdns.io/problems/body_too_large", "title": "Content Too Large", "status": 413, "code": "body_too_large", "detail": "request body too large", "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}