> ## 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.

# SIP Interconnect and Pinless PSTN dial-in

> Route incoming phone and SIP calls to Daily rooms via webhook, without requiring callers to enter a PIN code.

Pinless dial-in and SIP Interconnect allow incoming calls to trigger a webhook on your infrastructure, which then routes the call to a Daily room — no PIN required from the caller.

This pattern is common in contact centers, voice bots, and IVR flows where the destination room isn't known at call time.

## How it works

1. A caller dials your purchased phone number or a static SIP URI.
2. Daily places the caller on hold (hold music plays).
3. Daily sends a webhook to your configured [`room_creation_api`](/reference/rest-api/domain/set-domain-config#body-properties-pinless-dialin-items-room-creation-api) URL.
4. Your server creates or selects a Daily room and waits for [`dialin-ready`](/reference/daily-js/events/telephony-events#dialin-ready) to fire.
5. Your server calls [`pinlessCallUpdate`](/reference/rest-api/dial-in/pinless-update) with the room's `sip_uri` to connect the held caller.

## Configure pinless dial-in

[Configure your domain](/reference/rest-api/domain/set-domain-config#body-properties-pinless-dialin) with a `pinless_dialin` array. Each object represents one incoming number or SIP interconnect:

```bash theme={null}
curl --request POST \
  --url https://api.daily.co/v1/ \
  --header 'Authorization: Bearer $DAILY_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "properties": {
      "pinless_dialin": [
        {
          "phone_number": "$PURCHASED_NUMBER",
          "room_creation_api": "$WEBHOOK_URL",
          "name_prefix": "my-pinless-phone",
          "hmac": "base64-encoded-secret",
          "hold_music_url": "https://example.com/hold.mp3",
          "timeout_config": {
            "message": "Agent not available. Please call later."
          }
        },
        {
          "room_creation_api": "$WEBHOOK_URL",
          "name_prefix": "sip-interconnect"
        }
      ]
    }
  }'
```

You can omit `phone_number` for SIP Interconnect (no phone number needed). Otherwise, `phone_number` is required and must be a number [purchased from Daily](/reference/rest-api/phone-numbers/index).

The response is the room's `config` object, including an array of `pinless_dialin` entries, each with a static `sip_uri` and the corresponding `room_creation_api` URL — the `sip_uri` is the address your SIP system dials for interconnect flows:

```json theme={null}
{
  "config": {
    "pinless_dialin": [
      {
        "sip_uri": "8a1f0c4e2b7d9351--1739943585193@daily-8a1f0c4e2b7d9351-pinless-sip.dapp.signalwire.com",
        "phone_number": "+12095038039",
        "room_creation_api": "https://webhook.example.com/create_room",
        "hmac": "base64-encoded-secret"
      },
      {
        "sip_uri": "8a1f0c4e2b7d9351--1739943585194@daily-8a1f0c4e2b7d9351-pinless-sip.dapp.signalwire.com",
        "room_creation_api": "https://webhook.example.com/handle_twilio",
        "hmac": "base64-encoded-secret"
      }
    ]
  }
}
```

<Warning>
  Daily generates each `sip_uri` for your domain. Copy the exact value from the API response and store it. Do not build the address by hand and do not change any part of it.

  Incoming calls are matched against the exact address Daily generated. If your SIP system dials an address you built yourself, or an edited version of the real one, the call will not match. Daily ends the call, your `room_creation_api` webhook never fires, and you see no sign of the call at all.
</Warning>

<Tip>
  When you configure `pinless_dialin`, Daily sends a test request to your `room_creation_api` endpoint with the body `{"test": "test"}`. This test request is sent every time you configure `pinless_dialin`, not only the first time. It only checks that your endpoint is reachable. Your endpoint is still configured even if it does not return a 200 response, so that existing domains that do not recognize the test body keep working.

  This test request always carries an `X-Pinless-Timestamp` header. If you set an `hmac` on your `pinless_dialin` config, it is also signed the same way a real call is, with an `X-Pinless-Signature` header. Daily gives your endpoint 8 seconds to respond.

  Do not use "my webhook was called" as proof that call routing works. The test request looks nothing like a real call. Only a real incoming call includes `callId` and `callDomain` in the body, so check for those two fields when you want to know whether a real call reached you.
</Tip>

## Incoming webhook payload

When a call arrives, Daily POSTs to your `room_creation_api`:

```json theme={null}
{
  "From": "+CALLERS_PHONE",
  "To": "$PURCHASED_PHONE",
  "callId": "a7bf8461-7d33-4083-9677-5cfdb4f337a5",
  "callDomain": "9c975848-a067-4de0-bf47-1b4179ceba4e",
  "sourceIp": "203.0.113.10",
  "sipHeaders": {
    "x-custom-header": "value"
  }
}
```

* `From`: caller's phone or SIP address
* `To`: your Daily phone number or static SIP URI
* `callId` + `callDomain`: use these to connect the held call to a Daily room. They are only sent for real calls, never for the config-time test request
* `sourceIp`: the IP address the call was received from — use it to reject calls that did not come from your carrier. Sent for SIP-interconnect calls; **omitted entirely** for PSTN calls, which have no SIP originator, so treat it as optional
* `sipHeaders`: custom SIP headers sent to the `sip_uri` (e.g., for external SIP systems forwarding caller context). For example, when you receive a call on your Avaya on-premise SIP server and need to send the caller phone and called phone, the `to` and `from` fields will already be the Avaya sip addresses. In that case, you can add custom sip headers prepended with an `x-`. This would be something like `8a1f0c4e2b7d9351--1739943585193@daily-8a1f0c4e2b7d9351-pinless-sip.dapp.signalwire.com?x-caller=7861230000&x-called=6501230000`.

## Verifying the webhook signature (HMAC)

Each `pinless_dialin` entry has an `hmac` — a Base64-encoded HMAC-SHA256 secret shared between Daily and your server. Use it to verify that the webhook came from Daily.

Daily includes two headers with each webhook request:

* `X-Pinless-Timestamp`
* `X-Pinless-Signature`

To verify:

```javascript theme={null}
// You'll need to save the hmac value the API returned when you created your webhook and insert it here
const hmacSecret = 'NQrSA5z0FkJ44QPrFerW7uCc5kdNLv3l2FDEKDanL1U=';
const signature = headers['X-Pinless-Timestamp'] + '.' + JSON.stringify(body);
const base64DecodedSecret = Buffer.from(hmacSecret, 'base64');
const hmac = crypto.createHmac('sha256', base64DecodedSecret);
const computedSignature = hmac.update(signature).digest('base64');
// computedSignature should match headers['X-Pinless-Signature']
```

You can provide your own Base64-encoded secret in the `hmac` field when configuring. If omitted, Daily generates a new one each time you update `pinless_dialin`.

<Warning>
  Keep your `hmac` secret private. Anyone with it can forge webhook requests.
</Warning>

## Connecting the held call to a Daily room

Once your webhook handler has created or selected a room:

1. Join the room with a Daily participant (e.g., a Pipecat bot or agent) so the room is active.
2. Wait for [`dialin-ready`](/reference/daily-js/events/telephony-events#dialin-ready) to fire.
3. Call [`pinlessCallUpdate`](/reference/rest-api/dial-in/pinless-update) with the room's `sip_uri` and the `callId`/`callDomain` from the webhook:

```bash theme={null}
curl --request POST \
  --url https://api.daily.co/v1/dialin/pinlessCallUpdate \
  --header 'Authorization: Bearer $DAILY_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "callId": "a7bf8461-7d33-4083-9677-5cfdb4f337a5",
    "callDomain": "9c975848-a067-4de0-bf47-1b4179ceba4e",
    "sipUri": "sip:room-specific-id@example.sip.daily.co?x-daily_display_name=caller"
  }'
```

<Warning>
  Calling `pinlessCallUpdate` before `dialin-ready` fires may cause the call to drop.
</Warning>

Make sure the `sip_uri` you provide is not already in use by another SIP client. See [multiple SIP endpoints](/docs/guides/features/dial-in-dial-out/sip#multiple-sip-endpoints) for provisioning multiple endpoints per room.

For building voice bots with this pattern, see the [Pipecat dial-in docs](https://docs.pipecat.ai/pipecat/telephony/daily-pstn).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.