Table of Contents

    API

    Mock Server

    Use this URL to access a mockup of the API server. Your traffic will be recorded and compared to the documentation. You'll find your traffic analysis in the inspector or directly here in the documentation, right next to each resource.

SentlyPlus API v1.0

This is an authenticated API which uses Client Credentials Grant flow of the OAuth2 specification as the authentication mechanism.

To use this API:

  • An application encodes its consumer key and secret into a specially encoded set of credentials.
  • An application makes a request to the POST /api/token endpoint to exchange these credentials for a bearer token.
  • When accessing the REST API, the application uses the bearer token to authenticate.

Authentication flow

About Client Credentials Grant authorization

Tokens are passwords

Keep in mind that the consumer key & secret, bearer token credentials, and the bearer token itself grant access to make requests on behalf of an application. These values should be considered as sensitive as passwords and must not be shared or distributed to untrusted parties.

SSL absolutely required

This manner of authentication is only secure if SSL is used. Therefore, all requests (both to obtain and use the tokens) must use HTTPS endpoints, which is also a requirement of using API v1.0.

Issuing authenticated requests

Step 1: Encode consumer key and secret

The steps to encode an application's consumer key and secret into a set of credentials to obtain a bearer token are:

  1. URL encode the consumer key and the consumer secret according to RFC 1738. Note that at the time of writing, this will not actually change the consumer key and secret, but this step should still be performed in case the format of those values changes in the future.

  2. Concatenate the encoded consumer key, a colon character ":", and the encoded consumer secret into a single string.

  3. Base64 encode the string from the previous step.

Below are example values showing the result of this algorithm. Note that the consumer secret used in this page has been disabled and will not work for real requests.

Consumer Key M2E5MDdjMmYtZWM1NC00YmRlLTlkY1ItZjE3M2ZmMjY5MTA0
Consumer Secret NGU1Nzg5Y2UtYTYxNy01MDM2LWJiYWYtYzE4Y2I5ZGY2MTcx
RFC 1738 encoded consumer key
(does not change)
M2E5MDdjMmYtZWM1NC00YmRlLTlkY1ItZjE3M2ZmMjY5MTA0
RFC 1738 encoded consumer secret
(does not change)
NGU1Nzg5Y2UtYTYxNy01MDM2LWJiYWYtYzE4Y2I5ZGY2MTcx
Bearer token credentials M2E5MDdjMmYtZWM1NC00YmRlLTlkY1ItZjE3M2ZmMjY5MTA0:NGU1Nzg5Y2UtYTYxNy01MDM2LWJiYWYtYzE4Y2I5ZGY2MTcx
Base64 encoded bearer token credentials TTJFNU1EZGpNbVl0WldNMU5DMDBZbVJsTFRsa1kxSXRaakUzTTJabU1qWTVNVEEwOk
5HVTFOemc1WTJVdFlUWXhOeTAxTURNMkxXSmlZV1l0WXpFNFkySTVaR1kyTVRjeA==

Step 2: Obtain a bearer token

The value calculated in step 1 must be exchanged for a bearer token by issuing a request to POST api/token:

  • The request must be a HTTP POST request.
  • The request must include an Authorization header with the value of
    Basic <base64 encoded value from step 1>.
  • The request must include a Content-Type header with the value of
    application/x-www-form-urlencoded;charset=UTF-8.
  • The body of the request must be grant_type=client_credentials.

Example request (Authorization header has been wrapped):

POST /api/token HTTP/1.1
Host: plus.sent.ly
User-Agent: My SMS App
Authorization: Basic TTJFNU1EZGpNbVl0WldNMU5DMDBZbVJsTFRsa1kxSXRaakUzTTJabU1qWTVNVEEwOk
                     5HVTFOemc1WTJVdFlUWXhOeTAxTURNMkxXSmlZV1l0WXpFNFkySTVaR1kyTVRjeA==
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
Content-Length: 29
Accept-Encoding: gzip

grant_type=client_credentials

If the request was formatted correctly, the server will respond with a JSON-encoded payload:

Example response (access_token has been wrapped):

HTTP/1.1 200 OK
Status: 200 OK
Content-Type: application/json; charset=utf-8
...
Content-Encoding: gzip
Content-Length: 140

{"token_type":"bearer","access_token":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%2FAAAAAAAAAAAA
                                       AAAAAAAA%3DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"}

Applications should verify that the value associated with the token_type key of the returned object is bearer. The value associated with the access_token key is the bearer token.

Note that one bearer token is valid for an application at a time. Issuing another request with the same credentials to /api/token will return the same token until it is invalidated.

Step 3: Authenticate API requests with the bearer token

The bearer token may be used to issue requests to the REST API endpoints.

To use the bearer token, construct a normal HTTPS request and include an Authorization header with the value of

Bearer <base64 access_token value from step 2 response> . Signing is not required.

Example request (Authorization header has been wrapped):

GET /api/list HTTP/1.1
Host: plus.sent.ly
User-Agent: My SMS App
Authorization: Bearer AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%2FAAAAAAAAAAAA
                      AAAAAAAA%3DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Accept-Encoding: gzip

Example response

HTTP/1.1 200 OK
Status: 200 OK
Content-Type: application/json; charset=utf-8
...
Content-Encoding: gzip

{"errorMessage":"","errorCode":0, "responseData":"<json response from API>"}

The values associated with the errorMessage key and the errorCode key of the returned object may be used to see if an error occurred.

If there is no error, then the value associated with the responseData key of the returned object will contain the JSON response from the API.

Security Wrapper Errors

It is possible that while making an API call, an error occurs. In this section, we will discuss security wrapper errors, their meanings and resolutions. The underlying APIs are "wrapped" by a security layer that makes sure the APIs are not accessed in an unauthorized manner. We shall be discussing errors that can be generated by this layer.

We shall not be discussing resource specific API errors. Resource specific API errors will be discussed in the resource API description themselves.

As we see in the table below, all errors related to the security wrapper have an HTTP status code of 500, 400 or 403.

In addition to this HTTP status code, the response itself contains an error code supplied by the API security wrapper. This is in contrast to resource specific API errors which all have an HTTP status code of 200.

Http Status Code Sently Plus Error Code Description Scenario Resolution
500 10001 Error creating token The token could not be created in the underlying data storage May be due to network issues. Try again later
403 10002 Invalid access token The token could not be validated Go through the token issuing flow again to obtain a new token
400 10002 Token was missing in the request Authorization header does not contain token Authorization header value must be:
Bearer <token>
400 10003 Request needs HTTPS An attempt was made to access API using HTTP Reissue request using HTTPS
500 10004 Error setting security principal We could not set the security context for your token Contact administrator
500 10005 Error issuing token We could not create a token in the underlying storage Try again later. If problem persists, contact administrator
403 10006 Invalid credentials We could not validate the supplied credentials Send the correct credentials and try again
400 10007 Request does not contain Authorization header A request was made to API without Authorization header present Send the request with the Authorization header present
403 10008 Could not authenticate request The request could not be authenticated via an access token Go through token issuing flow again and try again with the new token
400 10009 Body missing grant_type The body of the request must be:
grant_type=client_credentials
Reissue request with grant_type=client_credentials present in body
400 10010 Body missing access token Body must contain
access_token=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...
Reissue request with access_token present in body
400 10011 Base64 decoding failed Error while decoding your Base64 encoded credentials string Make sure that your Base64 encoding is correct. See Wikipedia
400 10012 Message has incorrect number of parts Error while splitting credentials with : Make sure that you concatenate the credentials before Base64 encoding in the form consumerSecret:consumerKey
400 10013 Url decoding failed Error while url decoding consumerSecret or consumerKey Make sure that you correctly URL encode cedentials before concatenating with ':' and Base64 encoding them.
400 10014 Error calling underlying resource API Authentication suceeded, but calling the underlying resource API resulted in an uncaught exception If the problem persists, contact administrator

Example of a security wrapper error response

HTTP/1.1 403 Forbidden
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 23 May 2013 15:13:05 GMT
Content-Length: 123

{"errorMessage":"Please authenticate by a request to /api/token before calling any API methods","errorType":1,"errorCode":10008}

Note the non 200 HTTP Status code and "errorType":1 which indicate that this is a security wrapper error and not an API error.

Example of an API error response

All API error responses have a HTTP status code of 200. We will show an example of just one error response that results while trying to retrieve a list with an id that does not exist. Specific errors related to resources will be discussed when we discuss the resource API. The error response from a resource API error (and NOT from the security wrapper layer) is shown below:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 23 May 2013 16:09:11 GMT
Content-Length: 90

{"errorMessage":"The specified list does not exist.","errorCode":5005,"responseData":null}

One should note that the HTTP status code for this response was 200 and hence it is an resource API error specified by the API error code in the 5000 range. A detailed discussion of 5000 range API codes will ensue when we talk about Resource APIs later.

Token

This portion of the API pertains to obtaining a bearer token from the Security Wrapper. The bearer token thus obtained is passed in the Authorization header in all subsequent requests to the underlying resource APIs.

POST

/api/token

Get an access token based on Base64 encoded credentials (as discussed in the section above).

Response

200 (OK)
Content-Type: application/json
{"token_type":"bearer","access_token":"ZTkxMWJkODEtYjUwYy00MzUyLWFhYzEtODI3NWNkMjY0OGFj"}

POST

/api/invalidate_token

Should a bearer token become compromised or need to be invalidated for any reason, this API call can be used. The Authorization header should contain the Base64 encoded credentials. The body of the request should contain the access_token that needs to be invalidated.

Response

200 (OK)
Content-Type: application/json
{"access_token":"ZTkxMWJkODEtYjUwYy00MzUyLWFhYzEtODI3NWNkMjY0OGFj"}

List

This resource represents a grouping of prospects into lists. List names must be unique.

GET

/api/list

Get all the lists belonging to you

Response

200 (OK)
Content-Type: application/json
{
    "errorMessage": "",
    "errorCode": 0,
    "responseData": [
        {
            "listid": "69fa1030-f37b-4f1b-acee-31a3addf84c1",
            "columns": [
                {
                    "name": "Mobile phone number",
                    "type": "phone",
                    "isRequired": true,
                    "defaultValue": null
                }
            ],
            "unsubscribedCount": 0,
            "size": 3,
            "bounceCount": 0
        },
        {
            "listid": "f68e3cb6-170d-4ddb-b39b-a2b5211572d6",
            "columns": [
                {
                    "name": "Mobile phone number",
                    "type": "phone",
                    "isRequired": true,
                    "defaultValue": null
                },
                {
                    "name": "First Name",
                    "type": "text",
                    "isRequired": false,
                    "defaultValue": null
                },
                {
                    "name": "Last Name",
                    "type": "text",
                    "isRequired": false,
                    "defaultValue": null
                }
            ],
            "unsubscribedCount": 0,
            "size": 0,
            "bounceCount": 0
        }
    ]
}

GET

/api/list/69fa1030-f37b-4f1b-acee-31a3addf84c1

Get a list by id.

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5005 List does not exist The list specified by the provided id does not exist Provide a valid id in the request and try again

Response

200 (OK)
Content-Type: application/json
{
    "errorMessage": "",
    "errorCode": 0,
    "responseData": {
            "listid": "69fa1030-f37b-4f1b-acee-31a3addf84c1",
            "columns": [
                {
                    "name": "Mobile phone number",
                    "type": "phone",
                    "isRequired": true,
                    "defaultValue": null
                }
            ],
            "unsubscribedCount": 0,
            "size": 3,
            "bounceCount": 0
        }
}

POST

/api/list

Create a new list with the specified name and fields (columns).

  • The column types can be either "text" or "number" or "phone".
  • The list name must be unique.

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5001 Invalid list name The list name provided is empty, null or invalid Provide a valid list name in the request and try again
200 5002 List already exists There is another list present with the same name List names are unique. Provide a different name and try again
200 5020 Invalid field type The "type" key in each field object contained in the listFields object must be either "text" or "number" or "phone" Provide a valid type in the request and try again

Response

200 (OK)
Content-Type: application/json
{
    "errorMessage": "",
    "errorCode": 0,
    "responseData": {
        "listId": "ac13a8c3-8b85-4556-bd1e-688b70aaa757"
    }
}

PUT

/api/list

Edit an existing list (in our case we can only rename)

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5002 List already exists There is another list present with the same name List names are unique. Provide a different name and try again
200 5005 List does not exist The list specified by the provided id does not exist Provide a valid id in the request and try again

Response

200 (OK)
Content-Type: application/json
{
    "errorMessage": "",
    "errorCode": 0,
    "responseData": {
        "listId": "69fa1030-f37b-4f1b-acee-31a3addf84c1"
    }
}

DELETE

/api/list/69fa1030-f37b-4f1b-acee-31a3addf84c1

Delete an existing list The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5003 Campaign job exists which uses this list There is a campaign job that uses this list Delete the campaign job or try again later after campaign sending is over
200 5005 List does not exist The list specified by the provided id does not exist Provide a valid id in the request and try again

Response

200 (OK)
Content-Type: application/json
{
    "errorMessage": "",
    "errorCode": 0,
    "responseData": null
}

ListSchema

This resource allows yout to define schema for the list. Schema defintion includes column names, column types etc. There can be a maximum of 20 columns in a list in addition to the mandatory "Mobile Phone Number" column.

GET

/api/listschema/69fa1030-f37b-4f1b-acee-31a3addf84c1

Gets the column information for the list specified by the id.

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5005 List does not exist The list specified by the provided id does not exist Provide a valid id in the request and try again

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":[
         {
            "name":"Mobile Number",
            "type":"phone",
            "isRequired":true,
            "defaultValue":null
         },
         {
            "name":"First Name",
            "type":"text",
            "isRequired":false,
            "defaultValue":null
         },
         {
            "name":"Last Name",
            "type":"text",
            "isRequired":false,
            "defaultValue":null
         }
    ]
}

GET

/api/listschema/69fa1030-f37b-4f1b-acee-31a3addf84c1/First Name

Gets the schema information for a particular column in the specified list

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5005 List does not exist The list specified by the provided id does not exist Provide a valid id in the request and try again
200 5006 Column does not exist The column name specified in the request does not exist Provide a valid column name in the request and try again

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":{
         "name":"First Name",
         "type":"text",
         "isRequired":false,
         "defaultValue":null
   }
}

POST

/api/listschema

Adds the specified column to the list

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5004 Column already exists The list already contains a column with the specified name Provide a different column name in the request and try again
200 5005 List does not exist The list specified by the provided id does not exist Provide a valid id in the request and try again
200 5020 Invalid column type Columns type can be either "text" or "number" or "phone" Provide a valid column type in the request and try again

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":null
}

PUT

/api/listschema

Changes the name of a column

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5004 Column already exists Another column exists with the same name as specified in the renameTo value Provide another column name in the request and try again
200 5005 List does not exist The list specified by the provided id does not exist Provide a valid id in the request and try again
200 5006 Column does not exists The specified column to rename was not found in the list Provide a valid column name in the request and try again
200 5030 Cannot rename mobile phone number column The mobile phone number column cannot be renamed Provide a valid column name in the request and try again

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":null
}

DELETE

/api/listschema/69fa1030-f37b-4f1b-acee-31a3addf84c1/Home Address

Deletes the specified column from the specified list. All data for that column will be cleared!

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5005 List does not exist The list specified by the provided id does not exist Provide a valid id in the request and try again
200 5006 Column does not exists The specified column to delete was not found in the list Provide a valid column name in the request and try again

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":null
}

ListItem

This resource represents the actual information in the row of a list.

GET

/api/listitem/69fa1030-f37b-4f1b-acee-31a3addf84c1?take=50&skip=0

Gets the the specified number of items in take while skipping the number of items specified in skip.

Take and skip are mandatory parameters for this GET request

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5005 List does not exist The list specified by the provided id does not exist Provide a valid id in the request and try again
200 5012 Take/skip parameters missing The request did not have take/skip query string parameters Provide take and skip parameters and try again
200 5021 Failed to parse take/skip The specified take/skip parameters were not valid integers Provide a valid values for take/skip in the request query string and try again

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":[
        {
             "CustomId":"3B5E1B59-B4C6-4E2F-BAB4-A9E651741DAD",
             "rowData":{
                "Mobile Number":"+6583888388",
                "First Name":"Adam",
                "Last Name":"Smith",
                "Address":null,
                "column1":null,
                "IsUnsubscribed":"False",
                "IsBouncing":"False"
            }
        },
        {
             "CustomId":"3BC57B59-B4C6-4E2F-BAB4-A9E651741DAD",
             "rowData":{
                "Mobile Number":"+6583998399",
                "First Name":"Bill",
                "Last Name":"Gates",
                "Address":null,
                "column1":null,
                "IsUnsubscribed":"False",
                "IsBouncing":"False"
             }
        }
   ]
}

GET

/api/listitem/69fa1030-f37b-4f1b-acee-31a3addf84c1/3B5E1B59-B4C6-4E2F-BAB4-A9E651741DAD

Gets the specified item from the specified list.

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5005 List does not exist The list specified by the provided id does not exist Provide a valid id in the request and try again
200 5007 Item id was not present We could not read the item id from the request The format of the request should be /api/listitem/listid/itemid. Correct the format and try again

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":{
      "CustomId":"3B5E1B59-B4C6-4E2F-BAB4-A9E651741DAD",
             "rowData":{
                "Mobile Number":"+6583888388",
                "First Name":"Adam",
                "Last Name":"Smith",
                "Address":null,
                "column1":null,
                "IsUnsubscribed":"False",
                "IsBouncing":"False"
            }
   }
}

POST

/api/listitem

Adds the specified items to the list. A Custom Id can be provided to refer to an item. If no Custom Id is provided it will be generated by the system.

The Custom Id can be used to modify the fields of an item throughout the system (in all lists). If the call succeeds, then the response contains an array of items with their Custom Ids and Mobile phone numbers as they were saved in the system.

If the call fails due to some erroneous item, then the responseData key contains a list of errors.

The following shows an error response which results from duplicate items (adding the same items twice):

Content-Type: application/json; charset=utf-8
...
{
   "errorMessage":"Request items contained errors, please check the responseData value.",
   "errorCode":5008,
   "responseData":{
      "Errors":[
         {
            "MobilePhoneNumber":"+6583888388",
            "ErrorField":"MobilePhoneNumber",
            "ErrorMessage":"+6583888388 already exists",
            "ErrorType":0,
            "FieldValue":"+6583888388",
            "FieldType":7,
            "RowNumber":1
         },
         {
            "MobilePhoneNumber":"+6583998399",
            "ErrorField":"MobilePhoneNumber",
            "ErrorMessage":"+6583998399 already exists",
            "ErrorType":0,
            "FieldValue":"+6583998399",
            "FieldType":7,
            "RowNumber":2
         }
      ],
      "MainErroMessage":"An error occurred while processing your request. Please check the highlighted values."
   }
}

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5005 List does not exist The list specified by the provided id does not exist Provide a valid id in the request and try again
200 5007 List items not present We could not detect any posted items Please make sure that there are one or more items present in the request body
200 5008 List data validation failed One or more of the posted items has data errors Please check the responseData key for the Errors array (see the example above) to see which items had errors. You may post the items again after correcting the specified errors.
200 5010 List schema validation failed You have probably specified the value for a column that does not exist Please check the responseData key for the Errors array (see the example above) to see which items had errors. You may post the items again after correcting the specified errors.
200 5019 Database Error An error ocurred while saving the items Please check the errorMessage key for what may have gone wrong. If the problem persists, please contact administrator.
200 5022 Duplicate Custom Id You are trying to insert an item in a list which has another item already present with the same Custom Id Please provide a different Custom Id for the item and try again.

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":{
      "listItems":[
         {
            "MobilePhoneNumber":"+6583888388",
            "Id":"1234"
         },
         {
            "MobilePhoneNumber":"+6583998399",
            "Id":"f9794af3-d752-4941-a1ee-af5af3987764"
         }
      ]
   }
}

PUT

/api/listitem

Given a Custom Id and a list of column names and their values, this method will change the values of those columns in all lists that contain the specified columns. In the example below, the name "Albert" will be changed to "Bertie" in all lists that contain a column called "First Name" (case insensitive), the phone number will also be changed by the same logic.

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5007 List item not present The item specified in the body could not be found Provide a valid Custom Id of the item in the request and try again
200 5008 List data validation failed The new data specified in the request had validation errors in one or more lists where it needs to be changed Check the Errors key in responseData (like in POST) for a list of errors.

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":{
      "MobilePhoneNumber":"+6583998666",
      "Id":"f9794af3-d752-4941-a1ee-af5af3987764"
   }
}

DELETE

/api/listitem/f9794af3-d752-4941-a1ee-af5af3987764

Deletes the item specified by the Id in the URL

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5007 List item not present The item specified in the request could not be found Provide a valid Custom Id of the item in the request and try again

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":null
}

Campaign

This resource represents a campaign that contains the template text, the list that the campaign needs to be sent to and the identity (mobile phone number or custom text) that the messages will appear to be sent from. Once a campaign is created, it can be scheduled for sending by creating a Campaign Job for the particular campaign.

GET

/api/campaign

Retrieve all the campaigns under your account

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":[
      {
         "SenderIdValue":"+6583888388",
         "ListName":"Hello users!",
         "Reach":3,
         "Id":51,
         "ListId":"3b159568-cf58-41ea-b9f2-7f6ae5dd0732",
         "Text":"Hello *|First Name|*",
         "SuppressUnsubscribe":false,
         "SupressHeader":false,
         "UserId":20,
         "CampaignName":"Testing22",
         "DateCreated":"2013-04-26T07:07:37.423",
         "DateModified":"2013-04-26T07:08:03.483",
         "SenderId":"98051602-2401-4d87-b210-d3d826b0ac4f",
         "UnsubscribeTemplate":"Unsubscribe - http://plus.sent.ly/u/{0}",
         "CallbackUrlTemplate":"http://plus.sent.ly/d/{0}"
      }
   ]
}

GET

/api/campaign/51

Gets the campaign with the specified id.

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5023 Campaign does not exist The campaign specified in the request could not be found Provide a valid Id of the campaign in the request and try again

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":{
      "SenderIdValue":"+6583887908",
      "ListName":"Hello users!",
      "Reach":3,
      "Id":51,
      "ListId":"3b159568-cf58-41ea-b9f2-7f6ae5dd0732",
      "Text":"Hello *|First Name|*",
      "SuppressUnsubscribe":false,
      "SupressHeader":false,
      "UserId":20,
      "CampaignName":"Testing22",
      "DateCreated":"2013-04-26T07:07:37.423",
      "DateModified":"2013-04-26T07:08:03.483",
      "SenderId":"98051602-2401-4d87-b210-d3d826b0ac4f",
      "UnsubscribeTemplate":"Unsubscribe - http://plus.sent.ly/u/{0}",
      "CallbackUrlTemplate":"http://plus.sent.ly/d/{0}"
   }
}

POST

/api/campaign

Creates a new campaign using the specified list and identity. The response contains the Id of the new campaign.

If the callback URL is specified, then it will be hit with jobid, smsid and status (where jobid is the id of the campaign job that was created using the specified campaign, smsid is the list item in the list and status is specified as below) in the query string parameters. Allowing you to track the message in near real time. The following values describe the status:

Status Description Meaning
0 None Unused
1 Sent The message was sent to the gateway
2 Failed The gateway reported that the message failed
3 Delivered The gateway reported that the message was delivered to the recipient

Example callback:
http://yourserver.com/yourpage.php?jobid=55&status=3&smsid=5F19983D-EA5A-46ED-901C-4A63CBA87C04

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5005 List does not exist The list specified in the request could not be found Provide a valid Id for the list in the request and try again
200 5006 List field does not exist A list field specified in the campaign text could not be found Check the error message to see which field is invalid. Provide a valid field name in the campaign text and try again.
200 5014 Identity does not exist The identity specified in the request could not be found Provide a valid Id for the identity in the request and try again
200 5016 Duplicate campaign name Campaigns must have unique names Provide another campaign name and try again
200 5024 Campaign name is mandatory A campaign name must be specified in the request Provide a valid and unique campaign name in the request and try again
200 5025 Campaign text is mandatory Campaign text must be specified in the request Provide a valid string for the campaign text in the request and try again

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":{
      "Id":52
   }
}

PUT

/api/campaign

Changes the campaign specified by the campaign id.

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5005 List does not exist The list specified in the request could not be found Provide a valid Id for the list in the request and try again
200 5006 List field does not exist A list field specified in the campaign text could not be found Check the error message to see which field is invalid. Provide a valid field name in the campaign text and try again.
200 5013 Cannot modify campaign The campaign sending may be already be in progress Campaigns that are currently being sent or need to be sent within the next 1 minute cannot be modified.
200 5014 Identity does not exist The identity specified in the request could not be found Provide a valid Id for the identity in the request and try again
200 5016 Duplicate campaign name Campaigns must have unique names Provide another campaign name and try again
200 5024 Campaign name is mandatory A campaign name must be specified in the request Provide a valid and unique campaign name in the request and try again
200 5025 Campaign text is mandatory Campaign text must be specified in the request Provide a valid string for the campaign text in the request and try again

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":{
      "isCreditTopupNeeded":false,
      "campaign":{
         "Id":52,
         "ListId":"3b159568-cf58-41ea-b9f2-7f6ae5dd0732",
         "Text":"hello world via api *|Mobile phone number|*",
         "SuppressUnsubscribe":true,
         "SupressHeader":false,
         "UserId":20,
         "CampaignName":"Renamed campaign",
         "DateCreated":"2013-05-26T12:08:53.957",
         "DateModified":"2013-05-26T12:30:10.64289Z",
         "SenderId":"98051602-2401-4d87-b210-d3d826b0ac4f",
         "UnsubscribeTemplate":"Unsubscribe - /u?protocol=http/{0}",
         "CallbackUrlTemplate":"/d?protocol=http/{0}"
      }
   }
}

DELETE

/api/campaign/51

Delete the specified campaign

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5013 Cannot delete campaign The campaign sending may be already be in progress Campaigns that are currently being sent or need to be sent within the next 1 minute cannot be deleted
200 5023 Campaign does not exist The campaign specified in the request could not be found Provide a valid Id of the campaign in the request and try again

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":null
}

Campaign Job

This resource represents a scheduled campaign. You can create campaign jobs based on a campaign and specify the date and time the campaign should be sent.

GET

/api/campaignjob

Retrieve all the campaign jobs under your account

The following table describes the Status values in the response:

StatusMeaningDescription
0NoneUnused
1PendingThe job has been added to the queue and processing will start at the date and time specified while creating the job
2Calculating costThe job is being processed. We are going through all the recipients and constructing messages based on the template specified in the campaign text. Based on the text thus created, we are calculating the number of credits required for the job.
3Queueing and sendingThe job is being processed. We are adding messages to the send queue and are in the process of sending messages out
4SendingThe job is being processed. All messages have been queued, we are in the process of sending them out
5 Completed All messages have been sent to gateway. The sent, delivery, failure and unsubscribe counts will still change as we track messages as they are sent from the gateway and delivered to a handset.
6 Failed Something went wrong while sending your campaign. Contact administrator if the problem persists.

The dates returned in the response are UTC date/time.

If the job status is 6 (Failed), then then the failure reason will be specified. The following table lists the codes for this and their meaning:

Failure reason code Meaning Scenario Resolution
0 None Unused N/A
1 Failed to Queue There was an error while trying to queue messages for this job. Please try creating another job. If the problem persists, contact adminstrator.
2 Job too big The list specified for this campaign job has too many recipients Please try creating another job using a smaller list. If the problem persists, contact adminstrator.
3 Insufficient credits This job was abandoned as there were insufficient credits in your account to send this campaign Please topup credits and try again
4 List Deleted The list specified by the campaign no longer exists Please ensure that the campaign contains a valid list and try again
5 Campaign Deleted The campaign specified for the job no longer exists Please ensure that the campaign job contains a valid campaign and try again
6 Identity Deleted The identity specified by the campaign no longer exists Please ensure that the campaign contains a valid identity and try again

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":[
      {
         "Id":42,
         "CampaignId":51,
         "ListId":"3b159568-cf58-41ea-b9f2-7f6ae5dd0732",
         "DateScheduled":"2013-05-27T07:56:25.007",
         "Status":1,
         "CreditsNeeded":0,
         "MessagesSent":0,
         "MessagesDelivered":0,
         "MessagesFailed":0,
         "FailureReason":null,
         "DateUpdated":"2013-05-27T05:26:25.053",
         "IsCreditDeductionDone":false,
         "MessagesUnsubscribed":0
      },
      {
         "Id":41,
         "CampaignId":51,
         "ListId":"3b159568-cf58-41ea-b9f2-7f6ae5dd0732",
         "DateScheduled":"2013-05-27T07:52:23.65",
         "Status":1,
         "CreditsNeeded":0,
         "MessagesSent":0,
         "MessagesDelivered":0,
         "MessagesFailed":0,
         "FailureReason":null,
         "DateUpdated":"2013-05-27T05:22:23.707",
         "IsCreditDeductionDone":false,
         "MessagesUnsubscribed":0
      },
      {
         "Id":40,
         "CampaignId":51,
         "ListId":"3b159568-cf58-41ea-b9f2-7f6ae5dd0732",
         "DateScheduled":"2013-05-23T08:56:45.017",
         "Status":1,
         "CreditsNeeded":0,
         "MessagesSent":0,
         "MessagesDelivered":0,
         "MessagesFailed":0,
         "FailureReason":null,
         "DateUpdated":"2013-05-23T06:26:45.047",
         "IsCreditDeductionDone":false,
         "MessagesUnsubscribed":0
      }
   ]
}

GET

/api/campaignjob/40

Gets the specified campaign. See the other GET method documentation for an explanation of Status and Failure reasons.

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5026 Campaign job does not exist There was no campaign with the specified id Please change the id in the request and try again

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":{
         "Id":40,
         "CampaignId":51,
         "ListId":"3b159568-cf58-41ea-b9f2-7f6ae5dd0732",
         "DateScheduled":"2013-05-23T08:56:45.017",
         "Status":1,
         "CreditsNeeded":0,
         "MessagesSent":0,
         "MessagesDelivered":0,
         "MessagesFailed":0,
         "FailureReason":null,
         "DateUpdated":"2013-05-23T06:26:45.047",
         "IsCreditDeductionDone":false,
         "MessagesUnsubscribed":0
     }
}

POST

/api/campaignjob

Schedules a campaign for sending. The sendWhenMilliseconds contains the number of milliseconds the system will wait for after the API call before sending out the campaign. For example to send the campaign after one minute specify a value of 60000. To send the campaign immediately, specify a value of 0.

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5023 Campaign does not exist There campaign specified in the request does not exist Provide a valid campaign id and try again

Response

200 (OK)
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":{
      "Id":46,
      "CampaignId":51,
      "ListId":"3b159568-cf58-41ea-b9f2-7f6ae5dd0732",
      "DateScheduled":"2013-05-27T10:38:40.7131714Z",
      "Status":1,
      "CreditsNeeded":0,
      "MessagesSent":0,
      "MessagesDelivered":0,
      "MessagesFailed":0,
      "FailureReason":null,
      "DateUpdated":"2013-05-27T08:08:40.7472043Z",
      "IsCreditDeductionDone":false,
      "MessagesUnsubscribed":0
   }
}

DELETE

/api/campaignjob/40

Deletes the specified campaign.

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5026 Campaign job does not exist There was no campaign with the specified id Please change the id in the request and try again
200 5017 Cannot delete campaign Processing for the campaign may have already started or is about to start Try again later after the campaign has been processed

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":null
}

Identity

When an SMS is sent, the receiver of the SMS sees the SMS has originated from some mobile phone number or alphanumeric string. This resource allows you to view these identities.

GET

/api/identity

Gets all the identities associated with your account

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5018 No identities There are no identities associated with your account Please add some identities by logging in to your account using the UI.

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":[
      {
         "SenderId":"98051602-2401-4d87-b210-d3d826b0ac4f",
         "SenderIdValue":"+6583887908",
         "IsApproved":true
      }
   ]
}

GET

/api/identity/98051602-2401-4d87-b210-d3d826b0ac4f

Gets the specified identity

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5014 Identity no longer present There specified identity no longer exists Please change the id in the request and try again

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":{
         "SenderId":"98051602-2401-4d87-b210-d3d826b0ac4f",
         "SenderIdValue":"+6583887908",
         "IsApproved":true
    }
}

POST

/api/identity

Adds a new identity with the specified senderName.

This is a protected API. You need to contact us at support@sent.ly to enable it.

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5033 The specified senderName is already registered A previous request has been made to register this senderName (currently the error message mistakenly uses the word listName instead of identity. We will fix this soon.) Please change the senderName in the request and try again
200 10014 The underlying call failed The most common reason for this error is if you have not asked us to enable this API Please contact us at support@sent.ly with your account email and we will enable this API for you.

Response

200 (OK)
Content-Type: application/json
{
    "errorMessage":"",
    "errorCode":0,
    "responseData":{
        "SenderId":"98051602-2401-4d87-b210-d3d826b0ac4f",
        "SenderIdValue":"Zendesk",
        "IsApproved":true
    }
}

PUT

/api/identity

Changes the senderName of the specified identity

This is a protected API. You need to contact us at support@sent.ly to enable it.

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5014 The specified identity no longer exists The specified identity does not exist or was previously deleted Please change the senderId in the request and try again
200 10014 The underlying call failed The most common reason for this error is if you have not asked us to enable this API Please contact us at support@sent.ly with your account email and we will enable this API for you.

Response

200 (OK)
Content-Type: application/json
{
    "errorMessage":"",
    "errorCode":0,
    "responseData":{
        "SenderId":"98051602-2401-4d87-b210-d3d826b0ac4f",
        "SenderIdValue":"Salesforce",
        "IsApproved":true
    }
}

DELETE

/api/identity/98051602-2401-4d87-b210-d3d826b0ac4f

Deletes the specified identity

This is a protected API. You need to contact us at support@sent.ly to enable it.

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5014 The specified identity no longer exists The specified identity does not exist or was previously deleted Please change the senderId in the request and try again
200 10014 The underlying call failed The most common reason for this error is if you have not asked us to enable this API Please contact us at support@sent.ly with your account email and we will enable this API for you.

Response

200 (OK)
{
    "errorMessage":"",
    "errorCode":0,
    "responseData":null
}

Failed Messages

This resource can be used to retrieve the list items pertaining to a campaign job that had errors while sending messages

GET

/api/failedmessages/1?take=50&skip=0

Gets the specified number of the failed messages (according to take/skip parameters) for the specified campaign job. Take/skip parameters are mandatory in the query string.

Since message failures are recorded incrementally, multiple calls to this API at different times may result in more results. Only items that are still present in the list will be retrieved. If the items are subsequently deleted from the list they will not be included in the results returned from this API.

The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5012 Take/skip parameters missing The request did not have take/skip query string parameters Provide take and skip parameters and try again
200 5021 Failed to parse take/skip The specified take/skip parameters were not valid integers Provide a valid values for take/skip in the request query string and try again
200 5027 Failed to find specified number of failed messages This could be a result of skipping over too many items or specifying an incorrect campaign job id Adjust the parameters in the request and try again

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":{
      "CampaignJobId":1,
      "Items":[
         {
            "Mobile phone number":"+6583888388",
            "First Name":"Adam",
            "Last Name":"Smith",
            "IsUnsubscribed":"False",
            "IsBouncing":"False",
            "DateFlagged":"2013-01-04 16:19:19",
            "IsUnsubscribedDueToCampaign":"True",
            "IsFailedDueToCampaign":"False"
         }
      ]
   }
}

SMS

This resource can be used to shoot out a message to up to a 100 recipients without explicitly creating a list or campaign. Internally this resource does create temporary lists, campaigns and jobs, but these temporary structures are automatically cleared at the end of the month.

POST

/api/sms

Post the list of messages to send.

The following table describes the parameters in the request:

Parameter Meaning
phoneNumbers List of phone number the message will be sent to. Cannot be more than 100 numbers in this list
description A description that will show in the UI to help track this request
message Message to send to the specified receipients
senderId The Id of the identity that the message will apear to be sent from
callbackUrl If this URL is specified, it will be hit with jobid, smsid, status in the query string parameters. Allowing you to track the message in near real time.
sendWhenMilliseconds If this is not zero, the message will be sent after the specified number of milliseconds from the time the API call is made
clientDate This should be the current time in your time zone. It is used to calculate time zone offset from your time zone while dealing with dates
isUnsubscribeEnabled If this is set to true, an unsubscribe link will be included in the messages that are sent out

If the callback URL is specified the following list descibes the status parameter that will be sent in the querystring:

Status Description Meaning
0 None Unused
1 Sent The message was sent to the gateway
2 Failed The gateway reported that the message failed
3 Delivered The gateway reported that the message was delivered to the recipient
Example callback:
http://yourserver.com/yourpage.php?jobid=55&status=3&smsid=5F19983D-EA5A-46ED-901C-4A63CBA87C04


The following table lists errors that may occur as a result of this call:

Http Status Code Sently Plus Error Code Description Scenario Resolution
200 5008 List data validation failed One or more of the posted items has data errors Please check the responseData key for the Errors array (see the list item resource) to see which items had errors. You may post the items again after correcting the specified errors.
200 5014 The identity specified in senderId was not found No identities were found that matched the specified senderId Please provide a valid senderId in the request
200 5019 Database Error An error ocurred while saving the items Please check the errorMessage key for what may have gone wrong. If the problem persists, please contact administrator.
200 5028 One or more phone numbers must be supplied The request did not have any phone numbers Provide a list of phone numbers and try again
200 5029 Too many phone numbers in the request The specified request has too many phone numbers Break down your list and send 100 numbers at a time and try again

Response

200 (OK)
Content-Type: application/json
{
   "errorMessage":"",
   "errorCode":0,
   "responseData":{
      "campaignJobId":19,
      "listItems":[
         {
            "MobilePhoneNumber":"+6583887908",
            "Id":"012d01ad-7734-435c-960b-39ef1e23c664"
         },
         {
            "MobilePhoneNumber":"+6598509388",
            "Id":"14729a49-0ee2-4661-acd8-229b53dd98ca"
         }
      ]
   }
}