One call at the signup form decides who gets in
Verify the address, enrich the person only if a rule needs to, score the fit, and apply the rule you wrote in plain English. You get one decision back, with the rule that made it and the reasons in words.
Where your signup rules live today
In a Zapier filter, an if in the signup handler, a spreadsheet of blocked domains and a thread in Slack. None of it is versioned, none of it is measured, and nobody can say what happened to paid conversion when you started blocking Gmail. Decide puts the rules in one place, as data, with a history and a receipt on every request.
You write it in English
Don't allow temp emails or role accounts. Only business emails, and review anyone outside fintech or insurance. Anyone on the partners list is always allowed. Let AI agents in through the API-key flow.The compiler turns that into typed rules, once, when you click compile — and shows them back to you before anything is saved.
It compiles to rules you can read
First match wins, top to bottom. Anything that matches no rule is allowed.
| Rule | When | Then | Why it is here |
|---|---|---|---|
r_partners | email.domain is on list partners | allow | Checked first, so it overrides everything below. |
r_no_disposable | verification.email_type is disposable | deny | Temp-mail domains. |
r_no_role | verification.email_type is role | deny | info@, sales@ and the like. |
r_agents | verification.actor_class is agent_mailbox | allow_with_flow: agent | Agents go to your API-key flow instead of the signup form. |
r_business_only | verification.email_type is not business | deny | Gmail, Outlook.com, Yahoo, Apple and other free (social) mailboxes, relay aliases, and addresses Sortance cannot place. |
r_industry_fit | enrichment.company.industry not in fintech, insurance | review | Review, not deny: enrichment is missing on some corporate domains, and missing data should not become a lost signup. |
Every field, operator and value comes from a closed vocabulary. The compiler cannot invent company.vibe, and anything it produces goes through the same validator as a rule you write by hand. When your English is ambiguous — does “business emails only” mean deny consumer mailboxes, or review them? — it asks instead of guessing.
For the common case there is a switch instead of a sentence: the Email types card on the Policy screen sets free (social) email, role accounts, relay aliases and disposable addresses to Allow, Review or Block, as rules in the same policy. See email types.
Replay it before it touches a signup
Before you activate a version, Sortance runs it over your own recent decisions and shows what would have changed: the decision mix, how many each rule caught, which decisions flipped, a sample of them with the address masked, and what the change does to enrichment spend per 1,000 decisions.
// Illustrative. The shape of a replay response, not anyone's traffic.
{
"evaluated": 500,
"decisions": { "allow": 318, "allow_with_flow": 4, "review": 121, "challenge": 0, "deny": 57 },
"by_rule": [ { "rule_id": "r_no_disposable", "matched": 23 }, { "rule_id": "r_industry_fit", "matched": 121 } ],
"changed_vs_active": { "allow_to_deny": 41, "allow_to_review": 97 },
"estimated_cost_delta_usd_per_1k": 31.4,
"warnings": ["38 of 500 traces had no enrichment stored; those were evaluated with enrichment: null."]
}Then you choose: enforce now, or shadow first — evaluate the new version on every request and record what it would have done, while the current version keeps answering. See experiments.
What comes back
curl -X POST https://api.sortance.com/v1/decide \
-H "Authorization: Bearer $SORTANCE_KEY" \
-d '{"email":"mia@acme.com","context":{"purpose":"signup"}}'
{
"decision": "review",
"rule_id": "r_industry_fit",
"policy": { "slug": "default", "version": 14 },
"reasons": ["company.industry is 'logistics', not one of 'fintech', 'insurance'"],
"verification": { /* the full /v1/verify response */ },
"enrichment": { /* the profile, because r_industry_fit needed it */ },
...
}The full field list is in the decide reference.
You only pay for enrichment a rule actually needs
Rules are walked in order and a profile is bought only when evaluation reaches a rule that reads one. A disposable address denied by rule two never makes rule six pay to look up its company. A policy that reads only verification signals costs exactly what a bare verification costs.
Three things Decide will not do
- Put a model on the request path. A model helps write the policy, once. Every decision is a pure function of typed inputs — replayable, explainable, and fast.
- Deny anyone on its own authority. Sortance classifies; your policy decides. A
denyonly ever comes from a rule you confirmed, and the response names it. The compiler leans toreviewwhere data may be missing, recommendations proposereview, and the default isallow. - Fail closed. An enrichment outage, a slow vendor or a missing policy still returns
200with a decision, and adegraded:reason says what was missing.
Not a lead scorer, not a CRM, not a bouncer
No model emits a score: the ICP score is a rubric you wrote, computed by arithmetic, with its coverage next to it. Nothing is written to your CRM and nothing is sent to anyone. There is no visitor tracking of Sortance’s own; a website-visitor signal appears only if you connect a vendor that sends one. And your app still owns sign-in, sessions and the form — Decide answers “should this email proceed”, nothing more.