Test mode lets you build your integration against predictable, deterministic responses without consuming your monthly validation quota.
Test vs live keys
| Test key | Live key | |
|---|---|---|
| Prefix | fidro_test_... |
fidro_live_... |
| Data | Predefined scenarios | Real validation |
| Quota | Does not count | Counts toward monthly limit |
| Use for | Development, CI/CD, staging | Production |
Predefined test scenarios
Use these email addresses with your test key to simulate specific outcomes:
| Scenario | |
|---|---|
clean@example.com |
Clean email, no risk factors |
disposable@example.com |
Disposable email, medium risk |
temp@example.com |
Temporary email, high risk |
invalid@example.com |
Invalid email, no MX record |
malformed@example.com |
Malformed email, maximum risk |
temp-fake@example.com |
Temporary and fake, very high risk |
Any other address returns a clean result in test mode. The scenarios always return the same checks, making them ideal for automated tests and CI pipelines.
Test IPs
| IP | Scenario |
|---|---|
1.1.1.1 |
Clean IP, no risk factors |
2.2.2.2 |
VPN, low risk |
3.3.3.3 |
Proxy, low risk |
4.4.4.4 |
Tor exit node, high risk |
7.7.7.7 |
VPN, proxy and Tor, high risk |
9.9.9.9 |
Every risk factor, maximum severity |
The full matrix, including severity variants, is in the API reference.
Test events and velocity
Test keys keep their own event history, separate from live, so you can reproduce every anomaly on demand:
| To reproduce | Do this with a test key |
|---|---|
ip_signup_burst |
Three event: "signup" calls from the same ip inside an hour, with different emails |
email_pattern_burst |
Three signups in 24 hours with sam+1@example.com, s.a.m@example.com and sam42@example.com |
ip_many_users |
Five event: "login" calls from one ip with five different user_id values |
new_country_for_user |
Three logins for one user_id with country_code: "US", then one with country_code: "DE" |
impossible_travel |
Two logins for one user_id within an hour, country_code: "US" then country_code: "DE" |
In test mode the country_code you send stands in for the IP's country, which is what makes the travel rules reproducible. Test events follow the same retention as live ones and never count toward your quota.
Writing integration tests
// PHPUnit example
public function test_blocks_high_risk_signups()
{
// Use test API key in your test environment
$response = $this->post('/register', [
'email' => 'malformed@example.com',
'password' => 'SecurePassword123',
]);
$response->assertSessionHasErrors('email');
$this->assertDatabaseMissing('users', [
'email' => 'malformed@example.com',
]);
}
public function test_third_signup_from_one_ip_is_challenged()
{
foreach (['ann', 'bob', 'cat'] as $name) {
$response = $this->withServerVariables(['REMOTE_ADDR' => '1.1.1.1'])
->post('/register', [
'email' => "{$name}@example.com",
'password' => 'SecurePassword123',
]);
}
// Your register action sends event: "signup" to Fidro and
// asks for email verification when the recommendation is "challenge"
$response->assertRedirect('/verify-email');
}
Switching to live
When you're ready to go to production, swap your test key for a live key in your environment variables. No code changes needed, the API behaves identically, just with real data.