Test mode

Every account has two keys. A live key (tl_live_…) returns real intelligence and counts against your plan. A test key (tl_test_…) returns synthetic data and is free.

Scores from a test key are fabricated. They are derived from the value you send, not from anything we know about it. A test key pointed at a real visitor tells you nothing about that visitor — it is not a preview of our accuracy, and it is not a degraded version of the real answer. Use a live key to evaluate the data itself; the free plan includes 1,000 live lookups a month for exactly that.

Why it works this way

The same reason a payment processor’s test card cannot buy anything. If a test key returned real answers it would be the product with the price removed, and the only thing standing between it and production use would be a quota. Making the output synthetic removes the incentive instead of policing it — which is why test lookups can stay generous, and why test traffic never teaches our reputation network anything.

What test mode does exercise

Everything an integration test should assert on. Responses are byte-compatible with production:

  • — Authentication, rate limits and quota errors
  • — Response shapes, field types and status codes
  • — Error codes and messages, including validation failures on bad input
  • — Your own custom allow / block rules, applied exactly as in production
  • — The strictness parameter and its thresholds
  • — Combined scoring on /v1/score/user, using the real weighting

The one thing it cannot answer is what LayerCall actually thinks of a value.

Telling the two apart

Every test response carries mode, test_mode and test_mode_note, and every response on both keys carries an X-LayerCall-Mode header — so a proxy log or a curl -I shows which key produced it without parsing the body.

curl "https://www.layercall.com/v1/score/ip?ip=198.51.100.1" \
  -H "X-Api-Key: tl_test_your_key"

{
  "ip": "198.51.100.1",
  "risk_score": 92,
  "verdict": "block",
  "signals": { "is_vpn": true, "is_datacenter": true, ... },
  "mode": "test",
  "test_mode": true,
  "test_mode_note": "Synthetic data — this is a test key ..."
}

Documented fixtures

These values always return the same result, so you can assert on them. They come from the ranges reserved for documentation (RFC 5737, RFC 2606 and the 555-01xx block), which means they can never collide with a real value you might want scored.

IP addresses

?ip=Always returns
192.0.2.1Clean residential — allow, score 0
198.51.100.1VPN on a datacenter ASN — block, score 92
198.51.100.2Tor exit node — block, score 100
203.0.113.1Open proxy with recent abuse — block, score 88
203.0.113.2Datacenter, no other signal — review, score 55

Email addresses

?email=Always returns
clean@example.comDeliverable mailbox — allow, score 0
disposable@example.comDisposable domain — block, score 90
role@example.comRole account (info@, admin@) — review, score 45
invalid@example.comUndeliverable — block, score 95
catchall@example.comCatch-all domain, unverifiable — review, score 40

Phone numbers

?phone=Always returns
+12025550100Valid landline — allow, score 0
+12025550142VOIP number — review, score 50
+12025550188Premium rate — block, score 90

Domains

?domain=Always returns
example.comEstablished domain, full DNS — allow, score 0
disposable.invalidDisposable provider — block, score 90
newly-registered.invalidRegistered 3 days ago — review, score 60
nxdomain.invalidDoes not resolve — block, score 85

Device fingerprints

device_idAlways returns
00000000000000000000000000000000Clean browser — allow, score 0, bot_probability 0
ffffffffffffffffffffffffffffffffHeadless automation — block, score 95, bot_probability 0.98

Anything else you send

Values outside the tables above still work — they return a result derived from the value itself. The same input always produces the same output, so a suite that asserts on it will not flake, but the numbers are invented. There is no fixture list to exhaust.

Limits

Test lookups are free and never appear on an invoice. They are capped per calendar month — 10,000 on Free and 100,000 on paid plans — high enough for CI and a staging environment to run without anyone thinking about it. Live usage and its limits are on your dashboard.