# How to send text messages (SMS)

Create SMS connections and send text messages from Zato services

There are several popular SMS providers you can choose from for sending messages, and you communicate with each of them

using REST connections, where:

- A connection holds the provider's address and the path of its endpoint for sending messages
- A security definition holds the credentials, and the connection attaches them to each request
- Your service builds the message in the provider's format and posts it through the connection

## Step 1 - Choose a provider {#step-1-choose-a-provider}

Each provider has its own page with the details to collect from its console, the security definition and the connection to create:

| Provider | Security definition | Data format |
| --- | --- | --- |
| [Twilio](https://zato.io/docs/dev/examples/sms/send/twilio.html) | Basic Auth | Form data |
| [Vonage](https://zato.io/docs/dev/examples/sms/send/vonage.html) | Basic Auth | JSON |
| [Infobip](https://zato.io/docs/dev/examples/sms/send/infobip.html) | API key | JSON |
| [Africa's Talking](https://zato.io/docs/dev/examples/sms/send/africas-talking.html) | API key | Form data |

This tutorial uses Twilio.

## Step 2 - Create the connection {#step-2-create-the-connection}

Create the security definition and the outgoing REST connection described on the [Twilio](https://zato.io/docs/dev/examples/sms/send/twilio.html#creating-zato-connections) page, with the connection named `Twilio SMS`.

The connection can be used as soon as you click OK, and no restart is required.

## Step 3 - Write the service {#step-3-write-the-service}

Say a clinic sends its patients text messages - reminders, changes to appointments and results ready for pick-up - and several services are to send them. The service below is the one place they all send from:

- It takes the recipient's number and the text of the message
- It builds the message in Twilio's format and sends it
- It returns the ID Twilio gave the message and its status

Take the code below and deploy it, then invoke it from the Dashboard's IDE under `Services → IDE` with `{"to": "+12025550123", "text": "Your appointment is tomorrow at 9:00"}` on input.

```python
# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class SendSMS(Service):

    name = 'sms.send'
    input = 'to', 'text'

    def handle(self):

        input = self.request.input

        # The message in Twilio's format ..
        message = {
            'To': input.to,
            'From': '+12025550100',
            'Body': input.text,
        }

        # .. get the connection to Twilio ..
        conn = self.rest['Twilio SMS']

        # .. send the message ..
        response = conn.post(message)

        # .. make sure Twilio accepted it ..
        if not response.ok:
            code = response.data['code']
            reason = response.data['message']
            raise Exception(f'Twilio error {code}: {reason}')

        # .. and tell our caller what Twilio said.
        self.response.payload = {
            'message_id': response.data['sid'],
            'status': response.data['status'],
        }
```

## Step 4 - Run it {#step-4-run-it}

After invoking the service you'll see the ID of the message and its status as below:

```json
{"message_id": "SM9f2c5a1e8b7d4c3a2f1e0d9c8b7a6f5e", "status": "queued"}
```

The message reaches the phone within seconds, and the [audit log](https://zato.io/docs/admin/audit-log/index.html) of the connection records the request and Twilio's response.

## Sending from other services {#sending-from-other-services}

Other services do not need to know which provider sends their messages, or in which format. They invoke `sms.send` with a number and a text.

The service below sends a reminder for an appointment:

```python
# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class SendAppointmentReminder(Service):

    name = 'clinic.send-appointment-reminder'
    input = 'phone', 'location', 'starts_at'

    def handle(self):

        input = self.request.input

        # The text of the reminder ..
        text = f'Your visit at {input.location} is on {input.starts_at}.'

        # .. the request to the service that sends text messages ..
        request = {'to': input.phone, 'text': text}

        # .. and send the reminder through it.
        response = self.invoke('sms.send', request)

        self.response.payload = response
```

A scheduled job can invoke this service each morning for the next day's appointments, and a REST channel can invoke it for the appointments booked online.

## Changing providers {#changing-providers}

Because every service sends through `sms.send`, a change of provider is a change to that one service and to the connection it uses, and no other service changes.

For instance, with a [Vonage](https://zato.io/docs/dev/examples/sms/send/vonage.html) connection named `Vonage SMS`, the message and the call become:

```python
# The message in Vonage's format ..
message = {
    'message_type': 'text',
    'channel': 'sms',
    'to': input.to.lstrip('+'),
    'from': '12025550100',
    'text': input.text,
}

# .. sent through the connection to Vonage.
conn = self.rest['Vonage SMS']
response = conn.post(message)
```

## Phone numbers {#phone-numbers}

All four providers expect numbers in the international E.164 form, which is a country code followed by the number, e.g. `+12025550123`. Twilio and Africa's Talking take the number with its leading `+`, while Vonage and Infobip take it without one, e.g. `12025550123`.

## See also {#see-also}

- [Twilio](https://zato.io/docs/dev/examples/sms/send/twilio.html) - Send through Twilio and test for free with credentials that never deliver or charge for a message
- [Vonage](https://zato.io/docs/dev/examples/sms/send/vonage.html) - Send through Vonage with your organization's name as the sender, in countries that allow one
- [Infobip](https://zato.io/docs/dev/examples/sms/send/infobip.html) - Tell everyone at once - one request sends the same text to any number of recipients
- [Africa's Talking](https://zato.io/docs/dev/examples/sms/send/africas-talking.html) - Try every message for free in a sandbox that shows it on a simulated phone instead of delivering it
- [REST outgoing connections](https://zato.io/docs/dev/rest/outconns.html) - Make sure no message is lost, with timeouts, retries and a queue for messages the provider could not take
- [Calling external REST APIs](https://zato.io/docs/dev/rest/calling-apis.html) - Call any other REST API the same way, with parameters, headers and status checks

## Learn more {#learn-more}

- [Development documentation](https://zato.io/docs/dev/) - The complete reference for writing services
- [Requests and responses](https://zato.io/docs/dev/request-response/) - What a service receives, what it returns and how both are structured
- [Integration examples](https://zato.io/docs/dev/examples/) - Ready-made code for the systems you are likely to connect to
- [IDE and debugging](https://zato.io/docs/dev/ide/) - Write services in the Dashboard or in your own editor
- [Data models](https://zato.io/docs/dev/model/) - Declare inputs and outputs and have them validated for you
- [In-depth API tutorial](https://zato.io/tutorials/main/01.html) - The full platform tutorial, from installation to production patterns
