How to set up inbound SMS Support

Do you want to use SMSes as a part of your support?

We have previously covered the benefits of doing this. Now here’s a step-by-step on how to implement it in your system. The guide is divided into three sections:

  • In the first section we will focus on how to configure GatewayAPI and Zendesk.
  • In the second section, we will focus on enabling our customers to send SMS messages back to us in order to create and update tickets.
  • Lastly, we will will focus on how to set up Zendesk to send replies to tickets as SMS messages.

1. Configure GatewayAPI and Zendesk

To enable the system to receive SMS messages, it is necessary to do a bit of configuration in Zendesk and in the GatewayAPI account.

Zendesk

Start by clicking on ‘Settings’ on the left hand menu and under ‘Manage’ go to ‘Ticket Fields’. Click on ‘add custom field’ and select the ‘text-field’ option.

Adding a trigger

Adding a trigger

Give your new field a name, e.g. ‘phone’ and take note of the custom field ID. You will need it later.

Adding a trigger

Gatewayapi

To enable GatewayAPI to receive messages, you first need a phone number that can receive the messages. This can be done in a number of ways. Here I will be using a virtual phone, which can be leased through us, if you want to hear the other options, please contact us on our livechat.

When you have a number ready, you need to set up a URL that can be used to receive HTTP POST requests for the messages you receive. The request will contain a bunch of data: Among other the phone number and the text body of the message.

In this example I will be using the localhost tunnel tool ‘ngrok’, Python and the Flask library to run the code, and give me a public URL that i can use for the web hook, for a production environment, you will of course need to have it running on an actual server. Zendesk has support for a wide range of different programming languages including PHP. You can get a full overview of the languages they have libraries for here.

To complete the setup, go to ‘Settings’ in the GatewayAPI backend -> then ‘web hooks’ -> and lastly click on ‘add a new REST web hook’. Give your webhook a name and insert your url.

Now GatewayAPI and Zendesk are ready for the next step, in which will focus on how to enable customers to send SMSes to you.

Adding a trigger

2. Enable customers to send SMSes back

With Zendesk and GatewayAPI configured, It’s now time to start putting some actual functionality on the webhook. As mentioned, I will be using Python but you are free to use whatever programming language you prefer. You can also just communicate directly with Zendesks API which is very well documented

I will use the following libraries to perform the various tasks:

from flask import Flask, request, Response
from requests_oauthlib import OAuth1Session
from zenpy import Zenpy
from zenpy.lib.api_objects import Ticket, CustomField, Comment, User

To begin with, define a function that will send an SMS back to the customer to confirm what actions have been taken based on their input. It can also be a report indicating that their input was not understood or not allowed.

def _send_reply(number, message):
    key = 'Create-an-API-Key'
    secret = 'GoGenerateAnApiKeyAndSecret'
    api = OAuth1Session(key, client_secret=secret)
    req = {
        'sender': 'Put Your GatewayAPI number here',
        'message': message,
        'recipients': [{'msisdn': number}],
    }
    res = api.post('https://gatewayapi.com/rest/mtsms', json=req)
    res.raise_for_status()

You now need to make a set of commands for the users to get support via SMS. The code will casefold the command, so it can handle mix cased input correctly. All commands, except ‘Help’ will search for the command keyword first, followed by the message that the ticket will be created or updated with. A list of commands could be:

  • Help
  • New
  • [ID] - the integer id of the ticket to update.

This list can be extended with anything you might find useful by utilizing the Zendesk API.

Now we come to the exciting part of actually adding some Zendesk functionality to our solution. First you need to decide on your method of authentication. I will use token based authentication in this example. For this you need to create an API token in Zendesk by clicking ‘Settings’ in the menu, and under ‘Channels’ click ‘API’. Now you can use the token to set up a Zenpy client in Python.

credentials = {
    'email': 'The email used to access you zendesk account',
    'token': 'Your-Token-Here',
    'subdomain': 'Your zendesk account name here',
}

zenpy_client = Zenpy(**credentials)

If you are not familiar with Python, the ‘**credentials’ pass the content of the dictionary to Zenpy as keyword arguments. Define a route in Flask afterwards which should be the URL you have chosen for the webhook in GatewayAPI. It should be configured to only accept POST requests since that is how inbound messages are sent.

@app.route('/inbound', methods=['POST'])
def zendesk_support():
    req = request.get_json(force=True)
    msg = req['message'].split(' ')
    if msg[0].casefold() == 'new':
        msg.pop(0)
        if not msg:
            _send_reply(req['msisdn'], 'Please add a message after new,'
                        ' so we know what you need assistance with')
            return Response(status=204)
        message = ' '.join(msg)
        new_ticket = zenpy_client.tickets.create(
            Ticket(
                subject=message[:40],
                description=message,
    			requester=User(name=str(req['msisdn']),
                               external_id=req['msisdn']),
                custom_fields=[CustomField(id=YourCustomFieldID,
                                           value=req['msisdn'])],
                )
            )
        _send_reply(req['msisdn'],
                    'We have created a ticket with id: '
                    f'{new_ticket.to_dict()["ticket"].id}, if you have '
                    'furhter comments for your ticket please write us '
                    'a message starting with your id followed by your '
                    'new comment')

First get the JSON body of the incoming request and retrieve the message, then split the string at spaces, and check if the first word matches the keyword ‘new’. If that is case, you can discard the keyword since you don’t need it any longer.

Afterwards check that there is other words after ‘new’. If not, then write back to the customer and request that they send an actual message along with the keyword. If there are more words, join them back to a string and create a ticket using the first 40 characters as the subject and the full message as the body of the ticket.

Afterwards you need to set the requester of the ticket to an anonymous user. To do this, create a user with name, and external_id, both set to, the phone number that sent the SMS. If this is not configured, it will use the credentials from the API call which would make all SMS tickets look like they are from your developer.

Then set the custom field ‘phone to the phone number’. Remember we saved the custom field ID way back when we started, we finally need it, good luck finding your post-it note ;). The custom field is also needed so we can use the Zendesk placeholder later on.

Now to checking if the customer wishes to update an existing ticket.

elif msg[0].isnumeric():
    try:
        ticket = zenpy_client.tickets(id=msg[0])
        user = next(zenpy_client.search(
                    type='user', external_id=req['msisdn']))
    except RecordNotFoundException:
        _send_reply(req['msisdn'],
                    f'No ticket found with id: {msg[0]}')
        return Response(status=204)
    except StopIteration:
        _send_reply(req['msisdn'],
                    f'No tickets have been created from: {req["msisdn"]}')
    print(user.external_id == str(req['msisdn']))
    if user.external_id != str(req['msisdn']):
        _send_reply(req['msisdn'], 'You are trying to update a'
                    ' ticket that was not created by you')
        return Response(status=204)
    msg.pop(0)
    if not msg:
        _send_reply(req['msisdn'], 'Please add a message after your'
                    ' id, so we know what to update your ticket with')
        return Response(status=204)
    ticket.status = 'open'
    message = ' '.join(msg)
    ticket.comment = Comment(body=message, public=True,
                             author_id=user.id)
    zenpy_client.tickets.update(ticket)

First, get the existing ticket. If it doesn’t exist, you are done and you can tell the customer that there is no such ticket id in your system. Then check that the ticket is being updated from the same phone number that created it, if not we do not allow updating the ticket. This will avoid that tickets are updated randomly. Then throw the keyword part of the message away and check that there is a comment to update the ticket with, set the status of the ticket to ‘open’ and update it with the comment message. Then we need a

Now you need a command to show your customers what they can write to you. Enter the ‘help’ command.

elif msg[0].casefold() == 'help':
    _send_reply(
        req['msisdn'],
        f'Hi, we support the following commands: \n New - Create new, '
        ' ticket \n ID - update your ticket id \n Help - Show this '
        'menu'
    )

This will simply send back a reply showing what they can do. Lastly, you can set up a net that catches all other input and send back a reply indicating that the request was not understood.

else:
    _send_reply(
        req['msisdn'],
        f'You wrote {req["message"]}: text us help to see what options'
        ' you have'
    )
return Response(status=204)

Your customers are now able to contact you and your support team via SMS messages. In the last part of the guide, we will look at how you can set up Zendesk to send replies to tickets as SMS messages.

3. Replying to tickets with SMS.

To achieve this we are going to need to uses zendesks Target and Trigger systems.

Setting up a target

First you need an API token from GatewayAPI. You can get it from settings -> API Keys -> then click the button with the key symbol.

Adding a target

Now go to Zendesk’s backend -> click on the menu on the left side -> click on settings. Under Settings, click extensions -> click add target -> choose HTTP target.

Adding a target

Adding a target

Now you need to setup your Target. Fill out the input fields as follows:

Title: Your Target’s name.

URL: https://gatewayapi.com/rest/mtsms

Method: POST

Content type: JSON

Basic Authentication: Enabled, put your API token in Username leave Password empty.

Setting up your target

You can use the test Target option to make sure everything is working as intended and send yourself an SMS. Test Target prompt you to define the JSON body. You can copy the JSON below and use it to test your target. Remember to put your own phone number in the recipients list, and remember the country code, 45 is for Denmark.

{
  "message": "Hello world, from zendesk",
  "recipients": [{"msisdn": 4512345678}],
  "sender": "testzendesk"
}

When everything works, create the Target.

You now have a Target you can use to send SMS messages to your customers when an agent replies to their tickets using the custom field phone we added in the beginning of the guide.

The Target can also be used on other triggers to notify persons on your team, but unfortunately this can only be done to a predefined list of recipients and not in a dynamic way to notify specific agents, as Zendesk doesn’t offer access to the agents phone number under the triggers. But could potentially be used to send warnings if a ticket has not had a response within an hour or a day, whatever suits your business.

Setting up a trigger

To set up a trigger, go to settings in the Zendesk backend -> under ‘Business Rules’ click ‘triggers’ -> then ‘click add trigger’ or edit one of your existing triggers.

Adding a trigger

Under your trigger choose the conditions you want your trigger to react on. Here you can just edit the default trigger called ‘Notify requester of comment update’. All you need to do is add a notification to add the Target action to the trigger.

Chose the notify target action

Chose the notify target action

To define the JSON body for this trigger, you can use Zendesk’s ‘placeholders’ in the message. All available placeholders can be found by clicking ‘View available placeholders’. Your JSON body could look something like this.

{
  "message": "An agent has replied to your ticket .\n\nYou can send your reply by responding to this SMS with  followed by your message",
  "recipients": [{"msisdn": }],
  "sender": "Put your phone GatewayAPI number here"
}

You are now able to receive and reply to tickets using SMS messages.

Congrats.