Forbidden Domain Filter — API Reference
Screens a candidate .mk domain name against the registry's maintained set of forbidden and reserved patterns — literal, substring, regex, and fuzzy/typo matches. Requests are authenticated per registrar with an API key and rate-limited per key, per day.
Overview
Three endpoints matter for integration: /v1/check/{domain}
for a single lookup, /v1/check/bulk for many at once, and
/v1/meta — unauthenticated — to check whether the
ruleset has changed since you last cached it. Rules change at most a
few times a week, so most integrators only need to poll
/v1/meta rather than re-checking known-clean domains
repeatedly.
Authentication
Send your key in an X-API-Key header on every
/v1/check* request. Keys are issued by MARnet registry
operations — contact them to get one; /v1/meta requires
no key.
X-API-Key: sk_live_your_key_here
Rate limits
Each API key has a per-day request quota set when it's issued, visible to you as the limit you were told at onboarding. It resets at UTC midnight. Each domain in a bulk request counts individually against the quota.
When exceeded, the server returns HTTP 429 with a
Retry-After header and a retry_after field
giving the number of seconds until the quota resets.
Check a domain
GET/v1/check/{domain}
Checks a single domain against the active ruleset.
Response fields
| Field | Type | Description |
|---|---|---|
domain | string | The domain as submitted. |
forbidden | boolean | Whether any active rule matched. |
matched_rule_id | integer | null | ID of the matching rule, if any. |
category | string | null | Category of the matching rule, e.g. Trademark. |
match_type | string | null | One of exact, contains, regex, fuzzy. |
checked_at | datetime | Server timestamp of the check. |
Example response
{
"domain": "sazky-online.mk",
"forbidden": true,
"matched_rule_id": 2,
"category": "Adult / gambling",
"match_type": "contains",
"checked_at": "2026-09-08T10:16:57.871104"
}
Bulk check
POST/v1/check/bulk
Checks many domains in one call. Each is scored independently.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
domains | array of string | required | Domain names to check. |
Response
An object with a results array, each entry shaped exactly like the single-check response above.
Ruleset metadata
GET/v1/meta
No authentication required. Use this to detect ruleset changes without re-checking domains you've already cached.
| Field | Type | Description |
|---|---|---|
rules_version | integer | Bumped on every rule create, update, delete, or bulk import. |
last_published_at | datetime | When the ruleset last actually changed. |
rule_count | integer | Number of active rules currently loaded. |
cache_loaded_at | datetime | When this server instance last refreshed its cache. |
Errors
- 401
- Missing or invalid
X-API-Key. - 403
- Key is valid but has been revoked.
- 429
- Daily rate limit exceeded. Body:
{"error":"rate_limit_exceeded","retry_after":N} - 404
- Resource not found (admin endpoints only).
curl
curl -s https://domain-filter.marnet.mk/v1/check/sazky-online.mk \
-H "X-API-Key: sk_live_your_key_here"
curl -s https://domain-filter.marnet.mk/v1/check/bulk \
-H "X-API-Key: sk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"domains": ["sazky.mk", "example.mk", "www.sazky.mk"]}'
curl -s https://domain-filter.marnet.mk/v1/meta
Python
import requests
resp = requests.get(
"https://domain-filter.marnet.mk/v1/check/sazky-online.mk",
headers={"X-API-Key": "sk_live_your_key_here"},
)
resp.raise_for_status()
result = resp.json()
print(result["domain"], "forbidden:", result["forbidden"])
bulk = requests.post(
"https://domain-filter.marnet.mk/v1/check/bulk",
headers={"X-API-Key": "sk_live_your_key_here"},
json={"domains": ["sazky.mk", "example.mk", "www.sazky.mk"]},
)
for r in bulk.json()["results"]:
print(r["domain"], "→", "forbidden" if r["forbidden"] else "clean")
JavaScript (fetch)
const res = await fetch("https://domain-filter.marnet.mk/v1/check/sazky-online.mk", {
headers: { "X-API-Key": "sk_live_your_key_here" },
});
if (res.status === 429) {
const err = await res.json();
console.error(`Rate limited. Retry after ${err.detail.retry_after}s`);
} else {
const result = await res.json();
console.log(result.domain, "forbidden:", result.forbidden);
}