Skip to main content

Server API

The Server API is the server-side surface for your domain. Its primary endpoint is the History API, the authoritative, pull-based way to read a Risk Score and the signals behind it when you cannot risk a dropped webhook. The same surface also lets you read your profile and balance and set your webhook callback URL. This API is keyed by your Secret Key and must only be called from your backend. Never call it from the browser.

Base URL and authentication

Every Server API call lives under one base path that carries the credentials in the URL:
https://api.shieldlabs.ai/{domain}:{secret}/
PartValueNotes
{domain}Your registered domain, e.g. myshop.comThe hostname you set up in Domains
{secret}Your per-domain Secret KeyBackend only, minted on the Keys page
The credentials are validated against the domain’s Secret Key and its enabled status. Wrong credentials, an unknown domain, or a disabled domain return 401.
The Secret Key authenticates this API and verifies webhook signatures. Keep it server-side. It must never appear in the browser, the JS snippet, client logs, or a public repository. If it leaks, rotate it from the dashboard. The browser-safe credential is the Public Key, which goes in the snippet, not here.

Endpoints at a glance

MethodPathPurposeCost
GET/{domain}:{secret}/history/{type}/{value}?limit=NRead scored results by identifier (the History API)1 request per returned row (minimum 1)
GET/{domain}:{secret}/profileRead domain config, balance, masked keysFree (0 requests)
POST/{domain}:{secret}/callbackSet the webhook callback URLFree (0 requests)
There is no synchronous “identify” or “score” endpoint here. The score is produced asynchronously: the JS snippet posts signals to rest.shieldlabs.ai, ShieldLabs scores them in about a second, and the result is delivered by webhook and stored for the History API. The Identification Flow walks through that asynchronous path end to end.

GET /profile

Returns your domain’s configuration and current balance. The keys are masked to their last four characters. This call is free: it does not consume requests.
curl "https://api.shieldlabs.ai/myshop.com:YOUR_SECRET/profile"

Response

{
  "Domain":     "myshop.com",
  "Weight":     148230,
  "Callback":   "https://myshop.com/webhooks/shieldlabs",
  "PublicKey":  "•••• a3f8",
  "Secret":     "•••• 9c2d",
  "CreatedAt":  "2026-01-15T09:00:00Z"
}
Domain
string
The registered domain this profile belongs to.
Weight
integer
Your remaining balance, measured in requests. One identification consumes 1 request, and the History API consumes 1 request per returned row. When this reaches 0, scoring and History calls return 402, as the Billing page details.
Callback
string
The webhook URL ShieldLabs posts scored results to. Empty if no callback is set. Update it with POST /callback.
PublicKey
string
Your Public Key, masked to the last four characters. The browser-safe credential that goes in the snippet URL. Read the full value from the dashboard.
Secret
string
Your Secret Key, masked to the last four characters. Used for this API and webhook signature verification. The full value is shown only at creation in the dashboard.
CreatedAt
string
ISO 8601 UTC timestamp of when the domain was created.

POST /callback

Sets (or replaces) the webhook callback URL for the domain. The request body is the URL itself, as plain text (not JSON). This call is free.
curl -X POST "https://api.shieldlabs.ai/myshop.com:YOUR_SECRET/callback" \
  -H "Content-Type: text/plain" \
  --data "https://myshop.com/webhooks/shieldlabs"
callback URL
string
required
The raw HTTPS URL ShieldLabs should POST scored results to. Sent as the plain-text request body, not wrapped in a JSON object. Use a publicly reachable HTTPS endpoint.
After this is set, every identification on the domain delivers an initial webhook and, when a follow-up network check completes, an optional update webhook. Webhook delivery is at-most-once with no retries, so verify the signature, make your handler idempotent on RequestID, and fall back to the History API for anything that must not be missed.
You can also set and manage the callback from the dashboard. The dashboard and this endpoint write the same field. Either is fine.

GET /history/{type}/{value}

Searches the snapshots ShieldLabs has stored for your domain. Returns an array of Snapshot objects, newest first. This is the guaranteed read path for any scored result, the right choice when a webhook may have been missed.
curl "https://api.shieldlabs.ai/myshop.com:YOUR_SECRET/history/request_id/550e8400-e29b-41d4-a716-446655440000?limit=1"

Path parameters

type
string
required
The field to search on. One of:
  • ip: client IP address (IPv4 validated)
  • user_hid: the hashed user id you passed via the snippet (free-form string)
  • visitor_id: a VisitorID (UUID validated)
  • request_id: a single identification’s RequestID (UUID validated)
  • device_id: a DeviceID (UUID validated)
Any other value returns 404. A value in the wrong format (for example a non-UUID for device_id) returns 400.
value
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

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

Common search patterns

# Pull the scored result for a specific check (the guaranteed-read fallback
# when a webhook may have been dropped). Bills 1 request.
curl "https://api.shieldlabs.ai/myshop.com:YOUR_SECRET/history/request_id/550e8400-e29b-41d4-a716-446655440000?limit=1"

Billing

The History API bills 1 request per returned row. An empty result still bills 1 request (the lookup itself). So a search returning 20 snapshots costs 20 requests, and a search returning 0 costs 1. If your balance is insufficient for the result, the call returns 402. Webhooks, dashboard views, and exports are free, with the full cost breakdown on the Billing page.
The 1-request lookup charge is taken before the lookup is validated, so a 400 (malformed value) or 404 (unsupported {type}) still bills 1 request. Only 401 (bad credentials) and 402 (out of requests) cost 0. Send a well-formed {type} and {value} to avoid paying for a rejected call.
To keep reads cheap and predictable, query by request_id with limit=1 when you only need one scored result. Reserve the wider device_id / user_hid / ip searches for investigations, and set limit to the smallest value that answers your question.

The Snapshot object

A snapshot is a single scored identification. The History array returns a superset of the webhook body: the same identity and score fields, plus connection and network detail captured during scoring.
{
  "RequestID":            "550e8400-e29b-41d4-a716-446655440000",
  "SessionID":            "7a1b2c3d-4e5f-6789-abcd-ef0123456789",
  "CookieID":             "3f2e1d0c-9b8a-7654-3210-fedcba987654",
  "DeviceID":             "d290f1ee-6c54-4b01-90e6-d701748f0851",
  "VisitorID":            "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "IP":                   "203.0.113.10",
  "OS":                   "Windows",
  "Browser":              "Chrome",
  "DeviceType":           "desktop",
  "Country":              "US",
  "UserHID":              "e3b0c44298fc1c149afbf4c8996fb924",
  "ConnectionType":       "vpn",
  "Score":                45,
  "Details": [
    { "Value": 30, "Description": "IP Mismatch" },
    { "Value": 15, "Description": "VPN" }
  ],
  "LastRequestTime":      "2026-06-16T10:00:00Z"
}
The identity and score fields (RequestID, SessionID, CookieID, DeviceID, VisitorID, UserHID, IP, OS, Country, Score, Details, LastRequestTime) behave exactly as in the WebhookBody schema. The fields a snapshot adds on top, captured during scoring and useful for forensics and your own correlation logic:
Browser
string
Detected browser name, e.g. Chrome, Safari.
DeviceType
string
Form factor: desktop, mobile, or tablet.
ConnectionType
string
The classified connection type for the IP, one of seven values: direct, mobile, vpn, proxy, tor, privacy_relay, or unknown.
The snapshot may include additional Network Intelligence fields. One is a server-side correlation field for the local-IP entity; keep it server-side and do not display it. The full field-by-field schema for every object lives in Data Models.
A snapshot is a point-in-time record of one identification. The score on a snapshot is the score as computed at that time. If a later update webhook changed the result (after a follow-up network check completes), the stored snapshot reflects the recomputed value.

Reading the score

ShieldLabs scores. Your application decides. The Risk Score is a 0 to 100 number that falls into four Risk Score bands, and your code is the actor for allow, challenge, review, or block. Decide on Score + Details + action context, never the number alone: a legitimate user can score high behind a corporate proxy, a VPN, or a privacy browser. Tune your thresholds gradually, working from the per-band playbook and its worked examples.

Errors

Error bodies on this surface are not uniform, so branch on the HTTP status code, not on a body field. 401 and 402 return an empty body. 400 and 404 return a bare JSON string. The 429 and 503 statuses exist only on the REST ingest and WebRTC gateways, not on the Server API.
StatusMeaningWhat to do
200SuccessParse the response. A History search with a valid {type} that matches nothing returns 200 with [] and still bills 1 request.
400Bad parametersA malformed value, e.g. a non-UUID where a UUID is required. Fix the request.
401Bad credentials or disabled domainCheck {domain}:{secret} and that the domain is enabled.
402Out of requestsBalance exhausted (History needs 1 request per returned row). Top up from the Billing page.
404Unsupported history type{type} must be one of ip, user_hid, visitor_id, request_id, device_id.
500Internal errorTransient. Retry with backoff.
The Errors page is the full reference across every surface.

Next steps

Data Models

The full Snapshot, webhook body, and Score Detail schemas in one place.

Webhooks

The push delivery path: payload, Assing signature verification, and phases.

Identification Flow

How signals become a score and how the webhook and History API fit together.

Keys

Public Key vs Secret Key, where each one belongs, and how to rotate.