Skip to main content
An identification is one check by the snippet, the event layer under your users, devices, visitors and IPs. ShieldLabs scores it asynchronously: the browser snippet collects signals and posts them, and the POST returns an acknowledgment. The server computes the Risk Score (0 to 100) in about 300 ms and delivers it two ways: a webhook push and a History API read. Each identification belongs to one visitor, one device and one public IP, and to one of your users when the page passes a hashed User HID. The request_id ties the three steps together.
You normally do not call rest.shieldlabs.ai yourself. The JS snippet posts to it automatically. Your server-side work is to receive the webhook and, when you need a guaranteed read or the account behind an identification, query the History API.

The three steps

1

Snippet posts signals (browser → rest.shieldlabs.ai)

Load the current snippet from the official CDN. It generates a per-call request ID (a client UUID) and posts collected signals to rest.shieldlabs.ai. The response is an acknowledgment (the client IP as a JSON string), not the Risk Score.
2

Server scores asynchronously (about 300 ms)

The server computes the Risk Score. The webhook carries the breakdown in data.signals as { name, weight } (stable slugs, for example antidetect_browser). History API rows carry the same breakdown in score_details, a JSON string of { Value, Description } entries.
3

The result is delivered (webhook and History API)

The server pushes one final webhook per identification (typically about 300 ms after the check; at most about 10 seconds when follow-up network checks run). You can also read the result any time from the History API by request_id, and every identification of the account by user_hid.

Step 1: The identification POST (acknowledgment, not a Risk Score)

The JS snippet calls ingest for you. Load it from https://cdn.shieldlabs.ai. Do not self-host, mirror, bundle or pin copies of the snippet.
  • {requestID} is a client-generated UUID, unique per identification. It is the join key across the snippet call, the webhook and History.
  • publicKey is your per-domain Public Key. It is safe to expose in the browser.
The ingest response is an acknowledgment, not the result:
The body is the client IP as a JSON string (HTTP 200). It confirms the signals were received and the identification counted. The Visitor ID, Device ID and Risk Score are computed on the server and delivered in Step 3.
This response is a receipt, not the Risk Score; read the result from the webhook or History API.
In the browser, the snippet surfaces the requestID through optional onInitialized, so you can correlate client and server records. The ingest HTTP body stays a receipt and is not copied onto that object.
Within one visit (while a page of your site stays open in the browser, across route changes in a single-page app and across open tabs), checkAnonymous and checkAuthenticatedUser run at most one identification every five minutes for the same user. A call inside that window posts nothing, counts nothing, and its onInitialized handler receives { status: "not_initialized" }. On a multi-page site, a full page load in the only open tab can start a new visit with its own identification. forceCheckAnonymous and forceCheckAuthenticatedUser run an identification every time, keep the current Session ID and restart the five-minute window. The snippet install guide has the full method list and framework examples.

Step 2: Why scoring is asynchronous

Scoring runs on the server after ingest acknowledges the identification and typically takes about 300 ms. When follow-up network checks run, ShieldLabs waits for them for at most about 10 seconds, then delivers one final webhook per identification.

Step 3: Receiving the result

You get the result two ways. Use both: the webhook for low latency, the History API as the guaranteed read.

Webhook (push)

The server POSTs the result to each enabled webhook endpoint once per identification, joined by request_id: The webhook body is a signed snake_case envelope. The signature travels in the X-Shield-Signature header. The example below is shortened; every field is in WebhookEvent.
Verify X-Shield-Signature on the raw request body, keyed with that endpoint’s whsec_… signing secret (not the domain Secret Key). See the verification recipe.
Webhook delivery is at-most-once with no retries (a 1-second send timeout, no backoff, no dead-letter queue). Make your handler idempotent on request_id and use the History API for anything that must not be missed. Full payload and delivery guarantees are in Webhooks; copy-paste verification handlers in Node, Go and Python are in the webhook setup guide.

History API (read)

You can read the scored result for any request ID from the History API. This is the authoritative, pull-based path and the right choice when you cannot risk a dropped webhook.
The response is a { data, total } envelope of identifications, newest first. Search by user_hid to read an account’s identifications, or by device_id, visitor_id, ip, request_id, session_id or cookie_id. History reads never use your included identifications. The full schema is in the Server API reference.

The request ID lifecycle

The request ID is the single value that lets you stitch the asynchronous pieces together:

Snippet call

Minted in the browser as a UUID when the snippet runs. Returned to your page in the onInitialized callback.

Webhook

Echoed back as request_id. One scored POST per identification and endpoint.

History

Queryable as the request_id search type to read the stored identification any time.
Persist the requestID early, record risk_score and signals idempotently when the webhook arrives, and fall back to GET /api/v1/history/request_id/{requestID} on account.shieldlabs.ai if it has not arrived within about 10 seconds. The full reliability pattern, with signature verification, is in Webhooks.

From the identification to the account

Each identification carries the keys of the identities it belongs to: user_hid (your account), device_id, visitor_id, public_ip and local_ip. Pass a hashed User HID with checkAuthenticatedUser on every signed-in page. Users, account-level risk and all four High-Risk Events are built on it. To see an account as a whole, read its identifications from the History API by user_hid. The worst band across them is the account’s risk, and the Device IDs, Visitor IDs and public IPs in those rows are what the account is linked to. Devices, visitors and public IPs read the same way by device_id, visitor_id and ip. High-Risk Events (Multi-accounting, Account sharing, Impossible travel and Account takeover) are detected on your users, each at Medium or High confidence, and are available in the analytics dashboard, the API and webhooks. 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).

What you do with the result

The Risk Score lands in the 0 to 100 range (999 marks a rate-limited identification) and falls into three Risk Score bands: Trusted 0-29, Suspicious 30-59, Dangerous 60-100. The payload carries the number, so map it to a band in your backend. At signup, login, checkout or a payout, read the Risk Score of this identification together with the account behind it. The Risk Score and risk signals of this identification remain the input at that moment. When a High-Risk Event arrives for a user, or when you review it in the analytics dashboard, act on the account. Read a high Risk Score together with its named risk signals (signals on the webhook, score_details on the History API) 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 gives starting policies and worked examples.

Next steps

Webhooks

Full payload, X-Shield-Signature verification, and at-most-once delivery.

Server API

History search, the account read, and the Management API profile.

Users, devices, visitors and IPs

The five identities each identification links to, and the risk each one carries.

Identifiers

User HID, Device ID, Visitor ID, and the per-call request ID, Session ID and Cookie ID.