Streaming & events
Use the conversation's event stream to show progress and its durable journal to restore state. Both expose the same recorded history; the stream also carries temporary text updates for your UI.
Choose how to read
| Interface | Use it for | Ordering |
|---|---|---|
events.list | History, backfilling, or polling | Oldest durable event first |
conversations.stream | Replaying history, then following live work | Durable sequence plus live frames |
events.list returns data and nextCursor. Pass the cursor back unchanged until it is null, meaning the end as of that read. More history may arrive later.
Connect to the stream
Open GET /v1/users/{userId}/conversations/{conversationId}/stream with both authentication headers and Accept: text/event-stream. A cursor of 0 replays from the beginning. A positive cursor replays durable events strictly after that journal sequence.
curl --fail-with-body -sSN \
"$FIN_BASE_URL/v1/users/$FIN_USER_ID/conversations/$FIN_CONVERSATION_ID/stream?cursor=0" \
-H "X-Api-Key: $FIN_API_KEY" \
-H "Authorization: Bearer $FIN_USER_TOKEN" \
-H 'Accept: text/event-stream'
For a browser application, connect through your backend so your partner key stays server-side. Native EventSource does not accept arbitrary authorization headers; use your authenticated same-origin proxy or a streaming HTTP client suited to your session design.
Durable and live frames
This illustrates the framing, not a complete run transcript:
: connected
id: 42
event: run.started
data: {"delivery":"durable","seq":42,"payload":{"input":"Hello","runId":"…"}}
event: agent.text_delta
data: {"delivery":"live","payload":{"text":"Hello"}}
| Delivery | Persistence | Client behavior |
|---|---|---|
durable | Has a journal seq, appears in history, replays on reconnect | Apply to saved conversation state. |
live | Has no journal sequence and does not replay | Use for temporary presentation only. |
agent.text_delta provides text while the assistant is generating. Replace that temporary text with the canonical reply when durable agent.entry arrives. Lines beginning with : are comments or heartbeats, not events. Parse SSE framing before interpreting data as JSON.
Reconnect without losing your place
Record the last durable sequence you successfully applied. Reconnect with that value in Last-Event-ID or ?cursor=; Last-Event-ID takes precedence when both are supplied. Deduplicate durable events by conversation and sequence when reloading or replaying them. Live text deltas never advance this cursor.
Reconnect with backoff and honor Retry-After on 429. A stream uses the user's credential; if it expires, renew it through your authentication integration before reconnecting. Streams have their own capacity limits in addition to normal request limits.
Read resources after a reconnect
The journal shows progress; resource reads provide the current facts without reconstructing every event. runs.get returns the original request, current status, full public assistant response, structured output and pending approvals. The same public run id survives every continuation.
approval.opened announces a decision. Fetch approvals.get for its persisted tool input, summary, fingerprint and authorization contract, even after a decision. You do not need to find the original event to render those exact terms.
Handle approvals and continuations
approval.decided records a decision. approval.consumed records permission being spent before execution; it is not a successful tool result. Follow the journal for tool results and replies, or read the same run resource for its current result.
A run.ended event with status: "paused" ends an execution segment while its public run waits for a decision. Approval resume keeps the same public run id and emits no new run.started. After approval.decided, continue processing tool results, assistant entries and the eventual run.ended; do not wait for a fresh start event. The public run ends when its status becomes completed, failed or aborted.
Read financial evidence separately
financialOperations.get returns a financial request, its frozen plan, actual execution legs and complete public receipts. intents.progress and intents.settlement name the operationId; use settlement updates to refresh that resource. A model reply or completed run does not prove settlement.
Direct withdrawals have no conversation journal. Read their financial operation for consent and execution evidence. See Financial operations.
The event catalog describes each event. The quickstart shows a complete connection.