Skip to content

Block an abusive source prefix (admin).

POST
/v1/admin/source-blocks
curl --request POST \
--url https://api.opdns.io/v1/admin/source-blocks \
--header 'Content-Type: application/json' \
--cookie opdns_session=<opdns_session> \
--data '{ "cidr": "example", "reason": "example", "pops": [ "example" ], "jurisdictions": [ "example" ], "expires_at": "2026-04-15T12:00:00Z" }'

Republishes operator/sources.json (announced on NATS operator.changed) in the same transaction; edges in scope refuse plain DNS (Do53) queries from the prefix (REFUSED, no recursion) and close DoT, DoH and DoQ connections from it after the handshake, counting both. expires_at defaults to 7 days ahead and may be at most 90 days ahead. Prefixes wider than /8 (IPv4) or /19 (IPv6) are refused. Audited.

Idempotency-Key
string
>= 1 characters <= 255 characters

Makes the POST safe to retry: a repeat with the same key and the same request within 24 h returns the stored response (with Idempotent-Replayed: true) without creating again. 1 to 255 visible ASCII characters (a UUID is fine).

Media typeapplication/json
object
cidr
required

Prefix or single address, e.g. 192.0.2.0/24.

string
reason
required

Ticket id and cause; published to edges, never to clients.

string
>= 1 characters <= 200 characters
pops
Array<string>
jurisdictions
Array<string>
expires_at
string | null format: date-time
Examplegenerated
{
"cidr": "example",
"reason": "example",
"pops": [
"example"
],
"jurisdictions": [
"example"
],
"expires_at": "2026-04-15T12:00:00Z"
}

Added and published.

Media typeapplication/json
object
block
required
object
id
required
string format: uuid
cidr
required

Masked prefix, e.g. 192.0.2.0/24.

string
reason
required
string
pops
required
Array<string>
jurisdictions
required
Array<string>
expires_at
required
string format: date-time
created_by
required
string
created_at
required
string format: date-time
removed_by
required
string | null
removed_at
required
string | null format: date-time
file_version
required
integer
Examplegenerated
{
"block": {
"id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"cidr": "example",
"reason": "example",
"pops": [
"example"
],
"jurisdictions": [
"example"
],
"expires_at": "2026-04-15T12:00:00Z",
"created_by": "example",
"created_at": "2026-04-15T12:00:00Z",
"removed_by": "example",
"removed_at": "2026-04-15T12:00:00Z"
},
"file_version": 1
}

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

block_exists: a live entry has this prefix.

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/block_exists",
"title": "Conflict",
"status": 409,
"code": "block_exists",
"detail": "a live entry has this prefix",
"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"
}

not_implemented (cloud log queries not configured on this server) or shape_unsupported (node too old).

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_implemented",
"title": "Not Implemented",
"status": 501,
"code": "not_implemented",
"detail": "cloud log queries are not configured on this server",
"request_id": "5f2c9a0e7b1d4c38"
}