Skip to content

List the profile's devices.

GET
/v1/profiles/{id}/devices
curl --request GET \
--url 'https://api.opdns.io/v1/profiles/example/devices?limit=50' \
--cookie opdns_session=<opdns_session>

Token scope: profiles:read. Devices are learnt from query logs (DoH path segment, DoT/DoQ SNI prefix; resolver design section 3): ingest records the first and last time each device id was seen, its latest sanitised name and last transport, writing each device at most every 30 seconds, so last_seen lags by up to about a minute. Profiles that keep no logs (logs off, log destination none) have no devices. Newest (by first_seen) first.

queries_24h and blocked_24h count the last 24 hours from ClickHouse (top_devices) when the profile’s logs are in the cloud (cloud, both) and the server has ClickHouse; otherwise, or when the count query fails, they are null.

id
required

Public 6-character id; never 000000.

string
/^[a-z0-9]{6}$/
limit
integer
default: 50 >= 1 <= 200

Page size.

cursor
string
<= 1024 characters

The next_cursor of the previous page (opaque).

Devices.

Media typeapplication/json
object
next_cursor
required

Cursor of the next page (pass it as cursor); null on the last page.

string | null
devices
required
Array<object>
object
id
required

Stable per (profile, sanitised name); the device filter of logs and analytics.

string
name
required

Latest sanitised name the client sent (may be empty).

string
display_name
required

User override, null when unset.

string | null
label
required

display_name when set, else name, else id.

string
kind
required
One of:
string
Allowed values: phone laptop tv router other
notes
required
string
identification
required

How the device names itself, from the last transport (DoH/DoH3 path, DoT/DoQ SNI).

string
Allowed values: doh_path sni unknown
transport_last
required

Transport of the latest sighting (doh, doh3, dot, doq).

string | null
first_seen
required
string format: date-time
last_seen
required
string format: date-time
queries_24h
required

Queries in the last 24 hours; null when counts are unavailable.

integer | null
blocked_24h
required

Blocked queries in the last 24 hours; null when counts are unavailable.

integer | null
Example
{
"devices": [
{
"kind": "phone",
"identification": "doh_path"
}
]
}

Malformed request.

Media typeapplication/problem+json
object
type
required
string format: uri
title
required
string
status
required
integer
code
required

Stable machine code.

string
Allowed values: bad_request body_too_large bad_if_match unauthenticated invalid_credentials signup_closed invite_required waitlist_unavailable invalid_token token_expired token_used session_required insufficient_scope csrf_rejected not_found version_mismatch ip_conflict unknown_list too_many_rules validation_failed rate_limited internal node_revoked node_offline node_busy node_timeout node_error result_too_large shape_unsupported node_token_superseded relay_unavailable not_implemented query_timeout query_too_expensive range_too_large too_many_queries second_factor_required invalid_second_factor mfa_enrolment_required mfa_required reauth_required no_second_factor totp_already_enabled totp_not_enabled last_credential passkey_exists passkey_invalid passkeys_unavailable ceremony_invalid account_pending_deletion credential_required deletion_pending no_deletion_pending deletion_started organisation_has_members export_in_progress export_not_ready block_exists invalid_recovery_code profile_not_empty invalid_cursor bad_idempotency_key idempotency_key_reused idempotency_in_progress too_many_streams too_many_reports password_too_short password_too_long profile_suspended
detail
string
errors
Array<object>
object
field
required
string
message
required
string
request_id
string
retry_after

Seconds, repeating the Retry-After header (rate limits, offline nodes).

integer
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.

Media typeapplication/problem+json
object
type
required
string format: uri
title
required
string
status
required
integer
code
required

Stable machine code.

string
Allowed values: bad_request body_too_large bad_if_match unauthenticated invalid_credentials signup_closed invite_required waitlist_unavailable invalid_token token_expired token_used session_required insufficient_scope csrf_rejected not_found version_mismatch ip_conflict unknown_list too_many_rules validation_failed rate_limited internal node_revoked node_offline node_busy node_timeout node_error result_too_large shape_unsupported node_token_superseded relay_unavailable not_implemented query_timeout query_too_expensive range_too_large too_many_queries second_factor_required invalid_second_factor mfa_enrolment_required mfa_required reauth_required no_second_factor totp_already_enabled totp_not_enabled last_credential passkey_exists passkey_invalid passkeys_unavailable ceremony_invalid account_pending_deletion credential_required deletion_pending no_deletion_pending deletion_started organisation_has_members export_in_progress export_not_ready block_exists invalid_recovery_code profile_not_empty invalid_cursor bad_idempotency_key idempotency_key_reused idempotency_in_progress too_many_streams too_many_reports password_too_short password_too_long profile_suspended
detail
string
errors
Array<object>
object
field
required
string
message
required
string
request_id
string
retry_after

Seconds, repeating the Retry-After header (rate limits, offline nodes).

integer
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).

Media typeapplication/problem+json
object
type
required
string format: uri
title
required
string
status
required
integer
code
required

Stable machine code.

string
Allowed values: bad_request body_too_large bad_if_match unauthenticated invalid_credentials signup_closed invite_required waitlist_unavailable invalid_token token_expired token_used session_required insufficient_scope csrf_rejected not_found version_mismatch ip_conflict unknown_list too_many_rules validation_failed rate_limited internal node_revoked node_offline node_busy node_timeout node_error result_too_large shape_unsupported node_token_superseded relay_unavailable not_implemented query_timeout query_too_expensive range_too_large too_many_queries second_factor_required invalid_second_factor mfa_enrolment_required mfa_required reauth_required no_second_factor totp_already_enabled totp_not_enabled last_credential passkey_exists passkey_invalid passkeys_unavailable ceremony_invalid account_pending_deletion credential_required deletion_pending no_deletion_pending deletion_started organisation_has_members export_in_progress export_not_ready block_exists invalid_recovery_code profile_not_empty invalid_cursor bad_idempotency_key idempotency_key_reused idempotency_in_progress too_many_streams too_many_reports password_too_short password_too_long profile_suspended
detail
string
errors
Array<object>
object
field
required
string
message
required
string
request_id
string
retry_after

Seconds, repeating the Retry-After header (rate limits, offline nodes).

integer
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).

Media typeapplication/problem+json
object
type
required
string format: uri
title
required
string
status
required
integer
code
required

Stable machine code.

string
Allowed values: bad_request body_too_large bad_if_match unauthenticated invalid_credentials signup_closed invite_required waitlist_unavailable invalid_token token_expired token_used session_required insufficient_scope csrf_rejected not_found version_mismatch ip_conflict unknown_list too_many_rules validation_failed rate_limited internal node_revoked node_offline node_busy node_timeout node_error result_too_large shape_unsupported node_token_superseded relay_unavailable not_implemented query_timeout query_too_expensive range_too_large too_many_queries second_factor_required invalid_second_factor mfa_enrolment_required mfa_required reauth_required no_second_factor totp_already_enabled totp_not_enabled last_credential passkey_exists passkey_invalid passkeys_unavailable ceremony_invalid account_pending_deletion credential_required deletion_pending no_deletion_pending deletion_started organisation_has_members export_in_progress export_not_ready block_exists invalid_recovery_code profile_not_empty invalid_cursor bad_idempotency_key idempotency_key_reused idempotency_in_progress too_many_streams too_many_reports password_too_short password_too_long profile_suspended
detail
string
errors
Array<object>
object
field
required
string
message
required
string
request_id
string
retry_after

Seconds, repeating the Retry-After header (rate limits, offline nodes).

integer
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).

Media typeapplication/problem+json
object
type
required
string format: uri
title
required
string
status
required
integer
code
required

Stable machine code.

string
Allowed values: bad_request body_too_large bad_if_match unauthenticated invalid_credentials signup_closed invite_required waitlist_unavailable invalid_token token_expired token_used session_required insufficient_scope csrf_rejected not_found version_mismatch ip_conflict unknown_list too_many_rules validation_failed rate_limited internal node_revoked node_offline node_busy node_timeout node_error result_too_large shape_unsupported node_token_superseded relay_unavailable not_implemented query_timeout query_too_expensive range_too_large too_many_queries second_factor_required invalid_second_factor mfa_enrolment_required mfa_required reauth_required no_second_factor totp_already_enabled totp_not_enabled last_credential passkey_exists passkey_invalid passkeys_unavailable ceremony_invalid account_pending_deletion credential_required deletion_pending no_deletion_pending deletion_started organisation_has_members export_in_progress export_not_ready block_exists invalid_recovery_code profile_not_empty invalid_cursor bad_idempotency_key idempotency_key_reused idempotency_in_progress too_many_streams too_many_reports password_too_short password_too_long profile_suspended
detail
string
errors
Array<object>
object
field
required
string
message
required
string
request_id
string
retry_after

Seconds, repeating the Retry-After header (rate limits, offline nodes).

integer
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"
}