Events
Ingest telemetry events from your AI agent into Trenchcoat.
POST /api/v1/events
Ingest a batch of telemetry events. This is the primary write endpoint, used by the Trenchcoat plugin.
Required scope: read:sessions — the lowest capture level. Scopes describe what Trenchcoat records, not what a request may do, so any key can ingest; the level decides what survives ingestion. See Authentication.
Batch limit: 1 to 1000 events per request.
Rate limit tier: Ingestion.
Request
curl -X POST https://app.trenchcoat.io/api/v1/events \
-H "X-API-Key: ct_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" \
-H "Content-Type: application/json" \
-d '{
"events": [
{
"ts": "2026-01-15T10:30:00.000Z",
"event": "session_start",
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"seq": 0,
"data": { "cwd": "/Users/alice/projects/my-app" }
},
{
"ts": "2026-01-15T10:30:15.220Z",
"event": "tool_use",
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"seq": 1,
"data": {
"tool_name": "Read",
"input_preview": "/src/components/dashboard/Sidebar.tsx"
}
}
]
}'Request body
A JSON object with a single events array.
| Field | Type | Required | Description |
|---|---|---|---|
ts | string | Yes | ISO 8601 timestamp with an offset (e.g. 2026-01-15T10:30:00.000Z). A bare local timestamp is rejected. |
event | string | Yes | One of the values below. |
session_id | string | Yes | Any non-empty string. Not required to be a UUID. |
seq | integer | Yes | Non-negative counter ordering events within a session. |
data | object | No | Event-specific payload. Defaults to {}. |
Every field except data is required — seq in particular is easy to miss, and omitting it fails validation for the whole batch.
Event types
| Value | When it fires |
|---|---|
session_start | A session begins |
session_end | A session ends |
prompt_submit | The user submits a prompt |
tool_use | A tool is invoked |
tool_result | A tool returns |
skill_use | A Skill is invoked |
assistant_stop | The assistant finishes a turn |
subagent_start | A subagent begins |
subagent_stop | A subagent finishes |
pre_compact | Context is about to be compacted |
error | An error is recorded |
Any other value fails validation. Because the schema validates the array as a whole, one unrecognized event rejects the entire batch — including the valid events alongside it.
If you are reading the plugin's local JSONL files, note that four of these have different names on disk (tool_start, tool_end, prompt, stop). See Event Schema for the mapping and the data payload of each type.
Events sharing a session_id are grouped into one session. The session_start event creates the session record; later events attach to it.
Responses
Success — 201
{
"data": { "inserted": 42 },
"meta": {
"requestId": "req_msdf3l4f_lmjnos",
"timestamp": "2026-01-15T10:30:00.000Z"
}
}inserted is the number of rows written. Ingestion is all-or-nothing per request: a batch that passes validation is written in full, so there is no per-event rejection count.
Validation error — 400
Returned when the body is malformed or a field is missing or wrongly typed.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request body is invalid."
}
}The entire request is rejected. Common causes:
tswithout a timezone offset- a missing
seq - an
eventvalue not in the list above - an empty
eventsarray — at least one event is required - more than 1000 events in one request
Unauthorized — 401
The X-API-Key header is missing, or the key does not exist or has been revoked. Retrying will not help; issue a new key.
Rate limited — 429
Too many requests in the current window. The response carries a Retry-After header.