API · Events · Webhooks
Ordering
Per-entity sequence guarantees, exit ordering invariants, and SSE streaming.
Last updated
TL;DR. Per-entity ordering is strict and gap-free via the sequence field.
Cross-entity order is best-effort. Terminal entity events always follow their driving
corporate_transaction.closed.
Events about the same entity arrive in strict order — no reordering, no gaps. This is the one ordering guarantee agents need to reason about state without round-tripping the API.
Why this matters for agents
An autonomous tier-4 agent watching entity.state_changed for ent_Nq3KcAbc should be
able to maintain a local replica of that entity's state by applying events in the
order received. Out-of-order delivery means every event handler must defensively re-fetch
the resource — turning a state machine into a polling loop and burning the agent's
context window on reconciliation logic.
Strict per-entity ordering removes that problem. The agent applies events directly,
trusts the local replica between events, and only re-fetches when its sequence
contains a gap (which would indicate a bug — see below).
Per-entity sequence
Every event carries sequence: <integer> scoped to the subject resource (the entity
or top-level object referenced in data.object).
{
"id": "evt_1Pq3Kc...",
"type": "entity.state_changed",
"data": { "object": { "id": "ent_Nq3KcAbc", "object_type": "entity", ... } },
"sequence": 42
}Within a single entity, sequence is monotonic and gap-free: 1, 2, 3, ..., never
reordered, never skipped. If your handler observes sequence: 41 followed by
sequence: 43 on the same entity, that's a bug — capture both events and contact
support.
Cross-entity ordering is best-effort. An event with sequence: 7 on entity A may
arrive before or after an event with sequence: 7 on entity B. Sort cross-entity by
created if you need a consistent global order, but don't expect strict guarantees.
sequence is scoped to the subject resource, not the event type. Both
entity.state_changed and cap_table.shares_issued for the same entity share the
same sequence space and increment in lock-step.
Exit ordering
The lifecycle's terminal transitions have an additional invariant: terminal entity
events are always emitted after the driving corporate_transaction.closed. This makes
M&A close pipelines deterministic.
The canonical close sequence:
corporate_transaction.advanced (to_stage=closing)
→ filing.accepted (certificate_of_merger
/ bill_of_sale
/ stock_purchase_agreement)
→ corporate_transaction.closed
→ entity.acquired | entity.merged | entity.soldA handler waiting for the terminal entity event can rely on the corporate transaction being closed and the underlying filing being accepted. No partial-close states.
For mergers where the target entity does not survive, entity.merged is followed by
the full dissolution cascade on the non-surviving party:
entity.merged
→ entity.state_changed (active → dissolving)
→ filing.submitted (form_966)
→ filing.accepted (form_966)
→ filing.submitted (final_franchise_tax)
→ filing.accepted (final_franchise_tax)
→ filing.submitted (certificate_of_dissolution)
→ filing.accepted (certificate_of_dissolution)
→ entity.state_changed (dissolving → dissolved)
→ entity.dissolvedThe whole cascade lives on the non-surviving entity's sequence space. The surviving
entity, if any, sees only the entity.acquired (or entity.merged if it's the
acquirer in a triangular merger) on its own sequence.
Streaming via SSE
For long-lived agent runtimes, skip webhook registration entirely and subscribe to a live event stream:
GET /v1/events/stream?entity_id=ent_Nq3KcAbc&types=entity.*,filing.*Standard Server-Sent Events. Each event carries an id: line set to the event's id
field. Reconnect with Last-Event-ID: evt_1Pq3Kc... to resume from the exact point of
disconnection — Matter replays any events emitted during the gap before resuming the
live tail.
The Matter MCP server's matter_subscribe_to_events tool bridges this stream into
agent runtimes, surfacing events as tool-call results without your agent owning the
SSE socket directly.
SSE preserves the same per-entity ordering and exit-ordering invariants as webhook delivery. An agent processing the stream sees identical sequencing to a webhook handler — choose whichever transport fits your runtime.
Related
- Signing — webhook deliveries are signed; SSE uses bearer auth on the request.
- Retries & replay — replays preserve sequence; gaps after replay are still bugs.
- Event catalog — every type that participates in a sequence.
GET /events/stream