Skip to main content
The ShieldLabs Server API is how your backend reads results. The History API returns identifications: one by its request ID, or every identification of one user, device, visitor, public IP, session or cookie. ShieldLabs scores each identification asynchronously: the JS snippet collects signals, ShieldLabs scores them in about 300 ms, and the result arrives by webhook and is stored for this API to read. Two backend APIs, both server-side only. Never call them from the browser:
  • History API (recommended) on account.shieldlabs.ai. Read identifications by request ID or by the user, device, visitor, public IP, session or cookie they belong to. Free: reads never use your included identifications. Response envelope { data, total } (snake_case).
  • Management API on api.shieldlabs.ai. Read your profile: the remaining included volume on your account and your masked keys. For history, use the History API.
The History API accepts seven search types: user_hid (your account), device_id, visitor_id, ip (public IP), request_id, session_id and cookie_id. Register webhook endpoints in the analytics dashboard under Integration > Webhooks (up to 10 per domain); the setup guide walks through it.

See also

Base URLs

Paths start at the host: join the base URL and the path as they are written below. For development and staging, register a separate domain (for example dev.example.com) and call the same hosts with that domain’s keys. The environments guide walks through it.

Authentication

Each API uses a different backend credential. Both are server-side only; an unauthenticated request returns 401.
All server credentials must stay on your backend. Never put a Private API Key or Secret Key in the browser, the JS snippet, client logs, or a public repository. Webhook endpoints use separate whsec_… signing secrets. The browser-safe credential is the Public Key, which goes in the snippet, not here.

Trying it out

The fastest check: read one scored identification back by its request_id with your Private API Key.
A 200 with a data array (empty is valid) means your key and host are correct. Full endpoint detail follows.
Read stored identifications from your backend with the Private API Key (authentication above). Each key reads the domain it belongs to. Wrong or missing credentials return 401 with a JSON body like {"error":"invalid api key"}.

Endpoints at a glance

For a single identification, query history/request_id/{value} with limit=1 (shown below). For an account, use the recipe that follows.

Read every identification of one account

Your users are the accounts you pass as a hashed User HID with checkAuthenticatedUser. To see how risky an account has been, read its identifications by user_hid, newest first, and page with offset while offset is below total.
This is the paging form of the accountView helper in the shared tutorial helpers, which reads the newest 100 identifications. The worst band across the account’s identifications is the account’s risk, and the distinct Device IDs, Visitor IDs and public IPs are what the account is linked to. An all-zero Device ID (00000000-0000-0000-0000-000000000000) means no usable device signals reached ShieldLabs for that identification; the rate-limit marker (Risk Score 999) is one such case. Route it to review rather than allowing it; the recipe never counts it as a device. Read the same way by device_id, visitor_id or ip to see which accounts share a device, a visitor or an IP (skip rows whose user_hid is anonymous). Each call counts toward the soft limit of 15 requests per second per domain and never uses your included identifications. High-Risk Events on the account are available in the analytics dashboard, the API and webhooks. When one arrives for a user, act on the account; the Risk Score and risk signals of the identification remain the input at signup, login, checkout or withdrawal. The same account, with its band, its High-Risk Events and each linked device, visitor and IP with the band of the identifications it shares with the account, is on the user’s card in the analytics dashboard (User, device, visitor and IP cards).

GET /api/v1/history/{search_type}/{value}

Searches the identifications ShieldLabs has stored for your domain. Returns a paginated envelope, newest first. This is the guaranteed read path when a webhook may have been missed.

Path parameters

string
required
The field to search on. One of:
  • user_hid: the hashed User HID of one of your accounts (free-form string)
  • device_id: a Device ID (UUID)
  • visitor_id: a Visitor ID (UUID)
  • ip: a public IP address (IPv4)
  • request_id: the request ID of one identification (UUID)
  • session_id: a Session ID (UUID), the browsing session
  • cookie_id: a Cookie ID (UUID)
Always send one of the seven types above: an unknown type is not validated and returns the domain’s latest rows unfiltered. Local IPs have no search type; keep local_ip from each webhook to group by it.
string
required
The value to match for the chosen search_type.

Query parameters

integer
default:"20"
Maximum number of rows to return. Must be between 1 and 100; values outside that range fall back to 20. Rows are ordered newest first.
integer
default:"0"
Number of rows to skip for pagination. Page while offset is below total.

Response

The data array holds identifications in snake_case. The score_details field is a JSON string; parse it to get the signal list. Each entry carries a numeric Value (the weight) and a free-text Description; branch on Value and the row score, not on the Description text, which is written for people and can change. Skip entries whose Value is 0: they are diagnostic notes, not risk signals. Field names map to the webhook body (request_id to request_id, score to risk_score, parsed score_details to signals). The example shows the core fields; a full row also carries the connection, network, traffic-attribution and per-signal flag columns:
  • Flags use History names such as is_vpn, is_proxy, is_datacenter, is_antidetect, is_js_disabled, is_browser_automation, is_search_bot and check_incomplete. browser_vpn_proxy and ip_mismatch are on the webhook only.
  • Traffic attribution is flat on the row: traffic_channel, referrer_domain, entry_url, utm_source, utm_medium, utm_campaign, utm_content, utm_term and click_id_type. The webhook nests the same values under traffic_source, where channel is traffic_channel and landing_url is entry_url.
History reads never use your included identifications and never return 402.

Common search patterns

Query by request_id with limit=1 to read one identification. Query by user_hid to read an account before a sensitive action or during a review, and page with offset while offset is below total. Reads never use your included identifications; the History API accepts up to 15 requests per second per domain.

Management API (api.shieldlabs.ai)

The Management API runs on api.shieldlabs.ai. It returns your profile: the domain, the remaining included volume on your account and your masked keys. For identification history, use the History API.

Authentication

Credentials in headers, not in the URL:
Wrong credentials, an unknown domain, or a disabled domain return 401 with an empty body.

Endpoints at a glance

GET /v1/profile

Returns the domain, the remaining included volume on your account and your masked keys. Keys are masked to their last four characters. This call is free.

Response

string
The registered domain this profile belongs to.
integer
The remaining included volume on your account, in identifications, shared by all your domains. Each identification uses 1. When your account’s included volume is used up, the identification request returns HTTP 402 until the billing cycle resets or you change plan; the Billing page has the details. History and profile reads never use it.
string
Legacy field kept for older integrations. Webhook delivery uses the endpoints you register in the analytics dashboard under Integration > Webhooks.
string
Your Public Key, masked to the last four characters. The browser-safe credential that goes in the snippet URL. Read the full value in the analytics dashboard under Integration > API keys.
string
Your Secret Key, masked to the last four characters. Used for this API only. Copy it or replace it with Rotate in the analytics dashboard under Integration > API keys.
string
ISO 8601 UTC timestamp of when the domain was created.

GET /v1/history/{type}/{value}

Deprecated (Sunset 2027-01-01). Do not use this path for new integrations. Read identifications from the History API on account.shieldlabs.ai (GET https://account.shieldlabs.ai/api/v1/history/{search_type}/{value}, { data, total }, Private API Key). This endpoint remains live until sunset and returns Deprecation, Sunset, and Link: rel="successor-version" pointing at that History API URL.
Returns a JSON array of snapshot objects in PascalCase, newest first. Lookup types match the History API (seven identifiers). The call never uses your included identifications and never returns 402.

Path parameters

string
required
The field to search on. One of (same set as the History API):
  • user_hid: the hashed User HID of one of your accounts (free-form string)
  • device_id: a Device ID (UUID validated)
  • visitor_id: a Visitor ID (UUID validated)
  • ip: a public IP address (IPv4 validated)
  • request_id: the request ID of one identification (UUID validated)
  • session_id: a Session ID (UUID validated)
  • cookie_id: a Cookie ID (UUID validated)
Any other value returns 404. A value in the wrong format (for example a non-UUID for device_id) returns 400.
string
required
The value to match for the chosen type. UUID types are UUID validated, ip is IPv4 validated, user_hid is a free string.

Query parameters

integer
default:"100"
Maximum number of rows to return. Capped at 100: a higher value is clamped to 100. Rows are ordered newest first.

The Snapshot object (deprecated Management History)

On api.shieldlabs.ai, the deprecated History path returns identity and score fields in PascalCase, plus network columns captured during scoring. It carries no traffic source or detection flags. New work should parse the History API snake_case envelope instead.
The identity and score fields map across three surfaces. Names differ; do not assume one JSON shape: See Snapshot.
string
Detected browser name, for example Chrome or Safari.
string
Form factor: desktop, mobile, or tablet.
string
The classified connection type, one of direct, mobile, vpn, proxy, tor, privacy_relay, browser_vpn_proxy, or unknown (when the type could not be resolved).
A snapshot also carries optional network fields below. They describe the connection. Keep them on your server.
integer
Optional network attribute on the snapshot. Keep it server-side.
integer
Optional network attribute on the snapshot. Keep it server-side.
string
Optional network attribute on the snapshot (a short label). Keep it server-side.
string
Optional local IP field on the snapshot. Keep it server-side and do not display it to end users.
string
Country associated with that local IP, when present.
string
Connection type associated with that local IP, when present (for example direct).
A snapshot is a point-in-time record of one identification. The stored snapshot reflects the final Risk Score delivered on the webhook.

Reading the result

The Risk Score of one identification is a number from 0 to 100 that falls into three Risk Score bands: Trusted 0-29, Suspicious 30-59, Dangerous 60-100. The row carries the number (score), so map it to a band in your backend, and treat any value above 100 as the 999 rate-limit marker. A user, device, visitor or IP takes the worst band of its identifications, which the account read above computes. Read a high Risk Score together with its named risk signals (score_details, or signals on the webhook) and the user’s history. A real customer on a corporate VPN can reach the Suspicious band; the signals show why, and you choose the action for each case: allow, step up, review or block. The per-band playbook has starting policies and worked examples.

Errors

Error bodies are not uniform across surfaces, so branch on the HTTP status code first.

History API (account.shieldlabs.ai)

Management API (api.shieldlabs.ai)

On the Management API, 401 returns an empty body, and 400 and 404 return a bare JSON string. Only the identification request sent by the snippet returns 402, when your account’s included volume is used up; see Billing. The Errors page is the full reference across every surface.

Next steps

Data Models

The full Snapshot, webhook body, and Score Detail schemas, and the identity each identifier maps to.

Webhooks

The push delivery path: payload, X-Shield-Signature verification, and delivery guarantees.

Identification Flow

How an identification is scored and how the webhook and History API fit together.

API keys

Public Key, Private API Key, Secret Key: where each one belongs, and how to rotate.