Blocklists: your own blocklist and allowlist
Sortance keeps global lists of disposable domains for everyone. Your blocklists are yours alone: block a domain or a single address your business never wants, or allow one Sortance’s lists would otherwise stop. They apply to your account and no one else’s, on every check.
What a rule does
- Block. Every check for the domain ends in the free gate with the reason
domain_blocklisted: verdictinvalid, bounce probability 0.90 with interval [0.72, 0.97], no provider called,cost_usd: 0. On/v1/screenit addsdomain_blocklisted, which meansreview. - Allow. Sortance’s disposable lists, both the block tier and the signal tier, are set aside for the domain. Syntax and MX are still checked, so an allowed domain with no mail server still fails. The response carries the informational reason
domain_allowlisted.
Precedence, highest first:
- Your address blocklist
- Your address allowlist
- Your domain blocklist
- Your domain allowlist
- Your email-type rules (free, role, relay, disposable), in
/v1/decideonly - Sortance’s global tiers (block, then signal)
Steps 1 to 4 and 6 run in the verification itself, so they shape the verdict on every endpoint. Email-type rules are policy rules: they read the email_type the verification produced and turn it into a /v1/decide decision, never a verdict. A blocked address or domain has already failed by then. An allow keeps the address from being typed disposable, so a disposable rule cannot catch it, but it does not exempt it from your free, role or relay rules: an allowed Gmail address is still free.
A rule for acme.com also covers mail.acme.com and any other subdomain. If a domain and one of its parents are on different lists, the block wins, at any level.
Rules apply everywhere your key checks an address: /v1/verify, /v1/decide, /v1/check, /v1/screen, the MCP tools. Answers shaped by your allowlist are kept out of Sortance’s shared address cache, so another account never receives them.
Routes
Same key as every other call. These are configuration, not verification: they do not count against your monthly quota, and share the 600-a-minute rate limit.
| Method | Path | Does |
|---|---|---|
GET | /v1/domains/blocklist | Your blocked domains: { rule, domains: [{ domain, note, created_at }], count }. |
GET | /v1/domains/allowlist | Your allowed domains, same shape. |
POST | /v1/domains/blocklist | Add domains to the blocklist: { domains: string[], note?: string }. |
POST | /v1/domains/allowlist | Add domains to the allowlist, same body. |
DELETE | /v1/domains/blocklist | Remove domains from the blocklist: { domains: string[] }. |
DELETE | /v1/domains/allowlist | Remove domains from the allowlist, same body. |
POST | /v1/domains/check | What would happen to one domain on your account: { domain }. |
Add
curl -X POST https://api.sortance.com/v1/domains/blocklist \
-H "Authorization: Bearer $SORTANCE_KEY" \
-H "Content-Type: application/json" \
-d '{"domains":["competitor.com","spam-farm.net"],"note":"sales asked"}'{ "rule": "block", "added": 2, "moved": 0, "unchanged": 0, "total": 2 }A domain is on one list or neither. Adding it to the blocklist takes it off the allowlist, and the other way round; moved counts those. Adding a domain that is already there keeps its original date, and replaces its note only if you send a new one. total is your rules across both lists.
List
curl https://api.sortance.com/v1/domains/allowlist \
-H "Authorization: Bearer $SORTANCE_KEY"{
"rule": "allow",
"domains": [
{ "domain": "partner.io", "note": "reseller relay", "created_at": 1791400000 }
],
"count": 1
}Remove
curl -X DELETE https://api.sortance.com/v1/domains/allowlist \
-H "Authorization: Bearer $SORTANCE_KEY" \
-H "Content-Type: application/json" \
-d '{"domains":["partner.io"]}'DELETE removes from the list named in the path only. Removing a domain that is on the other list, or on neither, changes nothing.
Check one domain
curl -X POST https://api.sortance.com/v1/domains/check \
-H "Authorization: Bearer $SORTANCE_KEY" \
-H "Content-Type: application/json" \
-d '{"domain":"mail.competitor.com"}'{
"domain": "mail.competitor.com",
"org_rule": "block",
"matched": { "domain": "competitor.com", "note": "sales asked", "created_at": 1791400000 },
"global_tier": null,
"effective": "blocked"
}matched is the most specific entry that applied, which may be a parent. global_tier is block, signal or null whatever your rules say, so you can see what an allow rule is overriding. effective is one of:
| effective | Means |
|---|---|
blocked | Your blocklist matches. Every check ends with domain_blocklisted. |
allowed | Your allowlist matches. Sortance's disposable lists do not apply to this domain for you. |
disposable | No rule of yours matches, and the domain is on Sortance's block tier: checks end with disposable_domain. |
suspected | No rule of yours matches, and the domain is on the signal tier: not blocked, reported as disposable_suspected. |
none | Nothing applies. Syntax and MX decide as usual. |
What counts as an entry
A bare domain such as acme.com. Entries are trimmed and lower-cased, and internationalised names are stored in their ASCII form, the same way Sortance’s own lists are. Anything else is refused, and the whole request with it: a 400 lists every bad entry by its position in your array.
{ "error": {
"code": "invalid_request",
"message": "2 entries are not a valid domain. ...",
"trace_id": "...",
"invalid": [
{ "index": 0, "reason": "address_not_allowed" },
{ "index": 3, "value": "https://acme.com", "reason": "scheme_not_allowed" }
]
} }| reason | When |
|---|---|
address_not_allowed | The entry contains @. Rules take domains, never addresses, and the value is not echoed back. |
scheme_not_allowed | The entry starts with a scheme such as https://. |
path_not_allowed | The entry has a path, query or fragment. |
invalid_domain | Not a valid domain name after normalisation. |
not_a_string | The entry is not a string. |
- At most 1,000 domains per request, and 10,000 across both lists per account. Beyond either, the request is a
400 invalid_requestand nothing is written. - An empty
domainsarray is a400. - A
noteis optional, up to 200 characters, and stored as written, so a note that contains an email address is refused.
Address rules
The same idea for one address at a time. Block an address and every check for it ends in the free gate with address_blocklisted: verdict invalid, bounce probability 0.90 with interval [0.72, 0.97], no provider called, cost_usd: 0; on /v1/screen it means review. Allow an address and Sortance’s disposable tiers and your own domain blocks are set aside for it (syntax and MX still apply), with the informational reason address_allowlisted. An address rule beats any domain rule.
Sortance never stores the address. A rule is kept as a keyed hash of the normalized address (kept inside Sortance, never returned by any endpoint) and a masked display form, the first character, ••• and the domain: j•••@acme.com. Listings return only that masked form, so neither the API nor the dashboard can show you the full address you blocked. To ask about one address, use POST /v1/addresses/check.
| Method | Path | Does |
|---|---|---|
GET | /v1/addresses/blocklist | Your blocked addresses, masked: { rule, entries: [{ id, display, note, created_at, created_by }], count, cursor }. |
GET | /v1/addresses/allowlist | Your allowed addresses, same shape. |
POST | /v1/addresses/blocklist | Block addresses: { emails: string[], note?: string } or { trace_ids: string[], note? }. |
POST | /v1/addresses/allowlist | Allow addresses, same body. |
DELETE | /v1/addresses/blocklist | Remove from the blocklist: { emails }, { ids } or { trace_ids }. |
DELETE | /v1/addresses/allowlist | Remove from the allowlist, same body. |
POST | /v1/addresses/check | What happens to one address on your account: { email }. |
curl -X POST https://api.sortance.com/v1/addresses/blocklist \
-H "Authorization: Bearer $SORTANCE_KEY" \
-H "Content-Type: application/json" \
-d '{"emails":["spammer@example.com"],"note":"chargeback"}'{ "rule": "block", "added": 1, "moved": 0, "unchanged": 0, "total": 1 }curl -X POST https://api.sortance.com/v1/addresses/check \
-H "Authorization: Bearer $SORTANCE_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"spammer@example.com"}'{
"org_rule": "block",
"note": "chargeback",
"display": "s•••@example.com",
"created_at": 1791400000,
"domain_rule": null,
"effective": "blocked"
}- At most 1,000 addresses per request and 10,000 across both lists per account, counted separately from domain rules.
- A bad entry is reported by
indexandreasononly (invalid_address,not_a_string,invalid_trace_id,unknown_trace,invalid_id). The value is never echoed back, and nothing in that request is written. - Instead of
emails, POST and DELETE accepttrace_ids: thetrace_idof one of your own traces. Sortance looks up that trace’s address hash itself. That is how the dashboard blocks an address from the Traces tab without ever holding it. Such a rule shows as•••@domain. - The listing is paged, newest first:
?limitup to 100 and thecursorfrom the previous page. Each entry carriesid,display,note,created_atandcreated_by. Theidis scoped to your account (the same address has a different id in every account); DELETE takes it as{ ids: [...] }. - Changing a list needs the member role or above; any role can list and check. Changes take effect on the same schedule as domain rules, below.
When a change takes effect
The rules are stored in the database and copied to a fast cache on every change. Each API instance remembers an account’s rules for 30 seconds, and the cache itself can take up to a minute to reach every region, so a change usually applies everywhere within a minute. /v1/domains/check reads the stored rules directly and always shows the latest state. If the rules cannot be read during a check, the check runs as if you had none, rather than failing.
In the dashboard
In the dashboard, Rules → Blocklists has three tabs: Domains, Addresses and Lists. Domains and Addresses each list both lists, add and remove in bulk, and check one domain or address, using these same routes with your connected key. The Addresses tab previews the masked form before anything is sent. The Playground, and the Test history and Traces tabs of History, each offer “Block this address” for the address a check was about. A finished bulk job offers “Block undeliverable addresses” (POST /v1/bulk/jobs/:id/block), up to the 10,000 cap.
Named lists are sets a policy rule can test with in_list; on their own they change nothing. They sit on the Lists tab of the same screen. Rules here act on every check immediately; lists only act when a policy rule references them. Use a domain or address rule for “never this one” or “this one is fine, whatever the disposable lists say”, and a named list when a decision depends on more than that.