Skip to main content
Each payload starts with an event field that identifies which lifecycle event fired. Treat the body as a discriminated union and branch on that field.
Common fields on every event:
string
Discriminator. One of session.ended, call.ended, session.finalized, recording.ready.
string
The Pathors session ID.
string
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.
string
Pathway node the agent was on when the conversation ended.
number
Length of messages — the number of user/assistant turns delivered in this payload.
array
Conversation transcript as { role, content, timestamp? } objects, in turn order. role is user or assistant — tool calls/results and system prompts are stripped. timestamp is the ISO 8601 time of the turn, present when available. For finalized voice calls this is the agent-authoritative conversation the caller actually heard.
object
Variables extracted across the session, keyed by name. Besides agent-extracted values, this carries the variables injected at session start: startAt / endAt, call metadata (fromNumber, toNumber), and — for SIP calls on a phone number with header capture configured — the values of captured custom SIP headers, keyed by the attribute name configured for each header (e.g. an X-Campaign-Id header captured as campaignId appears as extractedVariables.campaignId).
string
deprecated
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.
string
The project that owns the agent.
string
Final domain status. One of userHangup, agentHangup, transferred, voicemail, errorTransferred, busy, userNoAnswer, userRejected, invalidNumber, sipTrunkFailure, agentNoAnswer, error, unknown, Ended.
number
Call duration in seconds. 0 for non-traffic outcomes (busy, no-answer, invalid number).

recording.ready

Fires after a call’s recording finishes processing — on both success and failure. Call sessions only; text sessions never produce this event. Recording processing gates session.finalized for call sessions: finalization waits until the recording succeeds or fails (with a timeout backstop), and the resulting recordingUrl also rides the session.finalized payload. Subscribe to recording.ready when you want the recording signal on its own — it is the only event that tells you a recording failed — otherwise session.finalized already carries the URL.
string
The project that owns the agent.
boolean
Whether the recording was processed and stored successfully. When false, recordingUrl is omitted.
string
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.
Success example:
Failure example:

session.finalized

Fires once everything is done for this session — for call sessions that includes recording processing, so the payload merges the data you would otherwise piece together from session.ended, call.ended, and recording.ready, and 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:
string
The project that owns the agent.
string
Pathway node the agent was on when the conversation ended.
number
Length of messages, same as session.ended’s messagesCount.
array
Conversation transcript, same shape and filtering as session.ended’s messages.
object
Same as session.ended’s extractedVariables — including captured custom SIP header values when the phone number has header capture configured.
string
Call sessions only. Same as call.ended’s callStatus. Omitted for text sessions.
number
Call sessions only. Same as call.ended’s callDuration. Omitted for text sessions.
string
Call sessions only. Temporary download URL for the composite audio file, same as recording.ready’s recordingUrl. Present when the call was recorded and processing succeeded; omitted for text sessions and failed recordings. Short-lived (~15 minutes) — download promptly.
Call session example:
Text session example:

Implementation example

A receiver that handles every event with event as the discriminator:

Ordering

session.finalized is always last for a given session: it fires only after every other expected step has completed — session.ended for text sessions; session.ended, call.ended, and recording.ready for call sessions. Typical order for a call session:
  1. session.ended
  2. call.ended
  3. recording.ready
  4. session.finalized
For text sessions, session.ended and session.finalized arrive back-to-back. The individual steps (session.ended, call.ended, recording.ready) are not strictly ordered with respect to each other in edge cases (e.g. hard hangup before the agent reaches its final node), and HTTP delivery of recording.ready can race the session.finalized request it unblocked. What you can rely on: when session.finalized arrives, recording processing has finished, and a successful recording’s URL is in that payload.