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

# Record a widget analytics event

> Idempotent on idempotencyKey (or eventId) per org. orgId/agentId in the body must match the verified widget identity when present…

Idempotent on `idempotencyKey` (or `eventId`) per org. `orgId`/`agentId` in the body
must match the verified widget identity when present. Bodies over 64 KB are rejected.
Credential-looking keys (`token`, `apiKey`, `authorization`, ...) are stripped from
`data` before storage. This route accepts the widget token as `token` in the body for
`navigator.sendBeacon` callers and is rate limited in its own bucket.

Widget identity is verified when signing is configured; tokenless compatibility does not establish tenant ownership. See the authentication and recovery guide for credential and retry rules.

### Request body

`WidgetAnalyticsEvent`

**action** `string` *required*

Event name (case-insensitive pattern match).

**sessionId** `string` *required*

Also accepted as `session_id`. Maximum length: `256`.

**idempotencyKey** `string` *required*

Also accepted as `eventId`; the stored event id is derived from it. Maximum length: `512`.

**eventId** `string`

**timestamp** `string (date-time)`

**threadId** `string`

**pageUrl** `string`

**referrer** `string`

**data** `object`

Stored as `metadata` after credential-looking keys are stripped.

**orgId** `string`

**agentId** `string`

**token** `string`

Widget token for `sendBeacon` callers that cannot set headers.

### Response

`object`

**ok** `boolean` *required*

Fixed value: `true`.

**eventId** `string (uuid)` *required*

Deterministic id derived from `orgId` and the idempotency key.

### Status codes

| Code | Meaning |
| - | - |
| `200` | Event stored (or already stored) |
| `400` | Event failed validation |
| `401` | Widget token missing, malformed, expired, from the future, or badly signed |
| `403` | Body identity disagrees with the verified widget identity, or token org/agent mismatch |
| `429` | Too many requests for this IP (scoped by verified org/agent) |
| `500` | Unhandled error |
| `502` | Analytics store rejected the write |
| `503` | Analytics store not configured |

### Using this contract

Read the [source OpenAPI document](https://docs.stateset.com/spec/chat-widget.json) for declared schemas and alternatives.
This page also includes documented corrections from the [spec overlays](https://github.com/stateset/docs/tree/main/spec/overlays).
Example IDs and values are illustrative; replace them with records from your workspace.

```bash cURL theme={null}
curl --silent --show-error --fail-with-body --request POST \
  --url 'https://api.example.com/api/analytics' \
  --header 'x-widget-token: YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
  "action": "string",
  "sessionId": "string",
  "idempotencyKey": "req_01J9X4Q8M2ZK7V3N",
  "eventId": "string",
  "timestamp": "2026-08-31T14:22:05Z",
  "threadId": "string",
  "pageUrl": "string",
  "referrer": "string",
  "data": {},
  "orgId": "string",
  "agentId": "string",
  "token": "YOUR_API_KEY"
}'
```

```json 200 theme={null}
{
  "ok": true,
  "eventId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
```


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