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
strictnessparameter 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.1 | Clean residential — allow, score 0 |
| 198.51.100.1 | VPN on a datacenter ASN — block, score 92 |
| 198.51.100.2 | Tor exit node — block, score 100 |
| 203.0.113.1 | Open proxy with recent abuse — block, score 88 |
| 203.0.113.2 | Datacenter, no other signal — review, score 55 |
Email addresses
| ?email= | Always returns |
|---|---|
| clean@example.com | Deliverable mailbox — allow, score 0 |
| disposable@example.com | Disposable domain — block, score 90 |
| role@example.com | Role account (info@, admin@) — review, score 45 |
| invalid@example.com | Undeliverable — block, score 95 |
| catchall@example.com | Catch-all domain, unverifiable — review, score 40 |
Phone numbers
| ?phone= | Always returns |
|---|---|
| +12025550100 | Valid landline — allow, score 0 |
| +12025550142 | VOIP number — review, score 50 |
| +12025550188 | Premium rate — block, score 90 |
Domains
| ?domain= | Always returns |
|---|---|
| example.com | Established domain, full DNS — allow, score 0 |
| disposable.invalid | Disposable provider — block, score 90 |
| newly-registered.invalid | Registered 3 days ago — review, score 60 |
| nxdomain.invalid | Does not resolve — block, score 85 |
Device fingerprints
| device_id | Always returns |
|---|---|
| 00000000000000000000000000000000 | Clean browser — allow, score 0, bot_probability 0 |
| ffffffffffffffffffffffffffffffff | Headless 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.