IP Cleanliness API
Use one endpoint for IP cleanliness scores, network type, proxy, VPN, Tor, location, and ASN. Web checks, batch jobs, and the API use the same detection standard.
Request
| Field | Type | Required | Description |
|---|---|---|---|
| ip | string | Yes | Public IPv4 address, up to 15 characters |
curl -X POST https://iprisk.top/v1/check \
-H "Authorization: Bearer ipr_live_xxx" \
-H "Content-Type: application/json" \
-d '{"ip":"1.1.1.1"}'IDEMPOTENCY_KEY="$(uuidgen | tr '[:upper:]' '[:lower:]')"
curl -X POST https://iprisk.top/v1/check \
-H "Authorization: Bearer ipr_live_xxx" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
-H "Content-Type: application/json" \
-d '{"ip":"1.1.1.1"}'Reuse the same Idempotency-Key when retrying one lookup; generate a new value for a new lookup.
const response = await fetch('https://iprisk.top/v1/check', {
method: 'POST',
headers: { Authorization: 'Bearer ipr_live_xxx', 'Content-Type': 'application/json' },
body: JSON.stringify({ ip: '1.1.1.1' })
});
const result = await response.json();const idempotencyKey = crypto.randomUUID();
const response = await fetch('https://iprisk.top/v1/check', {
method: 'POST',
headers: {
Authorization: 'Bearer ipr_live_xxx',
'Idempotency-Key': idempotencyKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({ ip: '1.1.1.1' })
});
const result = await response.json();Reuse the same Idempotency-Key when retrying one lookup; generate a new value for a new lookup.
import requests
response = requests.post(
'https://iprisk.top/v1/check',
headers={'Authorization': 'Bearer ipr_live_xxx'},
json={'ip': '1.1.1.1'},
timeout=60,
)
result = response.json()import uuid
import requests
idempotency_key = str(uuid.uuid4())
response = requests.post(
'https://iprisk.top/v1/check',
headers={
'Authorization': 'Bearer ipr_live_xxx',
'Idempotency-Key': idempotency_key,
},
json={'ip': '1.1.1.1'},
timeout=60,
)
result = response.json()Reuse the same Idempotency-Key when retrying one lookup; generate a new value for a new lookup.
<?php
$ch = curl_init('https://iprisk.top/v1/check');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ipr_live_xxx', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode(['ip' => '1.1.1.1']),
CURLOPT_RETURNTRANSFER => true,
]);
$result = json_decode(curl_exec($ch), true);<?php
$idempotencyKey = bin2hex(random_bytes(16));
$ch = curl_init('https://iprisk.top/v1/check');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ipr_live_xxx',
'Idempotency-Key: ' . $idempotencyKey,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['ip' => '1.1.1.1']),
CURLOPT_RETURNTRANSFER => true,
]);
$result = json_decode(curl_exec($ch), true);Reuse the same Idempotency-Key when retrying one lookup; generate a new value for a new lookup.
requestBody := strings.NewReader(`{"ip":"1.1.1.1"}`)
req, _ := http.NewRequest("POST", "https://iprisk.top/v1/check", requestBody)
req.Header.Set("Authorization", "Bearer ipr_live_xxx")
req.Header.Set("Content-Type", "application/json")
response, err := (&http.Client{Timeout: 60 * time.Second}).Do(req)idempotencyBytes := make([]byte, 16)
if _, err := rand.Read(idempotencyBytes); err != nil {
log.Fatal(err)
}
idempotencyKey := hex.EncodeToString(idempotencyBytes)
requestBody := strings.NewReader(`{"ip":"1.1.1.1"}`)
req, _ := http.NewRequest("POST", "https://iprisk.top/v1/check", requestBody)
req.Header.Set("Authorization", "Bearer ipr_live_xxx")
req.Header.Set("Idempotency-Key", idempotencyKey)
req.Header.Set("Content-Type", "application/json")
response, err := (&http.Client{Timeout: 60 * time.Second}).Do(req)Reuse the same Idempotency-Key when retrying one lookup; generate a new value for a new lookup.
Success response
Response fields
| Field | Type | Description |
|---|---|---|
| ip | string | Normalized public IPv4 address |
| score / cleanliness_level | number / string | 0–100 cleanliness score and its level; higher is cleaner |
| ip_type | string | Network type, such as residential, mobile, or datacenter |
| proxy / vpn / tor / hosting | boolean | Proxy, VPN, Tor, and datacenter detection results |
| country / country_code / city | string | null | Consensus geolocation; null when an Anycast address has no unique location |
| asn / organization | string | null | Autonomous system number and network organization |
| checked_at | string | ISO 8601 completion timestamp |
| credits_remaining | number | null | Remaining credits after this request; null for unlimited accounts |
Billing
Each API request that successfully returns a complete result uses one credit. Incomplete checks return a retryable error and do not use a credit.
Web checks, batch lookups, and the API use the same success standard.
Status codes
| HTTP | code | Meaning | Action |
|---|---|---|---|
| 200 | — | Check completed | Read data |
| 400 | invalid_ip / unsupported_ip / invalid_json / invalid_idempotency_key | Invalid request or parameter | Fix the request |
| 401 | invalid_api_key | Invalid API key | Check the key |
| 402 | insufficient_credits | Insufficient credits | Add credits |
| 403 | account_inactive / plan_required | Account or plan unavailable | Check the account |
| 409 | idempotency_request_in_progress / idempotency_key_reused / idempotency_key_conflict | Idempotency key is processing, used, or conflicting | Wait if processing; generate a new value for a new check |
| 413 | payload_too_large | Request body too large | Reduce the request body |
| 429 | rate_limited | Rate limit exceeded | Retry after Retry-After |
| 503 | check_incomplete / engine_busy / engine_recovering / service_restarting / backend_timeout / backend_unavailable / rate_limiter_unavailable / database_error | Check incomplete or service temporarily unavailable | No credit used; retry later |
Usage notes
- For automatic retries, reuse the same Idempotency-Key for one lookup and generate a new value for a new lookup.
- For 429 or retryable errors, retry after Retry-After.
- Keep the API key secure on your server. Share request_id, never the key, when requesting support.
