erp

processErpUpdatesEventsV3

Changed on

Handles updates from ERP systems using integration_id directly. This is the v3 version that removes the unused event_type field and renames object_type to event_name to align with the integration UI naming.

Requires the integration:ingest grant on integration_id; the wildcard grants integration:* and * (the owner role) include it. Without it the request is refused with 403 before anything is processed, charged to the interactive rate limit or recorded — closing a correlation (correlation_complete) included. Being rolled out: until a stage enforces it, a missing grant is logged and the request is still processed.

post/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

Request body

integration_idstring uuid required

UUID that identifies the integration configuration to use

correlation_idstring

Optional ID that identifies the specific request. Generated when omitted or empty, and returned in the response either way.

Where it can be waited on - the request closes it with correlation_complete, or an event that asks for interactive inherits it - it must be 1-255 characters of letters, digits, hyphens and underscores, or the request is a 400. The same rule applies to an event's own correlation_id when that event asks for interactive. Ids nobody can wait on are not checked.

group_idstring

Controls ordering and parallelism for this request's events.

By default, all events for a given integration_id are processed strictly in order, one at a time. For high-volume integrations this can become a throughput bottleneck.

Set group_id to opt into parallel processing:

  • Events sharing the same group_id are processed in the order received.
  • Events with different group_id values are processed in parallel.

Typical usage is to derive group_id from a logical partition key in your payload — for example the customer ID, contract ID, or meter ID — so updates to the same business object remain ordered while unrelated objects are processed concurrently.

Notes:

  • Individual events may set their own group_id, which overrides this request-level value for that event only.
  • Up to 20 groups per integration are processed concurrently. Using more distinct values than that yields no additional parallelism.
  • Omit this field if strict per-integration ordering is required.
  • 1 to 128 printable ASCII characters without spaces: letters, digits and punctuation (! to ~). Anything else is a 400.
interactiveboolean

Request interactive processing for this request's events.

Interactive events are carried on a dedicated, low-latency lane and recorded, so a caller can wait for their result with GET /v3/erp/updates/events?correlation_id=.... Use it for the pushes a person is waiting on — a registration, a self-service lookup — not for batch loads.

The use case has to allow it: its interactive setting must be on_request (this flag then selects the lane) or always (every event of that use case is interactive and this flag is unnecessary). On a use case that does not allow it the events are processed normally and the result says interactive: false.

An organization that asks for interactive processing faster than its agreed rate has the excess carried on its normal lane instead. Nothing is rejected and nothing is lost: those results still say interactive: true, with lane naming the queue that actually carried them, and the correlation can still be waited on - it will simply take as long as a bulk event does. Only events admitted as interactive count against that rate: an event refused at ingest (422), skipped as a duplicate, or past its correlation's event limit costs nothing. A request is admitted or spilled as a whole.

Individual events may set their own interactive, which overrides this request-level value for that event only.

correlation_completeboolean

Declares that no further events will follow for this request's correlation_id. A caller waiting on that correlation is answered as soon as the events already sent have finished, instead of waiting out its full budget.

Requires a request-level correlation_id - it closes that correlation and is never inferred from per-event correlation_id values; sending it without one is a 400.

It is valid on a request with an empty events array, which is how a bridge closes a correlation whose terminal marker arrived on its own. If nothing was ever pushed under that correlation id, it is created closed and empty, so a waiter is told straight away that nothing is coming rather than waiting for data that will never arrive.

A request that carries events closes the correlation whenever it exists - also when those events came back skipped as duplicates of events already sent (a retry of the closing request), or were processed on the normal lane - but never creates it: only a request with no events does. A request with no events that creates the correlation costs one unit of the organization's interactive rate; closing one that exists, or finding it closed already, costs nothing. When the organization is over its rate, it still closes a correlation that exists but creates none - send it again a few seconds later. The close is not applied when the response asks for a retry (422 or 429), when the queue refused one of the request's events, or when the correlation does not exist and the request carries events or could not pay for creating it; each of these raises a CORRELATION_CLOSE_IGNORED monitoring warning naming the cause. The response says what became of the close in correlation_close - applied, rate_limited (send it again a few seconds later) or ignored with its reasons.

Closing a correlation twice is a no-op. Events that arrive afterwards are still processed, and raise a CORRELATION_LATE_EVENT monitoring warning; once the correlation is complete they can no longer change its answer (see completion on GET /v3/erp/updates/events).

A correlation belongs to the integration whose event or close created it. A close sent for another integration under the same id is not applied and raises CORRELATION_CLOSE_IGNORED; an event sent for another integration under it is processed normally, not interactively, and its result says interactive: false with the reason.

Example request

{
  "group_id": "customer-42",
  "interactive": true,
  "correlation_complete": true,
  "events": [
    {
      "event_name": "business_partner",
      "timestamp": "2025-05-01T08:30:00Z",
      "format": "json",
      "use_case_slug": "business_partner",
      "deduplication_id": "evt-2025-05-01-12345-bp",
      "group_id": "customer-42",
      "correlation_id": "customer-42-sync-2026-08-26",
      "interactive": true
    }
  ]
}

Response

Some events failed to process

correlation_idstring

The request's correlation id, echoed, or the one generated for it when the caller omitted it. This is the id to pass to GET /v3/erp/updates/events?correlation_id=... to wait for these events. v3 and v2 generate one when the request has none, so they always return it, except that v2 omits it for an empty correlation_id. v1 never generates one: it echoes a non-empty meta.correlation_id and otherwise omits the field.

Changes

    • info

      added the optional property to the response with the status

    • info

      added the optional property to the response with the status

    • breaking

      the // request property's minLength was increased from 0 to 1

    • breaking

      the request property's minLength was increased from 0 to 1

    • breaking

      added the pattern ^[!-~]+$ to the request property //

    • breaking

      added the pattern ^[!-~]+$ to the request property

    • info

      added the non-success response with the status