Create conferences

A Conversation is the collection of one or more inbound calls to the virtual number associated to your Voice app. A named Conversation is a conference. The conversation NCCO is used to create a standard or moderated conference for the callers. A standard conference starts when the first caller calls in and ends when the last caller hangs up. A moderated conference starts and ends when the moderator calls in and hangs up. Before a moderated conference starts, you can send an audio stream to the waiting participants. When a conference starts, all audio from all inbound calls is mixed into it. You can record standard and moderated conferences.

The workflow for a conference is:

conference workflow

  1. Your users call the virtual number associated with your app.
  2. Nexmo retrieves an NCCO from your answer_url webhook endpoint.
  3. Nexmo follows the actions in your NCCO.
  4. Nexmo sends status information to your webhook endpoint at event_url.

To create a conference with the Voice API:

  1. Create a Nexmo application. Set answer_url to the URL of server that provides your NCCOs.
  2. Create the NCCOs for the business logic you are implementing in your Voice app:

    [
      {
        "action": "conversation",
        "name": "nexmo-conference-standard",
        "record": "true"
      }
    ]
    
    [
      {
        "action": "talk",
        "text": "Welcome to a Nexmo moderated conference",
        "voiceName": "Amy"
      },
      {
        "action": "conversation",
        "name": "nexmo-conference-moderated",
        "startOnEnter": "false",
        "musicOnHoldUrl": ["https://nexmo-community.github.io/ncco-examples/assets/voice_api_audio_streaming.mp3"]
      }
    ]
    
    [
      {
      "action": "conversation",
      "name": "nexmo-conference-moderated",
      "endOnExit": "true",
      "record": "true"
     }
    ]
    
  3. Create the webhook that provides the NCCO for your conference. The following code examples use the request parameters sent to answer_url to deliver one NCCO to the moderator and another to all other attendees:

    <?php
    
    $method = $_SERVER['REQUEST_METHOD'];
    $request = array_merge($_GET, $_POST);
    
    switch ($method) {
      case 'GET':
    
        //Retrieve with the parameters in this request
        $to = $request['to']; //The endpoint being called
        $from = $request['from']; //The endpoint you are calling from
        $uuid = $request['uuid']; //The unique ID for this Conversation
    
        //Send the header
        header('Content-Type: application/json');
    
        //For more advanced Conversations you use the paramaters to personalize the NCCO
        //Dynamically create the NCCO to run a moderated conversation from your virtual number
        if( $from == "441632960960")
          $ncco='[
                  {
                    "action": "conversation",
                    "name": "nexmo-conference-moderated",
                    "endOnExit": "true",
                    "record": "true"
                  }
                 ]';
        else
          $ncco='[
            {
              "action": "talk",
              "text": "Welcome to a Nexmo moderated conference",
              "voiceName": "Amy"
            },
            {
              "action": "conversation",
              "name": "nexmo-conference-moderated",
              "startOnEnter": "false",
              "musicOnHoldUrl": ["https://nexmo-community.github.io/ncco-examples/assets/voice_api_audio_streaming.mp3"]
            }
          ]';
    
        echo $ncco;
        break;
      default:
        //Handle your errors
        handle_error($request);
        break;
    }
    
    #To run this code, replace the MyHandler in
    #https://wiki.python.org/moin/BaseHttpServer With the following code,
    import time
    import BaseHTTPServer
    import re
    import json
    
    class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
        def do_GET(s):
            """Parse parameters in the GET request"""
            parsed_path = urlparse(s.path).query
            try:
                params = dict([p.split('=') for p in parsed_path[4].split('&')])
            except:
                params = {}
    
            #Retrieve the parameters for this request
            to = params["to"]
            frm = params["from"]
            uuid = params["uuid"]
    
            #For more advanced Conversations you use the paramaters to personalize the NCCO
            #Dynamically create the NCCO to run a conversation from your virtual number
            #Create NCCO Object for your conversation
    
            if frm == "441632960960":
                ncco=[
                  {
                    "action": "conversation",
                    "name": "nexmo-conference-moderated",
                    "endOnExit": "true",
                    "record": "true"
                  }
                 ]
            else:
                ncco=[
                    {
                      "action": "talk",
                      "text": "Welcome to a Nexmo moderated conference",
                      "voiceName": "Amy"
                    },
                    {
                      "action": "conversation",
                      "name": "nexmo-conference-moderated",
                      "startOnEnter": "false",
                      "musicOnHoldUrl": ["https://nexmo-community.github.io/ncco-examples/assets/voice_api_audio_streaming.mp3"]
                    }
                  ]
    
            s.send_response(200)
            s.send_header("Content-type", "application/json")
            s.end_headers()
            s.wfile.write(json.dumps(ncco))
    
    require 'socket'
    require 'uri'
    require 'json'
    
    #Dynamically create the NCCO to run a conversation from your virtual number
    
    def generate_ncco(request_line)
    #Parse the parameters and check if the message was delivered
      params = URI::decode_www_form(request_line).to_h
    
      #Retrieve with the parameters in this request
      to = params['to']         #The endpoint being called
      from = params['from']     #The endpoint you are calling from
      uuid = params['uuid']     #The unique ID for this Conversation
    
      #For more advanced Conversations you use the paramaters to personalize the NCCO
      #Dynamically create the NCCO to run a conversation from your virtual number
    
      #Create NCCO Object for your conversation
    
      if from == "441632960960"
        ncco=[
                {
                  "action": "conversation",
                  "name": "nexmo-conference-moderated",
                  "endOnExit": "true",
                  "record": "true"
                }
               ]
      else
        ncco=[
          {
            "action": "talk",
            "text": "Welcome to a Nexmo moderated conference",
            "voiceName": "Amy"
          },
          {
            "action": "conversation",
            "name": "nexmo-conference-moderated",
            "startOnEnter": "false",
            "musicOnHoldUrl": ["https://nexmo-community.github.io/ncco-examples/assets/voice_api_audio_streaming.mp3"]
          }
        ]
      end
      return ncco.to_json
    end
    
    # Initialize a TCPServer
    server = TCPServer.new('', 9999)
    # Wait for connections
    loop do
      # Wait until a client connects
      socket = server.accept
      method, path = socket.gets.split
      resp = generate_ncco(path)
      # Return the 200 OK
      headers = ["HTTP/1.1 200 OK",
                 "Content-Type: text/html; charset=iso-8859-1",
                 "Content-Length: #{resp.length}\r\n\r\n"].join("\r\n")
      socket.puts headers
      #Return the NCCO
      socket.puts resp
      # Close the socket, terminating the connection
      socket.close
    end
    
  4. Handle the call state changes at event_url. If you record your Conversations, the download URL for the mp3 recording is sent to this webhook endpoint when status is complete. The following code examples show you how to handle changes in Conversation state:

    <?php
    /*
     *  Place this script at event_url for your Nexmo application
     */
    $method = $_SERVER['REQUEST_METHOD'];
    // work with get or post
    $request = array_merge($_GET, $_POST);
    
    /*
     *  Do something for changed call status
    */
    function handle_call_status()
    {
      $decoded_request = json_decode(file_get_contents('php://input'), true);
      // Work with the call status
      if (isset($decoded_request['status'])) {
        switch ($decoded_request['status']) {
          case 'ringing':
              echo("Handle conversation_uuid, this return parameter identifies the Conversation");
              break;
          case 'answered':
              echo("You use the uuid returned here for all API requests on individual calls");
              break;
          case 'complete':
              //if you set eventUrl in your NCCO. The recording download URL
              //is returned in recording_url. It has the following format
              //https://api.nexmo.com/media/download?id=52343cf0-342c-45b3-a23b-ca6ccfe234b0
              //Make a GET request to this URL using a JWT as authentication to download
              //the Recording. For more information, see Recordings.
              break;
          default:
              break;
      }
          return;
      }
    }
    
    /*
     *  Handle errors
    */
    function handle_error($request){
         //code to handle your errors
    }
    
    /*
      Send the 200 OK to Nexmo and handle changes to the call
    */
    switch ($method) {
      case 'POST':
        //Retrieve your dynamically generated NCCO.
        $ncco = handle_call_status();
        header("HTTP/1.1 200 OK");
        break;
      default:
        //Handle your errors
        handle_error($request);
        break;
    }
    
    import time
    import BaseHTTPServer
    import re
    import json
    
    #To run this code, replace the MyHandler in
    #https://wiki.python.org/moin/BaseHttpServer With the following code,
    class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
        def do_POST(s):
            """Parse parameters in the POST request"""
            content_len = int(s.headers.getheader('content-length', 0))
            post_body = s.rfile.read(content_len)
            inbound_message = json.loads(post_body.decode('utf-8'))
    
            # Check if your messages are successful
            if inbound_message['status'] == 'ringing':
                print ("Handle conversation_uuid, this return parameter identifies the Conversation")
            if inbound_message['status'] == 'answered':
                print ("You use the uuid returned here for all API requests on individual calls")
            if inbound_message['status'] == 'complete':
                print ("Find your recording")
                #if you set eventUrl in your NCCO. The recording download URL
                #is returned in recording_url. It has the following format
                # https://api.nexmo.com/media/download?id=52343cf0-342c-45b3-a23b-ca6ccfe234b0
                #Make a GET request to this URL using a JWT as authentication to download
                #the Recording. For more information, see Recordings.
            """Tell Nexmo that you have recieved the POST request."""
            s.send_response(200)
            s.send_header("Content-type", "text/html")
            s.end_headers()
    
    require 'socket'
    require 'uri'
    require 'pstore'
    require 'JSON'
    
    def handle_inbound_message(request_line)
    
      #Parse the parameters and check if the message was delivered
      inbound_message = JSON.parse(request_line)
    
      #Check the is an inbound message
      if (inbound_message['status'] == 'ringing')
        p ("Handle the conversation_uuid return parameter that identifies this Conversation")
      elsif (inbound_message['status'] == 'answered')
        p ("YYou use the uuid returned here for all API requests on individual calls")
      elsif (inbound_message['status'] == 'complete')
        #if you set eventUrl in your NCCO. The URL to download
        #the recording from is set in recording_url.
        #To download the recording
        #curl recording_url&api_key=***&api_secret=***” -o “recording.mp3”
      end
    end
    
    # Initialize a TCPServer
    server = TCPServer.new('', 9999)
    
    # Wait for connections
    loop do
      # Wait until a client connects
      socket = server.accept
      method, path = socket.gets.split
      headers = {}
      while line = socket.gets.split(' ', 2)              # Collect HTTP headers
        break if line[0] == ""                            # Blank line means no more headers
        headers[line[0].chop] = line[1].strip             # Hash headers by type
      end
      content_length = headers["Content-Length"].to_i
      unless content_length == 0
        data = socket.read(content_length)
        handle_inbound_message(data)
      end
    
      # Return the 200 so Nexmo does not send the DLR to you repeatedly
      resp = "Thank you"
      headers = ["HTTP/1.1 200 OK",
                 "Content-Type: text/html; charset=iso-8859-1",
                 "Content-Length: #{resp.length}\r\n\r\n"].join("\r\n")
      socket.puts headers
      socket.puts resp
      # Close the socket, terminating the connection
      socket.close
    end
    

    To inspect and debug state changes without writing your own server, create an online endpoint service such as requestb.in  or https://hookbin.com/  .

  5. Your conference starts when somebody calls the virtual number associated with the application.

Note: to dial somebody into the conference, make an outbound call to your user and set answer_url to the webhook endpoint providing the conference NCCO.

The maximum allowable calls is 50. Conversations can also be moderated and recorded.