# Your first SMS

Create the connection, send a text message from a service and let other services send through it.

This tutorial will show you how to send a text message from a Python service.

Every SMS provider offers an HTTP API for sending messages, so Zato reaches a provider through a regular [outgoing REST connection](https://zato.io/docs/dev/rest/outconns.html):

- The 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 is ready the moment you click OK, with no restarts anywhere.

## 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) - The Twilio console details, the connection and a message sent through it
- [REST outgoing connections](https://zato.io/docs/dev/rest/outconns.html) - Every field of an outgoing REST connection, timeouts and retries
- [Calling external REST APIs](https://zato.io/docs/dev/rest/calling-apis.html) - Parameters, headers and the response object of a REST call

## Learn more {#learn-more}

- [Development documentation](https://zato.io/docs/dev/) - Everything about writing services, in one place
- [Requests and responses](https://zato.io/docs/dev/request-response/) - What a service receives, what it returns and how to shape both
- [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
