Impossible Travel Detection API Reference
POST/v1/risk/check
Compares a supplied IP's location against a stored per-user baseline and classifies the implied travel speed. A raw signal for your own fraud workflow, not a final verdict. There's no separate risk plan or price — each check counts as one request against your existing plan's monthly cap, the same secret key you already use for IP lookup.
Authentication
Provide a secret key via Authorization: Bearer YOUR_SECRET_KEY, the same key type as the lookup endpoints. Send a JSON body of userId, ip, and an optional commit boolean (defaults to true; set false for a speculative check that shouldn't move the stored baseline). To delete a stored baseline, call DELETE /v1/risk/baseline with a JSON body of userId — same auth, doesn't count against your monthly cap, and is idempotent if no baseline exists.
Response fields
- risk
- low, medium, or high.
- impossibleTravel
- Boolean shorthand for whether the implied speed between the previous and current location exceeds a plausible travel speed.
- distanceKm, impliedSpeedKmh, elapsedSeconds
- The distance and time between the previous and current observation, and the speed that implies. Null on a user's first-ever check, when there's no previous location to compare against.
- previousLocation
- country, latitude, longitude, and observedAt for the stored baseline before this call. Null when this is the first-ever check for this userId.
- currentLocation
- country, latitude, and longitude for the ip you supplied on this call.
Errors
- 400
- Malformed IP address or missing userId.
- 401
- Missing or invalid API key.
- 403
- A publishable key was used instead of a secret key.
- 422
- The supplied IP could not be resolved to a location.
- 429
- The per-minute rate limit or the plan's monthly request cap has been exceeded — see errors and rate limits for how to tell which.
Example
Request
curl https://api.watch-ip.com/v1/risk/check \
-H "Authorization: Bearer YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"userId": "u_123", "ip": "203.0.113.1"}'Response
{
"risk": "high",
"impossibleTravel": true,
"distanceKm": 8843.2,
"impliedSpeedKmh": 4421.6,
"elapsedSeconds": 7200,
"previousLocation": { "country": "FR", "latitude": 48.8566, "longitude": 2.3522, "observedAt": "2026-09-06T12:00:00.000Z" },
"currentLocation": { "country": "US", "latitude": 30.2672, "longitude": -97.7431 }
}Limits
v1 stores only the single most-recent location per user, not a history window — expect false positives from fast VPN-toggling or mobile-network IP churn, since there's no VPN/datacenter-aware suppression yet. Treat the result as a raw signal, not a final verdict. Because this endpoint stores a userId-linked location beyond a single request/response cycle, using it makes Watch-IP a processor of that data on your behalf — see the Data Processing Addendum, and DELETE /v1/risk/baseline above for how to fulfill a deletion request.
Related pages
- GET /v1/lookup/:ip referenceFull field reference for the arbitrary-IP lookup endpoint.
- AuthenticationPublishable vs. secret keys, origin-locking, and rate limits.
- Impossible travel detectionCompare a login's IP-derived location with the previous stored point for that user.
- Login risk detectionUse IP-derived location changes to inform login review.