# List events

Source: https://kirora.io/docs/api/reference/listEvents

`GET /v1/events`

Requires an API key with the `events:read` scope. [About keys and scopes](https://kirora.io/docs/api/reference/authentication)

Works with integration, agent and partner keys.

Every event the workspace tracked, accepted or rejected, newest first: did an integration's event arrive, and if not, why? Accepted events are ordered and filtered by when they happened, rejected ones by when they arrived; the log reaches back `meta.retention`. A rejected event is a tracked event the API refused (validation, an unknown contact, the name limit, a deleted name), kept as sent with the error it answered; a batch refused whole is listed event by event. A request refused before its body was read (credentials, rate limit, plan, size, broken JSON) is not kept. `query` matches an event name exactly, or a contact's id, email address or external id (accepted events only: a rejected one has no contact); property values are not searched. Complete, not sampled. For a member, a property whose key is a masked attribute is left out, as on contact reads.

## Query parameters

- `limit` (integer, optional, min > 0, max 100, default `20`) — How many items a page holds: 1 to 100, 20 by default.
- `cursor` (string, optional, 1–2,048 characters) — Where the page starts: the previous page's `meta.pagination.nextCursor`. Omit it for the first page, and send the same filters with it.
- `name` (string, optional, 1–128 characters) — Only events of this name.
- `status` (string, optional, one of `accepted`, `rejected`) — Only `accepted` events, or only `rejected` ones (refused, kept with the error).
- `source` (string, optional, one of `api`, `web`, `system`, `stripe`, `zapier`, `make`, `n8n`, `segment`) — Only events that came in this way. Nothing indexes it, so a page polling for new events also sets `occurredAfter`.
- `query` (string, optional, 1–320 characters) — An event name, exactly as tracked, or a contact's id, email address or external id. Property values are not searched.
- `occurredAfter` (string, optional, date-time) — Only events that happened at or after this time (inclusive), a rejected one by when it arrived; the log reaches back `meta.retention` at most.
- `occurredBefore` (string, optional, date-time) — Only events that happened before this time (exclusive).

## Header parameters

- `Kirora-Workspace` (string, optional, pattern `^[A-Za-z0-9._:-]{1,128}$`) — Partner keys only: the child workspace to act in, by the external id the partner gave it. Without it, a partner key acts in its own workspace. Any other key that sends it is refused with 403, and an unknown workspace is 404.

## Returns

Returns `200 OK` with a list of `Event` objects in `data`, and the next page's cursor in `meta` (see [pagination](https://kirora.io/docs/api/reference/pagination)). Otherwise returns an error; [Errors](https://kirora.io/docs/api/reference/errors) lists every code and which to retry.

- One of: **Accepted**
  - `id` (string, required, uuid)
  - `source` (string, required, one of `api`, `web`, `system`, `stripe`, `zapier`, `make`, `n8n`, `segment`) — The path it came in on, set by Kirora: `api` (an API key), `web` (the Kirora web SDK), `system` (recorded by Kirora) or the integration that sent it. A key made for an app labels its events with that app, whoever uses the key.
  - `receivedAt` (string, required, date-time) — When Kirora received it.
  - `status` ("accepted", required)
  - `name` (string, required)
  - `contact` (object, required)
    - `id` (string, required, uuid)
    - `externalId` (string | null, required)
    - `email` (string | null, required)
  - `properties` (map<string, any>, required) — As tracked, less any key masked from this viewer.
  - `context` (object | null, required)
    - `sessionId` (string, optional, up to 128 characters) — The visit, from the SDK.
    - `locale` (string, optional, up to 35 characters) — As BCP 47, `en-GB`.
    - `timezone` (string, optional, up to 64 characters) — As IANA, `Europe/Berlin`.
    - `page` (object, optional) — Web: the page as visited: query strings kept, fragments removed. A longer value is cut, not refused: `url`, `search` and `referrer` at 8192 characters, `path` at 2048, `title` at 256.
      - `url` (string, optional) — The canonical URL if the page has one, with the page's query string added unless it has its own; else the page's address.
      - `path` (string, optional)
      - `search` (string, optional) — The visited address's query string, `?plan=pro`; empty or absent when it has none.
      - `title` (string, optional)
      - `referrer` (string, optional)
    - `campaign` (object, optional) — Web: the `utm_*` parameters of the page, each cut to 256 characters.
      - `source` (string, optional)
      - `medium` (string, optional)
      - `name` (string, optional)
      - `term` (string, optional)
      - `content` (string, optional)
    - `device` (object, optional)
      - `id` (string, optional, up to 128 characters) — A random id the SDK keeps on the device; never a hardware id.
    - `library` (object, optional)
      - `name` (string, optional, up to 64 characters)
      - `version` (string, optional, up to 64 characters)
    - `ip` (string, optional, up to 64 characters)
    - `userAgent` (string, optional, up to 1,024 characters)
  - `occurredAt` (string, required, date-time) — When it happened.
  - `expiresAt` (string, required, date-time) — When retention deletes it: when it happened plus the days the plan kept events when it was stored. Fixed: a plan change moves only later events.
- One of: **Rejected**
  - `id` (string, required, uuid)
  - `source` (string, required, one of `api`, `web`, `system`, `stripe`, `zapier`, `make`, `n8n`, `segment`) — The path it came in on, set by Kirora: `api` (an API key), `web` (the Kirora web SDK), `system` (recorded by Kirora) or the integration that sent it. A key made for an app labels its events with that app, whoever uses the key.
  - `receivedAt` (string, required, date-time) — When Kirora received it.
  - `status` ("rejected", required)
  - `name` (string | null, required) — Null when the request had no valid name.
  - `occurredAt` (string | null, required, date-time) — When it happened; null when the request gave no valid time.
  - `payload` (object, required) — The event as sent, less masked property keys; null when it was over 32 KB.
  - `error` (object, required) — The error the API answered.
    - `code` (string, required, one of `BAD_REQUEST`, `ALREADY_EXISTS`, `CONFLICT`, `IN_USE`, `FORBIDDEN`, `SCOPE_MISSING`, `AGENT_KEY_REFUSED`, `INTERNAL_ERROR`, `NOT_FOUND`, `METHOD_NOT_ALLOWED`, `PAYLOAD_TOO_LARGE`, `UNSUPPORTED_MEDIA_TYPE`, `RATE_LIMITED`, `REVISION_CONFLICT`, `SERVICE_UNAVAILABLE`, `UNAUTHORIZED`, `VALIDATION_ERROR`, `API_KEY_IP_NOT_ALLOWED`, `AGENT_CONFIRMATION_REQUIRED`, `EMBED_BUILDER_UNAVAILABLE`, `EMBED_ORIGIN_NOT_ALLOWED`, `WORKSPACE_SUSPENDED`, `WORKSPACE_DELETION_PENDING`, `CONTACT_SEND_IN_PROGRESS`, `EXPORT_UNAVAILABLE`, `NOTHING_TO_EXPORT`, `EVENT_NAME_LIMIT_REACHED`, `PLAN_LIMIT_REACHED`, `SENDING_REVIEW_REQUIRED`, `PLAN_FEATURE_UNAVAILABLE`, `CAMPAIGN_AUDIENCE_CONFLICT`, `EMPTY_AUDIENCE`, `DRAFT_INCOMPLETE`, `INVALID_SCHEDULE`, `UNSUPPORTED_CHANNEL`, `POSTAL_ADDRESS_MISSING`, `CONSENT_MISSING`, `SUPPRESSED`, `TOPIC_UNSUBSCRIBED`, `SIGNUP_BLOCKED`, `INVALID_SENDER_ADDRESS`, `SENDING_DOMAIN_DMARC_MISSING`, `SENDING_DOMAIN_IDENTITY_CONFLICT`, `TEST_SEND_OUTCOME_UNKNOWN`, `TEST_SEND_ROUTE_NOT_READY`, `TEST_SEND_UNAVAILABLE`, `SENDING_DOMAIN_UNVERIFIED`, `IDEMPOTENCY_KEY_REUSED`, `IDEMPOTENCY_KEY_IN_USE`, `IDEMPOTENCY_KEY_OUTCOME_UNKNOWN`, `CONTENT_NOT_RETAINED`, `RECIPIENT_EMAIL_MISSING`, `RECIPIENT_EMAIL_UNSUPPORTED`, `TEMPLATE_NOT_PUBLISHED`, `TEMPLATE_ENVELOPE_INCOMPLETE`, `PUSH_APP_NOT_READY`, `PUSH_DESTINATION_MISSING`, `FORM_CLOSED`)
    - `message` (string, required)
    - `errors` (FieldError[], optional) — Each field the request got wrong: on `VALIDATION_ERROR` and `DRAFT_INCOMPLETE`.
      - `in` (string, optional, one of `body`, `query`, `params`, `headers`) — The part of the request the field is in, when known.
      - `field` (string, required) — Dotted path to the field (`blocks.0.text`); empty for the whole part.
      - `code` (string, optional) — The rule that failed (`too_big`, `invalid_type`, `custom`, …).
      - `message` (string, required) — Plain words, meant to be shown beside the field.
      - `minimum` (number, optional) — The bound a `too_small` rule set.
      - `maximum` (number, optional) — The bound a `too_big` rule set.
    - `details` (object, optional) — What else the error carries, by `code`: see that code's description.
    - `requestId` (string, optional)

## Example

```bash
curl https://api.kirora.io/v1/events \
  -H "Authorization: Bearer $KIRORA_API_KEY"
```

Response `200`:

```json
{
  "data": [
    {
      "id": "0192f3c0-3c4d-7e5f-8a61-7c8d9e0f1a2b",
      "status": "rejected",
      "name": "Order Completed",
      "source": "api",
      "occurredAt": null,
      "receivedAt": "2026-10-01T09:31:12.480Z",
      "payload": {
        "email": "not-an-email",
        "name": "Order Completed"
      },
      "error": {
        "code": "VALIDATION_ERROR",
        "message": "Some request values are invalid. Check the field errors.",
        "errors": [
          {
            "in": "body",
            "field": "email",
            "message": "Enter an email address, like name@example.com."
          }
        ]
      }
    },
    {
      "id": "0192f3c0-1a2b-7c3d-8e4f-5a6b7c8d9e0f",
      "status": "accepted",
      "name": "Order Completed",
      "contact": {
        "id": "0192f3a1-7c2e-7d4b-9a10-3e5f6a7b8c9d",
        "externalId": "customer-4821",
        "email": "amaka@example.com"
      },
      "properties": {
        "order_id": "1001",
        "total": 46.5,
        "currency": "USD"
      },
      "context": {
        "library": {
          "name": "kirora-web",
          "version": "1.4.0"
        },
        "page": {
          "url": "https://shop.example/checkout"
        }
      },
      "source": "web",
      "occurredAt": "2026-10-01T09:30:00.000Z",
      "receivedAt": "2026-10-01T09:30:01.204Z",
      "expiresAt": "2027-10-01T09:30:00.000Z"
    }
  ],
  "meta": {
    "pagination": {
      "limit": 20,
      "nextCursor": null
    },
    "retention": {
      "value": 30,
      "unit": "days"
    }
  }
}
```
