Skip to main content
Inbound only. Typed digits stay out of transcripts and logs. Time: ~20 minutes. You need:

1. Install the Twilio CLI and log in

Install
You can do every Twilio step by clicking instead, in the Console under Voice → Manage → Elastic SIP Trunking.

2. Fill in your details

Save these in a .env file in your working directory:
.env
Load it into your shell before running the commands below:
TRUNK_DOMAIN is a name you invent. It must end in .pstn.twilio.com and be unique across Twilio, so include your company name.

3. Create the SIP trunk

A SIP trunk is the connection Twilio uses to hand calls off to AssemblyAI. You will create an empty trunk here, then configure it in the next two steps. Create the trunk using the $TRUNK_DOMAIN you set in step 2:
Copy the sid from the response and save it in your shell:
You will use $TRUNK_SID in steps 4 and 5.

4. Send incoming calls to AssemblyAI

Reusing a trunk that already has an origination URL? Delete the old one first, or calls may go to the wrong place:

5. Put your number on the trunk

Look up your number’s SID:
Save it, then attach the number to the trunk:
The trunk now controls this number. Any Voice webhook set on the number itself no longer applies.

6. Create your agent

Your agent has three parts:
  1. A system prompt telling it how to behave on the call.
  2. A process_payment tool that charges the card. Card number, expiry, and authorization are collected from the keypad using dtmf_collected_arguments, so the model never hears or sees them.
  3. A send_receipt tool that emails the receipt after payment.
Save the following as agent.json:
agent.json
Then create the agent and save its ID:
Create agent

Keypad settings reference

Each entry in dtmf_collected_arguments controls one keypad prompt:

7. Register the number and attach the agent

Register and attach
201 then 200, and the last call should show your agent_id with "type": "imported".

8. Call it

Ring the number. Say yes when it offers to take payment, then: type a card number and press # → press 1 to confirm → type the four digit expiry → press 1 to authorize → say your email. Refresh webhook.site and you will see the payment request arrive, then the receipt request.

If it does not work

  • Nothing happens when you call. Check the number is on the trunk (5), the origination URL is exactly sip:sip.assemblyai.com and enabled (4), and an agent is attached (7). A number with a Voice webhook still set in the Console is not going through the trunk.
  • The agent asks out loud instead of using the keypad. parameter_name does not match a parameter name in the tool.
  • 409 number already registered · 404 agent_not_found wrong agent ID · 422 phone_number_has_no_agent do step 7 · 502 Twilio rejected it, retry.
  • Twilio command not recognised. Names change between CLI versions. Run twilio api:trunking:v1 --help, or use the Console.