Messages API Integration
You can integrate the Messages API with the Vonage Client SDK to allow for inbound messages to the Messages API to be sent to a Conversation, and for outbound messages to be delivered back via the Messages API.
To continue you should already be familiar with:
- Receiving inbound messages with the Messages API
- Conversations
- Users
- Conversation Members
- Sending Message Events with the Vonage Client SDK
How It Works
When dealing with Messages API there are the inbound and outbound cases to consider.
Inbound Messages
When you receive an inbound message to your Messages API Inbound webhook URL, you reply with a JSON object which tells the Messages API to forward this message to the Conversation API with some information about which Conversation the inbound message should be forwarded to.
Below is an example using JavaScript and Express.JS:
app.post('/message/inbound', (req, res) => {
const username = `+${req.body.from}`;
const conversationName = 'my_conversation';
const region = 'eu-3';
console.log(username, conversationName, region);
res.json([{
action: 'message',
conversation_name: conversationName,
user: username,
region: region,
}]);
});
This route gets called on each inbound message to the Vonage Application, for SMS this would be triggered by an SMS being sent to a virtual number linked to your Vonage Application but the process is the same for the other channels offered by the Messages API. The response is a JSON object, which is similar to the Call Control Objects used for Voice, which gives information to the Conversation API on how to handle this message. The Conversation API does a few things automatically for you with this response:
It looks up a Conversation with the name given in the
conversation_nameproperty, in the region given in theregionproperty. If it does not exist it will create one in the specified region.It looks up a User with the name given in the
userproperty, in the region given in theregionproperty. If it does not exist it will create one in the specified region.If they are a new User or are new to the specified Conversation, it will then add the User as a Member of the Conversation. Then a message event will be created in the Conversation with the body of the original inbound message sent to the webhook.
As you can see, the region is vital to make sure inbound messages from the Messages API get to the correct Conversation. The regions are the same ones used in the Voice API and Client SDK configuration. In a production environment, you will likely need to build a way to disambiguate the inbound message webhook to make sure it gets to the correct Conversation. This might look like a mapping from a phone number to a specific Conversation, or you may ask the sender to include some sort of predictable text in the message to control which Conversation the message goes to:
Conv1: Hello World!
Conv2: Hello Vonage!
You can split the string on : and use the first element, e.g. Conv1 as the Conversation name.
Outbound Messages
Outbound messages (new Conversation Message Events) will automatically be sent by the Conversation API back via the same channel that the inbound message was received on. When a User is added to a Conversation, this creates a Member. Membership can be seen as a binding of a User to a Conversation via a Channel. In addition to the Channels the Conversation API supports, the Messages API channels are supported for messaging.
When an inbound Messages API message gets forwarded to the Conversation API, it creates a Member in the specified Conversation with the Channel in which the inbound message was received. For example, if the above webhook code snippet was used in response to an inbound SMS message using the Vonage Server SDK you can get the member object:
const member = await vonage.conversations.getMember(
'my_conversation_id',
'sms_member_id'
);
Which would give the object:
{
"id": "MEM-644630b7-1ba6-4c71-9fae-834316f1d1d5",
"conversationId": "CON-0f9af192-d916-4365-b0cb-1b7e3c53576c",
"channel": {
"type": "sms",
"from": {
"number": "447441446999"
},
"to": {
"number": "441234567890"
}
},
...
}
As you can see, the channel object contains the type of SMS as expected, with the from.number being the virtual phone number linked to my Vonage Application, and the to.number is the number that sent the SMS. Compare this to another In-App Member object from the Client SDK:
{
"id": "MEM-f5fa689b-8a3f-43f3-87fd-5af0d3e35221",
"conversationId": "CON-0f9af192-d916-4365-b0cb-1b7e3c53576c",
"channel": {
"type": "app"
},
...
}
When a new Message Event is sent to the Conversation, the Conversation API will look up the channel for the Member and deliver the Message Event there. So for the first Member, an SMS will be sent via the Messages API to the to.number from the virtual from.number and for the second Member, it will be delivered via In-App Messaging.
Creating Message API Users and Members
As shown above, the Conversation API can create a User and Member for you automatically, but if you want to create this yourself you can do so using the Vonage Server SDK or the Conversation API directly:
const number = 'sms_sender_number';
const vonageNumber = "my_vonage_number";
const conversationId = 'my_conversation_id';
const formattedNumber = `+${number}`
const user = await vonage.users.createUser({
name: formattedNumber,
displayName: formattedNumber,
channels: {
sms: [{
number: number
}]
}
});
const member = await vonage.conversations.createMember(
conversationId,
{
state: 'joined',
user: {
name: user.name
},
channel: {
type: 'sms',
from: {
number: vonageNumber
},
to: {
number: number
}
}
}
);
console.log(member);
This will first create a User with an SMS Channel that contains the phone number the User will use to send an SMS. Then that User is added as a Member of the Conversation with an SMS Channel as described above. The Channels on the User are validated against the Channels supplied when creating a Member.