The signed JSON body of an outbound bridge notification.
SIGNATURE, verify before you parse. Every POST carries x-corebee-signature: the lowercase hex HMAC-SHA256 of the EXACT raw request body bytes, keyed by the shared secret we issued you. Recompute it over the raw bytes, not over a re-serialization of the parsed JSON, key order and whitespace are part of what was signed, and any JSON library that reorders keys will produce a digest that does not match. Compare with a constant-time equality function. A second header, x-corebee-event-type, repeats type for routing; it is NOT part of the signed string, so never make a trust decision on it.
⛔ The signed string contains no timestamp, so the signature alone does not prove freshness: a captured request stays verifiable forever. Until that is fixed, dedupe on event_id and treat an event whose session_id you have already seen in a terminal state as a replay, with one exception: a bridge.bridged or bridge.completed for a session you recorded as bridge.failed with failure_reason business_abandoned_bridge is a late-join correction (see bridge.completed), and is sent at most once per session. We consider this a gap in our scheme and not something you should design around permanently.
Ordering and duplicates. Delivery is at-least-once. event_id is stable and unique per transition, dedupe on it. previous_state lets you detect an out-of-order arrival: if it does not match the state you last recorded for the session, you received these two out of order. Retries are exponential with a bounded budget per attempt-cycle, and a notification that cannot be delivered inline is retried from a durable outbox, so a slow or briefly-down endpoint does not lose the event.
Only the fields below are sent. The session metadata bag is never forwarded: it holds internal orchestration keys, so customer_ref is the one value of yours that comes back.