Hybrid Messaging


With Hybrid Messaging you are able to deliver messages to any phone number via SMS or Push. When the end users phone number has your app or our free Notifire app installed, the platform can deliver your message via push which is 50% of the SMS price. If the end user on the phone number does not have your app or Notifire installed, the message will automatically be send as an SMS.

Sending a Hybrid Message HTTP

Endpoint URL: https://sgw01.cm.nl/gateway.ashx
Full SMS Gateway docs can be found here.


  • Make sure implement the Hybrid SDK in your app
  • Create the app in the App manager, select the messaging type, upload the Apple certificates and/or Android keys in the App manager.
  • The App manager will give you an App Key and App Secret, the App Key is needed in the request to the gateway.

<?xml version="1.0"?>
    <BODY>This message will be delivered as a push message.</BODY>

App Manager

iOS SDK v1.3.0



  • Apple iOS development environment (Xcode 6.0+, SDK, etc.)
  • Hybrid Messaging Application Key / Application Secret Key
  • Push enabled provisioning profile
  • Basic knowledge of iOS app development

Package Contents

The iOS SDK contains the following things:


CocoaPods is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries like HybridMessaging in your projects. See http://cocoapods.org for more information on how to install and use CocoaPods.


platform :ios, '7.0'

pod 'HybridMessagingSDK', '~> 1.2'

Installation via Static Library

The HybridMessaging SDK can be added to your application by dragging the HybridMessaging.h and libHybridMessaging.a file into your project in Xcode. Make sure to enable “Copy items if needed” in the “Choose options for adding these files” dialog.


  1. Open the Info.plist and add a new item with the key “Required background modes” and select “App downloads content in response to push notifications”
  2. Open your AppDelegate class and import the HybridMessaging header: #import <HybridMessaging.h>
  3. Add the following lines in the application:didFinishLaunchingWithOptions: method
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    [HybridMessaging configureWithKey:@"YOUR_APPLICATION_KEY"

    [HybridMessaging enable];

Notes: the "enable" method triggers a dialog to the user to request permission to sent push notifications. You may want to call the method at a later time to increase the likelihood that the user will accept the notifications. The permission dialog is only triggered once. When the user has denied the request it can be enabled again from the Settings menu.

Set development mode (optional)

Set the device development mode (defaults to production)

+ (void)setDevelopment:(BOOL)yesOrNo;

When this value is set to YES, the device registration is marked as a development device, and our server automatically uses the development push certificate (if configured) while sending a push notification to the device.

Set this value before calling any device verification methods, preferably at the start of the application in - (BOOL)application:didFinishLaunchingWithOptions:

Note: Remember to set this value to NO in a production build or remove the method call

Basic usage

The central class in the Hybrid Messaging SDK is called HybridMessaging and holds references to methods for notifications and authentication functionality. All methods calls are static.

The HybridMessaging class also contains a method for the Device ID and Push Token:

+ (NSString *)deviceId;
+ (NSString *)pushToken;
+ (NSString *)msisdn;
+ (NSString *)version;

Phone number verification


+ (void)requestPhoneVerification:(NSString *)msisdn 
                         handler:(void (^)(HMDeviceRegistrationStatus status))statusHandler;

+ (void)requestPhoneVerificationVoiceCall:(NSString *)msisdn 
                         handler:(void (^)(BOOL success))statusHandler;

+ (void)requestPinVerification:(NSString *)pin 
                        handler:(void (^)(HMDeviceRegistrationStatus status))statusHandler;

+ (void)requestVerificationStatus:(void(^)(HMDeviceRegistrationStatus status))statusHandler;

The device registration status can have one of the following values:

- HMDeviceRegistrationStatusUnknown
- HMDeviceRegistrationStatusUnverified
- HMDeviceRegistrationStatusWaitingForPin
- HMDeviceRegistrationStatusLastPinVerificationFailed
- HMDeviceRegistrationStatusPinVerified
- HMDeviceRegistrationStatusInvalid

Notes: Phone number is in MSISDN format and must start with the country code: e.g. 0031 for the Netherlands.


[HybridMessaging requestPhoneVerification:phoneNumberTextField.text 
                                  handler:^(HMDeviceRegistrationStatus status) {
    if (status == HMDeviceRegistrationStatusWaitingForPin
        || status == HMDeviceRegistrationStatusLastPinVerificationFailed) {
        // Show PIN view
    } else {
        // Handle error

Push notifications


Set the user notification types (optional). Defaults to Alert, Badge and Sound.

+ (void)setUserNotificationTypes:(HMUserNotificationType)types;

Get the current notification types

+ (HMUserNotificationType)userNotificationTypes;

All available notification types:

- HMUserNotificationTypeNone // the application may not present any UI upon a notification being received
- HMUserNotificationTypeBadge // the application may badge its icon upon a notification being received
- HMUserNotificationTypeSound // the application may play a sound upon a notification being received
- HMUserNotificationTypeAlert // the application may display an alert upon a notification being received

Notes: Make sure to set the notification types before calling the +enable method.


[HybridMessaging setUserNotificationTypes:(HMUserNotificationTypeBadge | 
                                           HMUserNotificationTypeAlert | 

Enable push notification.

+ (void)enable;

Disable push notification.

+ (void)disable;

Push notification blocks

You may set the following blocks in your application to react to the push notification events.

[HybridMessaging setDidReceiveRemoteNotificationBlock:^(NSDictionary *userInfo) { 
    NSLog(@"%@", userInfo);

Called when a push notification is received

[HybridMessaging setDidRegisterForRemoteNotificationsWithDeviceTokenBlock:^(NSData *deviceToken) { 
    NSLog(@"%@", [deviceToken description]);

Called when a push token is received

[HybridMessaging setDidFailToRegisterForRemoteNotificationsWithErrorBlock:^(NSError *error) { 
    NSLog(@"%@", error);

Called when the push registration fails


Methods to receive the messages that have been sent by the Hybrid Messaging.

+ (void)messages:(void (^)(NSArray *messages, NSError *error))handler;
+ (void)messagesWithLimit:(NSInteger)limit handler:(void (^)(NSArray *messages, NSError *error))handler;
+ (void)messagesWithLimit:(NSInteger)limit offset:(NSInteger)offset handler:(void (^)(NSArray *messages, NSError *error))handler;


Get the last 100 messages

[HybridMessaging messagesWithLimit:100 handler:^(NSArray *messages, NSError *error) { 
    if (error) {
        // Handle error
    } else {
        for (NSDictionary *message in messages) {
            NSString *id = message[@"ID"];
            NSString *body = message[@"Body"]; 
            NSString *dateTime = message[@"DateTime"]; 
            NSString *sender = message[@"Sender"];

            // Do something with message


Get geolocation information about the app user.

+ (void)requestGeoIpInfo:(void(^)(NSDictionary *info))handler;

Carrier update notification

Sets a callback to be executed when the carrier has changed.

+ (void)setDeviceDidUpdateCarrierBlock:(void(^)(CTCarrier *carrier))block;

Android SDK v2.1.0



  • GCM Sender ID (can be retrieved from the Google Developers Console)
  • Hybrid Messaging Application Key / Application Secret Key


The library is hosted in the Maven repository Bintray. All required changes (permissions, services and receivers) will automatically be merged as they're included in the Android Archive (AAR).

Add the dependency to your build.gradle:

dependencies {
    compile 'com.cm.hybridmessagingsdk:hybridmessagingsdk:2.1.0'

The heart of the SDK is the HybridMessaging class. It contains all the functionality (like registering, messaging and notification settings) and is the only class needed to communicate with the SDK.

  1. Initialize the SDK
  2. Check Google Play Services availability
  3. Register the device
  4. ...

Initialization is required before calling any other method in HybridMessaging


Initialize the SDK

Initialize the Hybrid Messaging SDK. Initialization is required before calling any other method in HybridMessaging. The initialization process should happen as early as possible, initializing in the Application class ensures the SDK is always initialized.

There's two ways to initialize the Hybrid Messaging SDK:

  1. By declaring the keys in metadata
  2. By passing the keys programmatically

Using metadata

Add this metadata to the <application /> tag in your Android Manifest:

    android:value="your_hybridmessaging_key" />
    android:value="your_hybridmessaging_secret" />
    android:value="@string/project_id" />

Add the GCM Sender ID to your strings.xml:

<string name="project_id">your_gcm_sender_id</string>

And call the initialize method:

HybridMessaging.initialize(Context context)

The keys will be read from the Android Manifest, so there's no need to provide them programmatically.

public class MyApplication extends Application {
    public void onCreate() {
        // initialize the Hybrid Messaging SDK

Declare your Application class in the <application /> tag in the Android Manifest:

<application [icon, label, theme, etc.] android:name=".MyApplication" />


Provide the keys programmatically, do this if you can't or prefer not to use metadata.

HybridMessaging.initialize(Context context, String apiKey, String apiSecret, String senderId)
public class MyApplication extends Application {
    private static final String API_KEY = "your_hybridmessaging_key";
    private static final String API_SECRET = "your_hybridmessaging_secret";
    private static final String SENDER_ID = "your_gcm_sender_id";

    public void onCreate() {
        // initialize the Hybrid Messaging SDK
        HybridMessaging.initialize(this, API_KEY, API_SECRET, SENDER_ID);

Declare your Application class in the <application /> tag in the Android Manifest:

<application [icon, label, theme, etc.] android:name=".MyApplication" />

Check Google Play Services

Google Play Services is required to receive push notifications. This is required by the Hybrid Messaging SDK in order to function. It's recommended to check if it's available through Google's API, so the user's guaranteed to be able to receive push notifications. Check this preferably in the startup activity.


Check if the Google Play Services is available. If it's not, a dialog with a solution will be shown if possible.

private boolean checkPlayServices() {
    GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
    int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
    if (resultCode != ConnectionResult.SUCCESS) {
        if (apiAvailability.isUserResolvableError(resultCode)) {
            apiAvailability.getErrorDialog(this, resultCode, REQUEST_GOOGLE_PLAY_SERVICES).show();
        } else {
            Log.w(TAG, "This device does not support the required Google Play Services.");
            // show the user an error message
        return false;
    return true;

And handle the result from the error dialog.

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
            // if Play Services is available now, re-init the SDK and continue
            super.onActivityResult(requestCode, resultCode, data);

REQUEST_GOOGLE_PLAY_SERVICES is the request code used to indentify the request in the onActivityResult(...) callback. Its value may be any number, but should be unique: no other requests should use the same value. For example:

private static final int REQUEST_GOOGLE_PLAY_SERVICES = 1;

Normal registration flow:

  1. Check the current verification status
  2. Register the user using a phone number
  3. The user receives a text containing a verification PIN
  4. Verify the user using the verification PIN

Phone numbers are in MSISDN format and have to start with the country code. Example: the country code for the Netherlands is 0031, the MSISDN will look like 0031612345678.

Check verification status

Get the status of the verification/registration of the user.

HybridMessaging.getVerificationStatus(OnVerificationStatus listener)


OnVerificationStatus interface:

void onVerificationStatus(VerificationStatus status);
void onError(Throwable throwable);

The enum VerificationStatus has four values:

VerificationStatus Meaning
Unverified The user is not registered
Verified The user is registered and the phone number is verified
LastPinVerificationFailed The user is registered, but the last provided pin was invalid
WaitingForPin The user is registered, but hasn't provided a pin


HybridMessaging.getVerificationStatus(new OnVerificationStatus() {
    public void onVerificationStatus(VerificationStatus status) {
        switch (status) {
            case Unverified:
                // show registration screen
            case Verified:
                // already registered
            case LastPinVerificationFailed:
            case WaitingForPin:
                // show pin input

    public void onError(Throwable throwable) {
        Log.e("MainActivity", "Error getting verification status", throwable);

Register new user

Register a new user.

HybridMessaging.registerNewUser(String msisdn, OnRegistrationListener listener)

The user will receive an SMS message containing a validation PIN.


OnRegistrationListener interface:

void onReceivedRegistration(Registration registration);
void onError(Throwable throwable);


HybridMessaging.registerNewUser(msisdn, new OnRegistrationListener() {
    public void onReceivedRegistration(Registration registration) {
        // ask user to enter verification PIN

    public void onError(Throwable throwable) {
        Log.e("MainActivity", "Error registering new user", throwable);

Verify PIN

Confirm the MSISDN by providing the verification PIN sent to the phone number when the user was registered.

HybridMessaging.registerUserByPincode(String verificationCode, OnVerificationStatus listener)


See Check verification status for information about this listener.


HybridMessaging.registerUserByPincode(verificationCode, new OnVerificationStatus() {
    public void onVerificationStatus(VerificationStatus status) {
        switch (status) {
            case Verified:
                // verification was successful
            case LastPinVerificationFailed:
                // provided PIN was invalid

    public void onError(Throwable throwable) {
        Log.e("MainActivity", "Error registering user by PIN", throwable);

Request new PIN

When the user wants the PIN re-sent.

HybridMessaging.requestNewVerificationPin(String msisdn, OnRegistrationListener listener)


See Register new user for information about this listener.


HybridMessaging.requestNewVerificationPin(msisdn, new OnRegistrationListener() {
    public void onReceivedRegistration(Registration registration) {
        // ask user to enter verification pin

    public void onError(Throwable throwable) {
        Log.e("MainActivity", "Error sending new PIN", throwable);

Request PIN over voice call

If the user prefers the PIN to be provided over a voice call, the user will be called in the language the device is set to.

HybridMessaging.doVoiceCall(String msisdn, VoiceCallListener listener)

listener is optional


VoiceCallListener interface:

void onSuccess();
void onError(Throwable throwable);


HybridMessaging.doVoiceCall(msisdn, new VoiceCallListener() {
    public void onSuccess() {
        // user is being called

    public void onError(Throwable throwable) {
        Log.e("MainActivity", "Error requesting PIN over voice call", throwable);

Check registration

Check if the user is registered.

HybridMessaging.hasRegistration() : boolean

Note: this does not replace checking the verification status, as this methods only checks the registration locally.

Reset registration

Remove the registration, so a new user could be registered.



The method reads the MSISDN from the SIM card if it's available, will read it from the registration otherwise.

HybridMessaging.getMsisdn() : String

Note: in order to read the MSISDN from the SIM card, the permission READ_PHONE_STATE is required. Without this permission, the MSISDN will only be read form the current registration.

Get Device ID

Get the Device ID of the registration.

HybridMessaging.getDeviceId() : String

Get messages

All messages

Get all messages.

HybridMessaging.getMessages(OnMessageListener listener)

Messages with limit

Get a certain amount of messages.

HybridMessaging.getMessages(int amount, OnMessageListener listener)

Messages with limit and offset

skip a certain number and get a certain amount of messages.

HybridMessaging.getMessages(int skip, int amount, OnMessageListener listener)

Messages after a certain date

Get all messages after a given date.

HybridMessaging.getMessagesFromDate(long dateInMillisec, OnMessageListener listener)

dateInMillisec: date formatted as a UNIX timestamp in milliseconds

Filtered messages

Get messages filtered by a custom filter.

HybridMessaging.getMessagesWithFilter(Filter filter, OnMessageListener listener)

You can add one or more options to the Filter. The filter works with OData. Filter options: OPTION_EXPAND, OPTION_FILTER, OPTION_ORDER_BY, OPTION_SELECT, OPTION_SKIP and OPTION_TOP.

Filter example
Filter filter = new Filter();
filter.addFilter(Filter.OPTION_SELECT, "ID,Body,DateTime,Sender,UpdateIDs");
filter.addFilter(Filter.OPTION_SKIP, "10");
filter.addFilter(Filter.OPTION_TOP, "5");
filter.addFilter(Filter.OPTION_FILTER, "DateTime gt DateTime'2016-01-01T12:00:00.000");


OnMessageListener interface:

void onReceivedMessages(int statusCode, Headers headers, Message[] messages);
void onError(Throwable throwable);


int skip = 10;
int amount = 5;
HybridMessaging.getMessages(skip, amount, new OnMessageListener() {
    public void onReceivedMessages(int statusCode, Headers headers, Message[] messages) {
        // show messages

    public void onError(Throwable throwable) {
        Log.e("MainActivity", "Error getting messages", throwable);

Mark as read

Mark read at current date

Mark a message as read by the recipient at the current date.

HybridMessaging.markMessageAsRead(Message message, MarkAsReadListener listener)

listener is optional

Mark read at specified date

Mark a message as read by the recipient at the specified date.

HybridMessaging.markMessageAsRead(Message message, Date date, MarkAsReadListener listener)

listener is optional


MarkAsReadListener interface:

void onSuccess();
void onError(Throwable throwable);


HybridMessaging.markMessageAsRead(message, new MarkAsReadListener() {
    public void onSuccess() {
        // message is successfully marked as read

    public void onError(Throwable throwable) {
        Log.e("MainActivity", "Error marking message as read", throwable);

The SDK automatically shows notifications in the status bar with the default settings.

Default title: The application name Default icon: The application icon Both are retrieved from the <application /> tag in the AndroidManifest.xml

Set title

Set a custom title for default notifications.

title: pass null to reset it to its default (application name).

HybridMessaging.setNotificationTitle(String title)

Set icon

Set a custom icon for default notifications.

HybridMessaging.setNotificationIcon(int resourceId)

resourceId: a drawable resource ID, pass 0 to reset it to its default (application icon).



Default notifications

Change the behaviour of the SDK showing notifications. By default, the SDK shows notifications when receiving a message.

HybridMessaging.fireNotificationsByDefault(boolean showNotifications)

This is best to be used in conjunction with notification listener and show custom notifications.

Receive notifications

If you want to be notified when a new Notification is received, you could register a listener for this. For example, when you want to show custom notifications.

HybridMessaging.setHybridNotificationListener(HybridNotificationListener listener)

Note: if you want to show custom notifications, default notifications should be disabled


HybridNotificationListener interface:

void onReceiveHybridNotification(Context context, Notification notification);


NotificationCompat.Builder notifBuilder = new NotificationCompat.Builder(context)
        .setContentTitle("Hybrid Messaging SDK Example")

// gets an instance of the NotificationManager service
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notificationId, notifBuilder.build());

Detect disabled notifications

Users have the ability to disable notifications for apps, the SDK can detect if the user has disabled notifications for this app. When notifications are disabled, SMS messages will be sent instead of push messages, so the user will still receive Hybrid messages.

Enable or disable automatic detection.

HybridMessaging.setDetectDisabledNotifications(boolean enable)

Get if automatic detection is enabled.

HybridMessaging.getDetectDisabledNotifications() : boolean

By default, automatic detection is enabled.

SIM card changes

If a device has a different SIM card, chances are the phone number has changed. As Hybrid Messaging is about phone numbers, it's a good idea to check if a user's phone number has changed. The Hybrid Messaging SDK is able to detect a replaced SIM card and could notify you. When a SIM card change is detected, it's recommended to reset the registration and let the user verify its phone number again.

HybridMessaging.setOnSimChangedListener(OnSimcardChangedListener listener)

Note: to be able to detect SIM card changes, the permission READ_PHONE_STATE is required.

Add this to the <manifest /> tag of your Android Manifest:

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>


Interface OnSimcardChangedListener:

void onSimcardChanged(boolean isChanged, String simState);


In any Activity override the Activity.onResume() and Activity.onPause() and call them on the SDK. This will make it start and stop listening for changes to respect the Activity lifecycle.


Recommended: call onResume() and onPause() in every Activity shown after the user is registered.


HybridMessaging.setOnSimChangedListener(new OnSimcardChangedListener() {
    public void onSimcardChanged(boolean isChanged, String simState) {
        if (isChanged) {
            // reset the registration
public class MainActivity extends Activity {

    protected void onResume() {

    protected void onPause() {

Manual check

It's also possible to check for SIM card changes manually.

HybridMessaging.didSimStateChange() : boolean

Get SDK version

Get the current version of the Hybrid Messaging SDK.

HybridMessaging.getSDKVersion() : String

Customize user agent

To customize the user agent sent to the Hybrid Messaging servers with every call, obtain the UserAgent instance. It's possible to change the app name, app version and language. By default, these properties will be read from the app.

HybridMessaging.getUserAgent() : UserAgent
Upgrade from 1.x
  1. Cleanup Android Manifest
  2. Upgrade dependency
  3. Apply code changes
  4. Replace deprecated methods

Cleanup Android Manifest

Since 2.0.0 are all required permissions, receivers and services declared in the library's Android Manifest. All required changes to the Android Manifest will automatically be merged.

More info: Include library

  1. Remove the permissions:

    <!--Necessary for all outgoing internet connections-->
    <uses-permission android:name="android.permission.INTERNET" />
    <!--Necessary for connecting with the play store and retrieving registration id-->
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <!--Keep the service awake during processing incoming notifications-->
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <!--Receive notifications from the CCS/GCM platform of google-->
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
  2. Remove receivers:

    <receiver android:name="com.cm.hybridmessagingsdk.receivers.GcmBroadcastReceiver"
         <action android:name="com.google.android.c2dm.intent.RECEIVE" />
         <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
         <category android:name="com.cm.hybridmessaging" />
  3. Remove services:

    <service android:name="com.cm.hybridmessagingsdk.GCMNotificationIntentService" />

Upgrade dependency

Upgrade the dependency to version 2.1.0 in your build.gradle:

dependencies {
    compile 'com.cm.hybridmessagingsdk:hybridmessagingsdk:2.1.0'

More info: Include library

Code changes

Due to switching from Apache HttpClient to OkHttp, the signature of the onReceivedMessages(...) method in the OnMessageListener has changed.


void onReceivedMessages(int statusCode, Header[] headers, Message[] messages);


void onReceivedMessages(int statusCode, Headers headers, Message[] messages);

More info: Get messages

Deprecated methods

Deprecated method Replacement
HybridMessaging#HybridMessaging(Context) HybridMessaging.initialize(Context)
HybridMessaging.setUserAgent() : UserAgent HybridMessaging.getUserAgent() : UserAgent
Message#getUpdateId() : String Message#getUpdateIds() : String[]
Message#setUpdateId(String) : void Message#setUpdateIds(String[]) : void
Notification#getNotificationId() : String Notification#getId() : int


  • Add an initialization method to pass the credentials programmatically.
  • Detect when the user disabled notifications and fall back to SMS messages (configurable)
  • When clicking on a notification, the launcher activity of the app will be started


  • Internal rewrite, highlights:
    • Move from Apache HttpClient (deprecated) to OkHttp.
    • Replace the (deprecated) way of registering at and receiving push messages from GCM.
    • Automatically retry sending the GCM registration token in case of a failure (using exponential back-off).
  • Support for providing PINs via voice calls.
  • Support for marking messages as read.
  • All required permissions, services and receivers are declared in the library's Android Manifest. It's not needed anymore to manually include them.
  • Allow re-initialization of the SDK.
  • Deprecation of several methods.

Hybrid Messaging API


Apps that register with and retrieve messages from CM’s Hybrid Messaging platform use a REST API to communicate. This document is a guide on how to use the API. There are some prerequisites (like authorization) for every request. These are explained in chapter 2.

In chapter 3 we explain how to register and chapter 4 is all about receiving messages. As this API is a RESTful interface, we use HTTP verbs to define an action:

  • GET - Retrieve something
  • POST - Create something new
  • PUT - Update something existing
  • DELETE - Delete something

More information on REST: http://en.wikipedia.org/wiki/Representational\_state\_transfer#Applied\_to\_web\_services

The data format is JSON. More information on JSON: http://www.json.org

  • Android Gradle Package
  • iOS CocoaPod
Request requirements


The Authorization header is used to verify requests from your app are originating from the app. The app 'signs' the request with a calculated OAuth 2.0 Message Authentication Code (MAC) signature and the REST API will check this by calculating the same signature itself and comparing this calculated signature with the mac value in the Authorization header.

The Authorization header needs three values:

  • The appKey identifies your app. You get the appKey from us.
  • ts is the timestamp of the request.
  • mac is the message authentication code, the signature of the request. It is the hash of the request signed with the appSecret. You get the appSecret from us.

The value of the Authorization header will look like this:

MAC kid="8eda08f7-5249-40c2-9ef7-ce573f3a8dca" ts="1464242891" mac="dkViwAV9Pi5xiab39VRUq+gU4Co="

The message authentication code (mac) is calculated by using hmac-sha-1 on a string representing the request. The string representing the request looks like this:

POST /v1.0/deviceregistrations HTTP/1.1

The query string, if used, should also be included:

POST /v1.0/messages?$top=100 HTTP/1.1

If authorization fails, the server will respond with HTTP Status 401 Unauthorized.

User Agent

Your app also needs to include a User-Agent header. This contains information about the app, the hybrid messaging library used and the device. It should at least contain the mobile platform (iOS, Android or WindowsPhone). Other information is optional. It is useful to include the operating system, app name, user name, device brand name, device model name, user language and/or the app version.

Android example:

MyApp/1.0 (Android 6.0.1; LGE; Nexus 5X; en_US)

If the UserAgent is not correct or missing, the server responds with HTTP Code 400 Bad Request.


To uniquely identify the app install on the device, the Hybrid Messaging platform generates a globally unique identifier (GUID). After you’ve retrieve a DeviceID as reply on the first device registration request, you need to include a DeviceID header on every request with this GUID as its value. It’s mandatory for every request, except when creating a new device registration.

If the DeviceID is not correct, the server responds with HTTP Code 400 Bad Request.

Do not mistake the DeviceID with the deviceID from your phone.

Date and time format

The API uses the ISO 8601 Date/Time format, with a T between the date and the time. In short, this is the format:


Do not use local time, but always use UTC time.


A full HTTP request will look like this:

PUT /v1.0/deviceregistrations HTTP/1.1
Host: api.cmtelecom.com
Authorization: MAC kid="8eda08f7-5249-40c2-9ef7-ce573f3a8dca" ts="1464242891" mac="dkViwAV9Pi5xiab39VRUq+gU4Co="
Content-Type: application/json
User-Agent: MyApp/1.0 (Android 6.0.1; LGE; Nexus 5X; en_US)
DeviceID: 0c6bf13c-8d1c-474c-ab66-74dadb1c3d7d
    "Msisdn": "0031600000000"
Device Registrations

A "device registration" in the context of this API is an install of an app on a device.

Get device registration information

To get information about the apps device registration, simply send a GET request to /v1.0/deviceregistrations and you get the following response:

    "UserAgent":"MyApp/1.0 (Android 6.0.1; LGE; Nexus 5X; en_US)"

RegistrationStatus can have the following values:

  • Unverified – registration without MSISDN (phone number)
  • WaitingForPin – verification code has been sent to the MSISDN
  • LastPinVerificationFailed – verification code was incorrectly verified
  • PinVerified – MSISDN is known and verified

When the device registration is not found, the server returns HTTP Code 404 Not found.

New device registration

To register a new device registration, you send a POST request to /v1.0/deviceregistrations. You can even send a request without any field, but you still have to provide an empty object:


You can also choose to include the push token and/or MSISDN already:


PushToken is the token that the app retrieves from a push notification cloud service like Windows Notification Services, Google Cloud Messaging or Apple Push Notification Server.

Update device registration

To update an existing device registration, you send a PUT request to /v1.0/deviceregistrations with any field you want to update. You can leave out any field you don’t want to update.


Msisdn is the mobile subscriber identification number. A internationally formatted phone number starting with the country prefix with leading zeroes.

Verification process

When a device registration request contains an MSISDN (phone number) which is not verified yet, the platform will automatically send a verification SMS message to that MSISDN.

You need to give your user a way to put in the verification code, after which your app sends a PUT request to /v1.0/deviceregistrations with the appropriate code:


If the code is correct, the server will respond with:


If the code is not correct, the server responds with:


Get messages

To retrieve all messages for the app, send a GET request to /v1.0/messages. The response looks like this:

        "Body":"Your first message!", 

Status can contain the following values:

  • Cancelled – the platform cancelled the message, it is not sent
  • Sent – the platform did not cancel the message and will try to send it
  • Rejected – the carrier or cloud rejected the message
  • Accepted – the carrier or cloud accepted the message
  • Failed – the carrier or cloud failed to deliver the message
  • Delivered - the message has been delivered on the device

The ID is a globally unique identifier (GUID) that uniquely identifies the message. The UpdateID is only guaranteed to be unique for 24 hours. This ID is needed to notify the platform that a message is retrieved by an app or read by the user, which is explained in the next paragraph.

DateTime is the time the message arrived at the Hybrid Messaging platform.

The messages API supports the ODATA Query language. You can specify $select, $top, $skip, $filter and $orderby to make your result set more specific.

See chapter 5 of this page for more information: http://www.odata.org/documentation/odata-version-3-0/url-conventions

Update messages

When your app retrieve a message as a push notification, it should notify the platform about this event. To do so, send the following PUT request to the server:


When your app displayed the message to a user, it should notify the platform using a Date/Time in the ReadByRecipient field.


Ack android messages

Messages sent from the HybridMessaging platform make use of the XMPP Android protocol. This allow us to monitor if a message is received on the device of the user. When receiving the message a connection from Google will be made with the phone of the user. This connection can be reused to send an ACK back to the originated address. In order to make HybridMessaging properely work on Android we need to know if a notification is received on the phone. If not a message will be send twice since we don't know for sure if the message was received correctly or on time. Follow the steps below to send back ACKS when succesfully receiving messages.

To receive messages from hybrid messaging you should first create a WakefulBroadcastReceiver with an IntentService capable of listening to incoming notifications.

In the IntentService you are able to retrieve the contents of the message and send an Ack back to the server over the XMPP protocol. In order to send the Ack back to the server you have to instantiate a GoogleCloudMessaging object and retrieve the message type.

final GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);

Also retrieve the bundle from the intent to retrieve the message

Bundle extras = intent.getExtras();

To send a message back to the server, make sure you wait a very short time. Let the Thread sleep for a very short while otherwise the Ack will not be send back to the server. Afterwards retrieve the bundle contents from the Extras received through the Intent. Important are time_to_live and messageId that need to be send back to the server. Send an ACK back to the server over the same GCM connection with as destination your Google project ID including an address as following: YOUR_PROJECT_ID + "@gcm.googleapis.com


public class GCMNotificationIntentService extends IntentService {

    public GCMNotificationIntentService() {

    protected void onHandleIntent(Intent intent) {

        Bundle extras = intent.getExtras();
        final GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
        String messageType = gcm.getMessageType(intent);

        if (extras != null) {
            if (!extras.isEmpty()) {
                if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {

                    for (int i = 0; i < 5; i++) {
                        try {
                        catch (InterruptedException e) {}

                    String messageId = null;
                    long ttl = 30L;

                     Bundle bundle = intent.getExtras();
                     messageId = bundle.getString("message_id");
                     String notificationId = bundle.getString("from");
                     String message = bundle.getString("message");
                     String tempttl = bundle.getString("time_to_live");

                     if(tempttl != null) {
                         ttl = Long.valueOf(bundle.getString("time_to_live"));

                    // ## Send ACK back to server containing the following KEY and VALUE ## //
                    Bundle dataBundle = new Bundle();
                    dataBundle.putString("message_type", "DLR");

                    try {
                        if(tempttl != null) {
                            gcm.send(PROJECT_ID + "@gcm.googleapis.com", messageId, ttl, dataBundle);
                    } catch (IOException e) {
        GcmBroadcastReceiver.completeWakefulIntent(intent); // Close the service


important: Make sure to send "message_type" along with "DLR" back to the server