openapi: 3.2.0 info: title: ShieldLabs API version: '1.2' description: "The ShieldLabs API surfaces visitor identification, anonymity detection, and\nabuse and fraud prevention for your application.\n\nThere are three surfaces:\n\n- The **JS snippet** posts collected signals to `rest.shieldlabs.ai` automatically.\n You do not call this endpoint yourself. See [Install the snippet](/setup/snippet).\n- **Webhooks** deliver the Risk Score and signals to your server shortly after a\n visit. See [Webhooks](/api/webhooks). Contract: schema_version `2026-06-01`\n (`identification.scored` / `webhook.ping`), signature in `X-Shield-Signature`.\n- The **Server API** has two backend hosts:\n - **History API** (recommended) on `account.shieldlabs.ai/api`.\n Private API Key (`Authorization: Bearer sec_…`).\n Envelope `{ data, total }`. See [Server API](/api/server-api).\n - **Management API** on `api.shieldlabs.ai`.\n Secret Key in headers (`X-Shield-Domain` + `Authorization: Bearer`).\n Profile and balance (Secret Key). Snapshot history: use History API.\n\nThe Risk Score is an integer from 0 to 100. ShieldLabs scores visits; your own\ncode decides whether to allow, challenge, review, or block.\n" contact: email: support@shieldlabs.ai servers: - url: https://account.shieldlabs.ai/api description: History API (Private API Key, recommended for snapshot reads) - url: https://api.shieldlabs.ai description: Management API (Secret Key — profile and balance) tags: - name: ShieldLabs API paths: {} webhooks: identificationScored: post: summary: identification.scored delivered description: 'ShieldLabs POSTs a signed JSON envelope to your configured webhook endpoint after a visit is scored. One delivery per check (at-most-once, no retries). Verify `X-Shield-Signature: sha256=` (HMAC-SHA256 over the raw body with your endpoint secret). Treat `data.request_id` as an idempotency key. Schema version is `2026-06-01` (`schema_version` field). Ping/test deliveries use `event_type: webhook.ping` with no `data`. ' parameters: - name: X-Shield-Signature in: header required: true description: 'HMAC-SHA256 of the raw request body, hex-encoded, prefixed with `sha256=`. Example: `sha256=9f1c2b3a…`. ' schema: type: string - name: Content-Type in: header required: true schema: type: string enum: - application/json requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/WebhookEvent' examples: scored: summary: identification.scored value: event_type: identification.scored schema_version: '2026-06-01' created_at: '2026-06-26T14:20:42Z' data: request_id: 13f84f05-7c2a-4e9b-9f1d-2a6b8c0e4d11 visitor_id: 161dfbad-8e7f-4a6b-9c5d-0e1f2a3b4c5d device_id: 5eb7fd5c-2a1b-4c3d-9e8f-7a6b5c4d3e2f session_id: 7a1b2c3d-4e5f-6789-abcd-ef0123456789 cookie_id: 3f2e1d0c-9b8a-7654-3210-fedcba987654 user_hid: null domain: example.com public_ip: ip: 203.0.113.42 country: US local_ip: ip: 198.51.100.23 country: DE connection_type: proxy os: Windows browser: Chrome device_type: desktop traffic_source: channel: Google Ads referrer_domain: google.com landing_url: https://example.com/lp?gclid=abc123 click_id_type: gclid utm_source: google utm_medium: cpc utm_campaign: summer_sale utm_content: ad_a utm_term: buy shoes risk_score: 30 signals: - name: proxy weight: 10 - name: datacenter_ip weight: 10 - name: abuser weight: 10 detection_flags: vpn: false privacy_relay: false browser_vpn_proxy: false tor: false proxy: true datacenter_ip: true abuser: true os_mismatch: false os_not_detected: false timezone_mismatch: false anti_detect_browser: false browser_automation: false ip_mismatch: true incognito: false search_bot: false suspicious_paid_click: false javascript_disabled: false stun_not_checked: false observed_at: '2026-06-26T14:20:42Z' ping: summary: webhook.ping value: event_type: webhook.ping schema_version: '2026-06-01' created_at: '2026-06-26T14:20:42Z' responses: '200': description: Acknowledged. Return 200 quickly. tags: - ShieldLabs API components: schemas: WebhookTrafficSource: type: object properties: channel: type: string referrer_domain: type: string landing_url: type: string click_id_type: type: string utm_source: type: string utm_medium: type: string utm_campaign: type: string utm_content: type: string utm_term: type: string WebhookSignal: type: object required: - name - weight properties: name: type: string description: Stable signal slug (e.g. proxy, vpn, datacenter_ip). weight: type: integer description: Points contributed to risk_score. Entries with weight 0 are omitted. WebhookDetectionFlags: type: object description: Detection flag booleans on the webhook payload. properties: vpn: type: boolean privacy_relay: type: boolean browser_vpn_proxy: type: boolean tor: type: boolean proxy: type: boolean datacenter_ip: type: boolean abuser: type: boolean os_mismatch: type: boolean os_not_detected: type: boolean timezone_mismatch: type: boolean anti_detect_browser: type: boolean browser_automation: type: boolean ip_mismatch: type: boolean incognito: type: boolean search_bot: type: boolean suspicious_paid_click: type: boolean javascript_disabled: type: boolean stun_not_checked: type: boolean WebhookIPAddress: type: object properties: ip: type: string country: type: string WebhookScoredData: type: object description: Payload inside identification.scored. required: - request_id - visitor_id - device_id - risk_score - signals - detection_flags - observed_at properties: request_id: type: string format: uuid description: Unique per visit. Use as an idempotency key. visitor_id: type: string format: uuid device_id: type: string format: uuid session_id: type: string format: uuid cookie_id: type: string format: uuid user_hid: type: - string - 'null' description: Your hashed user identifier, if provided; null when empty. domain: type: string public_ip: $ref: '#/components/schemas/WebhookIPAddress' local_ip: $ref: '#/components/schemas/WebhookIPAddress' connection_type: type: string description: Observed connection class; new values may appear. enum: - direct - mobile - vpn - proxy - tor - privacy_relay - browser_vpn_proxy - unknown os: type: string browser: type: string device_type: type: string traffic_source: $ref: '#/components/schemas/WebhookTrafficSource' risk_score: type: integer minimum: 0 maximum: 100 signals: type: array items: $ref: '#/components/schemas/WebhookSignal' detection_flags: $ref: '#/components/schemas/WebhookDetectionFlags' observed_at: type: string format: date-time WebhookEvent: type: object description: 'Webhook POST body envelope. Signature is NOT in the body — verify the X-Shield-Signature header. ' required: - event_type - schema_version - created_at properties: event_type: type: string enum: - identification.scored - webhook.ping schema_version: type: string const: '2026-06-01' created_at: type: string format: date-time data: $ref: '#/components/schemas/WebhookScoredData' description: Present for identification.scored; omitted for webhook.ping. securitySchemes: PrivateApiKey: type: http scheme: bearer description: Private API Key from the dashboard API tab (`sec_…`). SecretKeyHeader: type: http scheme: bearer description: Secret Key plus `X-Shield-Domain` header with your registered domain.