Reference

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: verdict invalid, bounce probability 0.90 with interval [0.72, 0.97], no provider called, cost_usd: 0. On /v1/screen it adds domain_blocklisted, which means review.
  • 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:

  1. Your address blocklist
  2. Your address allowlist
  3. Your domain blocklist
  4. Your domain allowlist
  5. Your email-type rules (free, role, relay, disposable), in /v1/decide only
  6. 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.

MethodPathDoes
GET/v1/domains/blocklistYour blocked domains: { rule, domains: [{ domain, note, created_at }], count }.
GET/v1/domains/allowlistYour allowed domains, same shape.
POST/v1/domains/blocklistAdd domains to the blocklist: { domains: string[], note?: string }.
POST/v1/domains/allowlistAdd domains to the allowlist, same body.
DELETE/v1/domains/blocklistRemove domains from the blocklist: { domains: string[] }.
DELETE/v1/domains/allowlistRemove domains from the allowlist, same body.
POST/v1/domains/checkWhat 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:

effectiveMeans
blockedYour blocklist matches. Every check ends with domain_blocklisted.
allowedYour allowlist matches. Sortance's disposable lists do not apply to this domain for you.
disposableNo rule of yours matches, and the domain is on Sortance's block tier: checks end with disposable_domain.
suspectedNo rule of yours matches, and the domain is on the signal tier: not blocked, reported as disposable_suspected.
noneNothing 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" }
    ]
} }
reasonWhen
address_not_allowedThe entry contains @. Rules take domains, never addresses, and the value is not echoed back.
scheme_not_allowedThe entry starts with a scheme such as https://.
path_not_allowedThe entry has a path, query or fragment.
invalid_domainNot a valid domain name after normalisation.
not_a_stringThe 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_request and nothing is written.
  • An empty domains array is a 400.
  • A note is 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.

MethodPathDoes
GET/v1/addresses/blocklistYour blocked addresses, masked: { rule, entries: [{ id, display, note, created_at, created_by }], count, cursor }.
GET/v1/addresses/allowlistYour allowed addresses, same shape.
POST/v1/addresses/blocklistBlock addresses: { emails: string[], note?: string } or { trace_ids: string[], note? }.
POST/v1/addresses/allowlistAllow addresses, same body.
DELETE/v1/addresses/blocklistRemove from the blocklist: { emails }, { ids } or { trace_ids }.
DELETE/v1/addresses/allowlistRemove from the allowlist, same body.
POST/v1/addresses/checkWhat 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 index and reason only (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 accept trace_ids: the trace_id of 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: ?limit up to 100 and the cursor from the previous page. Each entry carries id, display, note, created_at and created_by. The id is 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.

Not the same as named lists

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.