curl 'https://account.shieldlabs.ai/api/v1/history/identification_id/550e8400-e29b-41d4-a716-446655440000?limit=1' \
-H "Authorization: Bearer $SHIELDLABS_API_KEY"
{
"data": [{
"identification_id": "550e8400-e29b-41d4-a716-446655440000",
"device_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"visitor_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"user_hid": "example-account-token",
"domain": "example.com",
"ip": "203.0.113.10",
"country": "US",
"os": "Windows",
"browser": "Chrome",
"device_type": "desktop",
"connection_type": "vpn",
"score": 30,
"is_vpn": true,
"created_at": "2026-10-13 10:00:00"
}],
"total": 1
}
Get the result
Search identification history
Retrieve stored identifications by identifier with pagination and domain-scoped authentication.
GET
/
api
/
v1
/
history
/
{search_type}
/
{value}
curl 'https://account.shieldlabs.ai/api/v1/history/identification_id/550e8400-e29b-41d4-a716-446655440000?limit=1' \
-H "Authorization: Bearer $SHIELDLABS_API_KEY"
{
"data": [{
"identification_id": "550e8400-e29b-41d4-a716-446655440000",
"device_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"visitor_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"user_hid": "example-account-token",
"domain": "example.com",
"ip": "203.0.113.10",
"country": "US",
"os": "Windows",
"browser": "Chrome",
"device_type": "desktop",
"connection_type": "vpn",
"score": 30,
"is_vpn": true,
"created_at": "2026-10-13 10:00:00"
}],
"total": 1
}
Search identifications by Identification ID, user, device, visitor, session, cookie or IPv4 address. Results are scoped to the domain of your Private API Key.
An empty
Unsupported search types return 400. Empty values,
Invalid, empty or repeated pagination parameters return 400, including a limit outside 1–100.
History and webhooks have different field names:
History rows include identity, score, selected
The example deliberately caps the read and reports truncation. New identifications can arrive during offset pagination; use
A
curl 'https://account.shieldlabs.ai/api/v1/history/identification_id/550e8400-e29b-41d4-a716-446655440000?limit=1' \
-H "Authorization: Bearer $SHIELDLABS_API_KEY"
{
"data": [{
"identification_id": "550e8400-e29b-41d4-a716-446655440000",
"device_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"visitor_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"user_hid": "example-account-token",
"domain": "example.com",
"ip": "203.0.113.10",
"country": "US",
"os": "Windows",
"browser": "Chrome",
"device_type": "desktop",
"connection_type": "vpn",
"score": 30,
"is_vpn": true,
"created_at": "2026-10-13 10:00:00"
}],
"total": 1
}
Authentication
string
required
Bearer PRIVATE_API_KEY. Use the domain’s Private API Key, not its browser Public Key or Management Secret Key.data array is valid: no matching result is stored yet, or none matches in this domain. For a new Identification ID, use a bounded retry or an SDK retrieval helper. Handle an unavailable result explicitly.
Path parameters
string
required
One of
identification_id, user_hid, device_id, visitor_id, ip, session_id or cookie_id.string
required
The identifier to match, URL-encoded once.
ip accepts IPv4 addresses.. or .., slashes, backslashes, control characters and values longer than 1,024 bytes are rejected. Local IPs have no search type.
Query parameters
integer
default:"20"
Number of rows to return, from 1 to 100.
integer
default:"0"
Non-negative number of matching rows to skip.
Response
The endpoint returns a JSON object. The example shows a shortened History row.object[]
required
Matching identifications, newest first. An empty array is valid. See History row fields.
integer
required
Total matches for this identifier and domain, before pagination.
| History | Scored webhook data |
|---|---|
score | risk_score |
ip, country | public_ip.ip, public_ip.country |
is_vpn, is_proxy, is_antidetect | detection_flags.vpn, .proxy, .anti_detect_browser |
traffic_channel, entry_url | traffic_source.channel, .landing_url |
created_at | observed_at |
is_* flags and optional traffic-attribution fields. They do not expose the full webhook flag catalog. Server SDKs can normalize either operating-system mismatch result into detection_flags.os_mismatch. Use webhook signals for the weighted explanation of a new check.
Pagination
Search by the pseudonymous User HID and page withoffset:
async function readAccountHistory(userHid, maxRows = 500) {
const rows = [];
let total = 0;
while (rows.length < maxRows) {
const limit = Math.min(100, maxRows - rows.length);
const url = new URL(
`/api/v1/history/user_hid/${encodeURIComponent(userHid)}`,
'https://account.shieldlabs.ai',
);
url.searchParams.set('limit', String(limit));
url.searchParams.set('offset', String(rows.length));
const response = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.SHIELDLABS_API_KEY}` },
});
if (!response.ok) throw new Error(`History API ${response.status}`);
const page = await response.json();
total = page.total;
rows.push(...page.data);
if (page.data.length === 0 || rows.length >= total) break;
}
return { rows, total, truncated: rows.length < total };
}
identification_id to deduplicate rows if you save them. Treat a maximum score over these rows as a summary of the retrieved sample, not the analytics dashboard’s current identity category.
History reads do not consume identification quota. The History endpoint allows 15 requests per second per domain; back off on 429. It retrieves individual checks, not a replay of multi-account group changes.
Errors
| Status | Code or body | Meaning |
|---|---|---|
400 | code: "invalid_request" | Unsupported search type, malformed identifier or invalid pagination |
401 | error message | Missing or invalid Private API Key, or disabled domain |
429 | Rate-limit response | Domain request limit reached; retry with bounded backoff |
500 | code: "internal_error", or authentication error | History or authentication lookup failed |
200 response with an empty data array is not an API error. Do not assume that every error body includes code. Authentication middleware can return JSON text with a non-JSON content type.