Getting started
To use the Message REST API you need an account. Please get in touch with our friendly support team or your sales contact and you'll be up and running in no time!
Email: kund@genericmobile.se
Phone: 020-31 00 41
International: +46 86016666
Base URL: https://api.genericmobile.se/SmsGateway/api/v1
Messages sent and received with the REST API will be visible in the SMS Web portal.
Authentication
Authentication with API key
curl -X POST https://api.genericmobile.se/SmsGateway/api/v1/Message \
-H 'Authorization: Bearer 90be0b2c-b218-4070-a890-152821090464' \
-H 'Content-Type: application/json' \
-d '{
"From": "Alice",
"To": ["+46701740605"],
"Text": "Hello\nWorld!\uD83D\uDE42"
}'
require 'base64'
require 'uri'
require 'net/http'
require 'json'
uri = URI::HTTPS.build(
apikey: '90be0b2c-b218-4070-a890-152821090464',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Message'
)
headers = {
'Authorization' => "Bearer #{uri.apikey}",
'Content-Type' => "application/json"
}
body = {
'From' => 'Alice',
'To' => [ '+46701740605' ],
'Text' => "Hello\nWorld!\u{1F642}"
}
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_post(uri.path, JSON.generate(body), headers) do |response|
puts response.read_body
end
end
201 Created
{
"MessageId": ["deadc0de-2bad-c4fe-feed-beefca1ff00d"]
}
Bearer API Key (Recommended)
Access can be granted using an API key. For this method, all requests must contain an Authorization
header with Bearer
as the first parameter, followed by the API key. All administration of API keys is managed via our customer platform.
Basic authentication
For legacy reasons basic authentication using username and password are also supported, see RFC 7617 for details. All requests must contain an Authentication
header with Basic
as first parameter followed by a base64-encoded username:password
. If username or password contains non-ASCII characters, use UTF-8 encoding before the base64-encoding.
401 Unauthorized
Will be returned if your credentials are wrong or you have insufficient privileges.
Send messages
Immediate delivery
Note: Irrelevant headers will be omitted and json pretty-printed for clarity.
curl -X POST https://api.genericmobile.se/SmsGateway/api/v1/Message \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '{
"From": "Alice",
"To": ["+46701740605"],
"Text": "Hello\nWorld!\uD83D\uDE42"
}'
require 'base64'
require 'uri'
require 'net/http'
require 'json'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Message'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
'Content-Type' => "application/json"
}
body = {
'From' => 'Alice',
'To' => [ '+46701740605' ],
'Text' => "Hello\nWorld!\u{1F642}"
}
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_post(uri.path, JSON.generate(body), headers) do |response|
puts response.read_body
end
end
201 Created
{
"MessageId": ["deadc0de-2bad-c4fe-feed-beefca1ff00d"]
}
The send messages feature can be used to send one or more text messages immediately or at a specified date and time. You can combine most of the features described here to your liking.
POST /Message
In its simplest form only From
, To
and Text
are required, see parameters for details.
In the example, +46701740605
will get a new text message from Alice
containing two lines and a smiley
Hello
World!😄
HTTP Response
201 Created
A successful request contains a receipt object.
Throttling
By default we accept 40 messages/second. If you're sending more you'll get throttled (receive a 429 Too many requests response). It's important that your client can handle this properly. We recommend you queue up messages on your side and don't sent faster than your account is configured for. Or at least implement some form of re-try in case of 429. It might be an alternative to use scheduled delivery in order for you to batch multiple messages. In this case we're taking care of the rate limit for you.
Scheduled delivery
Scheduled delivery
curl -X POST https://api.genericmobile.se/SmsGateway/api/v1/Message \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '{
"From": "Alice",
"To": ["+46701740605"],
"Text": "Today is tomorrow",
"BatchJobName": "Future",
"SendAt": "2024-09-27T15:14:08+01:00"
}'
require 'json'
require 'base64'
require 'uri'
require 'net/http'
require 'date'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Message'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
'Content-Type' => "application/json"
}
body = {
'From' => 'Alice',
'To' => [ '+46701740605' ],
'Text' => 'Today is tomorrow',
'BatchJobName' => 'Future',
'SendAt' => '2024-09-27T15:14:08+01:00',
}
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_post(uri.path, JSON.generate(body), headers) do |response|
puts response.read_body
end
end
201 Created
{
"BatchId": "12345678-abcd-1234-5678-1234567890ab",
"MessageId": ["deadc0de-2bad-c4fe-feed-beefca1ff00d"]
}
POST /Message
By specifying SendAt
it's possible to schedule messages to be sent at a specified date and time. You may optionally set BatchJobName
for easy filtering and follow up with the SMS Web portal.
HTTP Response
201 Created
A successful request contains a receipt object with the BatchId
set to a unique ID that could be used to delete this batch.
Delete a batch
curl -X DELETE https://api.genericmobile.se/SmsGateway/api/v1/Message/12345678-abcd-1234-5678-1234567890ab \
--basic -u Alice:secretPwd
204 No Content
DELETE /Message/{BatchId}
Where {BatchId}
is from the Scheduled delivery response. If the batch have not yet been sent, deleting it will prevent it from ever doing so.
HTTP Response
204 No Content
The scheduled delivery was successfully deleted.
404 Not Found
The {BatchId}
was not found/already deleted.
Limited validity period
Limited validity period
curl -X POST https://api.genericmobile.se/SmsGateway/api/v1/Message \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '{
"From": "2FA",
"To": ["+46701740605"],
"Text": "Security code: 123456",
"ValidityPeriodMinutes": 5
}'
require 'json'
require 'base64'
require 'uri'
require 'net/http'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Message'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
body = {
'From' => '2FA',
'To' => [ '+46701740605' ],
'Text' => 'Security code: 123456',
'ValidityPeriodMinutes' => 5
}
headers['Content-Type'] = 'application/json'
json_body = JSON.generate(body)
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_post(uri.path, json_body, headers) do |response|
puts response.read_body
end
end
201 Created
{
"MessageId": ["deadc0de-2bad-c4fe-feed-beefca1ff00d"]
}
POST /Message
Text messages can't be delivered to mobile phones that are turned off or by other means unreachable. However messages are stored and new delivery attempts are made for a certain time, default is 4320 minutes (3 days). After this period the message is dropped. You may set ValidityPeriodMinutes
to a lower value in cases where the message bear no meaning if not delivered within a period of time.
The validity period starts when the message is sent.
HTTP Response
201 Created
A successful request contains a receipt object.
Flash message
Flash message
curl -X POST https://api.genericmobile.se/SmsGateway/api/v1/Message \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '{
"From": "Alice",
"To": ["+46701740605"],
"Text": "This is an urgent message",
"Flash": true
}'
require 'json'
require 'base64'
require 'uri'
require 'net/http'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Message'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
body = {
'From' => 'Alice',
'To' => [ '+46701740605' ],
'Text' => 'In your face',
'Flash' => true
}
headers['Content-Type'] = 'application/json'
json_body = JSON.generate(body)
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_post(uri.path, json_body, headers) do |response|
puts response.read_body
end
end
201 Created
{
"MessageId": ["deadc0de-2bad-c4fe-feed-beefca1ff00d"]
}
POST /Message
A flash message is delivered and shown directly on the mobile device display. The message will be shown until the receiver discards it and the message will not be stored by default. Enable this feature by setting Flash
to true
, however this feature can not be combined with SendAt
.
Flash messages may be suitable for important or sensitive information.
HTTP Response
201 Created
A successful request contains a receipt object.
Message with text parameters
Text parameters
curl -X POST https://api.genericmobile.se/SmsGateway/api/v1/Message \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '{
"From": "Boss",
"To": ["+46701740605", "+46701740606"],
"Text": "Hi {1}, you look {2}!",
"TextParameters": [
["Bob", "tired"],
["Alice", "great"]
]
}'
require 'json'
require 'base64'
require 'uri'
require 'net/http'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Message'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
body = {
'From' => 'Boss',
'To' => [
"+46701740605",
"+46701740606"
],
'Text' => "Hi {1}, you look {2}!",
'TextParameters' => [
[ 'Bob', 'tired' ],
[ 'Alice', 'great' ]
]
}
headers['Content-Type'] = 'application/json'
json_body = JSON.generate(body)
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_post(uri.path, json_body, headers) do |response|
puts response.read_body
end
end
201 Created
{
"MessageId": [
"deadc0de-2bad-c4fe-feed-beefca1ff00d",
"deadc0de-2bad-c4fe-feed-beefca1ff001"
]
}
POST /Message
Text parameters can be used to personalize the message for each receiver phone number.
This is done iteratively by replacing {1}, {2}, {3}, etc. in Text
with the corresponding strings from the TextParameters
array. The first phone number in the To
array will use the first replacement array from TextParameters
and so forth. Make sure the TextParameters
array have as many sub-arrays as the To
array have phone numbers.
In the example, +46701740605
will receive Hi Bob, you look tired!
where as +46768920857
will get Hi Alice, you look great!
.
HTTP Response
201 Created
A successful request contains a receipt object.
Parameters
Parameter | Required | Type | Default | Description |
---|---|---|---|---|
From | Yes | String1 | - | Phone number, alphanumeric sender or a Dynamic Answer pool. |
To | Yes | Array (1..1000) of Strings | - | List of recipient phone numbers. |
Text | Yes | String | - | The message body. |
DeliveryReportUrl | No | String (9..255) | null | http(s) URL for receiving delivery reports, if null or omitted no delivery report will be sent. |
BatchJobName | No | String (1..50) | Generated name | A name tag for a scheduled delivery. |
SendAt | No | ISO-8601 DateTime | Now | Max one year from now. Passed DateTimes will be sent immediately. |
ValidityPeriodMinutes | No | Integer | 4320 | The validity period of the message. |
Flash | No | Boolean | False | The message will be sent as flash SMS. |
ForceVoice | No | Boolean | False | If True, the recipient will be called and the Text read out loud using speech synthesis. |
TextParameters | No | Array of Arrays of Strings | Empty Array | Strings to insert into message body. The length of the outer Array must match the length of the Text Array. |
DynamicAnswer | No | Boolean | False | Enable the Dynamic Answer feature. |
Reference | No | String (0..255) | null | Tag the message with a custom reference. Usable when dissecting the message log or associate incoming messages when using Dynamic Answer. |
1 A phone number should be given in international format (leading + sign). An alphanumeric sender may contain A-Ö, a-ö, 0-9 or any of the special characters "#%&'()*+-./?
, max 11 characters. However some operators are not able to handle Swedish characters and because of that we recommend you to only use A-Z, a-z, 0-9.
Receipt object
Receipt object example
{
"BatchId": "12345678-abcd-1234-5678-1234567890ab",
"MessageId": ["deadc0de-2bad-c4fe-feed-beefca1ff00d"]
}
Key | Description | Type |
---|---|---|
MessageId | Array of Message IDs, one for each receiver phone number the message is destined for and in the same order. | Array |
BatchId | Present when SendAt is used to create a scheduled batch. |
String |
Delivery Report
Delivery reports are used to find out whether a message has been delivered or not. The most efficient way is to specify a callback URL for us to send/push the delivery report to as soon as we get it. But we also provide an API endpoint for you to poll for updates.
Delivery reports with push
Enable delivery report when sending a message
curl -X POST https://api.genericmobile.se/SmsGateway/api/v1/Message \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '{
"From": "Alice",
"To": ["+46701740605"],
"Text": "Hello",
"DeliveryReportUrl": "https://api.example.se/DR"
}'
require 'base64'
require 'uri'
require 'net/http'
require 'json'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Message'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
'Content-Type' => "application/json"
}
body = {
'From' => 'Alice',
'To' => [ '+46701740605' ],
'Text' => "Hello\nWorld!\u{1F642}",
'DeliveryReportUrl' => 'https://api.example.se/DR'
}
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_post(uri.path, JSON.generate(body), headers) do |response|
puts response.read_body
end
end
201 Created
{
"MessageId": ["deadc0de-2bad-c4fe-feed-beefca1ff00d"]
}
Turn on this feature by specifying DeliveryReportUrl
when sending a message. In case there are network issues, or your endpoint doesn't acknowledge the delivery report we will retry a couple of times during a 30 minute period. After that you'll have to poll for the delivery reports.
HTTP Request
Example HTTP session with
DeliveryReportUrl
set tohttps://api.example.se/DR
,
POST /DR HTTP/1.1
Host: api.example.se
Content-Type: application/json
{
"MessageId": "deadc0de-2bad-c4fe-feed-beefca1ff00d",
"StatusTime": "2020-01-19T04:14:08+01:00",
"Status": "Delivered"
}
We will make a POST
request containing a application/json
encoded delivery report object. The example http session shows how it may look like.
HTTP Response
200 OK
Your endpoint should acknowledge the delivery report by responding 200 OK
.
Delivery reports with poll
Get message status
curl https://api.genericmobile.se/SmsGateway/api/v1/Message/deadc0de-2bad-c4fe-feed-beefca1ff00d \
--basic -u Alice:secretPwd
require 'json'
require 'base64'
require 'uri'
require 'net/http'
message_id = 'deadc0de-2bad-c4fe-feed-beefca1ff00d'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: File.join('/SmsGateway/api/v1/Message', message_id)
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
delivery_report = nil
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_get(uri.path, headers) do |response|
delivery_report = JSON.parse(response.read_body)
end
end
puts JSON.pretty_generate(delivery_report)
200 OK
{
"MessageId": "deadc0de-2bad-c4fe-feed-beefca1ff00d",
"StatusTime": "2020-12-06T15:57:08+01:00",
"Status": "Delivered"
}
GET /Message/{MessageId}
See how a specific message is doing. Note that all messages will start off with Status = Sending
, even messages scheduled for later delivery. The {MessageId}
is the unique ID of a sent message found in the receipt object.
HTTP Response
200 OK
The response is a delivery report object.
Delivery report object
Example delivery report
{
"MessageId": "deadc0de-2bad-c4fe-feed-beefca1ff00d",
"StatusTime": "2020-12-06T15:57:08+01:00",
"Status": "Failed",
"ErrorCode": 52,
"Reason": "Invalid destination number"
}
Key | Type | Description |
---|---|---|
MessageId | String | The Id of the requested message. |
StatusTime | ISO-8601 DateTime | When the status was last updated. |
Status | String | Sending -> Sent -> Delivered / Failed. |
ErrorCode | Int | ErrorCode, only present if Status = "Failed". |
Reason | String | Description of problem, only present if Status = "Failed". |
Receive messages
List your inboxes
curl https://api.genericmobile.se/SmsGateway/api/v1/Inbox \
--basic -u Alice:secretPwd
200 OK
{
"Inboxes": [
{
"Inbox": "+46846500400",
"NotificationUrl": "https://example.com/inboxNotification"
}
]
}
Just as a mobile phone get its messages delivered to an inbox, it's possible to configure one or more phone numbers where you can receive messages. Those inboxes are visible on the SMS Web portal but could also be queried by the API. The phone numbers are provided by Generic and associated with your account. You can retrieve the list in inboxes as the example shows.
Setting URL for push messaging
Setting NotificationURL for an inbox
curl -X PUT https://api.genericmobile.se/SmsGateway/api/v1/Inbox/46701740605 \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '{
"NotificationURL": "https://example.com/inboxNotification"
}'
require 'json'
require 'base64'
require 'uri'
require 'net/http'
inbox_number = "46846500400"
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: File.join('/SmsGateway/api/v1/Inbox', 'inbox_number')
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
body = {
'NotificationURL': 'https://example.com/inboxNotification'
}
headers['Content-Type'] = 'application/json'
json_body = JSON.generate(body)
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_put(uri.path, json_body, headers) do |response|
puts response.read_body
end
end
By specifying a NotificationURL
on the Inbox we will send all incoming messages to that URL. This NotificationURL
could be set with the API, as shown in the example, or with the SMS Web portal.
If the notification endpoint isn't available new delivery attempts will be made every 15 minutes for 72 hours. Note that it's only the administrator that can set the NotificationURL.
PUT /Inbox/{phoneNumber}
Where {phoneNumber}
is the telephone number of the inbox for which the URL shall be set for.
Parameter | Description | Type |
---|---|---|
NotificationURL | URL received messages are sent to | String |
Receive messages with push
Example of inbox notification
POST /inboxNotification HTTP/1.1
Host: api.example.se
Content-Type: application/json
Connection: Keep-Alive
Expect: 100-continue
[
{
"Id": 12345678,
"From": "+46701740605",
"To": "+46701740606",
"Text": "You've got a new message",
"ReceiveTime": "2020-12-10T11:42:55+01:00"
}
]
If a NotificationURL
is specified we will send/push any incoming message to that URL as soon as it arrives to the inbox. This is the most efficient and preferred way to retrieve messages. The POST
request contains an array of up to 100 Message objects
.
Similar to how we push delivery reports it's important to respond with a 2xx
HTTP Status code to let us know you've successfully retrieved the message(s).
Fetch messages
Example of message polling
curl "https://api.genericmobile.se/SmsGateway/api/v1/Inbox/46846500400?beginid=3412266&newer=true&limit=5" \
--basic -u Alice:secretPwd
require 'json'
require 'base64'
require 'uri'
require 'net/http'
inbox_number = "46846500400"
query = {
'BeginId' => 3412266,
'Newer' => true,
'Limit' => 5
}
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: File.join('/SmsGateway/api/v1/Inbox', inbox_number),
query: URI.encode_www_form(query)
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_get(uri.path, headers) do |response|
puts response.read_body
end
end
200 OK
{
"Inbox": "+46846500400",
"Messages": [
{
"Id": 3412411,
"From": "+46701740605",
"To": "+46846500400",
"Text": "Räksmörgås",
"ReceiveTime": "2020-12-10T11:32:02+01:00"
},
{
"Id": 3412507,
"From": "+46701740605",
"To": "+46846500400",
"Text": "Hello 😎",
"ReceiveTime": "2020-12-10T11:42:55+01:00"
}
]
}
Example 429 Too Many Requests
HTTP/2 429
content-type: application/json
retry-after: 3
{
"description": "Quota exceeded. Maximum allowed: 1 per 5s. Please try again in 3 second(s)."
}
Fetching messages support pagination by the use of Limit
, BeginId
and Newer
which are passed in as URI parameters in the GET
request.
GET /Inbox/{PhoneNumber}
Where {PhoneNumber}
is the telephone number of the inbox.
Parameter | Required | Type | Default | Description |
---|---|---|---|---|
Limit | No | Integer | 100 | Max number of received messages in one response. |
BeginId | No | Integer | Max | Id to start from (will not be included). |
Newer | No | Boolean | false | Get newer or older messages than the BeginId . |
The sort order is based on the Id and descending as default. Setting Newer
=true
will reverse the order.
HTTP Response
200 OK
Key | Type | Description |
---|---|---|
Inbox | String | Phone number which the message(s) has been received on. |
Messages | Array | Array of message objects. |
429 Too Many Requests
Clients are allowed to fetch messages once every 5 seconds. If multiple requests are made within this time frame, the API will respond with HTTP status code 429 Too Many Requests.
Dynamic Answer
Send two messages with Dynamic Answer enabled
curl -X POST https://api.genericmobile.se/SmsGateway/api/v1/Message \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '{
"From": "Pool-1",
"To": ["+46701740605"],
"Text": "Rate our support! Answer 1-5 where 5 is awesome",
"DynamicAnswer": true,
"Reference": "support"
}'
201 Created
{
"MessageId": [ "deadc0de-2bad-c4fe-feed-beefca1ff001" ]
}
curl -X POST https://api.genericmobile.se/SmsGateway/api/v1/Message \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '{
"From": "Pool-1",
"To": ["+46701740605"],
"Text": "Would you recommend us to a friend? Answer 1-5 where 5 is absolutely",
"DynamicAnswer": true,
"Reference": "friend"
}'
201 Created
{
"MessageId": [ "deadc0de-2bad-c4fe-feed-beefca1ff002" ]
}
An answer from +46701740605 mapped to the support question
[
{
"Id": 3425333,
"From": "+46701740605",
"To": "+46846500400",
"Text": "5",
"ReceiveTime": "2020-12-11T13:30:52.903+01:00",
"Reference": "support"
}
]
The Dynamic Answer feature allows received messages to be associated with sent messages.
This is accomplished by dynamically selecting a sender phone number from a pool of numbers in order to create a session with the receiver. This number pool needs to be configured for you by Generic, but once in place you may enable this feature by setting DynamicAnswer
to true
.
Set a Reference
value when sending a message and the same reference value will be present when receiving messages, allowing you to treat incoming messages as answers to what you sent out.
You may have multiple pools of numbers, thus you need to state which pool to use by setting From
to the name or number of the pool.
Example explained Someone has just been in contact with your support and you'd like to get some feedback; How the support experience was and How likely you'd be recommended to a friend. Based on that you send two SMS, with one question each, to the customers mobile phone. To maximize the response rate, it must be easy for the user to respond. Here a single digit will suffice, and Dynamic Answer will keep track of which question a response belongs to.
POST /Message
Besides the required parameters needed to send a message you should set DynamicAnswer
and preferably also Reference
.
HTTP Response
201 Created
A successful request contains a receipt object.
Received answers
Answers on messages sent with the Dynamic Answer feature may be received as usual via either push or poll.
Such messages have the Reference
parameter set in the message object. The To
parameter shows which of the pool numbers was used to send the initial message.
Message Object
Key | Type | Description |
---|---|---|
Id | Integer | Unique id for the received message. |
From | String | Phone number which the message was sent from. |
To | String | Phone number which the message was sent to. |
Text | String | Message body. |
ReceivedTime | ISO-8601 DateTime | When the message was received by the service. |
Reference | String | Omitted if null, see DynamicAnswer. |
User Administration
Accounts are divided into two different types, admin users and regular users. Admin users are able to create and modify regular users
and provide them with a phone number for receiving messages. Admin users are also able to fetch statistics for a regular user,
for example the number of sent SMS during a specific time period.
A locked account can't access the API nor log into our SMSWeb portal.
Create a user
Create the user Bob
curl -X POST https://api.genericmobile.se/SmsGateway/api/v1/User \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '{
"UserID": "Bob",
"Password": "bobsNewPassword",
"Name": "Bob Smith",
"Description": "My uncle"
}'
require 'base64'
require 'uri'
require 'net/http'
require 'json'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/User'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
body = {
'UserID' => 'Bob',
'Password' => 'bobsNewPassword',
'Name' => 'Bob Smith',
'Description' => 'My uncle'
}
headers['Content-Type'] = 'application/json'
json_body = JSON.generate(body)
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_post(uri.path, json_body, headers) do |response|
puts response.read_body
end
end
201 Created
{
"UserID": "Bob",
"Description": "My uncle",
"Name": "Bob Smith",
"Locked": false
}
A new regular user is created by using at least UserID
and Password
.
POST /User
Note that UserID
must be globally unique.
HTTP Response
201 Created
The user was successfully created, the response contains a user object.
400 Bad Request
Will contain a message explaining the issue, e.g.
{"Message": "A user with this name already exists!"}
List/get users
List users
curl https://api.genericmobile.se/SmsGateway/api/v1/User \
--basic -u Alice:secretPwd
require 'base64'
require 'uri'
require 'net/http'
require 'json'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/User'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_get(uri.path, headers) do |response|
puts response.read_body
end
end
200 OK
[
{
"UserID": "Alice",
"Description": "Alice the kitten",
"Name": "",
"Locked": false
},
{
"UserID": "Bob",
"Description": "My uncle",
"Locked": true,
"IpRestrictions": ["127.0.0.1", "192.168.0.0/24"]
}
]
Admin users may list all users and their properties.
GET /User
HTTP Response
200 OK
The response contains an array of user object(s).
It's also possible for a admin user to list properties of a given user.
GET /User/{UserId}
Where {UserId}
is the unique identification of a regular user.
HTTP Response
200 OK
The response contains a single user object.
Delete user
Delete Bob
curl -X DELETE https://api.genericmobile.se/SmsGateway/api/v1/User/Bob \
--basic -u Alice:secretPwd
require 'base64'
require 'uri'
require 'net/http'
require 'json'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/User/Bob'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request(Net::HTTP::Delete.new(uri.path, headers)) do |response|
puts response.read_body
end
end
204 No Content
DELETE /User/{UserId}
Where {UserID}
is the unique identification of a regular user.
HTTP Response
204 No Content
The user was successfully deleted.
404 Not Found
Either the user don't exists or you don't have permission to delete the user.
Update user
Update Bob's
IpRestrictions
parameter
curl -X PUT https://api.genericmobile.se/SmsGateway/api/v1/User/Bob/IpRestrictions \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '["127.0.0.1", "192.168.0.0/24"]'
require 'base64'
require 'uri'
require 'net/http'
require 'json'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/User/Bob/IpRestrictions'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
body = [ "127.0.0.1", "192.168.0.0/24" ]
headers['Content-Type'] = 'application/json'
json_body = JSON.generate(body)
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_put(uri.path, json_body, headers)) do |response|
puts response.read_body
end
end
200 OK
{
"UserID": "Bob",
"Description": "My uncle",
"Name": "",
"Locked": false,
"IpRestrictions": ["127.0.0.1", "192.168.0.0/24"]
}
A regular user can be updated by an admin user. All but the user name may be updated.
PUT /User/{UserId}/{Attribute}
Where {UserId}
is the unique identification of a regular user and {Attribute}
the parameter to update, Description
, Name
, Password
, IpRestrictions
or Locked
.
HTTP Response
200 OK
All attributes except Password
.
The user was successfully updated, the response contains a user object.
204 No Content
When updating the password no content is returned to indicate a successful request.
User Parameters
Parameter | Required | Type | Default | Description |
---|---|---|---|---|
UserID | Yes | String | - | Identification of the user a-z, A-Z, 0-9, max 191 characters. |
Password | Yes | String | - | Password of the regular user (7-bit ASCII 6-191 characters). |
Name | No | String | Empty string | First- and lastname of the user, max 50 characters. |
Description | No | String | Empty string | Description of the regular user. |
IpRestrictions | No | Array of Strings | null | A list of IP-addresses and/or sub-networks from which the regular user may connect to the service. If not set no restrictions apply and the user may connect from anywhere. |
Locked | No | Boolean | false | Open or locked account. |
User Object
Key | Type | Description |
---|---|---|
UserID | String | Identification of a the user created. |
Description | String | Description of the regular user. |
Name | String | First- and lastname of the user. |
Locked | Boolean | Status of the user. |
IpRestrictions | Array of Strings | IP-addresses and/or sub-networks from which the user may connect to the service. Omitted if null. |
Contacts Administration
With the contact administration api function you are able to create, update and delete individual and group contacts visible in the SMS Web portal. With an Admin user it´s also possible to share contacts with regular users.
Create individual
Create the individual Bob
curl -X POST https://api.genericmobile.se/SmsGateway/api/v1/Contacts/Individuals \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '{
"Name": "Bob",
"Number": "+46701740605",
"IsShared": false,
"Groups" => [123]
}'
require 'base64'
require 'uri'
require 'net/http'
require 'json'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Contacts/Individuals'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
body = {
'Name' => 'Bob',
'Number' => '+46701740605',
'IsShared' => false
}
headers['Content-Type'] = 'application/json'
json_body = JSON.generate(body)
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_post(uri.path, json_body, headers) do |response|
puts response.read_body
end
end
201 Created
{
"Id": 5678,
"Name": "Bob",
"Number": "+46701740605",
"IsShared": false,
"Groups": []
}
To create a new individual send a POST
request with an individual object containing at least Name
and Number
. The Id
cannot be set, it will be generated by the API and any given value will be ignored. By providing the optional Groups
parameter you can assign group membership directly directly on create.
POST /Contacts/Individuals
HTTP Response
201 Created
The individual was successfully created, the response contains an individual object.
400 Bad Request
Will contain a message explaining the issue, e.g.
{"Message": "Validation failed - Number must be in international format"}
List/get individuals
List all individuals
curl https://api.genericmobile.se/SmsGateway/api/v1/Contacts/Individuals \
--basic -u Alice:secretPwd
require 'base64'
require 'uri'
require 'net/http'
require 'json'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Contacts/Individuals'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_get(uri.path, headers) do |response|
puts response.read_body
end
end
200 OK
[
{
"Id": 4321,
"Name": "Alice",
"Number": "+46701740606",
"IsShared": false
},
{
"Id": 5678,
"Name": "Bob",
"Number": "+46701740605",
"IsShared": false
}
]
A list of all individuals can be retrieved.
GET /Contacts/Individuals
HTTP Response
200 OK
The response contains an array of individual object(s).
It's also possible to retrieve a single individual.
GET /Contacts/Individuals/{Id}
Where {Id}
is the identifier of an individual.
HTTP Response
200 OK
The response contains a single individual object.
Delete individual
Delete user 5678
curl -X DELETE https://api.genericmobile.se/SmsGateway/api/v1/Contacts/Individuals/5678 \
--basic -u Alice:secretPwd
require 'base64'
require 'uri'
require 'net/http'
require 'json'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Contacts/Individuals/5678'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request(Net::HTTP::Delete.new(uri.path, headers)) do |response|
puts response.read_body
end
end
204 No Content
DELETE /Contacts/Individuals/{Id}
Where {Id}
is the identifier of an individual.
HTTP Response
204 No Content
The contact was successfully deleted.
404 Not Found
Either the individual doesn't exist or you don't have permission to delete it.
Update individual
Update Bob's
Number
curl -X PUT https://api.genericmobile.se/SmsGateway/api/v1/Contacts/Individuals/5678/Number \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '+46701740605'
require 'base64'
require 'uri'
require 'net/http'
require 'json'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Contacts/Individuals/5678/Number'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
'Content-Type' => "application/json",
}
body = "+46701740605"
json_body = JSON.generate(body)
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_put(uri.path, json_body, headers)) do |response|
puts response.read_body
end
end
204 No Content
An individual can be updated.
PUT /Contacts/Individuals/{Id}/{Attribute}
Where {Id}
is the identifier of an individual and {Attribute}
the individual object parameter to update, Name
, Number
or IsShared
. The parameter value shall be placed in the request body.
HTTP Response
204 No Content
The individual was successfully updated.
Individual Object
Parameter | Required | Type | Default | Description |
---|---|---|---|---|
Id | No | Int | - | The individual identifier. |
Name | Yes | String | - | Name of individual (max 50 characters). |
Number | Yes | String | - | Phone number to the individual in international format. |
IsShared | No | Boolean | false | Admin users can create and share contacts with regular users. |
Groups | No | List | [] | List of GroupIds (integers). Only used when creating an individual. |
Create group
Create the group MyFriends
curl -X POST https://api.genericmobile.se/SmsGateway/api/v1/Contacts/Groups \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '{
"Name": "MyFriends",
"Members": [4321, 5678],
"IsShared": false
}'
require 'base64'
require 'uri'
require 'net/http'
require 'json'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Contacts/Groups'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
body = {
'Name' => 'MyFriends',
'Members' => [4321, 5678],
'IsShared' => false
}
headers['Content-Type'] = 'application/json'
json_body = JSON.generate(body)
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_post(uri.path, json_body, headers) do |response|
puts response.read_body
end
end
201 Created
{
"Id": 6789,
"Name": "MyFriends",
"Members": [4321, 5678],
"IsShared": false
}
To create a new group send a POST
request with a group object containing at least Name
and Members
. Two groups are not allowed to have the same Name
. Members
is an array of individual identifiers, missing or duplicate identifiers are silently ignored. The Id
cannot be set, it will be generated by the API and any given value will be ignored.
POST /Contacts/Groups
HTTP Response
201 Created
The group was successfully created, the response contains a group object.
400 Bad Request
Will contain a message explaining the issue, e.g.
{"Message": "Group name must be unique"}
List/get groups
List all groups
curl https://api.genericmobile.se/SmsGateway/api/v1/Contacts/Groups \
--basic -u Alice:secretPwd
require 'base64'
require 'uri'
require 'net/http'
require 'json'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Contacts/Groups'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_get(uri.path, headers) do |response|
puts response.read_body
end
end
200 OK
[
{
"Id": 6789,
"Name": "MyFriends",
"Members": [4321, 5678],
"IsShared": false
},
{
"Id": 7890,
"Name": "OurCustomers",
"Members": [123, 456],
"IsShared": false
}
]
A list of all groups can be retrieved.
GET /Contacts/Groups
HTTP Response
200 OK
The response contains an array of group object(s).
It's also possible to retrieve a single group.
GET /Contacts/Groups/{Id}
Where {Id}
is the identifier of a group.
HTTP Response
200 OK
The response contains a single group object.
Delete group
Delete group 7890
curl -X DELETE https://api.genericmobile.se/SmsGateway/api/v1/Contacts/Groups/7890 \
--basic -u Alice:secretPwd
require 'base64'
require 'uri'
require 'net/http'
require 'json'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Contacts/Groups/7890'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request(Net::HTTP::Delete.new(uri.path, headers)) do |response|
puts response.read_body
end
end
204 No Content
DELETE /Contacts/Groups/{Id}
Where {Id}
is the identifier of a group.
HTTP Response
204 No Content
The group was successfully deleted.
404 Not Found
Either the group doesn't exist or you don't have permission to delete it.
Update group
Update MyFriends's
Members
curl -X PUT https://api.genericmobile.se/SmsGateway/api/v1/Contacts/Groups/6789/Members \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '[123, 456]'
require 'base64'
require 'uri'
require 'net/http'
require 'json'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Contacts/Groups/6789/Members'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
'Content-Type' => "application/json",
}
body = [123, 456]
json_body = JSON.generate(body)
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_put(uri.path, json_body, headers)) do |response|
puts response.read_body
end
end
204 No Content
A group can be updated.
PUT /Contacts/Groups/{Id}/{Attribute}
Where {Id}
is the identifier of a group and {Attribute}
the group object parameter to update, Name
, Members
or IsShared
. The parameter value shall be placed in the request body.
When updating Members
all previous members are deleted, invalid identifiers are silently ignored.
HTTP Response
204 No Content
The group was successfully updated.
Add group members
Add two members to the group MyFriends
curl -X POST https://api.genericmobile.se/SmsGateway/api/v1/Contacts/Groups/6789/Members \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '[123, 456]'
require 'base64'
require 'uri'
require 'net/http'
require 'json'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Contacts/Groups/6789/Members'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
body = [123, 456]
headers['Content-Type'] = 'application/json'
json_body = JSON.generate(body)
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_post(uri.path, json_body, headers) do |response|
puts response.read_body
end
end
204 No Content
To add members to a group send a POST
request with an array of identifiers to add.
POST /Contacts/Groups/{Id}/Members
HTTP Response
204 No Content
The members were successfully added, invalid identifiers are silently ignored.
Delete group member
Delete member 123 from group 7890:
curl -X DELETE https://api.genericmobile.se/SmsGateway/api/v1/Contacts/Groups/7890/Members/123 \
--basic -u Alice:secretPwd
require 'base64'
require 'uri'
require 'net/http'
require 'json'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Contacts/Groups/7890/Members/123'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request(Net::HTTP::Delete.new(uri.path, headers)) do |response|
puts response.read_body
end
end
204 No Content
DELETE /Contacts/Groups/{GroupId}/Members/{IndividualId}
Where {GroupId}
is the identifier of the group from which the individual with identifier `{IndividualId} is to be deleted.
HTTP Response
204 No Content
The member was successfully deleted from the group.
404 Not Found
Either the group or the individual doesn't exist or you don't have permission to delete it.
Group Object
Parameter | Required | Type | Default | Description |
---|---|---|---|---|
Id | No | Int | - | The group identifier. |
Name | Yes | String | - | Name of group (max 50 characters). |
Members | Yes | Array of int | - | Array of individual identifiers. |
IsShared | No | Boolean | false | Admin users can create and share contacts with regular users. |
Stop list Administration
The Stop list feature enables authenticated users to manage a list of phone numbers, effectively preventing SMS messages from being sent to these numbers. This provides detailed information on how to interact with the Stop list API, including adding, retrieving and deleting numbers from the list. Users have exclusive control over their own stop list, with no access to manage others' lists.
Add number to stop list
Add number to stop List
curl -X POST https://api.genericmobile.se/SmsGateway/api/v1/Stoplist/Alice \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '{
"Number": "+46701740605",
"Description": "SMS-free zone.",
}
require 'base64'
require 'uri'
require 'net/http'
require 'json'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Stoplist/Alice'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
body = {
'Number' => '+46701740605',
'Description' => 'SMS-free zone.'
}
headers['Content-Type'] = 'application/json'
json_body = JSON.generate(body)
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_post(uri.path, json_body, headers) do |response|
puts response.read_body
end
end
201 Created
{
"UserId": "Alice",
"Number": "+46701740605",
"Description": "SMS-free zone.",
"CreatedAt": "2020-01-19T09:36:14.2426241Z"
}
POST /Stoplist/{UserId}
To add a number to the stop list, submit a POST
request containing the number along with an optional description. The API automatically manages UserId
and CreatedAt
, with Number
1 being the only required field.
HTTP Response
201 Created
The number was successfully added to the stop list. The response body includes a Stoplist object.
400 Bad Request
Will contain a message explaining the issue, e.g.
{"Number": "Validation failed - Parameter \"Number\" must be an international phone number."}
409 Conflict
When attempting to add a number to the stop list, if the number already exists within the list, the API will respond with a status code of 409. This indicates a conflict with the current state of the resource, specifically that the number being added is already present in the user's stop list.
Retrieving Numbers from the Stop list
To list all numbers in your stop list or retrieve a specific number, use the GET method.
List All Numbers
Example request
curl -X GET "https://api.genericmobile.se/SmsGateway/api/v1/Stoplist/Alice?Limit=1234&offset=5"\
--basic -u Alice:secretPwd \
require 'json'
require 'base64'
require 'uri'
require 'net/http'
query = {
'Limit' => 1234,
'offset' => 5
}
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Stoplist/Alice?Limit=1234&offset=5'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_get(uri.path, headers) do |response|
puts response.read_body
end
end
200 OK
[
{
"UserId": "Alice",
"Number": "+46701740605",
"Description": "SMS-free zone.",
"CreatedAt": "2020-01-19T09:36:14.2426241Z"
},
{
"UserId": "Alice",
"Number": "+46701740606",
"Description": "SMS-free zone.",
"CreatedAt": "2020-01-19T09:36:14.2426241Z",
}
]
GET /Stoplist/{UserId}
This endpoint enables the retrieval of a list of phone numbers added to a stop list, with a maximum limit of 10 000 records per request to ensure efficient data management. To accommodate large datasets, pagination is supported through the use of limit
and offset
parameters.
HTTP Response
200 OK
The response will consist of an array of Stoplist object from the stop list, adhering to the specified range.
Retrieve a Specific Number
GET /Stoplist/{UserId}/{Number}
HTTP Response
200 OK
The response will contain a single Stoplist object
404 Not Found
The number specified in the URI is not included in the stop list.
Delete number
Delete number from stop list
curl -X DELETE https://api.genericmobile.se/SmsGateway/api/v1/Stoplist/Alice/46701740605 \
--basic -u Alice:secretPwd \
require 'json'
require 'base64'
require 'uri'
require 'net/http'
uri = URI::HTTPS.build(
userinfo: 'Alice:secretPwd',
host: 'api.genericmobile.se',
path: '/SmsGateway/api/v1/Stoplist/Alice/46701740605'
)
headers = {
'Authorization' => "Basic #{Base64.strict_encode64(uri.userinfo)}",
}
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request_delete(uri.path, headers) do |response|
puts response.read_body
end
end
204 No Content
DELETE /Stoplist/{UserId}/{Number}
The Number
specified in the URI is the one you wish to remove from your list.
HTTP Response
204 No Content
The number in the stop list was successfully deleted.
404 No Content
The number doesnt't exist in the authenticated user's stop list.
Stoplist Object
Parameter | Type | Default | Description |
---|---|---|---|
UserId | String | Authenticated user | Identification of the user a-z, A-Z, 0-9, max 191 characters. |
Number1 | String | - | Phone number in international format |
Description | String | Empty string | Optional description of the number in the stop list. |
CreatedAt | ISO-8601 DateTime | Now | When the number was added to the stop list. |
1 Parameter \"Number\" must be an international phone number.
Statistics
Example statistics
curl "https://api.genericmobile.se/SmsGateway/api/v1/Statistics/Alice/Sent?start=2020-12-01&end=2020-12-24T15:00:00%2B01:00" \
--basic -u Alice:secretPwd
200 OK
{
"FirstMessage": "2020-10-23T13:11:59+02:00",
"LastMessage": "2020-12-11T13:30:13+01:00",
"Sent": 66,
"Delivered": 61,
"Failed": 1,
"Unknown": 4,
"Countries":
[
{
"Name": "Sweden",
"CountryCode": "+46",
"Sent": 56,
"Delivered": 51,
"Failed": 1,
"Unknown": 4,
"FixedLine": {
"Sent": 50,
"Delivered": 49,
"Failed": 1,
"Unknown": 0
},
"Mobile": {
"Sent": 2,
"Delivered": 2,
"Failed": 0,
"Unknown": 0
},
"Pager": {
"Sent": 4,
"Delivered": 0,
"Failed": 0,
"Unknown": 4
}
},
{
"Name": "Norway",
"CountryCode": "+47",
"Sent": 10,
"Delivered": 10,
"Failed": 0,
"Unknown": 0
"Mobile": {
"Sent": 10,
"Delivered": 10,
"Failed": 0,
"Unknown": 0
}
}
...
]
}
An admin user may obtain statistics of SMS sent during a given time.
GET /Statistics/{UserId}/Sent?start={DateTime}&end={DateTime}
Where {UserId}
is the identification of a user. Both start
and end
are optional. Please note that you may need to URL encode the {DateTime}
as seen in the example. If no time zone is given CET/CEST is assumed (local time zone in Sweden).
HTTP Response
200 OK
A successful response contains a summary a long with a separation based on country and number type. Please note that a long message will be split up into several SMS. This statistic is based on the number of SMS rather than the number of messages sent.
429 Too Many Requests
Clients are allowed to fetch statistics once every 30 seconds. If multiple requests are made within this timeframe, the API will respond with the HTTP status code 429 Too Many Requests.
Key | Type | Description |
---|---|---|
FirstMessage | ISO-8601 DateTime | Date and time of the first sent SMS within the given timespan |
LastMessage | ISO-8601 DateTime | Date and time of the last sent SMS within the given timespan |
Sent | Integer | Number of sent SMS. |
Delivered | Integer | Number of delivered SMS. |
Failed | Integer | Number of failed, not delivered SMS. |
Unknown | Integer | Number of SMS in transit or where delivery report is not available. |
Countries | List | List of Country objects. Only countries with at least one SMS sent will be included. |
Country Object
Note: This object may contain several number types.
Key | Type | Description |
---|---|---|
Name | String | The name of the country, for descriptive purpose. |
CountryCode | String | The call code with leading + sign. |
Sent | Integer | Number of sent SMS. |
Delivered | Integer | Number of delivered SMS. |
Failed | Integer | Number of failed, not delivered SMS. |
Unknown | Integer | Number of SMS in transit or where delivery report is not available. |
Number Type | Stat Object | Present if there is at least one SMS sent to a number of this type. E.g. Mobile or Pager. |
Number Type
This classification is done according to the number plan in each country.
Key | Description |
---|---|
Mobile | Mobile phone numbers. |
FixedLine | Fixed line phone numbers. |
Pager | Primarily Minicall in Sweden. |
Other | E.g. Voip and Voicemail. |
Stat object
Key | Type | Description |
---|---|---|
Sent | Integer | Number of sent SMS. |
Delivered | Integer | Number of delivered SMS. |
Failed | Integer | Number of failed, not delivered SMS. |
Unknown | Integer | Number of SMS in transit or where delivery report is not available. |
Voice
With the voice APIs you can configure different call flows that can be used both for making and receiving calls. A flow may contain both dynamic contents, created by our text-to-speech (TTS) engine, or pre-recorded audio. Using DTMF tones, the flow may branch off, allowing different options during the call. Flow nodes may send messages containing various data, configuring those messages to be sent an SMS inbox with a NotificationURL configured you'll be able to integrate this voice channel with your own API.
Voice API structure
Path | Description |
---|---|
/voice/flow | The configured flows you may use to send voice messages or configure inbox messages. |
/voice/message | Create a voice call to deliver the message using a defined flow. |
/voice/inbox | List of configured inbound phone numbers configured on your account. |
/voice/inbox/{VoiceInboxId} | Actions on a specific inbox, e.g. add new messages. |
The flow
List available flows
curl "https://api.genericmobile.se/SmsGateway/api/v1/voice/flow" \
--basic -u Alice:secretPwd
200 OK
[
{
"FlowId": "deadc0de-2bad-c4fe-feed-beefca1ff00d",
"Description": "Reads the text and asks the caller to press 1 or 2."
},
{
"FlowId": "deadc0de-2bad-c4fe-feed-beefca1ff000",
"Description": "Plays a pre-recorded message explaining who called and why."
}
]
A voice flow is a graph over the call or parts of a call. They are rather flexible but at the cost of complexity. At the moment those flows are configured by Generic in collaboration with you.
Common building blocks in the flow allows audio files to be played, synthesized text (TTS), DTMF detection with flow branching, sending SMS and more. It is also possible to define where in the flow you need to reach in order to call it delivered.
You may list the flows configured for you with a description to see what you have at your disposal when sending a voice message or configuring a voice inbox.
Example flow: When the flow starts, a prerecorded audio file is played saying "Hello". Then the text message is transformed into voice and played. In this example the text might have been "Press 1...the story ends, you wake up in your bed and believe whatever you want to believe. You press 2...you stay in Wonderland.". If not 1 nor 2 is pressed in a specified time, the message will be repeated once. If 1 or 2 is pressed you end up in the corresponding node that might have a prerecorded audio file attached regarding "deep rabbit holes". Either way, those two nodes will send a message to a pre-configured number/inbox (API) including who made the choice (phone number) and the reference of the message. The call will end with a nice "Goodbye" if 1 or 2 was presses within due time, or a short notice that no action was taken.
GET /voice/flow
HTTP Response
200 OK
A successful request contains a list of flow objects.
Flow object
Key | Description | Type |
---|---|---|
FlowId | The unique ID of the flow used in various places in the /voice API. | Guid |
Description | Short description what the flow does. | String |
Voice call
Deliver message with a voice call
curl -X POST https://api.genericmobile.se/SmsGateway/api/v1/voice/message \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '{
"From": "+46846500400",
"To": ["+46701740605"],
"Text": "This is an urgent message",
"FlowId": "deadc0de-2bad-c4fe-feed-beefca1ff00d",
"Reference": "ID1234"
}'
201 Created
{
"MessageId": ["deadc0de-2bad-c4fe-feed-beefca1ff00d"]
}
Communicating a message could be done with more than just text. By using our voice message API, you can define what call flow we should use when making a phone call to someone.
It is a better user experience if the number we are calling from is a number that the person can call back on, in case he/she missed the call. One great option is to set up your own number and configure a voice inbox.
To simplify retry logic, additional call attempts, in case message was not delivered, retry delay and number of attempts are configured on the flow rather than per message. The flow description will have a short summary for you.
POST /voice/message
Voice call parameters
Parameter | Required | Type | Default | Description |
---|---|---|---|---|
From | No | Phone number1 | Hidden number | Phone number or empty for hidden number. |
To | Yes | Array (1..1000) of Strings | - | List of recipient phone numbers. |
Text | No | String | "" | Text to be synthesized. |
FlowId | Yes | Guid | - | The ID of the flow to use. |
Reference | No | String (0..255) | null | Tag the message with a custom reference. Usable when dissecting the message log. |
DeliveryReportUrl | No | String (9..255) | null | http(s) URL for receiving delivery reports, if null or omitted no delivery report will be sent. |
1 A phone number should be given in international format (leading + sign). Leave empty to hide the number.
HTTP Response
201 Created
A successful request contains a list of MessageIds, one per receiver. Similar to how our SMS message endpoint would.
Note: You may poll for delivery reports just as you do with any other message in our platform.
Voice inbox
curl "https://api.genericmobile.se/SmsGateway/api/v1/voice/inbox" \
--basic -u Alice:secretPwd
200 OK
[
{
"VoiceInboxId": "deadc0de-2bad-c4fe-feed-beefca1ff00d",
"PhoneNumber": "+46701740605",
}
]
You would need to have a phone number configured for incoming calls. This is something Generic will help you set up. Once in place you may, just like on a regular voice mail, leave messages for whom ever calls this number. However, our voice inbox is a little bit smarter and allow you to have different messages depending on who is calling.
By using your inbox number as caller when sending voice messages, you may allow the recipient to call back at a more convenient time and get your message that way instead.
Internally, inboxes are based on four flows describing the inbox graph as show in the Inbox flow structure diagram. This structure is configured by Generic in collaboration with you.
Inbox flow structure: Describes how the different flows in the inbox object are connected. The quotes are for illustration purpose only.
GET /voice/inbox
HTTP Response
200 OK
A successful request contains a list of index object.
Inbox object
Parameter | Type | Description |
---|---|---|
VoiceInboxId | Guid | The ID used to reference this inbox. |
PhoneNumber | String | Phone number configured to receive calls. |
Inbox messages
You may put multiple messages in your voice inbox. Those messages could use different call flows and have different receivers depending on what number is calling your inbox. This way, you can communicate a single number but tailer the experience depending on who calls it.
Create inbox message
Create inbox message
curl -X POST https://api.genericmobile.se/SmsGateway/api/v1/voice/inbox/deadc0de-2bad-c4fe-feed-beefca1ff00d \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '{
"MsgFlowId": "deadc0de-2bad-c4fe-feed-beefca1ff00d",
"MsgText": "Det e fredag mina bekanta",
"Receivers": ["+46701740605"]
}'
201 Created
{
"MessageId": ["deadc0de-2bad-c4fe-feed-beefca1ff00d"]
}
POST /voice/inbox/{VoiceInboxId}
Parameter | Required | Type | Default | Description |
---|---|---|---|---|
MsgFlowId | Yes | Guid | - | The flow ID to use for this messages. |
MsgText | No | String | "" | If the MsgFlowId contains a TTS state, this text will be used. |
Reference | No | String | "" | A custom reference that will be present in reports for convenient mapping. |
Receivers | No | Array of Strings | [] | The strings should all be valid phone numbers. |
HTTP Response
201 Created
A successful request contains the index message object.
400 Bad Request
List your voice inbox messages
GET /voice/inbox/{VoiceInboxId}
HTTP Response
200 OK
A successful request contains a list of index message objects.
Index message object
Parameter | Type | Description |
---|---|---|
VoiceInboxMessageId | Guid | The ID used to reference this inbox. |
VoiceInboxId | Guid | The ID of the voice inbox this message should be put in. |
MsgFlowId | Guid | The flow ID to use for this message. |
MsgText | String | If the MsgFlowId contains a TTS state, this text will be used. |
Reference | String | A custom reference that will be present in reports for convenient mapping. |
Receivers | Array of Strings | The strings should all be valid phone numbers. |
Remove a message from the voice inbox
DELETE /voice/inbox/{VoiceInboxId}/{VoiceInboxMessageId}
HTTP Response
204 No Content
Add receiver to inbox message
Add new receiver to a message
curl -X POST https://api.genericmobile.se/SmsGateway/api/v1/voice/inbox/deadc0de-2bad-c4fe-feed-beefca1ff00d/deadc0de-2bad-c4fe-feed-beefca1ff00d/receivers \
--basic -u Alice:secretPwd \
-H 'Content-Type: application/json' \
-d '"+46701740605"'
200 OK
{
}
After a inbox message is created you may add more receivers.
POST /voice/inbox/{VoiceInboxId}/{VoiceInboxMessageId}/receivers
Pass thephone number to add as a single string in the body.
HTTP Response
200 OK
Empty response. Even if the receiver was present already. No duplicates will be stored.
400 Bad Request
Will contain a message explaining the issue, e.g. {"Message": "The format of the phone number is wrong."}
Remove receiver from inbox message
curl -X DELETE https://api.genericmobile.se/SmsGateway/api/v1/voice/inbox/deadc0de-2bad-c4fe-feed-beefca1ff00d/deadc0de-2bad-c4fe-feed-beefca1ff00d/receivers/46701740605 \
--basic -u Alice:secretPwd
204 No Content
After a inbox message is created you may remove specific receivers. The phone number to be removed should be in the path with the leading plus sign striped out. See the example.
DELETE /voice/inbox/{VoiceInboxId}/{VoiceInboxMessageId}/receivers/{PhoneNumber}
HTTP Response
204 No Content
Empty response.
400 Bad Request
Will contain a message explaining the issue, e.g. {"Message": "The format of the phone number is wrong."}
404 Not Found
If the receiver was not a receiver of the message.
Errors
HTTP response codes
Success
HTTPS Code | Status | Description |
---|---|---|
200 | OK | Successful request. |
201 | Created | Successful request, content was created. |
204 | No Content | Successful request, no content will be returned. |
Errors
Example of error responses with body
400 Bad Request
{
"Message": "Failed to update user password"
}
400 Bad Request
{
"Code": 200,
"Description": "Parameter \"To[0]\" must be an international phone number"
}
Most error responses from the API will include a Message
or Description
property with more details of what went wrong.
Client
HTTPS Code | Status | Description |
---|---|---|
400 | Bad request | Something in the request is missing or wrong. |
401 | Unauthorized | Authentication failed. |
403 | Forbidden | The request is correct but cannot be performed. |
404 | Not found | Resource not found. |
405 | Method not allowed | The method specified is not allowed for the resource. |
406 | Not Acceptable | Content generated is not matched with the Accept header. |
411 | Length Required | Content-Length header is missing or wrong. |
415 | Unsupported Media Type | Content-Type header is missing or wrong. |
429 | Too many requests | Too many requests within the specified time slot. The HTTP header Retry-After specifies the number of seconds to wait before the next POST request can be made. |
Server Errors
HTTPS Code | Status | Description |
---|---|---|
500 | Internal Server Error | Server could not process the request due to internal error. |
502 | Bad Gateway | Invalid response or could not reach upstream server or application pool. |
503 | Service unavailable | Server is currently unavailable or down for maintenance. |
Delivery Report Errors
Error Code | Reason |
---|---|
0 | Success |
1 | Absent subscriber. |
7 | Validity expired |
49 | Temporary unknown error |
51 | Destination number is unknown |
52 | Invalid destination number |
57 | Message rejected because the destination number was blacklisted. |
58 | Country Information and local regulations, call Support |
59 | Invalid Source address |
99 | Permanent unknown error |
101 | Active disconnect / Delivery rule not fulfilled |
151 | Destination number is unknown |
152 | Invalid destination number |
Format and Encoding
Message body
Messages sent with the REST API are divided into one or more SMSs.
The message body, which is represented by the Text
parameter, is encoded using UTF-8.
When only GSM characters1 are used the maximum size of a single SMS is 160 characters. For longer messages the API will automatically split the text into multiple SMSs, each with a maximum of 153 characters.
When characters not represented in the GSM 03.38 are used, the message body will be encoded using UCS-2 (UTF-16 Big Endian) and the maximum size of each SMS is 70 characters. The API will split the message into several SMSs of maximum 67 characters.
GSM 03.38 character set
Each character is encoded to 7 bits (0x00..0x7F)
0x | 1x | 2x | 3x | 4x | 5x | 6x | 7x | |
---|---|---|---|---|---|---|---|---|
x0 | @ | Δ | SP | 0 | ¡ | P | ¿ | p |
x1 | £ | _ | ! | 1 | A | Q | a | q |
x2 | $ | Φ | " | 2 | B | R | b | r |
x3 | ¥ | Γ | # | 3 | C | S | c | s |
x4 | è | Λ | ¤ | 4 | D | T | d | t |
x5 | é | Ω | % | 5 | E | U | e | u |
x6 | ù | Π| & | 6 | F | V | f | v |
x7 | ì | Ψ | ' | 7 | G | W | g | w |
x8 | ò | Σ | ( | 8 | H | X | h | x |
x9 | Ç | Θ | ) | 9 | I | Y | i | y |
xA | LF | Ξ | * | : | J | Z | j | z |
xB | Ø | ESC | + | ; | K | Ä | k | ä |
xC | ø | Æ | , | < | L | Ö | l | ö |
xD | CR | æ | - | = | M | Ñ | m | ñ |
xE | Å | ß | . | > | N | Ü | n | ü |
xF | å | É | / | ? | O | § | o | à |
Phone number formats
All phone numbers should be given in international format, see E.164 and NANP.
MSISDNs (phone numbers) should start with +
, e.g. +46701740605
. If part of an URI the +
shall be omitted, e.g. 46701740605
.