SDKs
Official clients for Node and Python, and a CLI that needs no install at all. Both libraries have zero dependencies — a trust check sits on your signup path, which is the worst place in an application to introduce a dependency tree that has to resolve against whatever you already pin.
Try it with no install
export LAYERCALL_API_KEY=tl_live_... npx layercall ip 8.8.8.8 npx layercall email someone@mailinator.com npx layercall user --ip 1.2.3.4 --email a@b.com
Node / TypeScript
npm i layercall
import { LayerCall } from "layercall";
const lc = new LayerCall(process.env.LAYERCALL_API_KEY!);
const result = await lc.scoreUser({
ip: req.ip,
email: body.email,
phone: body.phone,
});
if (result.verdict === "review") {
await sendOtp(body.email); // a real user clears it themselves
}Python
pip install layercall
import os
from layercall import LayerCall
lc = LayerCall(os.environ["LAYERCALL_API_KEY"])
result = lc.score_user(ip=request.remote_addr, email=form["email"])
if result["verdict"] == "review":
send_otp(form["email"])Two things the clients enforce
Server-side only. The Node client throws if it detects a browser. An API key shipped to a browser is public the moment someone opens devtools, and it bills to your account.
Retries only what can succeed. 429 and 5xx retry with short backoff; other 4xx fail fast, because they will not succeed on a retry and this code sits in front of a user.
null means unknown, never “no”
newly_registered is null when a TLD publishes no RDAP — .de, .ru and .ac.uk among them — and mailbox_exists is null when the provider does not answer honestly. Gmail and Yahoo accept mail for addresses that do not exist, so any vendor claiming certainty there is inventing it. Treating either as a negative finding is the exact mistake those fields exist to prevent.
Prefer a challenge to a rejection on review — see acting on a verdict.