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

# List history

> List identifications or users for one domain.

Lists `identifications` or `user` for one domain. `{domain_id}` comes from [Domain](https://docs.shieldlabs.ai/api/history-domain.md). A list of `visitor`, `device`, or `ip` returns `403`. Read those with [Card](https://docs.shieldlabs.ai/api/history-card.md).

```bash theme={null}
curl 'https://account.shieldlabs.ai/api/v1/domains/7c9e6679-7425-40de-944b-e07fc1f90ae7/history/identifications?limit=20' \
  -H "Authorization: Bearer $SHIELDLABS_API_KEY"
```

```json theme={null}
{
  "data": [
    {
      "type": "identification",
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "risk": {
        "state": "ok",
        "band": "suspicious",
        "score": 30
      },
      "signals": {
        "state": "ok",
        "items": ["vpn"]
      }
    }
  ],
  "next_page_token": null
}
```

## Authentication

**Authorization** `string` *required*

`Bearer PRIVATE_API_KEY`. Use the domain's Private API Key.

## Path parameters

**domain\_id** `string` *required*

Public domain id from [Domain](https://docs.shieldlabs.ai/api/history-domain.md).

**resource** `string` *required*

`identifications` or `user`.

A hostname, `all`, an empty id, `.` or `..`, a slash, a backslash, or a control character is rejected.

## Query parameters

**from** `string`

Window start, RFC 3339. Send `from` and `to` together, or omit both. A list defaults to the last 24 hours.

**to** `string`

Window end, RFC 3339.

**snapshot** `string`

Value of the `History-Snapshot` response header. Sending it continues the same read.

**limit** `integer` (default: 20)

Page size, from 1 to 100.

**page\_token** `string`

Continuation from `next_page_token`.

**risk\_bands** `string`

Repeat for `trusted`, `suspicious`, or `dangerous`.

**ids** `string`

User id. Repeat the key. Only on the `user` list, up to 100 values.

**is\_vpn** `boolean`

`true` or `false`. The same form applies to the other published `is_*` flags, `network_check_incomplete`, `check_incomplete`, `ip_mismatch`, `latency_test`, `device_spoofing`, `banned_ip`, `ai_bot`, and `ai_browser`. Several flags combine with AND.

**risk\_signals** `string`

Repeat a public signal code, such as `vpn`. Several codes combine with OR.

**source** `string`

Traffic source. Repeat with `campaign`. At most 8 values together, matched if any value matches. `_empty` means no referrer.

**campaign** `string`

Campaign name. `No campaign` matches visits with no campaign.

**hre\_min\_accounts** `integer` (default: 3)

Minimum linked accounts for a high-risk event, from 3 to 99.

**hre\_min\_devices** `integer` (default: 4)

Minimum linked devices for a high-risk event, from 4 to 99.

A nested `filter`, `chips`, or `offset` returns `400`.

## Response

A list returns `{ "data": [ ... ], "next_page_token": null }`. Successful responses also send `History-Snapshot`, `History-Snapshot-Expires-At`, `History-Window-From`, and `History-Window-To`.

**data** `object[]` *required*

Cards for this page. See [History card](https://docs.shieldlabs.ai/api/models.md#history-card).

**next\_page\_token** `string`

`null` means there is no next page.

## Pagination

List one user's identifications and follow `next_page_token`:

```js theme={null}
async function readAccountHistory(domainId, userHid, maxRows = 500) {
  const rows = [];
  let pageToken = '';
  while (rows.length < maxRows) {
    const url = new URL(
      `/api/v1/domains/${domainId}/history/user`,
      'https://account.shieldlabs.ai',
    );
    url.searchParams.append('ids', userHid);
    url.searchParams.set('limit', String(Math.min(100, maxRows - rows.length)));
    if (pageToken) url.searchParams.set('page_token', pageToken);
    const response = await fetch(url, {
      headers: { Authorization: `Bearer ${process.env.SHIELDLABS_API_KEY}` },
    });
    if (!response.ok) throw new Error(`History API ${response.status}`);
    const page = await response.json();
    rows.push(...page.data);
    pageToken = page.next_page_token || '';
    if (!pageToken || page.data.length === 0) break;
  }
  return { rows, truncated: Boolean(pageToken) };
}
```

The read does not consume identification quota. The History API allows 15 requests per second per domain; back off on `429`.

## Errors

| Status | Code | Meaning |
| - | - | - |
| `400` | `invalid_query` / `invalid_domain_scope` / `invalid_id` | Bad parameter, hostname, or id |
| `401` | auth message | Missing or invalid Private API Key |
| `403` | `domain_scope_not_supported` / `entity_list_disabled` | `all`, or a list of visitor, device, or IP |
| `404` | `unknown_domain` | No such domain |
| `429` | rate limit | Domain request limit reached |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.