Search events


Request description

Endpoint: /events/search
Method: POST

Returns the events of an organization within a time range. Results are paginated: there is no maximum number of events per search, you read them page by page until the response says there are no more. This makes the endpoint suitable for exporting events to your own analytics tools (Power BI, Mixpanel, a data warehouse...).

{
  "Content-Type": "application/json",
  "Authorization": "Bearer <accessToken>"
}

Note: the <accessToken> is obtained as a result of the authentication

Payload

interface ISearchEventPayload {
  startTimestamp: number;
  endTimestamp: number;
  organizationId?: string;
  userId?: string;
  eventName?: string | string[];
  eventType?: EventType | EventType[];
  pageSize?: number;
  cursor?: string;
  outputFormat?: "json" | "csv";
  limit?: number; // Deprecated: use pageSize
}

type EventType = "INFO" | "WARNING" | "ERROR";

where:

  • startTimestamp: Start time (Unix time in milliseconds)
  • endTimestamp: End time (Unix time in milliseconds). Must be greater than or equal to startTimestamp
  • organizationId (optional): organization whose events are returned. By default, the organization selected in your session. You can search any organization in which you have the Organization Owner or Organization Admin role
  • userId (optional): return only the events of this user. Get it from Users list. When omitted, the events of every user in the organization are returned
  • eventName (optional): return only events with this name, e.g. "Complete medical consultation". Send an array (up to 50 values) to match any of several names
  • eventType (optional): return only events of this type ("INFO", "WARNING" or "ERROR"). Send an array to match several types
  • pageSize (optional): number of events per page. Integer between 1 and 5000. 500 by default
  • cursor (optional): the pagination.nextCursor value of the previous response. Omit it to get the first page
  • outputFormat (optional): Output format. (JSON by default)
  • limit (deprecated): previous name of pageSize, still accepted with the same range. If both are sent, pageSize is used

Numbers must be sent as numbers, not as strings. Events are returned from the most recent to the oldest.

Pagination

  1. Send the first request without cursor.
  2. Read pagination.hasMore in the response. When it is true, send the same request again adding cursor with the value of pagination.nextCursor.
  3. Repeat until pagination.hasMore is false (nextCursor is then null).
The cursor is an opaque string: store it as it is and do not build or modify it. Keep the rest of the payload unchanged while you read the pages of a search, otherwise the results are not consistent.
Each page is resolved in a single request that must finish in less than 30 seconds. If you receive a 504 response, retry the same page or split the search into shorter time ranges (for example, one day per search).
// Example: read every event of yesterday
let cursor: string | undefined;
const events = [];

do {
  const response = await fetch(`${BASE_URL}/events/search`, {
    method: "POST",
    headers: { "Content-Type": "application/json", Authorization: `Bearer ${accessToken}` },
    body: JSON.stringify({ startTimestamp, endTimestamp, pageSize: 5000, cursor }),
  });
  const { events: page, pagination } = await response.json();
  events.push(...page);
  cursor = pagination.nextCursor ?? undefined;
} while (cursor);

Payload example

{
  "startTimestamp": 1788281445980,
  "endTimestamp": 1790873445980,
  "eventName": ["Start medical report generation", "Complete medical consultation"],
  "pageSize": 1000,
  "outputFormat": "json"
}

Responses

Correct response

Successful request

Describe the characteristics of a satisfactory response

200

Response structure:

type SearchEventsResponseType = {
  events: IEvent[] | string; // IEvent[] for "json", a CSV string for "csv"
  pagination: {
    pageSize: number; // Page size applied to this search
    count: number; // Number of events in this page
    hasMore: boolean; // false when there are no more events to return
    nextCursor: string | null; // Send it as "cursor" to get the next page. null when hasMore is false
  };
};
Below we will describe the structure of the IEvent interface:
interface IEvent {
  timestamp: string; // Event date in UTC, format "YYYY-MM-DD HH:mm:ss.SSS" (not ISO 8601)
  eventName: string; // Event name, e.g. "Start medical report generation"
  userId: string;
  organizationId: string;
  eventType: string; // "INFO", "WARNING" or "ERROR"
  section: string; // Area of the platform where the event happened
  resource: string; // Related resource, empty when not applicable
  metadata?: Record<string, unknown>; // Additional event-specific data. Only present when the event has it
}
Response body example (outputFormat: "json"):
{
  "events": [
    {
      "timestamp": "2026-10-01 14:30:04.741",
      "eventName": "Complete medical consultation",
      "userId": "mock-user-id",
      "organizationId": "mock-organization-id",
      "eventType": "INFO",
      "section": "genesis",
      "resource": ""
    }
  ],
  "pagination": {
    "pageSize": 1000,
    "count": 1,
    "hasMore": false,
    "nextCursor": null
  }
}
Response body example (outputFormat: "csv"):The response is still a JSON object. The CSV of the page, including its header row, is returned as a string in events. Values containing commas, quotes or line breaks are quoted, and metadata is serialized as JSON:
{
  "events": "timestamp,eventName,userId,organizationId,eventType,section,resource,metadata\n2026-10-01 14:30:04.741,Complete medical consultation,mock-user-id,mock-organization-id,INFO,genesis,,",
  "pagination": {
    "pageSize": 500,
    "count": 1,
    "hasMore": false,
    "nextCursor": null
  }
}
Description: when there are no events in the requested range, events is an empty array (or a CSV with only the header row) and pagination.hasMore is false.

Wrong responses

Unauthorized request

Describe the characteristics of an unauthorized request

401

Response body

{
  "message": "Unauthorized"
}

Description: this error occurs when endpoint authorizers fail to validate the token sent in the request header.

Forbidden request

Describe the characteristics of an forbidden request

403

Response body

{
  "message": "Forbidden"
}

Description: this error occurs when your accessToken does not have permission to search for events of the organization: the user does not have the Organization Owner or Organization Admin role in the selected organization or, when organizationId is sent, in that organization.

Bad request

Describe the characteristics of a bad request

400

Response body

type SearchEventErrorResponseType = {
  errorType: SEARCH_EVENT_ERROR_TYPE;
  errorMessage: string;
};

enum SEARCH_EVENT_ERROR_TYPE {
  INVALID_START_TIMESTAMP = "invalidStartTimestamp",     // startTimestamp missing or not a number
  INVALID_END_TIMESTAMP = "invalidEndTimestamp",         // endTimestamp missing or not a number
  INVALID_TIMESTAMP_RANGE = "invalidTimestampRange",     // startTimestamp is greater than endTimestamp
  INVALID_PAGE_SIZE = "invalidPageSize",                 // pageSize is not an integer between 1 and 5000
  INVALID_LIMIT = "invalidLimitValue",                   // limit is not an integer between 1 and 5000
  INVALID_CURSOR = "invalidCursor",                      // cursor is not a value returned by this endpoint
  INVALID_USER_ID = "invalidUserId",                     // userId is not a valid identifier
  INVALID_ORGANIZATION_ID = "invalidOrganizationId",     // organizationId is not a valid identifier
  INVALID_EVENT_NAME = "invalidEventName",               // eventName is empty, has more than 50 values or invalid characters
  INVALID_EVENT_TYPE = "invalidEventType",               // eventType is not "INFO", "WARNING" or "ERROR"
  INVALID_OUTPUT_FORMAT = "invalidOutputFormat",         // outputFormat is not "json" or "csv"
}
Response body example:
{
  "errorMessage": "Page size must be an integer between 1 and 5000",
  "errorType": "invalidPageSize"
}

Search timeout

Describe the characteristics of a search that took too long

504

Response body

{
  "errorMessage": "The search took too long. Try a smaller time range or page size.",
  "errorType": "searchQueryTimeout"
}

Description: the page could not be resolved in time. Retry the same request (with the same cursor) or split the search into shorter time ranges.

Internal error

Describe the characteristics of an internal error

500

Response body

{
  "message": "Internal server error"
}

Description: the search failed. No partial results are returned: retry the same request.