Skip to content

Integrate an SMS Service Using the SMS API

Cloud Voice can hand message delivery off to an outside SMS (Short Message Service) provider through a generic SMS API. An API (Application Programming Interface) is an agreed set of web requests that lets two systems exchange data. The provider plugs its own messaging platform into your phone system: Cloud Voice calls the provider’s API to send outbound text and picture (MMS, Multimedia Messaging Service) messages, and the provider posts inbound messages back to Cloud Voice through a webhook (an automatic HTTP request the provider sends to a Cloud Voice URL whenever a new message arrives). This page describes what each side must implement, the request and response formats involved, and how an administrator adds the resulting SMS channel in Cloud Voice.

Both Cloud Voice and your SMS service provider must meet the following conditions before the integration will work.

Cloud Voice

  • Firmware: version 84.23.0.24 or later.
  • Domain name: the system domain must not contain any underscore characters. An underscore causes the channel to fail authentication or to stop receiving messages.
  • Domain certificate: a valid domain certificate must be installed.

SMS service provider

  • API: the provider exposes an HTTPS REST endpoint (a standard web address that accepts requests over a secure connection) for sending messages, and, if it wants Cloud Voice to prove its identity, an optional HTTPS endpoint for verifying authentication.
  • Customer portal: the provider’s portal issues an API key to authenticate requests from Cloud Voice, optionally a Secret for signing webhook requests, and a way to configure the webhook.
  • Number format: phone numbers follow the E.164 format (the international standard of a plus sign, the country code, then the national number, for example +14102161183).

Because the integration is a two-way API exchange, the provider issues two credentials: an API key and, optionally, a Secret.

The API key authenticates the requests that Cloud Voice sends to the provider. Cloud Voice includes it in the Authorization header of every request:

Authorization: Bearer {api_key}

When a request arrives, the provider checks the key. A valid key means the provider carries out the requested action; an invalid key fails the request. The key is used both in the connectivity check and in the outbound-message request described below.

The Secret authenticates the webhook requests that the provider sends to Cloud Voice. It is only needed when the provider signs its webhook requests.

For each webhook request, the provider uses the Secret with the SHA256 algorithm to produce a signature over the request body, and passes it in the X-Signature-256 header:

X-Signature-256: sha256={signature}

On receipt, Cloud Voice recomputes the signature from the body using the same Secret and algorithm, then compares it with the value in the header. If they match, the request is genuine and Cloud Voice delivers the message; otherwise it rejects the request. See Receive messages from the provider below.

Once the SMS channel exists in Cloud Voice, the system periodically calls the provider’s API address for verifying authentication, using the API key, to confirm the channel is still reachable.

Sequence of the channel connectivity check between Cloud Voice and the provider

  1. Cloud Voice sends an API request containing a randomly generated challenge code.
  2. The provider validates the API key.
  3. If the key is valid, the provider responds with status code 200 and echoes the challenge code in the response body.
  4. Cloud Voice compares the returned challenge code with the one it sent. A match means the channel is connected.
  • Method: GET

  • URL: the API address for verifying authentication, for example https://service-provider.example.com/verify

  • Header:

    ParameterTypeDescription
    AuthorizationStringThe API key, in the format Bearer {api_key}.
  • Query parameter:

    ParameterTypeDescription
    challengeStringA random string generated by Cloud Voice.

Example:

GET /verify?challenge=mAWpGnyeTZgguOPYlWitGPlRJYIhoLMy HTTP/1.1
Host: service-provider.example.com
Authorization: Bearer {api_key}

The provider replies in JSON.

Success: return status 200 and the same challenge code:

HTTP/1.1 200 OK
Body: mAWpGnyeTZgguOPYlWitGPlRJYIhoLMy

When the echoed challenge code matches the one that was sent, the channel connects and its status in Cloud Voice shows as Connected (Connected).

Failure: return the error in this format:

ParameterTypeDescription
codeStringError code.
titleStringError type (you define this).
detailStringError detail (you define this).

For example:

HTTP/1.1 401 Unauthorized
{
"errors": [
{
"code": "10004",
"title": "Authentication failed",
"detail": "No key found matching the ID with the provided secret."
}
]
}

When the check fails, the channel shows an abnormal status. Use the error code and response body to find the cause.

Error codes defined by Cloud Voice:

Error codeError messageDescription
10001channel.ErrInvalidPhoneNumberInvalid phone number.
10002channel.ErrInvalidParamInvalid parameter in the request.
10003channel.ErrUnsupportMediaResource type not supported (MMS).
10004channel.ErrAuthFailAuthentication failed.
10005channel.ErrAuthFailNo permission.
10006channel.ErrTooManyRequestToo many requests.
10007channel.ErrServiceUnavailableService unavailable on the recipient’s platform.
10008channel.ErrExceedsSizeLimitFile size exceeds the limit.

Channel status and what triggers it:

Channel statusTrigger
UnauthorizedAuthentication fails and the provider returns 401, 403, or 404; or the returned challenge code does not match the one sent.
Services of the recipient platform are unavailableThe provider returns 500.
UnknownThe provider returns a status code other than 401/403/404/500 and includes error details in the format above.
Request FailedThe provider returns no status code (for example, a TCP problem or a non-existent domain); or it returns a code other than 401/403/404/500 with no body, or a body that is not valid JSON.

When a Cloud Voice user sends a message, Cloud Voice calls the provider’s send-message API with the API key so the provider can deliver it to the external recipient.

Cloud Voice, sequence of steps for sending a message out through the provider

  1. A Cloud Voice user sends a message.
  2. Cloud Voice calls the provider’s send-message API.
  3. The provider validates the API key.
  4. If the key is valid, the provider returns status 200 and a data.id carrying the message’s unique ID.
  5. The provider delivers the message to the recipient.
  • Method: POST

  • URL: the API address for sending messages, for example https://service-provider.example.com/sendmessage

  • Headers:

    ParameterTypeDescription
    Content-TypeStringContent type of the payload. Value: application/json.
    AuthorizationStringThe API key, in the format Bearer {api_key}.
  • Body:

    ParameterTypeDescription
    fromStringSender’s phone number, in E.164 format (for example, +8618012121222).
    toStringRecipient’s phone number, in E.164 format (for example, +8618012121223).
    textStringText content of the message.
    media_urlsArray<String>URL(s) pointing to the message’s media content.

Send an SMS message:

POST /sendmessage HTTP/1.1
Host: service-provider.example.com
Content-Type: application/json
Authorization: Bearer {api_key}
{
"from": "+8618012121222",
"text": "Hello, World!",
"to": "+8618012121223"
}

Send an MMS message:

POST /sendmessage HTTP/1.1
Host: service-provider.example.com
Content-Type: application/json
Authorization: Bearer {api_key}
{
"from": "+8618012121222",
"to": "+8618012121223",
"media_urls": ["https://pbx.example.com/api/chat/70dee7e2f95041ca890f222ace06c2dc"]
}

The provider replies in JSON.

Success: return status 200 and a data.id with the unique message ID:

HTTP/1.1 200 OK
{
"data": {
"id": "b301ed3f-1490-491f-995f-6e64e69674d4"
}
}

Failure: return the error using the same code / title / detail format:

HTTP/1.1 400 Bad Request
{
"errors": [
{
"code": "10001",
"title": "Invalid 'to' address",
"detail": "The 'to' address should be a single valid number."
}
]
}

If a message cannot be delivered, Cloud Voice shows an error on the sender’s Cloud Voice App. Use the error code and response body to find the cause.

Error codes defined by Cloud Voice:

Error codeError messageDescription
10001channel.ErrInvalidPhoneNumberInvalid phone number.
10002channel.ErrInvalidParamInvalid parameter in the request.
10003channel.ErrUnsupportMediaResource type not supported (MMS).
10004channel.ErrAuthFailAuthentication failed.
10005channel.ErrAuthFailNo permission.
10006channel.ErrTooManyRequestToo many requests.
10007channel.ErrServiceUnavailableService unavailable on the recipient’s platform.
10008channel.ErrExceedsSizeLimitFile size exceeds the limit.

The prompt shown to the user and what triggers it:

Error promptTrigger
Failed to sendThe provider returns no data.id; or returns 404 (service not found); or delivery fails and the provider returns error details in the format above; or delivery fails with no error body, or a body that is not valid JSON.
Authentication FailedThe provider returns 401, or error code 10004 or 10005.
Recipient Platform Service UnavailableThe provider returns 403, or error code 10007.
Invalid Phone NumberThe provider returns error code 10001.
Invalid ParameterThe provider returns error code 10002.
This type of message is not supported due to the restriction of the recipient platform.The provider returns error code 10003.
Too frequent operations. Please try again later.The provider returns error code 10006.
The file size exceeds the limit of the recipient’s platform.The provider returns error code 10008.

Cloud Voice receives inbound messages through a phone number that the provider hosts. When someone messages that number, the provider posts the message to the Cloud Voice webhook URL.

Sequence of steps for delivering an inbound message from the provider to Cloud Voice

  1. An external sender sends a message.
  2. The provider posts a request to the Cloud Voice webhook URL, with the inbound message in the body and a SHA256 signature in the header.
  3. Cloud Voice verifies the signature: using the provider’s Secret, it recomputes a SHA256 signature over the received body and compares it with the header value. If they match, the request is valid and Cloud Voice returns status 204.
  4. Cloud Voice delivers the message to the user.
  • Method: POST

  • URL: the webhook URL that Cloud Voice provides, for example https://pbx.example.com/api/v1.0/webhook/general/429ced149ff9437695be795aff38407b

  • Headers:

    ParameterTypeDescription
    Content-TypeStringContent type of the payload. Value: application/json.
    X-Signature-256StringThe webhook signature, in the format sha256={signature}, where the signature is the lowercase SHA256 of the body computed with the Secret.
  • Body (only mandatory fields are listed; the provider may add more):

    ParameterRequiredTypeDescription
    data.event_typeYesStringEvent type. Value: message.received.
    data.payload.idYesStringMessage ID. Maximum 255 characters, and must be different every time.
    data.payload.from.phone_numberYesStringSender’s phone number, in E.164 format.
    data.payload.to.phone_numberYesStringRecipient’s phone number, in E.164 format.
    data.payload.textYesStringText content of the message. Provide either data.payload.text or data.payload.media.
    data.payload.mediaYesArray<media>Information and URL for the message’s media content. Provide either data.payload.text or data.payload.media.
    data.payload.received_atYesStringTime the message was received, in ISO 8601 format YYYY-MM-DDTHH:MM:SS.mmm+/-HH:MM (for example, 2019-12-09T20:16:07.588+08:00).
    data.payload.record_typeYesStringRecord type. Value: message.

    The media object:

    ParameterRequiredTypeDescription
    content_typeNoStringType of the media file.
    sha256NoStringSHA256 value of the media file.
    sizeNoIntegerFile size.
    urlYesStringURL pointing to the media file.

A webhook request that delivers an inbound message looks like this:

POST /api/v1.0/webhook/general/429ced149ff9437695be795aff38407b HTTP/1.1
Host: pbx.example.com
Content-Type: application/json
X-Signature-256: sha256={signature}
{
"data": {
"event_type": "message.received",
"id": "b301ed3f-1490-491f-995f-6e64e69674d4",
"occurred_at": "2019-12-09T20:16:07.588+00:00",
"payload": {
"direction": "inbound",
"from": {
"carrier": "T-Mobile USA",
"line_type": "long_code",
"phone_number": "+8618012121222"
},
"id": "84cca175-9755-4859-b67f-4730d7f58aa3",
"media": [
{
"content_type": "image/png",
"sha256": null,
"url": "https://media.example.com/mms/image.png"
}
],
"received_at": "2019-12-09T20:16:07.503+00:00",
"record_type": "message",
"text": "Hello from Cloud Voice!",
"to": [
{
"carrier": "Cloud Voice",
"line_type": "Wireless",
"phone_number": "+8618012121223"
}
],
"type": "SMS/MMS"
},
"record_type": "event"
}
}

Cloud Voice returns an HTTP status code:

Status codeDescription
204Success.
400Bad request, returned when the signature is incorrect.

Once the provider has implemented its side of the integration, an administrator adds the SMS channel in Cloud Voice.

ItemLimit
Supported message typesDetermined by the provider.
File size100 MB maximum.
File retention period72 hours.

Collect the following details.

From the provider:

  • API address for sending messages
  • (Optional) API address for verifying authentication
  • Message sending rate limit

From the provider’s customer portal:

  • API key
  • (Optional) Secret
  • The phone number used to send and receive messages
  1. In the Cloud Voice admin portal, go to Messaging > Message Channel.

  2. Click Add and select SMS.

  3. On the Authentication tab, complete the fields.

    Cloud Voice, Authentication tab of an SMS channel with the API credential fields

    • Name: a label that helps you recognize the channel.
    • ITSP (Internet Telephony Service Provider): select General.
    • API Key: the API key from the provider’s customer portal.
    • Secret: optional; enter it if the provider issued one for verification.
    • API Address for Sending Messages: the provider’s send endpoint, for example https://service-provider.example.com/sendmessage.
    • API Address for Verifying Authentication: optional; the provider’s verification endpoint, for example https://service-provider.example.com/verify.
    • Webhook URL: copy this URL, then use it to configure the messaging webhook for the phone number in the provider’s customer portal.
  4. On the Messaging Settings tab, set the sending rate, session behavior, and one or more number-routing rules (all described below). Save each rule as you add it.

  5. Click Save to create the channel.

The Messaging Settings tab includes the following options.

Message Sending Rate

Set how many messages per second Cloud Voice may send. If more messages are ready than the rate allows, Cloud Voice holds the extras in a queue and releases them at the configured rate.

Session settings

SettingDescription
Close Session AutomaticallySelect the checkbox to close sessions that have been inactive for a set period, then enter the number of days in the Session Timeout (Days) field.
Allow the Creation of Duplicate Active SessionsSelect the checkbox to allow a new session even when an active one already exists for the same sender and recipient. When enabled, if a user starts such a session in the Cloud Voice App while a matching active session already exists, a prompt appears; if the user continues, the existing session leaves the previous handler’s list and moves to the new user, along with its complete chat history.

Session timeout setting for automatically closing inactive conversations

Number routing

In the Number section, click Add to create a message-routing rule.

Dialog for adding a number-routing rule to the SMS channel

  • Number: enter the purchased phone number, or an alphanumeric sender ID (a short text name shown to the recipient as the sender instead of a number).

  • Destination for Inbound Messaging: choose where inbound messages for this number go.

    OptionDescription
    ExtensionChoose an extension. Only that user receives inbound messages from the number.
    Message QueueChoose a queue. Every agent in the queue sees the inbound message that starts a new session, but only the agent who picks it up receives and answers the follow-up messages in that session.
    Third-Party Message Analytics Platform (Transmitted via API)Inbound messages are automatically forwarded to a third-party analytics platform through the API for further processing.
  • Extensions allowed to create messaging sessions: select the extensions that may start a message conversation with customers.

  • Click Save to add the rule.

  • The channel is created and appears in the Messaging list with a status of Connected.

    SMS channel listed with a connected status on the Messaging page

  • Cloud Voice tracks how many messages the channel sends and receives. The Total column counts every outbound message, both successful and failed.

    Messaging report showing sent and received message counts for the channel

Send a text message to the number configured on the channel and confirm that the assigned user receives it in the Cloud Voice App.