> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fingerprintiq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# POST /v1/identify

Identify a device and get a stable visitor ID.

## Endpoint

```
POST https://fingerprintiq.com/v1/identify
```

The JavaScript SDK calls this endpoint automatically. You only need to call it directly if you're building a custom SDK or integrating without the official package.

## Request

### Headers

Must be `application/json`.

Your API key. See [Authentication](/api/authentication) for details.

### Body

Object containing all collected client-side signals. Each signal is a `SignalResult` with a `value` and `duration` (collection time in ms). See [Signal Types Reference](/sdk/signals-reference) for the full schema.

Unix timestamp in milliseconds when signal collection began on the client.

The page URL where identification occurred. Used for analytics and domain allowlist verification.

The referring page URL, if available.

Arbitrary key-value metadata to attach to this identification event. Stored with the event and returned via the Server API. Useful for associating a fingerprint with session context (e.g., `{ "page": "checkout", "experiment": "v2" }`).

A string identifier to associate with this event — typically an authenticated user ID, session ID, or order ID. Enables querying all events linked to a specific user via the Server API.

```bash cURL
curl -X POST https://fingerprintiq.com/v1/identify \
  -H "Content-Type: application/json" \
  -H "X-API-Key: fiq_live_your_api_key" \
  -d '{
    "signals": {
      "canvas": { "value": { "hash": "a3f2b1c4...", "isFarbled": false }, "duration": 12.5 },
      "webgl": { "value": { "renderer": "ANGLE (Apple, ANGLE Metal Renderer: Apple M1 Max)", "vendor": "Google Inc. (Apple)" }, "duration": 3.2 },
      "audio": { "value": { "hash": "d4e5f6...", "sampleRate": 44100 }, "duration": 45.0 },
      "navigator": { "value": { "hardwareConcurrency": 8, "platform": "MacIntel", "languages": ["en-US"] }, "duration": 0.1 }
    },
    "timestamp": 1712000000000,
    "url": "https://yoursite.com/checkout",
    "referrer": "https://yoursite.com/"
  }'
```

```javascript SDK (recommended)
import FingerprintIQ from '@fingerprintiq/js';

const fiq = new FingerprintIQ({ apiKey: 'fiq_live_your_api_key' });
const result = await fiq.identify({
  tag: { page: 'checkout' },
  linkedId: 'user_123',
});
// The SDK builds and sends the full payload automatically
```

## Response

```json 200 OK
{
  "requestId": "req_01hns3k6tez83695a6t7",
  "visitorId": "iq_01hns3k6tez83695a6t714s6n1",
  "confidence": 1.0,
  "botProbability": 0.05,
  "suspectScore": 0,
  "visitCount": 3,
  "firstSeenAt": 1712000000000,
  "lastSeenAt": 1712200000000,
  "riskFactors": [],
  "verdicts": {
    "bot": { "result": false, "probability": 0.05 },
    "vpn": { "result": false, "confidence": 0.92 },
    "tor": { "result": false },
    "proxy": { "result": false },
    "incognito": { "result": false },
    "tampering": { "result": false, "anomalyScore": 0 },
    "headless": { "result": false },
    "virtualMachine": { "result": false },
    "devtools": { "result": false },
    "privacyBrowser": { "result": false, "name": null },
    "highActivity": { "result": false },
    "ipBlocklist": { "result": false }
  },
  "ip": "203.0.113.42",
  "ipLocation": { "country": "US", "city": "New York", "region": "NY", "latitude": 40.71, "longitude": -74.01 },
  "timestamp": 1712000003000
}
```

```json 401 Unauthorized
{
  "error": "Invalid or missing API key"
}
```

```json 429 Rate Limited
{
  "error": "Monthly API call limit exceeded",
  "usage": 10001,
  "limit": 10000
}
```

## Response Fields

The identify endpoint returns a **compact response** — verdicts and top-level scores only. Raw signal data (all 41 browser signals plus full edge/server analysis) is available server-side via `GET /v1/events/:requestId`. See the [Events API](/api/events) reference.

**requestId**

Unique identifier for this specific identification event, in the format `req_<ulid>`. Pass this to your backend and use it to retrieve full signal data via the Server API.

**visitorId**

Stable device identifier in the format `iq_<ulid>`. This is the primary output — store it to link future visits to the same device.

**confidence**

Signal confidence score from 0.0 to 1.0. Low values indicate that many signals failed to collect, which may itself indicate a bot or privacy tool. Scores below 0.7 warrant extra scrutiny.

**botProbability**

Bot likelihood score from 0.0 to 1.0. Combines datacenter ASN, headless markers, software renderer, API tampering, and UA/TLS mismatch indicators.

**suspectScore**

Composite risk score from 0 to 100. Higher values indicate more risk signals. Combines bot probability, VPN/proxy detection, incognito mode, tampering, and high-activity flags into a single actionable number.

**visitCount**

Total number of times this device has been identified. A value of 1 means first-time visitor.

**firstSeenAt**

Unix timestamp (milliseconds) of the first identification for this device.

**lastSeenAt**

Unix timestamp (milliseconds) of the most recent identification for this device prior to this event.

**verdicts**

Per-signal boolean verdicts for this visit.

  **verdicts fields**

**verdicts.bot**

`result` (boolean) plus `probability` (0.0–1.0).
    **verdicts.vpn**

`result` (boolean) plus `confidence` (0.0–1.0).
    **verdicts.tor**

`result` (boolean).
    **verdicts.proxy**

`result` (boolean).
    **verdicts.incognito**

`result` (boolean).
    **verdicts.tampering**

`result` (boolean) plus `anomalyScore` (0–100).
    **verdicts.headless**

`result` (boolean).
    **verdicts.virtualMachine**

`result` (boolean).
    **verdicts.devtools**

`result` (boolean).
    **verdicts.privacyBrowser**

`result` (boolean) plus `name` (string or null — e.g., `"Brave"`, `"Tor Browser"`).
    **verdicts.highActivity**

`result` (boolean). True when the device has been seen an unusually high number of times in a short window.
    **verdicts.ipBlocklist**

`result` (boolean). True when the IP is on a known blocklist.

**ip**

The client's IP address as seen by the edge worker.

**ipLocation**

Geolocation derived from the IP address: `country` (ISO 3166-1 alpha-2), `city`, `region`, `latitude`, `longitude`.

**riskFactors**

Active risk indicators for this visit. Possible values include:
  - `HEADLESS_BROWSER` — WebDriver or automation markers detected
  - `SOFTWARE_RENDERER` — SwiftShader or LLVMpipe GPU
  - `TOR_EXIT_NODE` — Traffic from Tor network
  - `DATACENTER_ASN` — Traffic from cloud provider
  - `UA_TLS_MISMATCH` — User-Agent inconsistent with TLS fingerprint
  - `LOW_RTT_COHERENCE` — Geo coherence below 0.3 (likely VPN)

**timestamp**

Unix timestamp (milliseconds) of this specific identification event.

## Error Responses

| Status | Meaning |
|--------|---------|
| `400` | Invalid JSON body or missing required `signals` field |
| `401` | Invalid or missing `X-API-Key` header |
| `429` | Rate limit or monthly quota exceeded |
| `500` | Internal server error — retry with exponential backoff |