Skip to main content
When someone calls your Daily phone number, the call is placed on hold and triggers a webhook to initialize your Pipecat bot.

Setup Options

Let Pipecat Cloud handle the webhook automatically. Using the Dashboard:
  1. Go to Settings > Telephony in Pipecat Cloud
  2. Select your phone number
  3. Choose your deployed agent
  4. Save
Using the REST API:
curl --location 'https://api.daily.co/v1' \
--header 'Authorization: Bearer YOUR_DAILY_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
    "properties": {
        "pinless_dialin": [{
            "phone_number": "YOUR_DAILY_NUMBER",
            "room_creation_api": "https://api.pipecat.daily.co/v1/public/webhooks/{org_id}/{agent_name}/dialin"
        }]
    }
}'

Option 2: Custom Webhook Server

Host your own webhook server for custom logic (e.g., CRM integration, advanced routing, caller-based customization). Webhook payload from Daily:
{
  "To": "+15559876543",
  "From": "+15551234567",
  "callId": "uuid",
  "callDomain": "uuid"
}
Forward to Pipecat Cloud:
curl --request POST \
--url https://api.pipecat.daily.co/v1/public/{service}/start \
--header 'Authorization: Bearer $API_KEY' \
--header 'Content-Type: application/json' \
--data '{
    "createDailyRoom": true,
    "dailyRoomProperties": {
        "sip": {
            "display_name": "+15551234567",
            "sip_mode": "dial-in",
            "num_endpoints": 1
        }
    },
    "body": {
        "dialin_settings": {
            "from": "+15551234567",
            "to": "+15559876543",
            "call_id": "uuid",
            "call_domain": "uuid"
        }
    }
}'

Bot Configuration

Configure your bot to handle dial-in calls:
from pipecat.runner.types import DailyDialinRequest, RunnerArguments
from pipecat.transports.daily import DailyTransport, DailyParams, DailyDialinSettings

async def bot(runner_args: RunnerArguments):
    # Parse dial-in request
    request = DailyDialinRequest.model_validate(runner_args.body)

    # Configure dial-in settings
    dialin_settings = DailyDialinSettings(
        call_id=request.dialin_settings.call_id,
        call_domain=request.dialin_settings.call_domain
    )

    # Create transport
    transport = DailyTransport(
        runner_args.room_url,
        runner_args.token,
        "Voice Bot",
        DailyParams(
            api_key=request.daily_api_key,
            api_url=request.daily_api_url,
            dialin_settings=dialin_settings,
            audio_in_enabled=True,
            audio_out_enabled=True,
            vad_analyzer=SileroVADAnalyzer(),
        )
    )

    # Start speaking when caller joins
    @transport.event_handler("on_first_participant_joined")
    async def on_first_participant_joined(transport, participant):
        await task.queue_frames([LLMRunFrame()])

    # Your bot pipeline setup...
Personalize with caller info:
caller_phone = request.dialin_settings.From
customer = await get_customer_by_phone(caller_phone)
# Use customer data in your system prompt

Complete Example

Daily PSTN Dial-in Bot

Full implementation with STT, LLM, TTS, and caller personalization