Vonage
Send text messages (SMS) with Vonage

This page will show you how to send text messages through Vonage from Python:
- What to collect from the Vonage dashboard
- Which security definition and outgoing REST connection to create
- How to send a message from a service and read Vonage's response
Collecting Vonage config
You'll need three details from the Vonage API dashboard:
- The API key, on the dashboard's home page
- The API secret, on the same page
- The sender, which is a virtual number of the account, such as
12025550100, or an alphanumeric sender ID in the lands that permit one
Creating Zato connections
First, create a Basic Auth definition under Security → Basic Auth - the Messages API signs in each request with the API key as the username and the API secret as the password:
| Field | Value |
|---|---|
| Name | Vonage SMS |
| Username | The API key |
| Password | The API secret |

Next, create an outgoing REST connection under Connections → Outgoing → REST:
| Field | Value | Notes |
|---|---|---|
| Name | Vonage SMS | --- |
| Host | https://api.nexmo.com | --- |
| URL path | /v1/messages | --- |
| Data format | JSON | --- |
| Security | Basic Auth/Vonage SMS | The definition just created |

Sending a message
The service below will:
- Build the message from the input it received
- Send it to Vonage
- Return the ID Vonage gave the message
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class SendVonageSMS(Service):
name = 'sms.vonage.send'
input = 'to', 'text'
def handle(self):
input = self.request.input
# The message in Vonage's format ..
message = {
'message_type': 'text',
'channel': 'sms',
'to': input.to,
'from': '12025550100',
'text': input.text,
}
# .. get the connection to Vonage ..
conn = self.rest['Vonage SMS']
# .. send the message ..
response = conn.post(message)
# .. make sure Vonage accepted it ..
if not response.ok:
title = response.data['title']
detail = response.data['detail']
raise Exception(f'Vonage error {title}: {detail}')
# .. and tell our caller the ID of the message.
message_id = response.data['message_uuid']
self.response.payload = {'message_id': message_id}
Numbers go to Vonage in E.164 form without the leading +, so the service is invoked with {"to": "12025550123", "text": "Your appointment is tomorrow at 9:00"}.
After invoking the service you'll see:
Vonage answers with 202 Accepted and the UUID of the message, which means it has been accepted for delivery.
Errors
When Vonage does not accept a message, it answers with a 4xx status and a JSON body whose title and detail say why, e.g.:
{
"type": "https://developer.vonage.com/api-errors#unauthorized",
"title": "Unauthorized",
"detail": "You did not provide correct credentials.",
"instance": "bf0ca0bf927b3b52e3cb03217e1a1ddf"
}
The service above converts such a response to an exception containing the title and the detail.
See also
| Page | What it covers |
|---|---|
| How to send text messages (SMS) | Send every text from one service, so a change of provider later means editing that service alone |
| Twilio | Send through Twilio and test for free with credentials that never deliver or charge for a message |
| Infobip | Tell everyone at once - one request sends the same text to any number of recipients |
| Africa's Talking | Try every message for free in a sandbox that shows it on a simulated phone instead of delivering it |
| Basic Auth | Keep the username and password out of your code - Zato adds them to every request the connection makes |
| Calling external REST APIs | Call any other REST API the same way, with parameters, headers and status checks |