Every client Application (APP) has an API Key associated with it. This key is generated during the creation of the APP and can be re-generated from the show / edit screens in the Service Layer (SL) administrative console.
This key uniquely identifies an APP during the calls the APP does to the SL.
All calls should be performed with POST request. The API Key (api_key) is the only form field required to be present in every call to the service layer since it is necessary to identify the application.
There’s an API URL that is used at all times to which the name of the operation is appended:
URL: http://sl.holmesmobile.com/api/<operation> or https://sl.holmesmobile.com/api/<operation> (SSL support)
Parameters that you specify in the calls to API and receive in callbacks from the API can be of different types.
Regular text string.
Integer number, either positive or negative.
We are quite flexible with booleans.
Dates and times parsing is very liberal in the SL. We are capable of parsing almost everything that can be interpreted as a date / time or even a clue of them. Here are some examples of what the dates can look like:
If you need a stricter definition, you can refer to RFC2822 (3.3. Date and Time Specification).
This set of calls let the application to associate / dissociate more keywords with itself. All necessary checks are performed automatically to avoid conflicts.
Associates the keyword with the application.
Parameters:
Responses:
Breaks the link between the keyword and the application.
Parameters:
Responses:
If an application needs to send a message to a certain phone number, it uses this call. The message can be of arbitrary size. If it doesn’t fit into the standard message size (160 characters), the message will be broken into several parts automatically, like this:
Scheduled messages are sent in batches every 15 minutes. The format of the date (“on” field) may vary from very strict “10/12/2008 12:55AM -0500” to the relaxed “Tuesday 9 1:15PM”. If the timezone isn’t specified, the EST (GMT-5) is assumed.
Split Modes:
When message breaking is necessary, it can be performed in one of three predefined ways. The way can be chosen on per-application basis and is set in the Application preferences on the Service Layer side.
Parameters:
Responses:
Sometimes you need to send several slightly different messages to several phone numbers. You could issue multiple “send_message” requests, but there’s a better way. Basically, you specify a template to use as a basis for your messages and then for each number you only give the different parts to paste into the template for each number. Here’s an example:
The phone number 0123456789 will receive “Hello John. You have 5 credits left.” and the phone number 9876543210 will receive “Hello Mary. You have 10 credits left.”
Parameters:
Responses:
This call cancels messages scheduled for future delivery with the send_message call with parameter “on”. The send_message call returned the list of IDs corresponding to all scheduled messages or parts of the bigger message that didn’t fit into a single text message. You can use these IDs to cancel future messages at any moment.
Please note that this call can cancel only non-subscription messages. To cancel subscription-level messages, use “cancel_subscription_messages” call.
Parameters:
Responses:
This call accepts a single sent message ID or the list of IDs separated by commas and returns the status for each of the messages. If the message wasn’t found, it’s not mentioned in the results. The statuses have numeric values and are as follows:
Parameters:
Responses:
Assigns the list of tags to the list of phone numbers among the subscribers of your application.
Parameters:
Responses:
Removes the tags in the list from the phone numbers (all or specific, if they are given).
Parameters:
Responses:
Returns the number of subscribers in each tag.
Parameters:
Responses:
Sends a message to the application subscribers. The message is split into multiple parts using the preferred application splitting mode automatically.
If the list of tags is given, subscribers with these tags are chosen. If no tag is specified, all subscribers receive the message.
If the time in the “on” field is given the call operates in the scheduling mode. It schedules a message to be sent to the application subscribers in a future. The message text will be split and otherwise processed as in the usual subscription message sending. The date of the message sending has to be tomorrow or later. The date can contain the suggested time and the application will use it as a guidance. The message is guaranteed to not be sent before this time, but can be sent later. The messages are supposed to be sent in batches periodically during the day (currently every two hours). The format of the date may vary from very strict “10/12/2008 12:55AM -0500” to the relaxed “Tuesday 9 1:15PM”. If the timezone isn’t specified, the EST (GMT-5) is assumed.
Parameters:
Responses:
This call cancels subscription messages scheduled for future delivery with the send_subscription_message call with the parameter “on”. The send_subscription_message call returned the list of IDs corresponding to all scheduled messages. You can use these IDs to cancel future messages at any moment.
Please note that this call is for scheduled subscription messages. Use “cancel_messages” call for regular future messages cancellation.
Parameters:
Responses:
Client applications receive callbacks from the Service Layer through their Gateway URL. There are difference callbacks that let the application know of certain events with the user sessions, subscriptions and more.
Callback date and type are set as individual fields in the POST request to the client application. Field “type” contains the name / type of the function, and other fields contain additional information that may be useful to the application in its processing of the callback — phone numbers, message bodies and other parameters.
Callbacks aren’t required to be implemented. In fact, you can ignore all of them, although this application may be not very useful. We imagine that you will want to at least listen to incoming messages through the “incoming_message” callback.
Some of callbacks have optional responses expected, such as the list of tags to assign to a newly created subscription (see subscription_created callback). The format of the response is currently set to the plain text, but later this may be changed to the JSON. This step may be required to facilitate rich and structured responses.
It’s suggested that you process the callback as fast as possible on the client application side to release Service Layer resources.
Received when new MO arrives and it’s routed to this client application.
When the message initiates the session and the keyword that was a match is marked as for the auto-subscription, the “auto-subscribe” flag is set meaning that after this callback is processed there will be an automatic subscription of the texter performed by the service layer. As the result of this process, there will be a subscription confirmation message sent to the texter, meaning that you may decide not to send a normal response from this (incoming_message) call to avoid sending two messages.
If the message is marked as “auto_responded”, it means that the texter has already received the message that was associated with the keyword. You may choose to send another message or stay silent to avoid duplicates.
Parameters:
Responses:
When the message is sent with send_message (either in the future or immediately), the list of message IDs is returned. Each ID represents the part of the original message if it was larger than the maximum allowed number of characters in the single SMS message.
Parameters:
Responses:
This callback is performed when the user session with an application is closed for any reason. It can be the session expiry or the explicit command from the user.
Parameters:
Service Layer, when it takes care of the subscription management (Subscription Module is enabled for the application), consumes all messages related to the subscription cycle, such as STOP, SUB, Y and others. In order to still let the application know and react to subscription / cancellation events, we provide convenient callbacks.
This callback is performed when a new subscription is created. The application may decide that this particular subscription has to be tagged in some way. If it does, the comma-separated list of tags can be returned as the HTTP response to this callback request. Tags can contain spaces, letters, digits, ‘-’ and ‘_’ characters.
Parameters:
Responses:
This is invoked when a user decides to unsubscribe from the application.
Parameters:
Modules let developers to add more standard processing options to the service layer. Modules are called when an incoming message arrives to the application, and are expected to return either nil (if they don’t know how to handle the message), or the hash with the following fields:
Modules are organized in the chain (see App#MODULES), and are processed in this order. If the first module returns the result, the second listed isn’t called and even not instantiated.

The example of a module is the subscription processing. Given that many applications share this functionality, we extract the processing of keywords “SUB”, “Y”, “STOP” in a module and place it before the “Client App Call” module so that if one of these keywords arrive, we can process them ourselves on the Service Layer instead of sending the request to the client application.
You can have any number of modules.
Sometimes modules will require different configuration from application to application. It’s suggested to have a separate table for configuration options for a specific module and link it to the application table through the 1-to-1 relationship. However, with the potential growth of modules the approach may be overlooked in favor of an module settings table that will hold key/value rows suitable for the use by any modules in a unified way.
Help module listens for the HELP keywords to applications and makes sure that the response the application sends is delivered as Free To End User (FTEU) message.
The module doesn’t do anything besides that. It delegates the processing to the client application, and wraps the response in the correct structure.
Static responses module provides an extremely flexible feature — automated responses to certain keywords — to client applications or SMSCs in general. Static responses are stored in the table where keywords are associated with responses.
When MO arrives, its contents are checked against the table associated with the target application (or with SMSC it came through if no application is currently associated with the phone number). If the message finds its response, the client application never receives it, but instead the MT is sent automatically.
An application or SMSC can have any number of static responses that can be registered through the application (or SMSC) details page. Every message can have the Free flag set which means that the response has to be sent as an FTEU message.
Configuration:
Subscriptions module when enabled controls whole cycle of subscription management and enables the applications to use subscription registration, tagging and message sending.
The module monitors incoming messages for the keywords and processes them when detected without passing the messages to the client applications. Keywords and responses to them are entered in the Subscription Configuration on per-application basis.
All subscribers are registered in the Subscriptions table and can be tagged by the client application for the purpose of grouping.
Configuration:
Welcome module is intended to send Welcome responses to the first-time users of SMSCs or applications.
This module works on two levels: SMSCs and Applications. In most cases, responses belong to a specific application and they will be passing through the application-level module. In rare cases, when the message is not associated with any application, the module of the SMSC it came through will be working with it.
This module doesn’t stop the processing of the message. It sends the welcome message (if entered) in addition to the further processing which may or may not result in any additional messages.
Configuration:
Service Layer lays in the heart of the system. The goals of the Service Layer are:
The high-level design of the system is presented on the first page of the document attached ( Service Layer.pdf ). You can clearly see that the system is composed of three main parts: the database, service layer and web-based front-end.
Service Layer is intended to communicate with Kannel and client applications acting as a midware and controlling the workflow. The web-based front-end is the so-called “face” of the system that is used to configure, manage and monitor the system.
Each Client (Application) can be assigned a certain service plan that specifies the prices and (maybe later) available features. Currently there’s a need to have two plans, but the number can grow with time. It’s even possible that current requirement can be reduced to a single plan.
Service Layer, as a module, has no graphical interface. Although there’s a web-based front-end that the clients of the system and staff use to:
The front-end works with the same database as the Service Layer. Even though the front-end and the Service Layer can be fit into the boundaries of the same web application, it’s suggested to think of them as of two different modules to aid proper separation of concepts and responsibilities.
Building user applications with an operating Service Layer is extremely easy. It’s necessary to understand though that an Application is external to the Service Layer. Service Layer contains no logic specific to any application, but rather abstract common information usually in the form of the workflows.
What is a workflow? A Workflow represents some common logic of the application. For example, many applications use the same logic of providing the response to the HELP message, as well as many applications provide means of SUBSCRIBING and UNSUBSCRIBING to/from some service. These typical scenarios can be handled by the middleware (Service Layer) once it’s instructed about what to do when a certain event happens (what text to show in response to the HELP message, and what URL to use to notify about new subscriptions). A proper workflow can be selected for each application through selecting and configuring any of provided modules.

The two-way communication between an Application and the Service Layer is required. By this I mean that the initiator of the exchange can be both the Service Layer (an external message has arrived and an action from the Application is required) and the Application (something happened on the Application side and messages have to be delivered). This requirement dictates that there have to be at least two URL’s known to the developer of an application:
http://myserver.com/notification.php
http://sl.holmeslabs.com/api/...?api_key=<key>
As you already know, Gateway URL is used to communicate from the Service Layer to the Application when a new MO is to be delivered. Service Layer makes a POST HTTP request and provides the following data:
All MO’s are stored on the Service Layer side for billing and any reviews.
After processing of the Gateway URL request, an Application has two options:
We agreed that in order to make the service as simple and as accessible as possible, simple and accessible data transmission formats are to be used. By these formats I mean JSON and possibly XML-RPC. There will be a known degree of flexibility in choosing the format a client wants to work with, and it will be possible to add new formats later.
It’s assumed that the chosen format will be used to send data in both directions, but it’s also very easy to change.
The layout of the messages still has to be defined.
Why not Apache? Apache has a feature which is nice and dangerous at the same time — worker threads reusing. It’s nice because it uses the same worker threads over and over to process requests and return responses. It’s dangerous because the threads grow in size allocating memory. Initially, the server starts with minimum memory requirements. To serve an image it takes, say 100Kb of memory. Now the same worker is used to respond to a dynamic call and allocates 5Mb of memory. Since it never releases this memory (under load if threads don’t have time to terminate and be re-created, or the minimum pool size is set to some value), soon all workers due to the reusing feature will be of the maximum size (5Mb in our example). NGINX + Mongrel Cluster solves this problem. NGINX is used to send these little files quickly, while giving the heavier requests to Mongrels.
If you have an application that you want to accept incoming messages, all you need to do is to give us (register on your application page) the URL you’d like us to call when they arrive. The response will be in the form of a POST request containing all of the message details. Moreover, you can even respond with the text to send back to that phone as a reply if you’d like.
So, no, you don’t need to poll our system for new messages. Simply write a handler that accepts POST requests and do whatever your business logic requires with it. This handler will receive other events as well (subscriptions, delivery reports, etc.), but you are free to implement only the parts you need. For details, consult with the Callbacks documentation.
When you want to deliver a message to a single phone number, use the “send_message” API call, specifying the message body, phone number, whether the response is expected, and the time of delivery if you’d like to schedule it to be sent later.
When you have something to say to several phone numbers, you can use the “send_message” API call as you would with a the single phone number (above), but specify all of your numbers as a comma-separated list.
When you want to send a personalized message that follows a common pattern to several numbers, you can do that with the “send_messages” API call. Just specify the template (like “Hello {{name}}”) and then provide a JSON-formatted hash of phone numbers to the substitutions map (like “{’0123456789’: {’name’: ’Jack’}, …}”. We will place your custom values for each number in the corresponding placeholders and deliver.
When you send a message, we return the ID of this message that you could use for your internal records, and for asking for the delivery status of the message. Even though you will be notified through the callback when the status of the message changes, you can still ask the Service Layer for the status directly at any moment.
When the delivery status is reported or you get it back as the result of your direct query, it can be one of the following values:
We have one shortcode and several applications. When a message from a cell phone arrives, it’s the Service Layer’s responsibility to identify which application to send this message to. The Service Layer maintains the table of sessions (virtual links with phone numbers and applications). If there’s a record for the cell phone number in question, it knows the application to send the message body to.
Once a user is in session with your application, you can treat the shared shortcode as thought it were dedicated, with a wide-open keyword space. For instance, if you’re building a chat application, there’s no need for your users to memorize strange commands, like “reply to every message with MYCHATKEYWORD then your message,” to send in free-form messages. Just initiate a session and let them text naturally.
If there’s no record in the sessions table, the Service Layer takes the body of the message and attempts to find an application that is expecting something resembling that message body. For example, when your application is associated with the keyword “Surf,” when a message with this text arrives, the Service Layer will establish a virtual link between the source phone number and your application. All of the following messages (no matter the content) from this phone number will be sent directly to your application until the session expires (based on inactivity type) or until the phone number sends an opt-out message, such as “STOP.”
Traditionally (so far as SMS has traditions), keywords were the primarmy means of interacting with a text-messaging system. You would set up a simple marketing campaign and have users subscribe to it by texting in a keyword to a shortcode, or set up an auto-responder to kick back a coupon when a user texts in a particular keyword.
With our API, keywords are used to identify which application a user intends to talk to. Any application can have multiple keyword associations. All keywords can be matched in either “Starts with” or “Matches exactly” modes. We treat keywords as only the starting point for a truly functional SMS application.
If your app has no keywords associated with it, we won’t be able to route any messages to it. When a message from a phone number with no active session comes, we scan it for keywords and see which application matches, create a session for it and send the message over. If you don’t have keywords, your app will never be matched, and your users will be shouting into the ether.
“Starts with” mode matches any keywords a user texts in that begin with the keyword you associate. For example, if you have a weather forecasting application, you may want to associate the keyword “Forecast” and set the mode to “Starts with.” That will allow your users to send messages like “Forecast Miami, Florida.” The Service Layer will see your target keyword at the beginning, establish a session and send the whole message to your application for processing.
“Matches exactly” mode is used when the message is supposed to contain only the target keyword. It can have spaces and letters in mixed cases, but only this keyword will match and your application will be selected.
Note that keywords are case insensitive. Talk to us if you need more advanced tools, like RegEx-generated keywords.
If you have Subscription Module enabled for your application, you can make it so that when a particular keyword is recognized, the user is also automatically subscribed. If you specify the list of tags, they will be used to tag the user when being subscribed through this keyword. Remember, that you can send messages to the users with certain tags, so it’s a flexible way to organize your subscribers list.
Imagine that you have an app that just sends one-off responses, like weather forecasts for a given area or time table information for a given station. You don’t need to maintain a persistent session between the user and the application.
Another scenario is when your application sends alerts of different type and you want to minimize the implementation effort. For different keywords, you enable the auto-subscription feature (along with the Subscription Module) and auto-tag the users without creating a session. Then a user can send several keywords one after another and all you will need to do is to send messages to your subscribers filtered by tags.
The auto-response is just the text you want your users to receive when they send you a given keyword. It can be used with other options in different combinations to achieve stunning effects. In the above scenario, the auto-response can be used to send confirmations back to the users saying that you’ve successfully subscribed them to your alerts.
This feature, however, has a side-effect. If you use the Subscription Module in your application and the Auto-response for the keyword that has auto-subscription enabled, your users will receive at least two messages (the third message could be the First-Timers Message when the user texts you for the first time) — one for your Auto-response and another one for the confirmation on successful subscription.
There are currently two ways to send messages in the system:
If you intend to use our Subscription Module features, for example, for sending bulk messages, the only way to put a phone number on the list is to let them subscribe themselves. You cannot tell the system to add numbers to the list, as we keep our system compliant with the Mobile Marketing Association’s Best Practices. Users must go through the full opt-in cycle and confirm that they indeed want to be subscribed, preventing unsolicited messaging. For a slightly more open set of standards, we recommend PennySMS.com, which uses a different, less regulated messaging protocal, but is limited to only outbound texts.
Currently, no. Users can only unsubscribe themselves. However, we’ll consider adding this feature if there’s a demand.
Tags are used to organize your subscribers in a free-form fashion, familiar to users of Facebook, Flickr or any number of web applications. It’s possible to have a flat subscribers list, but you may want to split it into groups (geographically, for instance) so that you can address each one separately when sending bulk messages. Tags can be stacked and tagged lists rearranged in an intuitive, non-hierarchical way. We use these in place of ‘categories’ and ‘lists.’
A good use for tagging is A/B testing advertising, especially of any marketing you do outside of the internet that’s otherwise hard to measure. For example, you can find out which of several newspapers is the more cost-effective advertising channel by printing the same ads but with a different keyword in each of them. Those keywords should have two tags associated with them: one for the campaign, and another for the paper it was shown in. You could then measure your opt-in rate against the number of impressions (or your CPMs), and still keep all of your subscribers in the same common bucket for sending mass texts later.
Tags make it easy to do any kind of layered segmentation.
There are two simple ways to assign tags:
If, at any point you need to remove tags from some numbers on your subscriber list, you can use the “untag_subscribers” API call.
Static Responses let you build a basic SMS application without writing any code. If all you need is a canned responses to a given set of keywords, you can enter them through your application ‘edit’ screen and the Service Layer will automatically send those back to your users when a matching message arrives. For example, if you want to send your card to everyone who sends “Jack” to your application, you could write an application that would receive a message from the Service Layer, see if it reads “Jack” and respond. But with Static Responses, you can simply tell the Service Layer to send your desired text any time it sees incoming message with the text “Jack.”
Static Responses are canned responses to the known client messages. They work exactly as if the message was sent to your application, recognised and replied with the known text. This means that in order for the Static Responses to work, there has to be a session established between the phone number and your application first. If there’s no session (or virtual link) between the phone number and your application, we don’t know which application to send a message to, and thus it never reaches your Static Responses.
If you’d like to set up simple auto-responders when there’s no session in place (when a new user texts in, for example), you can simply set up a keyword with an “auto-response.”
You can find details on how Sessions work in the corresponding section.
There are three main modules that work together for the application — Welcome, Help and Subscription Module. Each of them has associated messages that can be customized or left blank. We’ll examine them in the following sections.
Every application can be configured to welcome its new users with a message. We know when it’s the first time someone texts you and can send a reply to them automatically, but also give you a chance to provide your own content. Think of this welcome message as an optional additional message. Since it’s optional, you can leave it blank if you don’t need it.
If your response to HELP message never changes, you may want to use our next module — Help Module. It will send an automatic response to anyone asking for help (case-insensitive messages ‘H’, ‘HLP’ and ‘HELP’ with any number of spaces around). If you leave this message blank, the message will be sent to your application as any other message.
Here we have two messages that work only when the Subscription Module is enabled:
Customize these messages to include your store name, and links to your web site. There are guidelines on how to properly compose these messages on example of the HELP message that can be found in one of articles on our blog.