Human verification service with fraud detection and risk scoring
Stop bots and automated abuse with human verification challenges that adapt to risk level. The CAPTCHA service provides invisible and interactive challenge modes, integrates with fraud scoring, and works as a drop-in widget for login, registration, and checkout forms on any web application.
X-API-Key header with every request.
All requests go through the API gateway which handles authentication, rate limiting, and usage tracking.
{
"token": "hvs_abc123...",
"siteKey": "site_key_here"
}
| Field | Type | Description |
|---|---|---|
token |
string |
Verification token from the client widget |
siteKey |
string |
Site key identifying your application |
{
"success": true,
"score": 0.95,
"action": "login",
"challengeTimestamp": "2026-03-25T14:30:00Z",
"hostname": "example.com"
}
| Field | Type | Description |
|---|---|---|
success |
boolean |
Whether the operation succeeded |
score |
number |
Risk/confidence score (0-100) |
action |
string |
Field value |
challengeTimestamp |
string |
Field value |
hostname |
string |
Target hostname to inspect |
| Status | Meaning |
|---|---|
200 | Request completed successfully |
400 | Bad request — invalid or missing parameters |
401 | Missing or invalid X-API-Key header |
429 | Rate limit exceeded — check Retry-After header |
500 | Internal server error |
400 Invalid or expired tokenRequest that triggers this:
{"token": "invalid_token", "siteKey": "site_key_here"}
Error response:
{"type": "/problems/validation-error", "title": "Invalid Token", "status": 400, "detail": "The token is invalid or has expired"}
How to fix: Ensure the token was generated recently and matches the siteKey. Tokens expire after 5 minutes.
401 Mismatched site keyRequest that triggers this:
{"token": "hvs_xyz...", "siteKey": "wrong_key"}
Error response:
{"type": "/problems/unauthorized", "title": "Site Key Mismatch", "status": 401, "detail": "The provided siteKey does not match the token origin"}
How to fix: Use the correct siteKey that matches where the token was generated. Check your CAPTCHA configuration.
curl -X POST /v1/captcha/verify \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"token": "hvs_abc123...",
"siteKey": "site_key_here"
}'
// Node.js (18+) or modern browser
const response = await fetch("/v1/captcha/verify", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
"token": "hvs_abc123...",
"siteKey": "site_key_here"
}),
});
const data = await response.json();
console.log(response.status, data);
import requests
response = requests.post(
"/v1/captcha/verify",
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"token": "hvs_abc123...",
"siteKey": "site_key_here"
},
)
print(response.status_code)
print(response.json())
package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{
"token": "hvs_abc123...",
"siteKey": "site_key_here"
}`)
req, _ := http.NewRequest("POST", "/v1/captcha/verify", body)
req.Header.Set("X-API-Key", "YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
data, _ := io.ReadAll(resp.Body)
fmt.Println(resp.StatusCode)
fmt.Println(string(data))
}
{
"name": "captcha",
"description": "Human verification service with fraud detection and risk scoring",
"inputSchema": {
"type": "object",
"properties": {
"api_key": {"type": "string", "description": "Your Orovai API key"},
"request": {"type": "object", "description": "Request body"}
},
"required": ["api_key", "request"]
},
"endpoint": "/v1/captcha/verify",
"method": "POST",
"headers": {
"X-API-Key": "{{api_key}}",
"Content-Type": "application/json"
}
}