# Events API

> Send behavioral events to the Thoth audit ledger with POST /v1/events/batch.

Source: https://docs.atensecurity.com/docs/api-reference/events

The SDKs batch and send events for you. Call this endpoint directly only for a
custom integration or a non-SDK event source. It uses your unified tenant API
base URL; see [Authentication](https://docs.atensecurity.com/docs/api-reference#connection-and-authentication).

## Send a batch of events

**POST** `/v1/events/batch`

Queues behavioral events for ingestion and returns `202 Accepted`. Retention and
signed receipt.

The body is a JSON array of events. An object of the form `{"events": [...]}`
is also accepted for compatibility. Every event in a batch must belong to one
tenant.

Authenticate with a runtime key, or with `X-Thoth-Event-Ingest-Token` when a
dedicated ingest token is configured.

### Event fields

- `tenant_id` (string, required): Your Thoth tenant identifier.
- `session_id` (string, required): Session the event belongs to.
- `user_id` (string, required): User who initiated the agent action.
- `source_type` (string, required):
  `agent_tool_call` for a tool call through an SDK, or `agent_llm_invocation` for
  a model completion inside an agent.
- `event_type` (string, required):
  `TOOL_CALL_PRE` (before a tool runs, after the policy check passes),
  `TOOL_CALL_POST` (after it returns), `TOOL_CALL_BLOCK` (enforcement refused the
  call) or `LLM_INVOCATION` (a model completion).
- `approved_scope` (string[], required): Tool names the agent is intended to use in this session.
- `session_tool_calls` (string[], required): Tool names already called in this session.
- `enforcement_mode` (string, required): `observe`, `progressive`, `step_up` or `block`.
- `content` (string, required): JSON-serialized arguments (`TOOL_CALL_PRE`) or result (`TOOL_CALL_POST`).
- `occurred_at` (string (ISO 8601), required): When the event happened.
- `event_id` (string):
  Unique event ID; a UUID v4 is recommended. If omitted, the server derives a
  stable hash-based ID. Keep IDs stable across retries.
- `agent_id` (string): Agent identifier.
- `tool_name` (string): Tool being called, when applicable.
- `metadata` (object):
  Key-value pairs for your own use. For token-spend analytics on
  `LLM_INVOCATION` events, include `prompt_tokens`, `completion_tokens`,
  `total_tokens`, `provider` and `model_name`. camelCase aliases such as
  `promptTokens` are normalized.

### Returns

- `status` (string): `"accepted"` on success.
- `queued` (string): Number of events queued for ingestion.
- `replay_dropped` (string): Events dropped by replay and duplicate protection in this request. Omitted when the batch is empty.

A malformed body or event returns `400` with a `detail` message naming the
problem, for example the index of an event missing `tenant_id`.

### Batching and retries

Send up to 100 events per request. Ingestion is best effort: `queued` reports
how many events were forwarded. Duplicates within a request are removed, and
short-window replays are dropped when replay protection is enabled, so retry a
failed batch with the same `event_id` values.

```bash title="Request"
curl -X POST "$THOTH_API_URL/v1/events/batch" \
  -H "X-API-Key: $THOTH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "event_id": "550e8400-e29b-41d4-a716-446655440000",
      "tenant_id": "acme-corp",
      "agent_id": "invoice-processor-v2",
      "session_id": "550e8400-e29b-41d4-a716-446655440001",
      "user_id": "user-123",
      "source_type": "agent_tool_call",
      "event_type": "TOOL_CALL_PRE",
      "tool_name": "search_docs",
      "approved_scope": ["search_docs", "read_invoice"],
      "enforcement_mode": "progressive",
      "session_tool_calls": [],
      "content": "{\"query\": \"invoice INV-001\"}",
      "metadata": { "request_id": "req-abc123" },
      "occurred_at": "2026-03-13T10:00:00.000Z"
    }
  ]'
```

#### Responses

**Accepted**

```json title="202 Accepted"
{
  "status": "accepted",
  "queued": "1",
  "replay_dropped": "0"
}
```

**Invalid event**

```json title="400 Bad Request"
{
  "detail": "Invalid event at index 0: missing tenant_id"
}
```

Values are illustrative. Replace the tenant, agent and session values with your own.
