livekit sip api initiate call without creating a r...
# ask-ai
d
livekit sip api initiate call without creating a room first, create a room when user picks up a phone
✅ 1
t
Thanks for reaching out, Eugene. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — great question. You can initiate an outbound SIP call without creating a LiveKit room ahead of time and have the room created when the call is answered. What’s possible • You can call the LiveKit SIP API (for example, use
CreateSIPParticipant
) to place an outbound SIP call without first calling
CreateRoom
. • If the specified room does not already exist, LiveKit will automatically create the room when the first participant joins — which in an outbound SIP flow happens when the called party answers the phone. The room is created dynamically at that moment. How you’d use this in practice 1. Initiate the outbound call with
CreateSIPParticipant
(or your equivalent SIP-create call). 2. Wait for the SIP leg to be answered. 3. When the call is answered, LiveKit will create the room and add the SIP participant into it. At that point you can have your agent or web client join the room and exchange media. Notes and helpful tips • If you need to set specific room settings or metadata, include those in the API call that creates the SIP participant (or apply them when the first participant joins). • Design your client logic to handle the brief window before the room exists (e.g., show "calling" state until you receive confirmation the SIP leg is connected and the room is available). If you want, tell me: • which SDK or language you’re using (REST, Node/Python server SDK, or client SDK), and • any room settings or participant behavior you need (e.g., recording, specific metadata), and I’ll give a short example tailored to that setup. Sources: Outbound Calling Script | LiveKit Documentation | Agent dispatch | LiveKit Documentation | CreateRoom() is taking too long | LiveKit, with interactive elements
d
what will be an exact configuration?
t
Thanks — I’ll give a concrete example. Below I show a complete REST request JSON for CreateSIPParticipant, explain required and optional fields, and include a short Node.js snippet you can adapt. This configuration will place an outbound SIP call without creating the room first; LiveKit will auto-create the room when the SIP leg is answered. Required / important fields in CreateSIPParticipant • room: target room name (if room does not exist it will be created when the first participant joins). • participant_identity: an identifier for the SIP participant in the room. • sip_uri: the destination SIP URI (or phone number in SIP URI form). • send_audio / recv_audio: enable/disable audio for the SIP leg. • headers / auth: optional SIP headers or credentials if your SIP gateway requires them. • join_params / metadata: optional room/participant metadata (useful to set room behavior or to pass context). Example REST JSON request (CreateSIPParticipant)
Copy code
{
  "room": "support-room-123",
  "participant_identity": "sip-outbound-678",
  "sip_uri": "sip:+14155551234@sip.provider.com",
  "audio": {
    "send": true,
    "recv": true
  },
  "headers": {
    "X-Custom-Header": "support-queue-1"
  },
  "auth": {
    "username": "sipuser",
    "password": "sippass"
  },
  "metadata": {
    "case_id": "CASE-001",
    "priority": "high"
  }
}
Notes on the fields above • `room`: the named room that will be created automatically when the SIP call is answered. • `participant_identity`: internal identity used inside the room; choose a unique value per SIP leg. • `sip_uri`: target SIP destination; format depends on your SIP provider. •
audio.send
and `audio.recv`: ensure they are true to send/receive audio on the SIP leg. •
headers
and `auth`: include only if your SIP provider/gateway requires SIP headers or authentication. • `metadata`: optional JSON you can use to tag the room/participant; it will be available to other participants once the room exists. Minimal example cURL 1. Replace AUTH_TOKEN with an admin API key or appropriate auth token and adjust URL to your LiveKit control plane endpoint.
Copy code
curl -X POST "https://your-livekit-host/api/sip_participants" \
  -H "Authorization: Bearer AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "room":"support-room-123",
    "participant_identity":"sip-outbound-678",
    "sip_uri":"sip:+14155551234@sip.provider.com",
    "audio":{"send":true,"recv":true}
  }'
Node.js example (short)
Copy code
const fetch = require('node-fetch');

async function createSipParticipant() {
  const url = 'https://your-livekit-host/api/sip_participants';
  const body = {
    room: 'support-room-123',
    participant_identity: 'sip-outbound-678',
    sip_uri: 'sip:+14155551234@sip.provider.com',
    audio: { send: true, recv: true },
    metadata: { case_id: 'CASE-001' }
  };

  const res = await fetch(url, {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(body)
  });

  const data = await res.json();
  console.log('CreateSIPParticipant response:', data);
  return data;
}

createSipParticipant().catch(console.error);
How to handle the flow on your side • After sending CreateSIPParticipant, show a “calling” state until you receive a callback/event indicating the SIP leg connected. • When the SIP leg is answered, LiveKit will create the room and add the SIP participant. You can then: ◦ Have your agent or web client join the room (use a valid token for that room). ◦ Listen for participant-joined events to know when the SIP participant is present. • If you need specific room settings (recording, participant permissions, etc.), set those either via API when you create/join, or include relevant metadata so your joining logic can apply them immediately when the room is available. If you want a more exact snippet tailored to your environment, please tell me: • Which LiveKit host / control-plane endpoint you use (self-hosted URL or livekit.cloud). • Which SDK / language you prefer (Node, Python, Go, REST/cURL). • Any SIP gateway auth requirements or special SIP headers you need to set. I’ll return a ready-to-run example with those specifics. , with interactive elements
d
I need to make sure we dont create a livekit room when sip call is not answered
t
Thanks — I understand you want to ensure a LiveKit room is only created when the outbound SIP call is actually answered (so no rooms are created for unanswered calls). That’s a good precaution. Short answer • If you use the SIP API to create a SIP participant without pre-creating the room (for example,
CreateSIPParticipant
), LiveKit will not create the room until the SIP leg is actually answered. The room is created dynamically when the first participant successfully joins (i.e., when the call is answered). Recommended flow to guarantee no stray rooms 1. Place the outbound SIP call with
CreateSIPParticipant
and point it to your intended room name. 2. Treat the call as “calling” on your side until you receive a connected/answered event from LiveKit or your SIP gateway. 3. Only when you get the answered/participant-joined event should you proceed to create or join client peers for that room. 4. Optionally, implement cleanup: ◦ If the SIP call fails, is rejected, or times out, no room should have been created. If your environment could create rooms in edge cases, detect and delete any empty rooms after a short grace period. Events and checks to rely on • Listen for the SIP participant connection / participant-joined event indicating the SIP leg answered. Use that event to trigger client join logic. • If you receive a failure, rejected, or timeout status for the SIP participant, keep the “calling” state and do not attempt to join or create clients for the room. Example safeguards (high level) • Use a short dialing timeout on your SIP call; if unanswered after timeout, mark it failed and do not join the room. • When you get the answered event, issue tokens and have your agent/client join immediately. • If you must be absolutely certain no room exists before answering, you can check room existence via the control-plane API right after the call ends; delete the room if it was created but remains empty. If you want, I can provide: • A short Node or cURL example that shows placing the SIP call, waiting for the answered event, and only then joining clients. • A cleanup snippet that deletes an empty room after a timeout. Which would you prefer, and which SDK or language are you using? , with interactive elements
d
From the Admin settings I have this checkbox Automatically create rooms on participant join what it does does it affect phone calls ?
t
Thanks — good question. You’re asking whether the Admin setting "Automatically create rooms on participant join" affects phone (SIP) calls. Short answer: yes — it does. What the setting does • When enabled, LiveKit will automatically create a room the moment the first participant joins. This applies to all participant types, including SIP participants (both inbound and outbound calls). • For outbound calls placed via
CreateSIPParticipant
, if the named room does not yet exist, the room will be created when the SIP leg is answered and the SIP participant joins. • For inbound calls routed by a SIP dispatch rule, the same behavior applies: the target room is created when the SIP caller joins. What this means for your workflow • If you want to guarantee that no room is created unless the call is actually answered, keep this setting enabled — rooms will only be created at join time (i.e., when the call is answered). • If you disable the setting, you must explicitly create the room (for example with
CreateRoom
) before the SIP participant attempts to join; otherwise the SIP join will not create the room and the call flow may fail. Practical recommendation • To avoid stray rooms from unanswered dials, rely on the join/answered event to trigger your agent/client join logic and tokens. With auto-create enabled, you can initiate dialing without pre-creating rooms and only act when you get the answered/participant-joined event. • If you prefer stricter control (no automatic room creation under any circumstance), disable the setting and call
CreateRoom()
before dialing. If you want, I can: • Show a short flow example (cURL or Node) that places the outbound call and only joins an agent after you receive the answered event, or • Explain how to detect the answered event for your preferred SDK/language. Which would you like? Sources: livekit/livekit_composite | DeepWiki | sip | livekit/livekit_composite | DeepWiki | Accepting calls overview | LiveKit Documentation | SIP Lifecycle Management Agent | LiveKit Documentation | Making calls overview | LiveKit Documentation, with interactive elements