---
title: "queryErpUpdateEvents"
method: GET
path: "/v3/erp/updates/events"
tags: ["erp"]
---

# queryErpUpdateEvents

`GET /v3/erp/updates/events`

## Request

- Base URL: `https://integration-toolkit.sls.epilot.io`
- URL: `https://integration-toolkit.sls.epilot.io/v3/erp/updates/events`
- Auth: HTTP bearer

Waits for the events of one correlation — the long poll behind interactive
registration — and returns the correlation's summary.

Pass the `correlation_id` returned by `POST /v3/erp/updates/events` and say
what you are waiting for:

- `wait_for_entities` — entity slugs, optionally with a selector:
  `contact`, `contract[billing_account_number=4711]`.
- `wait_for_use_cases` — inbound use case slugs: `contract`, `meter_reading`.
  A meter reading is not an entity, so this is how a wait names one.

The call returns as soon as `completion` is decided, or after `wait`
seconds. `completion` is one of:

- `requirements_met` — every listed requirement is satisfied. This wins even
  if an unrelated event of the correlation failed; `errors` still lists it.
- `complete` — the partner closed the correlation (`correlation_complete`)
  and every event it sent has finished. Nothing further can arrive, so the
  wait ends even if a requirement is unmet. A correlation closed with zero
  events is `complete` at once: the partner sent nothing and never will.
  **`complete` is final.** From `completed_at` on, the correlation's answer
  is frozen: an event that still arrives under it (a late event) is
  processed and counted in `events_received`, `events_done` and
  `late_events`, and its errors are listed with `after_completion: true`,
  but it adds nothing to `use_cases` or `entities` and never changes
  `completion` — every later read gives the answer the first one got.
- `error` — a requirement can no longer be met because an event it depends
  on failed: every event of a required use case ended in error, or an
  entity requirement is still missing when the correlation is complete and
  one of its events failed. Without requirements, `error` means the
  correlation completed with failures. An event that ended `partial` counts
  as failed here: a use case requirement is met only by an event that ended
  `done`.
- `timeout` — the budget ran out first. The body still shows what has
  landed so far; call again to keep waiting.

**When `entities_omitted` is present, an entity requirement can be
undecided.** `entities` lists at most 200 entity writes; the rest are only
counted. An entity requirement that no listed entity satisfies may then still
have been written, so it is neither met nor missing: it is named in
`undecided_entity_requirements`, it never makes `completion` `error`, and the
wait still ends `complete` once the correlation completes (if every other
requirement is met, `complete` rather than `requirements_met`). Look such an
entity up yourself, e.g. by its unique id through the entity API. Use case
requirements are never undecided: their counts are never omitted.

**Every requirement is met by the first matching event.** A use case
requirement is satisfied by the first event of that use case to finish, and
an entity requirement without a selector by the first entity of that slug;
neither says anything about the rest. So, unless the partner sends
`correlation_complete`, `requirements_met` does not mean the partner has
finished: more data for the same customer may still be arriving.
`correlation_complete` is the only signal that nothing further is coming —
strongly recommended for every partner, never required. When you know the
identifier you are waiting for, an entity requirement with a selector is the
precise tool: `contract[billing_account_number=4711]` is satisfied by that
contract and by nothing else.

An event fails when nothing will retry what went wrong, including when its
mapping could not run or ran only in part: a disabled or unconfigured use
case, an item without its unique identifiers, a field or relation that could
not be mapped. Such an event ends `error` when it wrote nothing and `partial`
when it wrote something, and `errors` says why. A mapping that writes
nothing on purpose (an `enabled` expression that is false, an empty list)
ends `done`.

A requirement is only as good as the use case configuration it refers to:
model one inbound use case per partner event type, and give every use case a
slug. A legacy use case without a slug is counted, and can be named, only by
its use case id, which differs between environments.

An unknown correlation, or one with no interactive events, reads as
`events_received: 0, closed: false` — "not yet" and "never" look the same,
which is why `correlation_complete` exists. Waiting on a correlation before
anything was sent under it is normal — mint the id, hand it to the partner,
wait — and the wait picks the correlation up as soon as its first event is
ingested.

A correlation belongs to one integration: the one whose event (or close)
created it. Events and closes of another integration under the same id are
not applied to it — see `correlation_complete` and the event results.

Waiting holds a connection, so concurrent waits are capped per organization
and overall. A wait that starts before anything was sent under its
correlation counts against a separate, smaller per-organization cap instead,
for its whole duration, so waits on ids nothing is ever sent under cannot
crowd out waits on correlations that exist. Over a cap the call is refused
with 429 and `Retry-After`; fall back to calls with `wait=0` (they never need
a slot) or retry later. Calls that do not have to wait — `wait=0`, or a
correlation that is already decided — are never refused.

Requires `integration:view` on the correlation's integration. The organization
is always the token's own, so no other organization's correlation is ever
visible.

## Query parameters

- `correlation_id` string, required
- `wait` integer
- `wait_for_entities` string[]
- `wait_for_use_cases` string[]

## Response `200`

The correlation's summary and the wait's verdict

- CorrelationWaitResult: One correlation's summary.
  - `correlation_id` string, required
  - `integration_id` string
  - `closed` boolean, required: The partner sent `correlation_complete`.
  - `closed_at` string, date-time
  - `complete` boolean, required: The correlation is complete — closed, and every event it received before completing has finished (or it was closed having received none). FINAL once `true`: the field to read for "is it done", on the listing as on a wait. Do not derive it from `events_done >= events_received`: a late event raises `events_received` after completion without reopening anything.
  - `completed_at` string, date-time: When the correlation became complete. Present exactly when `complete` is `true` (except on correlations completed before 2026-10-14); the correlation's `use_cases`, `entities` and `completion` are frozen at this instant.
  - `events_received` integer, required
  - `events_done` integer, required: Events that reached a terminal status, failed ones included.
  - `late_events` integer, required: Events that arrived after the correlation was closed. Those that arrived after it completed are counted here and in `events_received` / `events_done`, but not in `use_cases` or `entities`.
  - `first_ingested_at` string, date-time: When the first event of the correlation was accepted. Absent while none was — a correlation created by a zero-event close.
  - `last_done_at` string, date-time
  - `use_cases` CorrelationUseCaseCounts[], required: Per use case counts, frozen at `completed_at`.
    - `use_case_slug` string, required: The use case's slug, or its id for a use case that has no slug — such a use case is counted but cannot be named in `wait_for_use_cases`.
    - `received` integer, required
    - `done` integer, required
    - `error` integer, required: Events of this use case that ended `error` or `partial`.
  - `entities` ErpUpdateProcessedEntity[], required: Every entity the correlation's events wrote before it completed, one entry per entity with its writes merged (see `operation` and `unique_ids`). A correlation lists at most 200 entity writes; see `entities_omitted`.
    - `slug` string, required: Entity schema slug, e.g. `contact`.
    - `_id` string, required: The entity id.
    - `operation` 'created' | 'updated' | 'deleted' | 'unchanged', required: What the writes did, merged over every write of the entity — by the event, or on a correlation by all its events: `deleted` wins, then `created`, `updated`, `unchanged`. So an entity the event (or the correlation) created reads `created` however often it was written again, and one it deleted reads `deleted`. `unchanged` means the entity already matched; it still counts as written.
    - `unique_ids` object, required: The unique ids the entity was looked up by — the use case's configured `unique_ids` for that entity and nothing else, as far as they could be recorded. A value longer than 256 UTF-16 code units, not counting surrounding whitespace, is not recorded, and one write records its unique ids, in key order, within 1,024 bytes: an id that would not fit is left out. A selector cannot name an id that is not recorded. These and `_id` are what a caller can tell several entities of one slug apart by, and the only attributes a `wait_for_entities` selector can match. On a correlation they are the union over its events: two use cases that wrote one contact by different unique ids both match. A unique id two events wrote with different values shows one of them here, and a selector matches either.
  - `entities_omitted` integer: Entity writes of the correlation's events that are not in `entities`, because the list was full (at most 200), or because an event's record could not be written and the event ended `error` with `PROCESSING_STATE_LIMIT`. The entities may well have been written; they are only missing from the list, so a `wait_for_entities` requirement cannot be met by them — one that no listed entity satisfies is undecided instead (see `undecided_entity_requirements`). Present only when there are any.
  - `errors` ErpUpdateProcessingError[], required: The correlation's first 50 failures, whatever `completion` says. `errors_total` counts them all.
    - `code` string, required: The v2 monitoring code of the failure.
    - `message` string, required
    - `event_id` string: Which event of the correlation failed. Present on the correlation's errors only; on an event's own errors it would repeat the event's id.
    - `occurred_at` string, date-time, required
    - `after_completion` boolean: `true` on a correlation's error of an event that arrived after the correlation completed. Listed for the record — while the list has room, and counted in `errors_total` either way; it is not part of the correlation's answer, which was final at `completed_at`. Absent otherwise.
  - `errors_total` integer, required: Every failure in the correlation, including those not listed in `errors` (the first 50 are) and those of events that arrived after completion (`after_completion`), which do not change the answer.
  - `completion` 'requirements_met' | 'complete' | 'timeout' | 'error', required: Why the wait ended. See the operation description.
  - `undecided_entity_requirements` string[]: The `wait_for_entities` requirements this record cannot decide, each exactly as you passed it. Present only when the correlation omitted entities (`entities_omitted`) and a requirement is satisfied by none of the listed ones: the list holds at most 200 entity writes, so the entity may well have been written, and an omitted one is never listed later. Such a requirement is neither met nor missing — it never makes `completion` `error`, and the wait still ends `complete` once the correlation completes. Look the entity up yourself, e.g. by its unique id through the entity API.

## Other responses

- `400`: The request is invalid: a missing `correlation_id`, `wait` out of range, a malformed requirement, more than 20 occurrences of a requirement parameter (or more than 20 use case slugs), or a requirement that can never match. For a `wait_for_entities` requirement, `slug`, `rejected_key` (absent when no inbound use case writes the slug) and `allowed_keys` say what would have worked; for a `wait_for_use_cases` entry, `use_case_slug` names the entry as passed — one that is not a use case slug, or a slug no inbound use case has. A requirement is refused only against the configuration as read after the request arrived, so the wait accepts a use case or unique id saved just before the call at once. Accepting is not processing: processing applies a changed use case configuration — its unique ids, its mapping, enabled or disabled — within up to 5 minutes, and events pushed meanwhile are processed with the previous configuration. A selector on a unique id added in that time is accepted but cannot match those events. The other direction is cached: a use case deleted, or a unique id removed, up to about a minute before the call may still be accepted, and such a requirement can then never be met.
- `401`: Unauthorized: the request carries no bearer token. The API gateway answers `{"message": "Unauthorized"}`. A token that is present but invalid or expired is refused with 403, not 401.
- `403`: Forbidden: the token lacks a permission the operation requires, or it is invalid or expired — the API gateway refuses those with `{"message": "Forbidden"}` before the request reaches the API.
- `429`: Too many correlation waits are open — for this organization or overall — so this one was not admitted. Nothing about the correlation changed. Retry after `Retry-After`, or call with `wait=0`, which never needs a slot.
- `500`: Internal Server Error

## Changes

- **2026-10-16** `ef6bbb0d5a31`: 2 info
  - added the optional property `allOf[#/components/schemas/CorrelationStatus]/entities_omitted` to the response with the `200` status
  - added the optional property `allOf[subschema #2]/undecided_entity_requirements` to the response with the `200` status
- **2026-10-15** `53e2cdce2751`: 5 info
  - added the optional property `allOf[#/components/schemas/CorrelationStatus]/completed_at` to the response with the `200` status
  - added the optional property `allOf[#/components/schemas/CorrelationStatus]/errors/items/after_completion` to the response with the `200` status
  - added the optional property `use_case_slug` to the response with the `400` status
  - added the required property `allOf[#/components/schemas/CorrelationStatus]/complete` to the response with the `200` status
  - …1 more
- **2026-10-14** `7500d8e50bd0`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/epilot/apis/integration-toolkit-api/changes/v3/erp/updates/events/get.md)

---

[API](https://skmtc.dev/epilot/apis/integration-toolkit-api.md) - [All operations](https://skmtc.dev/epilot/apis/integration-toolkit-api/llms.txt) - [OpenAPI document](https://skmtc.dev/epilot/apis/integration-toolkit-api/revisions/7d07c4eb8d37?raw)
