event field that identifies which lifecycle event fired. Treat the body as a discriminated union and branch on that field.
Discriminator. One of
session.ended, call.ended, session.finalized, recording.ready.The Pathors session ID.
ISO 8601 timestamp of when the event was emitted.
session.ended
Fires when the conversation has ended. For call sessions, the call’s final status and duration may not be available yet at this moment.
Pathway node the agent was on when the conversation ended.
Total messages exchanged in the session.
Variables extracted across the session, keyed by name.
Legacy alias for
event from before multi-event support existed; Will be removed in a future version — new receivers should branch on event.call.ended
Fires when the call has ended. Call sessions only — text sessions never produce this event.
The project that owns the agent.
Final domain status. One of
userHangup, agentHangup, transferred, voicemail, errorTransferred, busy, userNoAnswer, userRejected, invalidNumber, sipTrunkFailure, agentNoAnswer, error, unknown, Ended.Call duration in seconds.
0 for non-traffic outcomes (busy, no-answer, invalid number).session.finalized
Fires once everything is done for this session. The payload merges the data you would otherwise piece together from session.ended and call.ended, so your receiver only has to handle one event.
For text sessions, the call fields (callStatus, callDuration) are omitted entirely — not set to null. Branch on whether they’re present to discriminate call vs text:
The project that owns the agent.
Pathway node the agent was on when the conversation ended.
Total messages exchanged in the session.
Variables extracted across the session.
Call sessions only. Same as
call.ended’s callStatus. Omitted for text sessions.Call sessions only. Same as
call.ended’s callDuration. Omitted for text sessions.recording.ready
Fires after a call’s recording finishes processing — on both success and failure. Call sessions only; text sessions never produce this event.
Unlike the lifecycle events, this one is independent of session.finalized — it does not gate finalization and can arrive either before or after session.finalized, depending on how long recording processing takes.
The project that owns the agent.
Whether the recording was processed and stored successfully. When
false, recordingUrl is omitted.Temporary download URL for the composite audio file. Present only when
success is true. The link is short-lived (valid for ~15 minutes) — download the file promptly. Once it expires there is currently no API to re-fetch it; download the recording from the call log in the Pathors dashboard instead.Implementation example
A receiver that handles every event withevent as the discriminator:
Ordering
Among the lifecycle events (session.ended, call.ended, session.finalized), session.finalized is always last for a given session.
Typical order for a call session:
session.endedcall.endedsession.finalized
session.ended and session.finalized arrive back-to-back.
session.ended and call.ended are not strictly ordered with respect to each other in edge cases (e.g. hard hangup before the agent reaches its final node).
recording.ready sits outside this order. It does not gate session.finalized and may arrive before or after it — do not assume the recording is ready just because session.finalized has fired.