SMS subscriber

The SMS subscriber module acts as a unique and global client in the system that can dispatch SMS notifications to many subscribers, which makes it possible for more than one module to receive SMS messages.

The module provides functions to register and unregister SMS listeners, which are the modules that need to send or receive SMS messages. Each listener is identified by a unique handle and receives the SMS data and metadata through a callback function. The module also provides a possibility to send SMS messages.

SMS listeners can be registered or unregistered at run time. The SMS data payload is parsed and processed before it is given to the client.

The SMS module uses AT commands to register as an SMS client to the modem. In addition, AT commands are also used to send SMS messages. SMS notifications are received using AT commands, but those are not visible for the users of this module. The module automatically acknowledges the SMS messages received on behalf of each listener.


Configure the following Kconfig options when using this library:


Only a single SMS client can be registered to the modem in the system. If there is already an SMS client registered in the system (for example, using AT commands), the initialization of this module fails, and an error is returned.

API documentation

Header file: include/modem/sms.h
Source file: lib/sms/sms.c
group sms

Public APIs of the SMS subscriber manager module.



Maximum length of SMS in number of characters as specified in 3GPP TS 23.038 Section 4 and Section


Maximum length of SMS address, i.e., phone number, in characters as specified in 3GPP TS 23.040 Section


typedef void (*sms_callback_t)(struct sms_data *const data, void *context)

SMS listener callback function.


enum sms_type

SMS message type.



SMS-DELIVER message type.


SMS-STATUS-REPORT message type.


int sms_register_listener(sms_callback_t listener, void *context)

Register a new listener to SMS library.

Also registers to modem’s SMS service if it’s not already subscribed.

A listener is identified by a unique handle value. This handle should be used to unregister the listener. A listener can be registered multiple times with the same or a different context.

  • listener[in] Callback function. Cannot be null.

  • context[in] User context. Can be null if not used.

Return values
  • -EINVAL – Invalid parameter.

  • -ENOSPC – List of observers is full.

  • -EBUSY – Indicates that one SMS client has already been registered towards the modem and SMS subscriber module is not able to do it.

  • -ENOMEM – Out of memory.


Handle identifying the listener, or a negative value if an error occurred.

void sms_unregister_listener(int handle)

Unregister a listener.

Also unregisters from modem’s SMS service if there are no listeners registered.

  • handle[in] Handle identifying the listener to unregister.

int sms_send_text(const char *number, const char *text)

Send SMS message.

Sending is done with GSM 7bit encoding used to encode textual SMS messages. SMS-SUBMIT message is specified in 3GPP TS 23.040 Section and data encoding in 3GPP TS 23.038 Section 4 and Section 6.2. This function doesn’t support sending of 8bit binary data messages or UCS2 encoded text.

  • number[in] Recipient number in international format.

  • text[in] Text to be sent.

Return values

-EINVAL – Invalid parameter.


0 on success, otherwise error code. A positive value on AT error with “ERROR”, “+CME ERROR”, and “+CMS ERROR” responses. The type can be resolved with nrf_modem_at_err_type and the error value with nrf_modem_at_err.

struct sms_time
#include <sms.h>

SMS time information specified in 3GPP TS 23.040 Section

Public Members

uint8_t year

Year. Last two digits of the year.

uint8_t month


uint8_t day


uint8_t hour


uint8_t minute


uint8_t second


int8_t timezone

Timezone in quarters of an hour.

struct sms_address
#include <sms.h>

SMS address, i.e., phone number.

This may represent either originating or destination address and is specified in 3GPP TS 23.040 Section

Public Members

char address_str[20 + 1]

Address in NUL-terminated string format.

uint8_t length

Address length in number of characters.

uint8_t type

Address type as specified in 3GPP TS 23.040 Section

struct sms_udh_concat
#include <sms.h>

SMS concatenated short message information.

This is specified in 3GPP TS 23.040 Section and

Public Members

bool present

Indicates whether this field is present in the SMS message.

uint16_t ref_number

Concatenated short message reference number.

uint8_t total_msgs

Maximum number of short messages in the concatenated short message.

uint8_t seq_number

Sequence number of the current short message.

struct sms_udh_app_port
#include <sms.h>

SMS application port addressing information.

This is specified in 3GPP TS 23.040 Section and

Public Members

bool present

Indicates whether this field is present in the SMS message.

uint16_t dest_port

Destination port.

uint16_t src_port

Source port.

struct sms_deliver_header
#include <sms.h>

SMS-DELIVER message header.

This is for incoming SMS message and more specifically SMS-DELIVER message specified in 3GPP TS 23.040.

Public Members

struct sms_time time


struct sms_address originating_address

Originating address, i.e., phone number.

struct sms_udh_app_port app_port

Application port addressing information.

struct sms_udh_concat concatenated

Concatenated short message information.

union sms_header
#include <sms.h>

SMS header.

This can easily be extended to support additional message types.

Public Members

struct sms_deliver_header deliver
struct sms_data
#include <sms.h>

SMS PDU data.

Public Members

enum sms_type type

Received message type.

union sms_header header

SMS header.

int payload_len

Length of the payload buffer.

uint8_t payload[160 + 1]

SMS message payload.

Reserving enough bytes for maximum number of characters but the length of the received payload is in payload_len variable.

Generally the message is of text type in which case you can treat it as string. However, header may contain information that determines it for specific purpose, e.g., via application port information, in which case it should be treated as specified for that purpose.