> ## Documentation Index
> Fetch the complete documentation index at: https://docs.daily.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Dial-in and dial-out

> Use daily-js to initiate outbound SIP/PSTN calls, handle inbound callers, send DTMF tones, and track telephony session lifecycle.

This guide covers the daily-js APIs for SIP and PSTN telephony. For an overview of how dial-in and dial-out work across all APIs, see the [dial-in/dial-out guide](/docs/guides/features/dial-in-dial-out).

## Prerequisites

Before calling any telephony methods:

* Your Daily account must have a credit card on file.
* For dial-out, the room must have `enable_dialout: true` and your account must be [approved for dial-out](https://forms.gle/Q5eaHLEosuKyzC7BA).
* The local participant must join with an [owner meeting token](/reference/rest-api/meeting-tokens/create-meeting-token#body-properties-is-owner).

## Dial-out

### Starting a session

[`startDialOut()`](/reference/daily-js/instance-methods/start-dial-out) initiates an outbound call to a SIP URI or PSTN phone number. The called party joins the room as a regular participant.

<Tabs>
  <Tab title="SIP">
    ```javascript theme={null}
    const { session } = await call.startDialOut({
      sipUri: 'sip:conference@pbx.example.com',
      displayName: 'Conference Bridge',
      video: false,
      codecs: { audio: ['OPUS', 'G722'] },
    });

    const sessionId = session?.sessionId;
    ```
  </Tab>

  <Tab title="Phone (PSTN)">
    ```javascript theme={null}
    const { session } = await call.startDialOut({
      phoneNumber: '+15551234567',  // E.164 format
      displayName: 'Jane Smith',
      callerId: '+18005551000',
      extension: '4321',
      waitBeforeExtensionDialSec: 3,
    });

    const sessionId = session?.sessionId;
    ```
  </Tab>
</Tabs>

The returned `sessionId` identifies this telephony session. Hold onto it — you'll need it for `stopDialOut()`, `sendDTMF()`, and transfer methods.

See [`startDialOut()`](/reference/daily-js/instance-methods/start-dial-out) for the full parameter reference, including `videoSettings` for SIP video calls and codec defaults.

### Stopping a session

```javascript theme={null}
await call.stopDialOut({ sessionId });
```

### Sending DTMF tones

[`sendDTMF()`](/reference/daily-js/instance-methods/send-dtmf) sends touch-tone signals into an active session — commonly used to navigate IVR menus:

```javascript theme={null}
await call.sendDTMF({
  sessionId,
  tones: '1234#',
  method: 'auto',
  digitDurationMs: 100,
});
```

The `method` parameter controls how tones are signaled:

* `'telephone-event'` — RTP telephone-event packets per RFC 4733 (most compatible)
* `'sip-info'` — SIP INFO messages per RFC 6086
* `'auto'` — Daily picks the best method for the connection

### Dial-out events

Listen to these events to track the lifecycle of an outbound session:

```javascript theme={null}
call.on('dialout-connected', ({ sessionId, destination, sipCallId, provider }) => {
  // Call is established and ringing at the remote end
});

call.on('dialout-answered', ({ sessionId, destination, callerId, sipCallId }) => {
  // Remote party answered — media is now flowing
});

call.on('dialout-stopped', ({ sessionId, destination }) => {
  // Session ended (remote hung up or stopDialOut() was called)
});

call.on('dialout-error', ({ sessionId, errorMsg, details }) => {
  // Fatal error — session will not recover
  console.error(`Dial-out failed: ${errorMsg}`);
});

call.on('dialout-warning', ({ sessionId, errorMsg }) => {
  // Non-fatal warning (e.g. codec fallback applied)
});
```

`dialout-connected` fires when the SIP/PSTN network acknowledges the call; `dialout-answered` fires when the remote party actually picks up. Both events include `provider` and `sipCallId` for correlating with server-side logs. See the [telephony events reference](/reference/daily-js/events/telephony-events) for full payload details.

## Dial-in

Dial-in allows external SIP or PSTN callers to join a Daily room. Set `enable_dialin: true` on the room via the REST API or dashboard. For setup details — including PIN dial-in, pinless dial-in, and SIP interconnect — see the [dial-in/dial-out guide](/docs/guides/features/dial-in-dial-out).

### Dial-in events

```javascript theme={null}
call.on('dialin-ready', ({ sipEndpoint, provider }) => {
  // The room's SIP endpoint is ready to accept inbound calls
  console.log('SIP endpoint:', sipEndpoint);
});

call.on('dialin-connected', ({ sessionId, sipFrom, sipCallId, provider }) => {
  // An inbound caller has connected and media negotiation is underway
  // Note: media is not yet flowing — wait for the participant-joined event
  console.log(`Caller ${sipFrom} connecting — session ${sessionId}`);
});

call.on('dialin-stopped', ({ sessionId, sipCallId }) => {
  // Inbound caller disconnected
});

call.on('dialin-error', ({ sessionId, errorMsg, type }) => {
  console.error(`Dial-in error [${type}]: ${errorMsg}`);
});

call.on('dialin-warning', ({ sessionId, errorMsg }) => {
  // Non-fatal warning (e.g. codec fallback)
});
```

All dial-in events include `provider` and `sipCallId` fields for correlating sessions with server-side logs. See the [telephony events reference](/reference/daily-js/events/telephony-events) for full payload details.

## Call transfers

To transfer an active SIP or PSTN session to another destination, use [`sipCallTransfer()`](/reference/daily-js/instance-methods/sip-call-transfer) or [`sipRefer()`](/reference/daily-js/instance-methods/sip-refer). See the [call transfers guide](/docs/guides/features/dial-in-dial-out/transfers) for a full explanation of when to use each method, including a decision table and scenario examples.

## Example: full dial-out flow

```javascript theme={null}
let activeSessionId = null;

async function callPhoneNumber(phoneNumber) {
  try {
    const { session } = await call.startDialOut({ phoneNumber });
    if (session) {
      activeSessionId = session.sessionId;
      updateUI({ status: 'ringing' });
    }
  } catch (err) {
    console.error('Failed to start dial-out:', err);
    updateUI({ status: 'error' });
  }
}

call.on('dialout-answered', ({ sessionId }) => {
  if (sessionId === activeSessionId) {
    updateUI({ status: 'connected' });
  }
});

call.on('dialout-stopped', ({ sessionId }) => {
  if (sessionId === activeSessionId) {
    activeSessionId = null;
    updateUI({ status: 'idle' });
  }
});

call.on('dialout-error', ({ sessionId, errorMsg }) => {
  if (sessionId === activeSessionId) {
    activeSessionId = null;
    updateUI({ status: 'error', message: errorMsg });
  }
});

async function endCall() {
  if (activeSessionId) {
    await call.stopDialOut({ sessionId: activeSessionId });
  }
}

async function pressKey(key) {
  if (activeSessionId) {
    await call.sendDTMF({ sessionId: activeSessionId, tones: key, method: 'auto' });
  }
}
```

## See also

<CardGroup>
  <Card title="Methods" icon="code" iconType="solid">
    * [startDialOut()](/reference/daily-js/instance-methods/start-dial-out)
    * [stopDialOut()](/reference/daily-js/instance-methods/stop-dial-out)
    * [sendDTMF()](/reference/daily-js/instance-methods/send-dtmf)
    * [sipCallTransfer()](/reference/daily-js/instance-methods/sip-call-transfer)
    * [sipRefer()](/reference/daily-js/instance-methods/sip-refer)
  </Card>

  <Card title="Events" icon="bolt" iconType="solid">
    * [Telephony events](/reference/daily-js/events/telephony-events)
  </Card>

  <Card title="Guides" icon="book-open" iconType="solid">
    * [Dial-in/dial-out overview](/docs/guides/features/dial-in-dial-out)
    * [Call transfers](/docs/guides/features/dial-in-dial-out/transfers)
  </Card>
</CardGroup>
