Twilio’s Conversations SDK builds virtual spaces (conversations) for users to communicate across multiple channels. Instead of building separate solutions for online chat versus SMS or WhatsApp engagement, we can provide the communication experience across all of them using one SDK.

In this lesson, we’ll interact with a demo Conversations application. To get the demo application up and running, we need to go through the following steps:

  1. Create a conversation.

  2. Add an SMS participant to the conversation.

  3. Add a second participant to the conversation.

  4. Create an access token.

  5. Run the demo application. We’ll see our conversations listed in the sidebar. Select a conversation and start chatting.

Create the first conversation

Now, let’s create our first conversation. The conversation is the primary source that will include the participants and messages.

To create a conversation, we’ll first create a client object and initialize it using our Account SID and Auth Token.

We’ll create a conversation in the following code. We can define a friendly name for our conversation by passing it as an input parameter.

const accountSid = '{{ACCOUNT_SID}}';
const authToken = '{{AUTH_TOKEN}}';
const client = require('twilio')(accountSid, authToken);

client.conversations.v1.conversations
                       .create({friendlyName: 'My first conversation'})
                       .then(conversation => console.log('\n',"Make sure to copy the following conversation SID \n","Conversation SID: ",conversation.sid,"\n"));
Create a Conversation

The following is a breakdown of the above code:

  • Line 3: We create a client object using Account SID and Auth Token.

  • Lines 5–7: We create a conversation with a friendly name, My first conversation. We then print the conversation SID.

Make sure to copy the conversation SID because it will be used as an input parameter in the upcoming steps.

Add a participant

After creating a conversation, we need to add a participant. A participant is someone who will be able to send and receive messages in the conversation.

We can add two types of participants in a conversation:

  1. Non-chat participants: These are SMS or WhatsApp-based participants.

  2. Chat participants: These are SDK-based participants.

Non-chat participants

We need to add a non-chat participant to our conversation to chat by using our phone number.

The following table details the parameters required to add a non-chat participant to our conversation.

Request parameters

Name

Type

Category

Description

conversation_sid

String

Mandatory

The SID associated with our conversation.

messagingBinding.address

String

Mandatory

Our phone number. It can be used to send SMS or WhatsApp messages in the form “+ [country code] [phone number].”

messagingBinding.proxyAddress

String

Mandatory

Our Twilio phone number.

Let’s add a non-chat participant to our conversation. Enter the conversation SID copied from the above code by clicking “Edit.”

Note: Make sure your phone number is in the format “+ [country code] [phone number].”

async function nonChatParticipant ()
{
    try {
        const accountSid = '{{ACCOUNT_SID}}';
        const authToken = '{{AUTH_TOKEN}}';
        const client = require('twilio')(accountSid, authToken);

        const create_participant = await client.conversations.v1.conversations('{{CONVERSATION_SID}}')
        .participants
        .create({
           'messagingBinding.address': '{{YOUR_PHONE_NUMBER}}',
            'messagingBinding.proxyAddress': '{{TWILIO_PHONE_NUMBER}}'
         })
        .then(participant => console.log("\n Participant SID:   ",participant.sid,"\n"));
        
    } catch(error){
        console.log(error);
    }

 }

nonChatParticipant();

Add a non-chat participant

The following is a breakdown of the above code:

  • Lines 8–14: We create a non-chat participant in our conversation by providing our phone number in the messagingBinding.address field and displaying the participant.Sid in the console.

Participant creation error

If we try to create a participant again using the same values of  messageBinding.proxyAddress and messageBinding.address, we will get the following error:

Press + to interact
Participant creation error
Participant creation error

As the error says, there’s already a binding of the two phone numbers in another conversation. To resolve this error, delete the other conversation using the following code. Replace the conversation ID in line 8 with the one shown in the error above.

Press + to interact
async function deleteParticipant ()
{
try {
const accountSid = '{{ACCOUNT_SID}}';
const authToken = '{{AUTH_TOKEN}}';
const client = require('twilio')(accountSid, authToken);
const remove_participant = client.conversations.v1.conversations('CHXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')
.remove();
} catch(error){
console.log(error);
}
}
deleteParticipant();

In the code above, we have the following:

Lines 8–9: We delete a conversation by providing its conversation_SID.

Once the participant is deleted, we can add that participant to our conversation by sending another participant creation request.

Chat participants

Now, let’s try to add a chat participant to our conversation. We can add as many chat participants as we want by providing a unique identity, which is used as a username in our conversation.

async function chatParticipant ()
{
    try {
        const accountSid = '{{ACCOUNT_SID}}';
        const authToken = '{{AUTH_TOKEN}}';
        const client = require('twilio')(accountSid, authToken);

        const create_participant = await client.conversations.v1.conversations('{{CONVERSATION_SID}}')
                                    .participants
                                    .create({identity: 'educative'})
                                    .then(participant => console.log("\n Participant SID:   ",participant.sid,"\n"));
    }catch(error){
        console.log(error);
    }
}

chatParticipant();

Add a chat participant

In the code above, we have the following:

  • Lines 8–11: We create a chat participant and set its identity to educative.

Create an access token

We need an access token to run our demo application. To generate an access code, we need to provide the following parameters:

Request parameters

Name

Type

Category

Description

twilioAccountSid

String

Mandatory

The SID of our Twilio account.

twilioApiKeySID

String

Mandatory

The API key associated with our account.

twilioApiSecret

String

Mandatory

The API secret generated for our account.

serviceSid

String

Mandatory

The service SID which can be found in the chat services on our Twilio console.

identity

String

Mandatory

A unique code used to define a username in the conversation.

Let’s generate an access token through the following code. Click “Edit” to provide your API key SID and secret, which can be found on the Twilio console, and chat service SID, which can be found on the Twilio Chat Services page.

Press + to interact
const AccessToken = require('twilio').jwt.AccessToken;
const ChatGrant = AccessToken.ChatGrant;
// Used when generating any kind of tokens
const twilioAccountSid = '{{ACCOUNT_SID}}';
const twilioApiKey = '{{API_Key_SID}}';
const twilioApiSecret = '{{API_Secret}}';
// Used specifically for creating Chat tokens
const serviceSid = '{{CHAT_SERVICE_SID}}';
const identity = 'educative';
// Create a "grant" which enables a client to use Chat as a given user,
// on a given device
const chatGrant = new ChatGrant({
serviceSid: serviceSid,
});
// Create an access token which we will sign and return to the client,
// containing the grant we just created
const token = new AccessToken(
twilioAccountSid,
twilioApiKey,
twilioApiSecret,
{identity: identity}
);
token.addGrant(chatGrant);
// Serialize the token to a JWT string
console.log(token.toJwt());

The following is a breakdown of the above code:

  • Line 11: We define the identity, which is used as a username.

  • Lines 15–17: We set the chat grant by providing the service ID.

  • Lines 21–26: We create a token by providing the required input parameters.

  • Line 28: We add the chat grant to our token.

Make sure to save the generated access token by clicking “Save.”

Demo application

The following demo application provides a basic JavaScript-based chat interface in which we can send and receive messages in our new conversation. As explained earlier, this demo application requires an access token added in src/ConversationApp.js in line 71.

To start the application, click the “Run” button in the widget below.

const config     = require('./config');
const express    = require('express');
const bodyParser = require('body-parser');
const twilio     = require('twilio');

const app = new express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded

app.post('/token/:identity', (request, response) => {
  const identity = request.params.identity;
  const accessToken = new twilio.jwt.AccessToken(config.twilio.accountSid, config.twilio.apiKey, config.twilio.apiSecret);
  const chatGrant = new twilio.jwt.AccessToken.ChatGrant({
    serviceSid: config.twilio.chatServiceSid,
  });
  accessToken.addGrant(chatGrant);
  accessToken.identity = identity;
  response.set('Content-Type', 'application/json');
  response.send(JSON.stringify({
    token: accessToken.toJwt(),
    identity: identity
  }));
})

app.listen(config.port, () => {
  console.log(`Application started at localhost:${config.port}`);
});


// ============================================
// ============================================
// ====== HANDLE NEW-CONVERSATION HOOK ========
// ============================================
// ============================================
let client = new twilio(config.twilio.accountSid, config.twilio.authToken);

app.post('/chat', (req, res) => {
  console.log("Received a webhook:", req.body);
  if (req.body.EventType === 'onConversationAdded') {
    const me = "Tackleton";
    client.conversations.v1.conversations(req.body.ConversationSid)
      .participants
      .create({
          identity: me
        })
      .then(participant => console.log(`Added ${participant.identity} to ${req.body.ConversationSid}.`))
      .catch(err => console.error(`Failed to add a member to ${req.body.ConversationSid}!`, err));
  }

  console.log("(200 OK!)");
  res.sendStatus(200);
});

app.post('/outbound-status', (req, res) => {
  console.log(`Message ${req.body.SmsSid} to ${req.body.To} is ${req.body.MessageStatus}`);
  res.sendStatus(200);
})

Sign in to the application by using the identity defined while generating the access token. Then, start conversing!