Skip to content

Events

This page documents the Events endpoints in the Event History API microservice.

The Event History service is used to store and retrieve historical activity for a client environment. During client creation in the main Autologyx system, a client-specific ClickHouse database is created for history data, and a corresponding tenant entry is created in the default ClickHouse database. The tenant entry is used to resolve the correct client database from the client_id.

WARNING

This section documents technical and service-level Event History APIs and is intended for internal platform use and controlled engineering workflows. It should not be treated as part of the main general-purpose external Catalyst integration surface. This area is outside general support coverage, so please contact your Customer Success team if you need guidance.

API overview

This page covers the following endpoints:

  • POST /api/event-bridge/create-event
  • POST /api/system-events/batch
  • GET /api/history/events
  • GET /api/history/events/event_id/file

POST /api/event-bridge/create-event

Creates a History Event record in ClickHouse through the AWS EventBridge → Lambda → Event History API flow.

Permissions

Requires authentication.

Request

Headers

text
Request Method: POST
Content-Type: application/json
X-API-Key: API_KEY

Body schema

json
{
  "version": "string",
  "id": "string",
  "detail-type": "string",
  "source": "string",
  "account": "string",
  "time": "2022-11-10T10:26:12.111Z",
  "region": "string",
  "resources": [],
  "detail": {
    "event_id": "string",
    "event_time": "2022-11-10T10:26:12.111Z",
    "event_type_id": 1,
    "record_id": 0,
    "source_id": 0,
    "source_type_id": 0,
    "event_data": [
      "string"
    ]
  }
}

Response

Success

  • Status: 201 Created
json
{
  "detail": "<string>"
}

Filtering

No filters are supported.

Errors

ErrorResponse codeMessage
Tenant not found400 Bad Request"detail": "'{tenant}' tenant not found in database."
Wrong API key401 Unauthorized"detail": "Unauthorized API Key."
Missing authorization header401 Unauthorized"detail": "Unauthorized API Key."

POST /api/system-events/batch

Overview

Inserts a batch of System Events into the tenant-specific system_events table in ClickHouse.

Intended producers are internal platform services that emit lifecycle, authentication, or configuration events (for example the Catalyst backend or the auth service) and need a high-throughput, idempotent write path. Records are routed to the per-tenant ClickHouse database resolved from the X-Client-Id header, and persisted to the system_events table in that database.

Authentication

Both headers are required.

HeaderNotes
X-API-KeyService API key. Same key shape as the rest of the Event History API.
X-Client-IdTenant identifier (UUID v4). Used to resolve the destination ClickHouse database.

Request

Headers

text
Request Method: POST
Content-Type: application/json
X-API-Key: API_KEY
X-Client-Id: client_id

Body schema

json
{
  "events": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "event_timestamp": "2026-06-19T10:00:00.000000Z",
      "category": 1,
      "event_type": 1,
      "source_id": 42,
      "source_type": 1,
      "source_info": "browser",
      "source_ip": "1.2.3.4",
      "event_data": "{\"auth_type\": \"PW\"}"
    }
  ]
}

Event fields

KeyTypeRequiredDefaultNotes
iduuidYesEvent identifier. Idempotency key — see Idempotency contract.
event_timestampdatetimeYesISO 8601 UTC timestamp with microsecond precision.
categoryenum (int)YesEvent category. See Category values.
event_typeenum (int)YesEvent type within the category. See Event type values.
source_idintNo0Identifier of the source entity (e.g. user ID).
source_typeenum (int)No0Source type. See Source type values.
source_infostringNo""Free-form metadata about the source (e.g. user agent label).
source_ipstringNo""Origin IP address.
event_datastringNo""JSON-encoded event payload. Schema is event-specific and is stored as a raw string.
Category values

Defined by the backend EventCategories enum.

ValueNameDescription
1authAuthentication-related events.
Event type values

Defined by the backend SystemEventTypes enum. Values are scoped by category — currently all defined event types belong to category = 1 (auth).

ValueNameDescription
1login_successSuccessful login.
2login_failedLogin failed (generic).
3login_failed_ssoLogin via SSO failed.
4login_failed_inactive_accountLogin rejected because the account is inactive.
5login_failed_invalid_auth_methodLogin rejected because the auth method is not allowed for the account.
6account_lockedAccount was locked (e.g. after repeated failed logins).
7password_reset_request_successPassword reset request submitted successfully.
8password_reset_request_failedPassword reset request failed.
9password_reset_successPassword reset completed successfully.
10password_reset_failedPassword reset attempt failed.
Source type values

Defined by the backend SourceTypes enum (shared with the History Events API).

ValueNameDescription
1userEvent originated from a user action.
2sequenceEvent originated from an automated sequence.
3systemEvent originated from the platform itself.
4mcpEvent originated from an MCP integration.

Response

Success

  • Status: 201 Created
json
{
  "inserted": 1
}
KeyTypeNotes
insertedintNumber of rows actually written to system_events after deduplication. May be lower than the batch size if some ids were duplicates within the batch or already present in the table.

Idempotency contract

The endpoint provides at-most-once write semantics keyed by id:

  • Intra-batch dedup — If the same id appears more than once in a single request, only the first occurrence is written; the rest are skipped silently.
  • Cross-batch dedup — If an id is already present in the system_events table, the incoming row is skipped silently.
  • Reported count — The inserted value reflects rows actually persisted after both dedup steps.

ClickHouse MergeTree caveat

Deduplication is enforced on the write path by checking id against the bloom filter index and the table. ClickHouse MergeTree does not enforce primary key uniqueness on its own, so producers must not rely on the database to reject duplicates outside of this endpoint — any direct INSERT bypassing this API can introduce duplicate ids.

Limits

LimitDefaultConfiguration
Maximum events per request10000SYSTEM_EVENTS_BATCH_MAX_SIZE environment variable.

Requests containing more than the configured maximum are rejected with 422 Unprocessable Entity.

Errors

ErrorResponse codeMessage
Wrong API key401 Unauthorized"detail": "Unauthorized API Key."
Missing authorization header401 Unauthorized"detail": "Unauthorized API Key."
Tenant not found400 Bad Request"detail": "'{tenant}' tenant not found in database."
Client ID header is missing400 Bad Request"detail": "Unauthorized Client."
Client from header does not match any tenant400 Bad Request"detail": "Failed to connect to tenant db."
Malformed JSON body400 Bad Request"detail": "Invalid JSON body."
Batch exceeds size limit422 Unprocessable Entity{"detail": [{"loc": ["body", "events"], "msg": "ensure this value has at most 10000 items", "type": "value_error.list.max_items", "ctx": {"limit_value": 10000}}]}
Missing required field on an event422 Unprocessable Entity{"detail": [{"loc": ["body", "events", 0, "id"], "msg": "field required", "type": "value_error.missing"}]}
Invalid id (not a UUID)422 Unprocessable Entity{"detail": [{"loc": ["body", "events", 0, "id"], "msg": "value is not a valid uuid", "type": "type_error.uuid"}]}
Invalid event_timestamp format422 Unprocessable Entity{"detail": [{"loc": ["body", "events", 0, "event_timestamp"], "msg": "invalid datetime format", "type": "value_error.datetime"}]}
Invalid category / event_type / source_type value422 Unprocessable Entity{"detail": [{"loc": ["body", "events", 0, "category"], "msg": "value is not a valid enumeration member", "type": "type_error.enum"}]}
ClickHouse write failure after retries500 Internal Server Error"detail": "Failed to persist system events."
Upstream ClickHouse unavailable503 Service Unavailable"detail": "ClickHouse temporarily unavailable."

Example

Request

bash
curl -X POST https://<host>/api/system-events/batch \
  -H "Content-Type: application/json" \
  -H "X-API-Key: API_KEY" \
  -H "X-Client-Id: 1a2b3c4d-5e6f-4a8b-9c0d-1e2f3a4b5c6d" \
  -d '{
    "events": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "event_timestamp": "2026-06-19T10:00:00.000000Z",
        "category": 1,
        "event_type": 1,
        "source_id": 42,
        "source_type": 1,
        "source_info": "browser",
        "source_ip": "1.2.3.4",
        "event_data": "{\"auth_type\": \"PW\"}"
      }
    ]
  }'

Response

  • Status: 201 Created
json
{
  "inserted": 1
}

Operational notes

  • Bloom filter index on id — The system_events table carries a bloom filter secondary index on the id column to keep the cross-batch dedup lookup cheap. Producers should treat id as a stable, high-entropy UUID v4 so the filter retains its selectivity.
  • async_insert enabled — Writes use ClickHouse async_insert, so the 201 response is returned once the batch is accepted into the server-side buffer, not once it is fully merged into the part. Reads issued immediately after a successful write may not see the new rows until the buffer flushes.
  • Retry on ServerError — The endpoint retries transient ClickHouse ServerError responses up to 5 attempts with exponential backoff before surfacing a 500 / 503 to the caller. Idempotency by id makes these retries safe.

GET /api/history/events

Returns a paginated list of History Events based on query parameters.

Permissions

Requires authentication and client_id in the request header.
client_id must be a UUID v4 value.

Request

Headers

text
Request Method: GET
Content-Type: application/json
X-API-Key: API_KEY
X-Client-Id: client_id

Response

Top-level response

KeyTypeNotes
limitintPage size
offsetintPage offset
total_countintTotal number of history events visible to the API client
filtered_countintNumber of events returned after filters are applied
resultsArrayEvent records

results array fields

KeyTypeNotes
event_iduuidEvent identifier
event_datetimedatetimeEvent timestamp
event_typeenumValues include record_created, owner_initialized, owners_added, owners_removed, assignees_added, assignees_removed, field_values_changed, record_deleted, document_generated, status_initialized
event_datajsonSchema depends on event_type
source_typeenumValues: user, sequence, system, mcp
source_idintSource identifier
source_namestringSource display name. For source_type: mcp, resolved from the users table by source_id. Returns null if the source_id does not exist in the users table.
source_infostringAdditional information about the event source. For MCP events, contains the AI model identifier (e.g. "claude-code 2.1.158"). Returns "" for all other event types.

results.event_data by event type

The structure of event_data depends on the event_type.

owner_initialized, owners_added, owners_removed

Returns an array of owner objects.

KeyTypeNotes
idintUser ID
typeenumValue: user
namestringUser label
json
[
  {
    "id": 9768,
    "type": "user",
    "name": "John Smith"
  }
]

assignees_added, assignees_removed

Returns an array of assignee objects.

KeyTypeNotes
idintUser ID
typeenumValue: user
namestringUser label
permission_setObjectPermission Set object
permission_set
KeyTypeNotes
idintPermission Set ID
namestringPermission Set label
json
[
  {
    "id": 9768,
    "type": "user",
    "name": "John Smith",
    "permission_set": {
      "id": 35,
      "name": "PermSet"
    }
  }
]

field_values_changed, record_created

Returns an array of field-value objects.

KeyTypeNotes
field_idintField ID
field_typeenumField type
field_valueAnyAny JSON-compatible field value
field_namestringField label
json
[
  {
    "field_id": 9768,
    "field_type": "string",
    "field_value": "Value",
    "field_name": "Car"
  }
]

record_deleted

Returns an empty array.

json
[]

document_generated

The source page indicates this event contains document-related payload data. A representative example is:

json
[
  {
    "document_template_id": 123,
    "field_id": 12,
    "file_id": "1a2b3c4d-5e6f-7g8h-9i0j-1k2l3m4n5o6p"
  }
]

Response examples

Example: record_deleted

  • Status: 200 OK
json
{
  "limit": 1,
  "offset": 0,
  "filtered_count": 2,
  "total_count": 4,
  "results": [
    {
      "event_id": "6e165f4b-8729-487c-93eb-7bf3445554e9",
      "event_datetime": "2021-10-27T12:27:43.462803+00:00",
      "event_type": "record_deleted",
      "source_type": "mcp",
      "source_id": 6,
      "source_name": null,
      "source_info": "claude-code 2.1.158",
      "event_data": []
    }
  ]
}

Example: document_generated

  • Status: 200 OK
json
{
  "limit": 1,
  "offset": 0,
  "filtered_count": 2,
  "total_count": 4,
  "results": [
    {
      "event_id": "6e165f4b-8729-487c-93eb-7bf3445554e9",
      "event_datetime": "2021-10-27T12:27:43.462803+00:00",
      "event_type": "document_generated",
      "event_data": [
        {
          "document_template_id": 123,
          "field_id": 12,
          "file_id": "1a2b3c4d-5e6f-7g8h-9i0j-1k2l3m4n5o6p"
        }
      ],
      "source_type": "user",
      "source_id": 1
    }
  ]
}

Sorting

Sorting cannot be controlled through the request.

Results are returned in descending order by event_datetime. No other sorting is supported.

Notes:

  1. record_created is the first event in chronological order, so it is sorted at the end of the descending result set.
  2. owner_initialized immediately follows record_created in chronological order.

Filtering

For the full description of standard predicates, see ALX API standards - Developers guide.

ParameterExample
event_datetime/api/history/events?event_datetime=2022-01-01
event_datetime!/api/history/events?event_datetime__exclude=2022-01-01
event_datetime_gt/api/history/events?event_datetime__gt=2022-01-01
event_datetime_gt!/api/history/events?event_datetime__gt__exclude=2022-01-01
event_datetime_gte/api/history/events?event_datetime__gte=2022-01-01
event_datetime_gte!/api/history/events?event_datetime__gte__exclude=2022-01-01
event_datetime_range/api/history/events?event_datetime__range=2022-01-01,2022-02-01
event_datetime_range!/api/history/events?event_datetime__range__exclude=2022-01-01,2022-02-01
record_id/api/history/events?record_id=1
source_type/api/history/events?source_type=user
source_type!/api/history/events?source_type__exclude=sequence
source_type__in/api/history/events?source_type__in=system,user
source_type__in!/api/history/events?source_type__in__exclude=sequence
source_id/api/history/events?source_id=user
source_id!/api/history/events?source_id__exclude=sequence
source_id__in/api/history/events?source_id__in=system,user
source_id__in!/api/history/events?source_id__in__exclude=sequence
source_info/api/history/events?source_info=claude-code+2.1.158
source_info__exclude/api/history/events?source_info__exclude=claude-code+2.1.158
source_info__in/api/history/events?source_info__in=claude-code+2.1.158,cursor+1.0.0
source_info__in__exclude/api/history/events?source_info__in__exclude=claude-code+2.1.158
field_id/api/history/events?field_id=1
field_id__in/api/history/events?field_id__in=121,122,150
field_id__in!/api/history/events?field_id__in__exclude=121,122

field_id__in returns events whose field_id matches any value in the comma-separated list; field_id__in__exclude returns events whose field_id matches none of the listed values. Both variants only apply to events that actually carry a field_id (currently field_values_changed); they combine with all other filters (record_id, event_type__in, source_*, event_datetime__*) via AND. Non-integer values in the CSV are silently dropped; an all-invalid CSV skips the filter entirely.

Notes on source_info filters

  • Filtering is case-sensitive (ClickHouse compares byte-by-byte).
  • source_info (exact match) accepts an empty string "" — filters for events without metadata (i.e. non-MCP events).
  • source_info__in ignores empty entries (e.g. a trailing comma value is treated as a value).

Errors

ErrorResponse codeMessage
Tenant not found400 Bad Request"detail": "'{tenant}' tenant not found in database."
Source type invalid400 Bad Request{'detail': [{'loc': ['query', 'source_type'], 'msg': "value is not a valid enumeration member; permitted: 'user', 'sequence', 'system', 'mcp'", 'type': 'type_error.enum', 'ctx': {'enum_values': ['user', 'sequence', 'system', 'mcp']}}]}
Source ID invalid400 Bad Request{"detail": [{"loc": ["query", "source_id"], "msg": "value is not a valid integer", "type": "type_error.integer"}]}
Field ID invalid400 Bad Request{"detail": [{"loc": ["query", "field_id"], "msg": "value is not a valid integer", "type": "type_error.integer"}]}
Client ID header is missing400 Bad Request"detail": "Unauthorized Client."
Client from header does not match any tenant400 Bad Request"detail": "Failed to connect to tenant db."
Wrong API key401 Unauthorized"detail": "Unauthorized API Key."
Missing authorization header401 Unauthorized"detail": "Unauthorized API Key."
Any request method other than GET is used405 Method Not Allowed
Event datetime range wrong format - too many items422 Unprocessable Entity{'detail': [{'loc': ['range_value'], 'msg': 'ensure this value has at most 2 items', 'type': 'value_error.list.max_items', 'ctx': {'limit_value': 2}}]}
Event datetime range wrong format - too few items422 Unprocessable Entity{'detail': [{'loc': ['range_value'], 'msg': 'ensure this value has at least 2 items', 'type': 'value_error.list.min_items', 'ctx': {'limit_value': 2}}]}
Event datetime range wrong format on range item422 Unprocessable Entity{'detail': [{'loc': ['range_value', 0], 'msg': 'invalid datetime format', 'type': 'value_error.datetime'}, {'loc': ['range_value', 0], 'msg': 'invalid date format', 'type': 'value_error.date'}]}

GET /api/history/events/event_id/file

Generates a presigned URL for downloading a file from S3.
The client instance is identified through the X-Client-Id header.

Permissions

Requires authentication.

Request

Headers

text
Request Method: GET
Content-Type: application/force-download
X-API-Key: API_KEY
X-Client-Id: client_id

Example path

text
GET /api/history/events/1a2b3c4d-5e6f-7g8h-9i0j-1k2l3m4n5o6p/file

Errors

ErrorResponse codeMessage
Tenant not found400 Bad Request"detail": "'{tenant}' tenant not found in database."
Client ID header is missing400 Bad Request"detail": "Unauthorized Client."
Client from header does not match any tenant400 Bad Request"detail": "Failed to connect to tenant db."
Wrong API key401 Unauthorized"detail": "Unauthorized API Key."
Missing authorization header401 Unauthorized"detail": "Unauthorized API Key."
Any request method other than GET is used405 Method Not Allowed
Event not found404 Not Found"detail": "Event not found."