Skip to main content

Overview

Phone numbers in Unpod come from two sources:
  • Unpod Numbers - provision numbers directly through the Unpod platform (no external carrier account needed)
  • BYON (Bring Your Own Number) - port or route numbers you already own from any provider
Once a number is in your account, you attach it to a Speech Pipe. All inbound calls to that number are routed to the Speech Pipe’s AgentRunner.
Support for Twilio, Telnyx, and Plivo numbers is coming soon - you will be able to import numbers from these providers directly into Unpod.

Number Sources

SourceDescription
UnpodProvision numbers directly from the Unpod platform
BYONBring numbers from your existing provider
TwilioComing soon
TelnyxComing soon
PlivoComing soon

Getting Numbers from Unpod

Numbers provisioned through Unpod are immediately available in your account. You can browse and acquire them from the dashboard under Dev Platform -> Numbers. Once provisioned, list them via the SDK:
import asyncio
from unpod import AsyncClient

async def main():
    async with AsyncClient(api_key="sk-...") as client:
        numbers = await client.numbers.list()
        for n in numbers:
            print(n.number_id, n.number, n.status, n.pipe_id or "unattached")

asyncio.run(main())

Bringing Your Own Number (BYON)

If you already have numbers with a carrier, configure them as a BYON trunk in the Unpod dashboard:
  1. Go to Dev Platform -> Telephony and click Add Trunk -> BYO SIP.
  2. Provide your carrier’s SIP server details:
    • Termination URI - e.g. sip:your-carrier.com
    • Credentials - auth username and password
  3. At your carrier, set inbound routing to point at the Unpod SIP endpoint shown in the dashboard.
  4. Your numbers will appear in Unpod and can be attached to Speech Pipes.

Listing Numbers

import asyncio
from unpod import AsyncClient

async def main():
    async with AsyncClient(api_key="sk-...") as client:
        # All numbers
        numbers = await client.numbers.list()

        # Filter by status or country
        active = await client.numbers.list(status="active")
        us_numbers = await client.numbers.list(country="US")
        byon = await client.numbers.list(trunk_type="byo")

        for n in numbers:
            print(n.number_id, n.number, n.status, n.pipe_id or "unattached")

asyncio.run(main())

Number fields

FieldTypeDescription
number_idstrUnique number ID (num_...)
numberstrE.164 format, e.g. +14155550100
statusstractive, inactive, pending
trunk_typestrunpod or byo
pipe_idstr | NoneAttached Speech Pipe, or None if free
countrystrISO 3166-1 alpha-2 country code

Attaching a Number to a Speech Pipe

A number can be attached to exactly one Speech Pipe at a time. Inbound calls to that number are routed to the Speech Pipe’s configured runners.
import asyncio
from unpod import AsyncClient

async def main():
    async with AsyncClient(api_key="sk-...") as client:
        number = await client.numbers.attach(
            number_id="num_...",
            pipe_id="pipe_...",
        )
        print("Attached:", number.number, "-> pipe", number.pipe_id)

asyncio.run(main())

Detaching a Number

import asyncio
from unpod import AsyncClient

async def main():
    async with AsyncClient(api_key="sk-...") as client:
        number = await client.numbers.detach("num_...")
        print("Detached:", number.number)

asyncio.run(main())

Common Patterns

Find the first free number and attach it

import asyncio
from unpod import AsyncClient

async def attach_first_free(pipe_id: str) -> None:
    async with AsyncClient(api_key="sk-...") as client:
        numbers = await client.numbers.list(status="active")
        free = [n for n in numbers if n.pipe_id is None]
        if not free:
            raise RuntimeError("No free numbers available")
        await client.numbers.attach(free[0].number_id, pipe_id)
        print("Attached", free[0].number)

asyncio.run(attach_first_free("pipe_..."))

Rotate numbers across Speech Pipes

import asyncio
from unpod import AsyncClient

async def rotate(numbers: list[str], pipes: list[str]) -> None:
    async with AsyncClient(api_key="sk-...") as client:
        for num_id, pipe_id in zip(numbers, pipes):
            await client.numbers.attach(num_id, pipe_id)
            print(f"{num_id} -> {pipe_id}")

asyncio.run(rotate(["num_a", "num_b"], ["pipe_x", "pipe_y"]))

Next Steps

Voice Profiles

Choose the voice profile for your Speech Pipe.

Speech Pipe

Create and configure your Speech Pipe via the SDK.