---
title: "Dialer SDK Events, Sessions and Transcripts | Trellus"
description: "Subscribe to dialer SDK snapshots and six typed events, look up confirmed call sessions, and handle live transcript text that stays provisional until final."
source: "https://www.trellus.ai/developers/dialer-sdk/events"
note: "Text-only copy of the page for AI assistants and agents. Link to the source address, not this file."
site_summary: "https://www.trellus.ai/llms.txt"
---

# Events, sessions and transcripts

Read state with snapshots, react to six typed events, look up confirmed sessions, and treat live transcript text as provisional until the final snapshot arrives.

Two ways to observe a dialer

## Snapshots with subscribe()

`subscribe(listener, options)` calls your listener with a new snapshot each time the state changes. It returns an unsubscribe function.

- By default the listener receives future changes only.
- Pass `{ emitCurrent: true }` to also receive the current state once, right away.
- Use snapshots to render the whole interface: status, queue, calls and pending wrap-up.

The snapshot shape is in the [API reference](https://www.trellus.ai/developers/dialer-sdk/api#snapshot).

## Typed events with on()

`on(type, listener)` calls your listener for future events of one type. It returns its own unsubscribe function. Use events to react to one kind of change, such as a call connecting or a transcript update.

Subscribe to state and events

```javascript
const offState = dialer.subscribe(render, { emitCurrent: true });
const offSession = dialer.on('session.created', event => {
  // event.sessionId is a confirmed Trellus session ID.
  addSession(event.call);
});
const offTranscript = dialer.on('transcript.updated', event => {
  replaceTranscript(event.sessionId, event.segments);
});

const sessions = dialer.getSessions(); // DialSession[]
const session = sessions[0] ? dialer.getSession(sessions[0].sessionId) : null;
```

`render`, `addSession` and `replaceTranscript` are your own functions.

**`on()` does not replay history.** It delivers future events only. To render calls that already exist, read `getSessions()`.

## The six events

Events and their additional fields

| Event and additional fields | Behavior |
| --- | --- |
| `session.created` No additional fields | The call has a confirmed Trellus session. It comes before any buffered connection or transcript events for that call. |
| `call.connected` No additional fields | Emitted once, the first time the rep is confirmed as connected on that attempt. |
| `call.ended` No additional fields | Emitted once when the end of the call is confirmed. Final transcript updates can follow. |
| `transcript.updated` Adds `segments: TranscriptSegment[]` | The complete corrected transcript. Replace the previous view with it. Not emitted when nothing changed. |
| `detection.updated` Adds `value: string` | The new classification of the call. Repeated values are not emitted. |
| `error` Adds `error: { code, message, outcomeUnknown }` | A sanitized state or runtime failure. A global failure has `attemptId: null`, `taskId: null` and `call: null`, and no `sessionId`. |

### Call event payload

The five call events all carry these fields. They always have a confirmed string `sessionId`, so a handler can use it directly.

Fields on every call event

```typescript
{
  type: string;
  attemptId: string;
  sessionId: string;
  taskId: string;
  call: DialSession; // Detached confirmed public view at this event's transition.
}
```

### Error event payload

An `error` event carries `error: { code, message, outcomeUnknown }`. It comes in two forms. An error before the session is confirmed can omit `sessionId`. A global error has no call context.

The two forms of an error event

```typescript
// An error tied to a call. sessionId is absent before the session is confirmed.
{ type: 'error'; attemptId: string; sessionId?: string; taskId: string; call: DialCall; error: DialerFailure }

// A global error.
{ type: 'error'; attemptId: null; taskId: null; call: null; error: DialerFailure }
```

Event names and payloads are typed through the exported `DialerEventMap` and `DialerEvent`.

## Delivery rules

- Each listener receives its own detached payload.
- An exception in one listener does not affect dialing or other listeners.
- A state change made inside a listener queues behind the current delivery. Every observer sees transitions in the same order.
- Unsubscribe when your component is torn down.
- No public view contains credentials, tokens or transport session handles.

## Session lookups

`getSessions()` returns the confirmed calls of the current queue. `getSession(sessionId)` returns one of them, or `null` when the session is unknown.

DialCall and DialSession

```typescript
interface DialCall {
  attemptId: string;
  sessionId?: string;
  taskId: string;
  name?: string;
  phoneNumber: string;
  status: 'creating' | 'ringing' | 'connected' | 'ending' | 'ended' | 'failed' | 'unknown';
  muted: boolean;
  transcript: TranscriptSegment[];
  detection?: string;
  summary?: string;
  reason?: string;
}

// A confirmed call view.
interface DialSession extends DialCall { sessionId: string }
```

- A `DialSession` is the public `DialCall` view with a required `sessionId`.
- Only confirmed sessions appear. A pending or unconfirmed create does not.
- Ended calls stay in the list until `setTasks()` replaces the queue or `destroy()` clears it.
- These are local views of this dialer’s queue. They do not load account history.
- `getSession()` always returns the latest view. `event.call` keeps the view from the moment of that event.
- Lookups take the Trellus `sessionId`. Controls such as `hangup()` take the SDK `attemptId`.

## Transcript finality

A `transcript.updated` event carries the complete corrected transcript in `segments`. Replace what you display. Do not append.

Render transcripts and ended calls

```javascript
const stopState = dialer.subscribe(render, { emitCurrent: true });
const stopTranscript = dialer.on('transcript.updated', ({ sessionId, segments }) => {
  renderTranscript(sessionId, segments); // Replace the displayed transcript.
});
const stopEnded = dialer.on('call.ended', ({ sessionId, call }) => {
  showCompletedCall(sessionId, call);
});

const sessions = dialer.getSessions();
const session = sessions[0] ? dialer.getSession(sessions[0].sessionId) : null;
```

`render`, `renderTranscript` and `showCompletedCall` are your own functions.

TranscriptSegment

```typescript
interface TranscriptSegment {
  id?: string;
  text: string;
  speaker?: string;
  isFinal: boolean; // false while the text is provisional.
}
```

- Live transcript text is provisional (`isFinal: false`) until the final snapshot arrives after the call ends.
- A later update can rewrite or remove provisional text.
- A call ending does not make its text final. Final corrections can arrive after `call.ended`.
- If the final snapshot never arrives, the segments stay `isFinal: false`.
- An unchanged transcript does not emit another update.

## Detection and summary

`detection.updated` carries `value`, a string that classifies the call. The latest value is also on the call view as `detection`. A detection value describes the call. It does not mean the rep has joined; only `call.connected` means that.

The call view also has an optional `summary` field. In this preview the supplied Trellus transport delivers transcripts and detection values. It does not deliver summaries. Showing an ended call should not imply that all final call data is available.
