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

FieldTypeDescription
domainstringThe domain as submitted.
forbiddenbooleanWhether any active rule matched.
matched_rule_idinteger | nullID of the matching rule, if any.
categorystring | nullCategory of the matching rule, e.g. Trademark.
match_typestring | nullOne of exact, contains, regex, fuzzy.
checked_atdatetimeServer 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

FieldTypeRequiredDescription
domainsarray of stringrequiredDomain 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.

FieldTypeDescription
rules_versionintegerBumped on every rule create, update, delete, or bulk import.
last_published_atdatetimeWhen the ruleset last actually changed.
rule_countintegerNumber of active rules currently loaded.
cache_loaded_atdatetimeWhen 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);
}