Comment on page
Welcome!
We are pleased to present you our new REST API. At the begining of this documentation we would like to give you some general informations about this API:
- 1.It's based on JSONAPI specification. We hope that following the rules of this specification will make our API easy to understand.
- 2.
- 3.This API always accept application/json format at the API input and always return the same format as output.
- 4.API output always follows this scheme:
{
"meta": {
"numberOfErrors": NUMBER_OF_ELEMENTS_IN_ERRORS (number),
"numberOfData": NUMBER_OF_ELEMENTS_IN_DATA (number),
"status": HTTP_STATUS (number),
"uniqId": UNIQUE_REQUEST_ID (string)
},
"data": [],
"errors": [
{
"title": ERROR_TITLE (string),
"message": ERROR_MESSAGE (string),
"code": ERROR_CODE (string),
"meta":{
"parameter": SOME_VALUE (string),
"value": SOME_VALUE (string),
"source": SOME_VALUE (string),
"somefield": SOME_VALUE (string)
}
}
]
}
Following rules applies to the above scheme:
meta
element is always presentmeta.numberOfErrors
indicates how many elementserrors
array includesmeta.numberOfData
indicates how many elementsdata
array includesmeta.status
indicates response HTTP statusmeta.uniqId
is used to identify request, if your will have some troubles with your request, please make sure that you sent usmeta.uniqId
valuemeta
may contain additional fieldsdata
array cannot be present witherrors
array if status code is different than HTTP 207 (MULTI-STATUS)errors
array always consists object with fields:title
,message
andcode
.meta
element may be present inside single error object and contain additional information (that can be parsed) about errorparameter
the parameter that causes the errorvalue
the value of this parameter passedsource
a link to the entity that caused the error, e.g. externalIdsomefield
additional fields that may appear
Second version of VercomAPI offers authentication with pair of keys: Application-Key and Authorization. You can generate your keys in your account panel. To authenticate simply add to your request header with name
Authorization
and your authorization key as value (string of 128 characters length) and header with name Application-Key
and your app key as value.Example:
$ curl --request POST \
--header 'Content-Type: application/json' \
--header 'Application-Key: ' \
--header 'Authorization: ' \
--url '...'
--data '{ ... }'
To make integration with our API clear, we have provided examples for some well known REST clients. Feel free to play with these samples.
This API provide some actions that should be used in different way. When we have to deal with long running tasks we don't want to make client wait. To resolve this case we provided support for
Retry-After
header. How it works? Pretty simple:- 1.Client executes long running action (ex. POST /long-running)
- 2.If response data is available then response with HTTP status 200 and data array is returned
- 3.If request is not yet available API returns following response:
HTTP/1.1 202 ACCEPTED
​
Content-Type: application/json
Retry-After: <delay-seconds>
Expires: <http-date>
​
...
And here we have to explain the meaning of above response headers:
HTTP/1.1 202 ACCEPTED
indicates that response is not yet availableRetry-After
indicates how long client should wait before making next request to this endpointExpires
contains the date/time after which the response is considered stale (client should NOT make another request to this endpoint after time specified at this header)
That all. Pretty simple. Isn't it?
This API supports following compression algorithms: gzip. To enable this feature just add following header to your request:
Content-Encoding: gzip
Note that API always returns
application/json
response body.In case of sending not compressed data with
Content-Encoding: gzip
header error will be returned.This API supports filters for
GET
methods. Almost all of these methods support two filters: limit
and offset
. They are used for pagination.limit
is used to limit number of elements that should API returnoffset
is used to ommit number of elements from begining
In some
GET
methods you can also use additional filters:getFullDate
is used to get pretty printed DateTime instead Timestamp, accept int values, 0 means get timestamp, 1 means get formated DateTime
With this feature, you can dynamically generate e-mail content (HTML/TEXT of the e-mail) based on additional variables passed in
to
parametr as vars
or in globalVars
parameter. You can see examples of these parameters in the description of the method.This feature is best suited for transactional e-mails to generate e.g. product lists or personalise the e-mail to suit each individual recipient. Remember that the overall pers request payload limit applies.
How to use this feature? Easy.
Your HTML/TEXT should contain variables and/or:
foreach
loop, if else
statement. For example like this:<!DOCTYPE html>
<html>
<head>
<!--some headers-->
</head>
<body>
<div data-gb-custom-block data-tag="if" data-0='female'>
<p>Dear Madame,</p>
<div data-gb-custom-block data-tag="elseif" data-0='male' data-1='male'></div>
<p>Dear Sir,</p>
<div data-gb-custom-block data-tag="else"></div>
<p>Hello,</p>
</div>
<br>
​
<div data-gb-custom-block data-tag="if">
<div>Thank you for ordering some products!</div>
</div>
​
<br><br>
​
<div data-gb-custom-block data-tag="if">
You have some promos!
<ul>
<div data-gb-custom-block data-tag="for">
<li> {{promo.name}}: <b>{{promo.value}}</b></li>
</div>
</ul>
</div>
​
<br><br>
​
BASIC PRODUCT LIST
<ul>
<div data-gb-custom-block data-tag="for">
<div style=\"background-color: {{product.color}}\">
{{product.name}}: {{product.id}} <br>
</div>
</div>
</ul>
​
<br><br>
​
Show some alpaca if user has newsletter option! <br>
<div data-gb-custom-block data-tag="if" data-0='true' data-1='true' data-2='true' data-3='true'>
<img src=\"https://www.publicdomainpictures.net/pictures/310000/nahled/llama-1575022717hXs.jpg\">
</div>
​
{{footer}}
</body>
</html>
And then your
to
parameter could look like this:{
"to":[
{
"email":"[email protected]",
"messageId":"[email protected]",
"name":"Jane Doe",
"vars":{
"hasNewsletter":true,
"products":{
"1":{
"name":"skirt",
"id":1,
"color":"green"
},
"2":{
"name":"hoodie",
"id":6,
"color":"red",
"options":[
"pocket",
"print",
"glitter"
]
},
"3":{
"name":"dress",
"id":"100",
"color":"blue"
}
},
"promos":{
"1":{
"name":"test40",
"value":300
},
"2":{
"name":"test800",
"value":3008
}
},
"footer":"<div style=\"background-image: linear-gradient(red, yellow, green);\"><strong>crazy custom footer</strong></div>"
}
}
]
}
And that's the tea. Happy sending! :)
Sms billing table. GSM-7 characters are standard characters used in SMS messages. The use of other characters significantly shortens the length of individual messages. The tables below illustrate this rule.
Only GSM7 characters | SMS count |
---|---|
1 - 160 characters | 1 |
161 - 306 characters | 2 |
307 - 459 characters | 3 |
460 - 612 characters | 4 |
613 - 765 characters | 5 |
766 - 918 characters | 6 |
919 - 1071 characters | 7 |
1072 - 1224 characters | 8 |
1225 - 1377 characters | 9 |
Characters not included in the GSM7 table | SMS count |
---|---|
1 - 70 characters | 1 |
71 - 134 characters | 2 |
135 - 201 characters | 3 |
202 - 268 characters | 4 |
269 - 335 characters | 5 |
336 - 402 characters | 6 |
403 - 469 characters | 7 |
470 - 536 characters | 8 |
537 - 603 characters | 9 |
Listen for events on your account so your integration can automatically trigger reactions.
It is possible to receive delivery and/or click and/or open statuses of all your sendouts from different channels of communication via webhook. A webhook enables us to push real-time notifications to your app. We use HTTPS to send these notifications to your app as a JSON payload. You can then use these notifications to execute actions in your backend systems. Webhooks are particularly useful for sendouts in which you wish to act on the event or display information about delivery in your systems as soon as possible. Alternatively when you need very detailed status information for each message for a large dataset that cannot be found in our panel (for example due to TTL).
- 1.Identify the events you want to monitor and the event payloads to parse (payloads are described below).
- 2.Create a webhook endpoint as an HTTPS endpoint (URL) on your server.
- 3.Handle requests by saving each event object (parse it later) and returning 200 response status codes with a string message 'ok'.
- 4.Test that your webhook endpoint is working properly using settings in our panel
- 5.Save your webhook configuration in panel
The events you can monitor are dependent on your plan and features that you use. The full list is available in the configuration page in our panel under Account -> Settings -> Webhooks.
Generally you can specify two URLs for each webhook type. Default URL and secondary URL. Unless specified otherwise (in send request), the webhook will be sent to the main URL and when it’s unavailable or fails to respond properly, to the secondary URL.
The data is provided in a POST request that consists of an array of events. Each event is structured as an event object but its structure varies in accordance to the type of the event (see below for detailed descriptions for each type). Your endpoint should: check the authorization (in accordance to the setting in panel), save the payload, respond with
Status: 200
and Message: ok
. The ‘ok’ is a lowercase string. Your server should NOT validate the payload before giving the response. The only reasons to respond with something other than success should be authorization failure or an actual internal server error. You should parse your stored payload data into intended structures in a different process (than the receiving endpoint).Our request can look like this:
[{"externalId":"xxxxxxxxxxxxxxxxxxxxxxxx","phoneNumber":"+48XXXXXXXXX","status":1,"statusDesc":"DELIVERED","statusTime":"2021-04-27T00:00:18","webhookUrl":"xxxxxxxxxxxxxxx"}]
or like this:
[{"externalId": "xxxxxxxxxxxxxxxxxxxxxxxx","appId": "xxxxxxxxxxxxxxxxxxxxxxxx","platform": 1,"status": 1,"statusDesc": "Accepted by push operator","statusDetails": "NOTIFICATION_CLICK_ACTION","statusTime": "2020-12-08T11:57:08","actionId": null,"code":null}]
The specific fields depend on the type of webhook (see below).
Make sure that the webhooks actually come from us and stay secure. In the panel you can see 2 options for authentication:
- None
- Basic auth.
Whether you choose to additionally use basic auth or not, you should always check the hash of incoming webhook. With our POST request, in addition to the standard HTTP headers, we send three headers will allow you to verify if the data actually come from us:
Header | Type | Description |
---|---|---|
X-Webhook-Date | string | Date on which the webhook is sent |
X-Webhook-Checksum | string | Checksum |
Request-Id | string | Unique request ID |
Now, the checksum is generated from a string built like this:
secretkey|X-Webhook-Date|Request-Id
Value | Description |
---|---|
secretkey | is a key given to you when you configure your webhook inside the panel |
X-Webhook-Date | from headers |
Request-Id | from headers |
Additionally, you can protect your script with basic auth. All you need to do is turn the option on and set login and password in the panel. Then, of course, add authentication to your endpoint.
Transactional e-mails
Remember to use unique message_ids so that you can later aggregate all the webhooks (with consecutive statuses).
example:
[
{
"subject": "Your chosen subject",
"smtpAccount": "1.accountname.smtp",
"to": {
"email": "[email protected]",
"name": "Jane Doe",
"messageId": "[email protected]"
},
"from": {
"email": "[email protected]",
"name": "Test Corp."
},
"tags": null,
"status": "dropped",
"statusTime": 1580996271,
"statusDesc": "[email protected] in blacklist",
"allStatuses": [
{
"status": "injected",
"statusTime": 1580996275,
"statusDesc": "injected"
},
{
"status": "dropped",
"statusTime": 1580996271,
"statusDesc": "[email protected] in blacklist"
}
]
}
]
Transactional SMS - delivery reports
Field | Type | Example |
---|---|---|
externalId | string | test123 |
status | int | 1 |
statusDesc | string | DELIVERED |
statusTime | string | 2021-12-12T12:12:12 |
webhookUrl* | string | https://test.pl/test.aspx |
*This object contains a
webhookUrl
field because, when sending transactional SMS it is possible to specify a webhook URL inside send request directly. In that case, both default URL and secondary URL configured in the panel will be ignored and the webhook will be sent to this, additionally specified, URL.example:
[{"externalId":"xxxxxxxxxxxxxxxxxxxxxxxx","phoneNumber":"+48XXXXXXXXX","status":1,"statusDesc":"DELIVERED","statusTime":"2021-04-27T00:00:18","webhookUrl":"xxxxxxxxxxxxxxx"}]
Transactional SMS - clicked link
Field | Type | Example |
---|---|---|
externalId | string | test123 |
url | string | http://www.test.pl/kontact/?place=menu |
clickTime | string | 2021-12-12T12:12:12 |
ip | string | 111.222.11.22 |
userAgent | string | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/xxx.xx (KHTML, like Gecko) Chrome/xxx.xx.xxx.xx Safari/xxx.xx Google |
webhookUrl* | string | https://test.pl/test.aspx |
*This object contains a
webhookUrl
field because, when sending transactional SMS it is possible to specify a webhook URL inside send request directly. In that case, both default URL and secondary URL configured in the panel will be ignored and the webhook will be sent to this, additionally specified, URL.2-way communication - Incoming SMS
Field | Type | Example |
---|---|---|
id | string | F2D21CA2-916E-4B92-B686-606231D9165F |
phoneNumber | string | +48111222333 |
message | string | Thank You |
ndi | string | 48111222333 |
statusTime | string | 2021-11-15T12:25:32 |
Push messages - delivery reports
Field | Type | Example |
---|---|---|
externalId | string | xxxxxxxxxxxxxxxxxxxxxxxx |
appId | string | xxxxxxxxxxxx |
platform | int | 1 |
status | int | 1 |
statusDesc | string | Accepted by push operator |
statusDetails | string | NOTIFICATION_CLICK_ACTION |
actionId | int | 1 |
code | string | null |
statusTime | string | 2021-11-15T12:25:32 |
Values for field
platform
:1 | IOS |
2 | ANDROID |
Values for field
status
:1 | DISCARDED |
2 | SCHEDULED |
3 | SENT |
4 | FAILED |
5 | RECEIVED |
6 | REACTED_ON |
Values for field
statusDesc
:DISCARDED | "Push validation failed" |
SCHEDULED | "Push accepted by push operator" |
SENT | "Push accepted by FCM/APNS servers" |
FAILED | "Push dropped by FCM/APNS" |
RECEIVED | "Push received by device" |
REACTED_ON | "User reacted on push" |
Values for field
statusDetails
:NOTIFICATION_CLICK_ACTION |
NOTIFICATION_SWIPE_ACTION |
DIALOG_DISSMISS_ACTION |
example:
[{"externalId": "xxxxxxxxxxxxxxxxxxxxxxxx","appId": "xxxxxxxxxxxxxxxxxxxxxxxx","platform": 1,"status": 1,"statusDesc": "Accepted by push operator","statusDetails": "NOTIFICATION_CLICK_ACTION","statusTime": "2020-12-08T11:57:08","actionId": null,"code":null}]
Email campaign webhooks
Field | Type | Example |
---|---|---|
id | string | 345dfsg2-dfws-w451-1245-sdfgsdf23441 |
contact | object | ​ |
contact[externalId] | string | 78b556af-c01b-4341-8059-f5ce08f5ad14 |
contact[email] | string | |
contact[phoneNumber] | string | +48111222333 |
campaign | object | ​ |
campaign[externalId] | string | DFG2345T-3456-6734-6345-FHDF65341235 |
status | object | ​ |
status[id] | int | 4 |
status[desc] | string | CLICKED |
status[time] | string | 2023-08-08T11:15:53.053 |
details | object | ​ |
details[id] | int nullable | 2 |
details[desc] | string nullable | HARD_BOUNCE |
details[ip] | string nullable | 100.20.30.400 |
details[userAgent] | string nullable | Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36 |
details[referer] | string nullable | https://www.redlink.pl/ |
Example:
{
"id": "345dfsg2-dfws-w451-1245-sdfgsdf23441",
"contact": {
"externalId": "78b556af-c01b-4341-8059-f5ce08f5ad14",
"email": "[email protected]",
"phoneNumber": "+48111222333"
},
"campaign": {
"externalId": "DFG2345T-3456-6734-6345-FHDF65341235"
},
"status": {
"id": 4,
"desc": "CLICKED",
"time": "2023-08-08T11:15:53.053"
},
"details": {
"id": null,
"desc": null,
"ip": "100.20.30.400",
"userAgent": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36",
"referer": "https://www.redlink.pl/"
}
}
Values for field
status
:id | desc |
---|---|
0 | SENT |
1 | DELIVERED |
2 | FAILED |
3 | RECEIVED |
4 | CLICKED |
Values for field
details
:id | desc |
---|---|
1 | TRANSIENT |
2 | HARD_BOUNCE |
3 | AUTO_RESPONDER |
4 | ADDRESS_CHANGE |
5 | CHALLENGE_VERIFICATION |
6 | DNS_ERROR |
7 | SPAM_NOTIFICATION |
8 | OPEN_RELAY_TEST |
9 | UNKNOWN |
10 | SOFT_BOUNCE |
11 | VIRUS_NOTIFICATION |
12 | CANCELLED |
13 | CUSTOM_SMTP_SERVER_ERROR |
14 | REDLINK_SMTP_SERVER_ERROR |
15 | REDLINK_SMTP_EMAIL_TOO_BIG |
16 | INSUFFICIENT_FUNDS |
17 | LIMIT_EXCEEDED |
18 | CONTROL_GROUP |
19 | CAPPING_LIMIT_EXCEEDED |
Sms campaign webhooks
Field | Type | Example |
---|---|---|
id | string | 345dfsg2-dfws-w451-1245-sdfgsdf23441 |
contact | object | ​ |
contact[externalId] | string | 78b556af-c01b-4341-8059-f5ce08f5ad14 |
contact[email] | string | |
contact[phoneNumber] | string | +48111222333 |
campaign | object | ​ |
campaign[externalId] | string | DFG2345T-3456-6734-6345-FHDF65341235 |
status | object | ​ |
status[id] | int | 4 |
status[desc] | string | CLICKED |
status[time] | string | 2023-08-08T11:15:53.053 |
details | object | ​ |
details[id] | int nullable | 2 |
details[desc] | string nullable | SMS_ERROR |
details[ip] | string nullable | 100.20.30.400 |
details[userAgent] | string nullable | Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36 |
details[referer] | string nullable | https://www.redlink.pl/ |
Example:
{
"id": "345dfsg2-dfws-w451-1245-sdfgsdf23441",
"contact": {
"externalId": "78b556af-c01b-4341-8059-f5ce08f5ad14",
"email": "[email protected]",
"phoneNumber": "+48111222333"
},
"campaign": {
"externalId": "DFG2345T-3456-6734-6345-FHDF65341235"
},
"status": {
"id": 4,
"desc": "CLICKED",
"time": "2023-08-08T11:15:53.053"
},
"details": {
"id": null,
"desc": null,
"ip": "100.20.30.400",
"userAgent": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36",
"referer": "https://www.redlink.pl/"
}
}
Values for field
status
:id | desc |
---|---|
0 | SENT |
1 | DELIVERED |
2 | FAILED |
3 | RECEIVED |
4 | CLICKED |
Values for field
details
:id | desc |
---|---|
1 | SMS_CANCELED |
2 | SMS_ERROR |
3 | SMS_BAD_NUMBER |
4 | SMS_MESSAGE_TOO_LONG |
5 | SMS_MESSAGE_INCORRECT |
6 | SMS_WAITING |
7 | SMS_MESSAGE_TOO_SHORT |
8 | SMS_UNKNOWN_ERROR |
10 | SMS_ECO_AS_ABROAD_NUMBER |
11 | SMS_ABROAD_NOT_ALLOWED |
12 | SMS_NOT_ALLOWED |
13 | INSUFFICIENT_FUNDS |
14 | SMS_SERVICE_FORBIDDEN |
15 | LIMIT_EXCEEDED |
16 | UNSUBSCRIBE |
17 | CONTROL_GROUP |
18 | CAPPING_LIMIT_EXCEEDED |
19 | MMS_SEND |
20 | MMS_ERROR |
21 | MMS_BAD_NUMBER |
22 | MMS_MESSAGE_TOO_LONG |
23 | MMS_MESSAGE_INCORRECT |
24 | MMS_WAITING |
25 | MMS_MESSAGE_TOO_SHORT |
26 | MMS_UNKNOWN_ERROR |
27 | MMS_CANCELED |
Push campaign webhooks
Field | Type | Example |
---|---|---|
id | string | 345dfsg2-dfws-w451-1245-sdfgsdf23441 |
contact |