Documentation sections

Admin API: blocklist registries

Methods for registries of blocked domains: list, create, edit, delete, check, test fetch, the replacement log and rollback.

Eight methods manage the same things as the Settings → PL registry («Настройки → Реестр PL») tab: lists of blocked domains, checking them and the auto-replacement log. All methods require a token with Full access («Полный доступ») (full).

Authorization is described on the Admin API: overview and authorization page, and the request format and common error codes on the Request, response and error format page. How auto-replacement works is described on the Blocklist registry (PL) and automatic domain replacement page.

Registry object

The list, create, update and check methods return a registry in this form:

FieldTypeDescription
idstring, UUIDRegistry ID
workspace_idstring, UUIDTeam ID
namestringName. May be empty
urlstringList URL
geostringThe registry's country code in upper case, for example PL
enabledbooleanScheduled checks are enabled
auto_replacebooleantrue — replace the domain in streams, false — only mark domains and write to the system log
interval_minnumberCheck interval in minutes
reserve_group_idstring, UUID or nullThe domain group the replacement is taken from
last_fetch_atdateTime of the last check at which the list was received. The field is absent until the registry has been checked at least once
last_errorstringError or warning from the last check. An empty string if there are no remarks
entry_countnumberHow many entries the list had at the last successful check. Before the first check, 0
created_atdateCreation time
json
{
  "id": "5b1f0c1e-6f0a-4d0e-9a3b-2c7d8e9f0a11",
  "workspace_id": "0d9c8b7a-1234-4abc-8def-001122334455",
  "name": "PL registry",
  "url": "https://registry.example.com/domains.txt",
  "geo": "PL",
  "enabled": true,
  "auto_replace": true,
  "interval_min": 30,
  "reserve_group_id": "7a6b5c4d-3e2f-4a1b-8c9d-0e1f2a3b4c5d",
  "last_fetch_at": "2026-10-04T09:30:00Z",
  "last_error": "",
  "entry_count": 48213,
  "created_at": "2026-10-01T12:00:00Z"
}

Registries

List registries

http
GET /api/v1/blocklist-sources

Returns all of the team's registries. No parameters.

Response — code 200 and an array of registry objects sorted by creation date, oldest first. If there are no registries, an empty array is returned.

Add a registry

http
POST /api/v1/blocklist-sources

Creates a registry. The tracker checks an enabled registry on its own on schedule; to avoid waiting, call the check.

FieldTypeRequiredDescription
urlstringyesList URL. Must start with http:// or https://
namestringnoName. Empty by default
geostringnoTwo-letter country code, for example PL. Converted to upper case. Default PL
enabledbooleannoCheck on schedule. Default true
auto_replacebooleannoReplace the domain automatically. Default true
interval_minnumbernoCheck interval in minutes. Default 30, minimum 5. Values from 1 to 4 are replaced with 5, 0 and negative values with 30
reserve_group_idstring, UUIDnoReserve domain group. Without the field, with null or an empty string no group is selected, and auto-replacement does not run

Response — code 201 and a registry object.

bash
curl -X POST https://panel.example.com/api/v1/blocklist-sources \
  -H "Api-Key: <token>" \
  -H "Content-Type: application/json" \
  -d '{"name":"PL registry","url":"https://registry.example.com/domains.txt","geo":"PL","interval_min":30,"reserve_group_id":"7a6b5c4d-3e2f-4a1b-8c9d-0e1f2a3b4c5d"}'

Errors:

CodecodemessageCause
400bad_requestinvalid jsonThe body was not parsed as a JSON object
400bad_requestнекорректный идентификатор или значение (invalid ID or value)reserve_group_id is not in UUID format
422validationнужен http(s)-адрес реестра (an http(s) registry address is required)url is empty or starts with neither http:// nor https://
422validationрезервная группа доменов не найдена (reserve domain group not found)The team has no group with the reserve_group_id

Edit a registry

http
PUT /api/v1/blocklist-sources/{id}

Replaces the registry's settings. {id} is the registry ID.

The body has the same fields as on creation; url is required. The record is replaced as a whole, so pass all fields, not only the changed ones:

  • without name, the name becomes empty;
  • without enabled and auto_replace, both switches are turned on;
  • without interval_min, the interval becomes 30;
  • without reserve_group_id, the reserve group is reset;
  • without geo or with an empty string, the country code stays the same.

Response — code 200 and a registry object. The last_fetch_at, last_error and entry_count fields are kept on update.

Errors — the same as on creation, plus 404 not_found if there is no registry with this {id}, and 400 bad_request if {id} is not in UUID format.

Warning.

A PUT request without reserve_group_id resets the reserve group, and auto-replacement stops running. First get the registry from the list and send its fields back together with your change.

Delete a registry

http
DELETE /api/v1/blocklist-sources/{id}

Deletes a registry. The replacement log entries remain.

Response — code 204 with no body. If there is no such registry, you get 404 not_found; if {id} is not in UUID format, 400 bad_request.

Check and test fetch

Both methods are subject to a rate limit.

Check a registry now

http
POST /api/v1/blocklist-sources/{id}/check

Downloads the list, compares the domains against it and, if the registry has auto-replacement enabled, replaces domains in streams. The Check («Проверить») button in the registry's row does the same. The method also works for a registry with enabled: false. No request body is needed.

The response comes after the check finishes — code 200 and a registry object with updated last_fetch_at, entry_count and last_error.

Code 200 does not mean the check passed without remarks. Read last_error: it keeps a warning, for example автозамена не выполнена: не выбрана резервная группа доменов — менять не на что (auto-replacement not performed: no reserve domain group selected — nothing to replace with). The messages are covered in the If something went wrong section.

Errors:

CodecodeCause
400bad_request{id} is not in UUID format
404not_foundThere is no registry with this {id}
502fetch_failedThe list was not received or contains no domains. The cause is in message, and it is also written to the registry's last_error. last_fetch_at and entry_count do not change

Examples of message with code 502:

  • реестр ответил 404 Not Found (the registry responded 404 Not Found) — the list server returned a code other than 200;
  • ответ реестра больше 64 МиБ — принимать нельзя, снимок был бы неполным (the registry response is larger than 64 MiB — it cannot be accepted, the snapshot would be incomplete);
  • в ответе реестра не найдено ни одного домена — источник отдал не тот формат или заглушку (no domains found in the registry response — the source returned the wrong format or a placeholder);
  • Get "https://registry.example.com/domains.txt": … — a network error; its text follows the colon, for example слишком много редиректов (too many redirects).

Test-fetch a list

http
POST /api/v1/blocklist-sources/test

Downloads the list from the address and shows what was recognized in it and which of the team's domains it contains. Saves and changes nothing. In the panel, this is the Check button next to the List URL («Адрес списка») field.

FieldTypeRequiredDescription
urlstringyesList URL, starts with http:// or https://

Response — code 200:

FieldTypeDescription
totalnumberHow many entries were recognized in the list
samplearray of strings or nullThe first entries of the list, no more than 20. null if there are no entries
matchedarray of stringsDomains from the Domains («Домены») section found in the list, in alphabetical order. An empty array if there are no matches
bash
curl -X POST https://panel.example.com/api/v1/blocklist-sources/test \
  -H "Api-Key: <token>" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://registry.example.com/domains.txt"}'
json
{
  "total": 48213,
  "sample": ["blocked-one.example", "blocked-two.example"],
  "matched": ["go.example.com"]
}

If total is 0, there is no list of domains in a recognizable format at the address.

Errors:

CodecodeCause
422validationThe body was not parsed, or url starts with neither http:// nor https://. message is нужен http(s)-адрес реестра
502fetch_failedThe list was not received. The cause is in message

Replacement log

List replacements

http
GET /api/v1/domain-replacements

Returns entries about automatic domain replacements in streams, newest first.

ParameterTypeRequiredDescription
limitnumbernoHow many entries to return. Default 100, maximum 500. With a value outside the range from 1 to 500, 100 entries are returned

Response — code 200 and an array of entries. If there were no replacements, an empty array is returned.

FieldTypeDescription
idstring, UUIDEntry ID. Needed for rollback
workspace_idstring, UUIDTeam ID
stream_idstring, UUID or nullThe stream in which the domain was replaced. null if the stream was deleted
campaign_idstring, UUID or nullThe stream's campaign. null if the campaign was deleted
stream_namestringThe stream's name at the time of replacement
old_domainstringThe domain that was in the stream
new_domainstringThe domain from the reserve group put in its place
geostringThe registry's country code
reasonstringReason, for example домен найден в реестре PL (запись «example.com») (domain found in the PL registry, entry “example.com”)
revertedbooleantrue if the replacement was rolled back
created_atdateReplacement time

Roll back a replacement

http
POST /api/v1/domain-replacements/{id}/revert

Puts the previous domain back into the stream and removes its “in the registry” mark. {id} is the log entry ID. No request body is needed.

Only the domain changes in the stream's link. The log entry gets reverted: true. If the domain is still in the list, the next check will mark and replace it again.

Response — code 204 with no body.

Errors:

CodecodemessageCause
400bad_requestнекорректный идентификатор или значение (invalid ID or value){id} is not in UUID format
404not_foundresource not foundThere is no entry with this {id}
409conflictзамена уже откачена (replacement already rolled back)The entry has already been reverted
409conflictв потоке уже другой домен — откат не нужен (the stream already has a different domain — no rollback needed)The link in the stream was changed after the replacement
410goneпоток удалён — откатывать нечего (stream deleted — nothing to roll back)The stream no longer exists or its campaign is archived
422validationне удалось разобрать ссылку потока (could not parse the stream's link)The link in the stream cannot be parsed as an address

Rate limit

POST /api/v1/blocklist-sources/{id}/check and POST /api/v1/blocklist-sources/test accept no more than 10 requests per minute from one IP address. The counter is shared by both methods. It also counts clicks on the Check button in the panel from the same IP address, as well as license activation requests and saving IP2Proxy settings. When the limit is exceeded, code 429 is returned:

json
{"code": "rate_limited", "message": "слишком много запросов, попробуйте позже"}

The message means “too many requests, try again later”. Try again in a minute. The limit does not apply to the other methods in the group.

Updated Need help? ↗