Introduction
Welcome to the Delivery API (DAPI) documentation. This page will fully describe all available API’s within the Delivery API.
This document has been written with developers in mind. So it is technical oriented and assumes basic development skills, for you to understand how to use the Delivery APIs in your software.
On the right side of API documentation pages you can find examples in different programming languages. Currently we support Curl and Python. In the near future we will add more languages .
Authentication
$ curl https://api.dapi.io/v1/providers \
-u "USER_ID:USER_SECRET" \
-X GET
import requests
requests.get("https://api.dapi.io/v1/providers",
auth=('USER_ID', 'USER_SECRET'))
User authentication must be added every time the API is called. An unique user-id and secret-key is generated for each new account that is created. These identifiers can be retrieved only via the frontend interface once an user is logged in. Each user only has one token. In case the original token is being lost, it can be regenerated via the frontend. Once a new token is generated, the previous token becomes unavailable and all the subsequent API calls with the old token will be rejected.
Accounts
Show the limits of your account
$ curl https://api.dapi.io/v1/accounts/limits \
-u "USER_ID:USER_SECRET" \
-X GET
{
"mps": "1",
"lists": "100",
"contact-per-list": "100"
}
import requests
requests.get("https://api.dapi.io/v1/limits",
auth=('USER_ID', 'USER_SECRET'))
Each account has its own limits, based on the subscription you have chosen and activated. This API is going to show you the limits of your account / subscription.
Request type | Limit |
---|---|
Message throughput | 1 per second |
Number of lists | 100 |
Number of contacts in each list | 100 |
Before contacting us to increase your limits, please make sure your account at the messages provider you are going to use is also able and set to support your requested throughput.
Show the credits of your account
$ curl https://api.dapi.io/v1/accounts/credits \
-u "USER_ID:USER_SECRET" \
-X GET
{
"balance": "54.23",
}
import requests
requests.get("https://api.dapi.io/v1/credits",
auth=('USER_ID', 'USER_SECRET'))
Each account has a credit balance. This is the amount of money available in your account that can be used to send your messages. Depending on the subscription you have selected and activated a fee will be charged per messages you send. Your available credits can be topped up once your are logged in into your account via a web browser. Currently we do not support top ups via the API.
However it is possible to use this API to retrieve the current account balance, so that you can monitor if your credits are running low.
Request headers
All the APIs are only going to return valid json
objects.
All the APIs that require the user to send information, must send valid json
objects. For this reason, all those type of requests must have the header
Content-Type: application/json
, otherwise the request will be refused and
an error code will be returned.
In all the examples we are also going to include the correct headers and the correct HTTP method, that should be used. So copying the example (and changing the example parameters into your own) should work out of the box.
Errors
This section shows a list of all the errors that APIs may return if something is wrong in the request.
HTTP Status Codes
Each API call will return a status code. This table shows all possible status codes.
Status code | Description |
---|---|
200 | OK - Everything works as expected. |
400 | Bad Request - The request was not correct, more information about the exact reason will be returned. |
401 | Unauthorized - The token provided is not valid for this request. |
404 | Not Found - The requested resource does not exist. |
5xx | Server Error - Something went wrong on the server, if the issue persists, please let us know. |
Error codes
$ curl https://api.dapi.io/v1/providers/amazon-sms \
-u "USER_ID:USER_SECRET" \
-H 'Content-Type: application/json' \
-X PUT \
-d '{
"ACCESS_KEY": "AKIAIOSFODNN7EXAMPLE",
"AUTH_TOKEN": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"REGION_NAME": "us-east-1"
}'
{
"error-code": "provider-invalid"
"error-description": "The provider in the argument is not supported"
}
import requests
payload = {
"ACCESS_KEY": "AKIAIOSFODNN7EXAMPLE",
"AUTH_TOKEN": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"REGION_NAME": "us-east-1"
}
requests.put("https://api.dapi.io/v1/providers/amazon-sms",
auth=('USER_ID', 'USER_SECRET'), json=payload)
Some APIs may return additional error codes because the parameters were wrong. All these error codes will return together with a response code 400. Here are the possible additional error codes that can be returned.
Code | Description |
---|---|
json-invalid | The json value passed as argument is invalid. |
provider-invalid | The provider in the argument is not supported. |
provider-missing-keys | The provider needs specific identifiers, like keys and secret(s). Some of them are not provided in the request. |
message-invalid-type | The message-type provided is not valid. |
message-invalid-provider | The provider defined to deliver the message(s) is not valid or not added to the system yet. |
message-invalid-arguments | The arguments provided are not valid for the type and provider selected. |
list-metadata-size | The size of the metadata is bigger than the system limit. |
list-invalid-contact | One of the contacts in the list is invalid. |
invoke-invalid-throughput | The throughput provided is invalid or above the account limits. |
Providers
Dapi support multiple message delivery providers and multiple types of messages. With the
providers
API calls you can add, edit or update all the providers you want
to use.
Add a new provider to your account
$ curl https://api.dapi.io/v1/providers/amazon-ses \
-u "USER_ID:USER_SECRET" \
-H 'Content-Type: application/json' \
-X PUT \
-d '{
"ACCESS_KEY": "AKIAIOSFODNN7EXAMPLE",
"AUTH_TOKEN": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"REGION_NAME": "us-west-2"
}'
import requests
payload = {
"ACCESS_KEY": "AKIAIOSFODNN7EXAMPLE",
"AUTH_TOKEN": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"REGION_NAME": "us-west-2"
}
requests.put("https://api.dapi.io/v1/providers/amazon-ses",
auth=('USER_ID', 'USER_SECRET'), json=payload)
As stated before Dapi supports multiple message delivery providers, and multiple type of messages. The next table shows a list of all supported providers (in alphabetical order) , the types of messages they support and their name as being used in the Delivery API.
Provider | Types | Input name |
---|---|---|
Nexmo | SMS | nexmo |
Twilio | SMS, Voice | twilio |
Plivo | SMS, Voice | plivo |
Mailgun | mailgun | |
Amazon SES | amazon-ses | |
Amazon SNS | Push | amazon-sns |
Bluemix | Push | bluemix-push-notifications |
Each provider has different keys and secrets as unique identifiers, so we store different values for each provider. The following are the values that should be added to the request of each provider.
Provider | Values |
---|---|
Nexmo | API_KEY, API_SECRET |
Twilio | ACCOUNT_SID, AUTH_TOKEN |
Plivo | AUTH_ID, AUTH_TOKEN |
Mailgun | API_KEY, DOMAIN_NAME |
Amazon SES | ACCESS_KEY, SECRET_KEY, REGION_NAME |
Amazon SNS | ACCESS_KEY, SECRET_KEY, REGION_NAME |
Bluemix | APP_GUID, APP_SECRET, REGION_NAME |
Get a providers information
$ curl https://api.dapi.io/v1/providers/amazon-ses \
-u "USER_ID:USER_SECRET" \
-X GET
{
"name": "amazon-ses",
"credentials": {
"ACCESS_KEY": "AKIAIOSFODNN7EXAMPLE",
"AUTH_TOKEN": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"REGION_NAME": "us-west-2"
}
}
import requests
requests.get("https://api.dapi.io/v1/providers/amazon-ses",
auth=('USER_ID', 'USER_SECRET'))
If you have already added a provider, and you don’t remember which token has been stored in the database, you can always retrieve the providers information using this API.
Update a providers information
$ curl https://api.dapi.io/v1/providers/amazon-ses \
-u "USER_ID:USER_SECRET" \
-H "Content-Type: application/json" \
-X POST \
-d '{
"ACCESS_KEY": "AKIAIOSFODNN7EXAMPLE",
"AUTH_TOKEN": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"REGION_NAME": "us-west-2"
}'
import requests
payload = {
"ACCESS_KEY": "AKIAIOSFODNN7EXAMPLE",
"AUTH_TOKEN": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"REGION_NAME": "us-west-2"
}
requests.post("https://api.dapi.io/v1/providers/amazon-ses",
auth=('USER_ID', 'USER_SECRET'), json=payload)
If you have changed the token for one of your providers, you should update the information also in Dapi, otherwise the subsequent messages will fail.
Delete a provider from the account
$ curl https://api.dapi.io/v1/providers/amazon-ses \
-u "USER_ID:USER_SECRET" \
-X DELETE
import requests
requests.delete("https://api.dapi.io/v1/providers/amazon-ses",
auth=('USER_ID', 'USER_SECRET'))
Delete any provider from your Dapi account if you are not planning to use the provider anymore.
Get all the providers in the account
$ curl https://api.dapi.io/v1/providers \
-u "USER_ID:USER_SECRET" \
-X GET
{
"providers": [
{
"name": "amazon-ses",
"credentials": {
"ACCESS_KEY": "AKIAIOSFODNN7EXAMPLE",
"AUTH_TOKEN": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"REGION_NAME": "us-west-2"
}
}
]
}
import requests
requests.get("https://api.dapi.io/v1/providers/amazon-ses",
auth=('USER_ID', 'USER_SECRET'))
Retrieve all the providers that have already been added to the system. This is going to return a json array with all the providers that are available in your Delivery API account.
Messages
A message
in DAPI is any type of message sent to any of the configured
providers. Dapi currently supports the following type of messages:
- sms
Using the messages
API one message at a time is going to be send to one of the
configured providers. If multiple messages should be sent at the same time,
then the lists
API should be used.
Create a new message
$ curl https://api.dapi.io/v1/messages \
-u "USER_ID:USER_SECRET" \
-H "Content-Type: application/json" \
-X PUT \
-d '{
"provider": "nexmo",
"type": "sms",
"arguments": {
"from": "Dapi",
"to": "+31612345678",
"text": "This is a test"
}
}'
{
"id": "1"
}
import requests
payload = {
"provider": "nexmo",
"type": "sms",
"arguments": {
"from": "Dapi",
"to": "+31612345678",
"text": "This is a test"
}
}
requests.put("https://api.dapi.io/v1/messages",
auth=('USER_ID', 'USER_SECRET'), json=payload)
Whenever a new message is created, a new message will be sent to the selected provider, via the selected message type.
Every time a new message is created, multiple arguments need to be passed as parameters, to make sure the API does not fail.
There are two parameters that are mandatory for the API to understand which provider to chose and which type of message it is:
- provider
- type
The type
must be one of the valid types mentioned before, while the provider
is one of the providers already configured via the providers
API.
Each provider has its own arguments
that needs to be added to perform the
operation correctly and without any error. Those arguments are added as a
parameter to the API.
Based on the type of message and the provider selected the right parameter(s)
need to be added. When you want to change the provider or the type of message,
you also need to update/modify the parameters.
Each successful API request is going to return an id
that is the id of the
message request.
Get a message
$ curl https://api.dapi.io/v1/messages/1 \
-u "USER_ID:USER_SECRET" \
-X GET
{
"id": "1",
"status": "completed",
"provider": "nexmo",
"type": "sms",
"error-code": "",
"error-description": "",
"provider_reply": {
"status": "returnCode",
"message-id": "messageId",
"to": "+31612345678",
"client-ref": "client-ref",
"remaining-balance": "remaining-balance",
"message-price": "message-price",
"network": "network",
"error-text": "error-message"
},
"arguments": {
"from": "Dapi",
"to": "+31612345678",
"text": "This is a test"
}
}
import requests
requests.get("https://api.dapi.io/v1/messages/1",
auth=('USER_ID', 'USER_SECRET'))
Once a message has been created, you can retrieve the message details.
Key | Value |
---|---|
id | The unique identifier of the message |
status | The status of the message |
provider | The provider used to send this message |
type | The type of message |
provider_reply | The full reply of the request from the provider. This value will depend on the selected provider. |
The status
key can be one of the following:
Status | Description |
---|---|
pending | The message has been received correctly and is currently in the queue, waiting to be processed |
completed | The message has been processed correctly |
failed | The message has failed because of some reason |
The list of reasons why a message may fail is listed here:
Error | Description |
---|---|
provider-not-found | The provider credentials specified in the message are not available in the system |
List all messages
$ curl https://api.dapi.io/v1/messages \
-u "USER_ID:USER_SECRET" \
-X GET
{
"page": "0",
"messages": [
{
"id": "1",
"status": "success",
"provider": "nexmo",
"type": "sms",
"error-code": "",
"error-description": "",
"provider_reply": {
"status": "returnCode",
"message-id": "messageId",
"to": "+31612345678",
"client-ref": "client-ref",
"remaining-balance": "remaining-balance",
"message-price": "message-price",
"network": "network",
"error-text": "error-message"
},
"arguments": {
"from": "Dapi",
"to": "+31612345678",
"text": "This is a test"
}
}
]
}
import requests
requests.get("https://api.dapi.io/v1/messages",
auth=('USER_ID', 'USER_SECRET'))
A list of all messages can be retrieved using the following API. This API is going to return a json array with all the messages that have been created.
Lists
A list
in DAPI is a set of contacts that can be reached simultaneously.
Dapi is designed to be able to handle a lot of (different) messages concurrently at a high throughput. This means you can create a list with hundreds or thousands of contacts. Dapi will take care of sending all messages as quickly as possible (according to the limitations explained above, or given your custom throughput rate).
Each list can contain multiple contacts, and each contact can be contacted via multiple different types of media (sms, email etc.).
All different messages can coexist within the same list, without any problem.
Dapi will make sure the correct, selected, provider per contact is being used
to deliver the message, once an invoke
associated to the list is created.
Create a new list
$ curl https://api.dapi.io/v1/lists \
-u "USER_ID:USER_SECRET" \
-H 'Content-Type: application/json' \
-X PUT \
-d '{
"metadata": {
"name": "Test",
"description": "This is a test list"
}
}'
{
"id": "1"
}
import requests
payload = {
"metadata": {
"name": "Test",
"description": "This is a test list"
}
}
requests.put("https://api.dapi.io/v1/lists",
auth=('USER_ID', 'USER_SECRET'))
This API is used to create a new empty list. The unique list id will be returned
as result of this API. This list-id will later be used to add contacts to the
list and to create an invoke
for this list.
The metadata
object is optional, and can be added to each list. As long as it is
a valid json object, the user can specify any information that may be relevant
to the list and is important to store in the list, inside the metadata object.
Update list metadata
$ curl https://api.dapi.io/v1/lists/1 \
-u "USER_ID:USER_SECRET" \
-H 'Content-Type: application/json' \
-X POST \
-d '{
"metadata": {
"name": "New name",
}
}'
{
"id": "1"
}
import requests
payload = {
"metadata": {
"name": "New name",
}
}
requests.post("https://api.dapi.io/v1/lists",
auth=('USER_ID', 'USER_SECRET'))
This API is used to edit the metadata for an existing list. If after the list has been generated you would like to edit (or add) metadata, this API should be used.
Whatever is passed in the metadata
object will be saved as the the new
metadata for the list. If no metadata object is passed, the current metadatas
will be removed from the list.
Add contacts to the list
$ curl https://api.dapi.io/v1/lists/1/contacts \
-u "USER_ID:USER_SECRET" \
-H 'Content-Type: application/json' \
-X PUT \
-d '{
"contacts": [
{
"type": "sms",
"provider": "twilio",
"order": "1",
"contact": "+31612345678"
},
{
"type": "email",
"provider": "mailgun",
"order": "2",
"contact": "support@dapi.io"
}
]
}'
{
"ids": ["1", "2"]
}
import requests
payload = {
"contacts": [
{
"type": "sms",
"provider": "twilio",
"order": "1",
"contact": "+31612345678"
},
{
"type": "email",
"provider": "mailgun",
"order": "2",
"contact": "support@dapi.io"
}
]
}
requests.put("https://api.dapi.io/v1/lists/1/contacts",
auth=('USER_ID', 'USER_SECRET'), json=payload)
This API is used to add multiple contacts to a specific list. Each contact must have the following parameters assigned to it.
Key | Description |
---|---|
type | The type of message to be sent to the contact |
provider | The provider that must be used to send the message to the contact |
contact | The contact that must be notified |
order | The order which the contact must be contacted. If multiple contacts have the same order, the order will be undefined |
Get all contacts in a list
$ curl https://api.dapi.io/v1/lists/1/contacts \
-u "USER_ID:USER_SECRET" \
-X GET
{
"page": "0",
"contacts": [
{
"id": "1",
"type": "sms",
"provider": "twilio",
"order": "1",
"contact": "+31612345678"
},
{
"id": "2",
"type": "email",
"provider": "mailgun",
"order": "2",
"contact": "support@dapi.io"
}
]
}
import requests
requests.get("https://api.dapi.io/v1/lists/1/contacts",
auth=('USER_ID', 'USER_SECRET'))
This API is used to retrieve the list of all the contacts that are part of a list.
Get a single contact in a list
$ curl https://api.dapi.io/v1/lists/1/contacts/2 \
-u "USER_ID:USER_SECRET" \
-X GET
{
"id": "2",
"type": "email",
"provider": "mailgun",
"order": "2",
"contact": "support@dapi.io"
}
import requests
requests.get("https://api.dapi.io/v1/lists/1/contacts/2",
auth=('USER_ID', 'USER_SECRET'))
This API is used to retrieve the information of a single contact in a list.
Update contact in a list
$ curl https://api.dapi.io/v1/lists/1/contacts/2 \
-u "USER_ID:USER_SECRET" \
-H "Content-Type: application/json" \
-X POST \
-d '{
"type": "email",
"provider": "mailgun",
"order": "2",
"contact": "hello@dapi.io"
}'
import requests
payload = {
"type": "email",
"provider": "mailgun",
"order": "2",
"contact": "hello@dapi.io"
}
requests.post("https://api.dapi.io/v1/lists/1/contacts/2",
auth=('USER_ID', 'USER_SECRET'))
This API is used to update the information of a single contact in a specific list.
Delete contact in a list
$ curl https://api.dapi.io/v1/lists/1/contacts/2 \
-u "USER_ID:USER_SECRET" \
-H "Content-Type: application/json" \
-X DELETE
import requests
requests.delete("https://api.dapi.io/v1/lists/1/contacts/2",
auth=('USER_ID', 'USER_SECRET'))
This API is used to delete a single contact in a specific list.
Delete a list
$ curl https://api.dapi.io/v1/lists/1 \
-u "USER_ID:USER_SECRET" \
-H "Content-Type: application/json" \
-X DELETE
import requests
requests.delete("https://api.dapi.io/v1/lists/1",
auth=('USER_ID', 'USER_SECRET'))
This API is used to delete a complete list, this will also delete all the contacts in that list.
Get all lists
$ curl https://api.dapi.io/v1/lists \
-u "USER_ID:USER_SECRET" \
-X GET
{
"page": "0",
"lists": [
{
"id": "1",
"metadata": {
"name": "Test",
"description": "This is a test list"
}
}
]
}
import requests
requests.get("https://api.dapi.io/v1/lists",
auth=('USER_ID', 'USER_SECRET'))
This API is used to retrieve all the lists stored in the system.
Get a list
$ curl https://api.dapi.io/v1/lists/1 \
-u "USER_ID:USER_SECRET" \
-X GET
{
"id": "1",
"metadata": {
"name": "Test",
"description": "This is a test list"
}
}
import requests
requests.get("https://api.dapi.io/v1/lists/1",
auth=('USER_ID', 'USER_SECRET'))
This API is used to retrieve the information about a specific list.
Invokes
An invoke
is a started list. When a list is configured, it
is stored in your account on the Delivery API server, waiting to be started. When an invoke
is created,
the list is started and all the contacts in the list will be informed / notified.
Create a new invoke
$ curl https://api.dapi.io/v1/invokes \
-u "USER_ID:USER_SECRET" \
-H "Content-Type: application/json" \
-X PUT \
-d '{
"list_id": "42",
"providers": [
{
"type": "sms",
"provider": "nexmo",
"arguments": {
"from": "Dapi",
"text": "This is a test from Nexmo"
}
},
{
"type": "sms",
"provider": "twilio",
"arguments": {
"From": "Dapi",
"Body": "This is a test from Twilio"
}
}
],
"throughput": {
"voice": {
"mps": "1",
"mpm": "10"
},
"sms": {
"mps": "10"
}
}
}'
{
"id": "1"
}
import requests
payload = {
"list_id": "42",
"providers": [
{
"type": "sms",
"provider": "nexmo",
"arguments": {
"from": "Dapi",
"text": "This is a test from Nexmo"
}
},
{
"type": "sms",
"provider": "twilio",
"arguments": {
"From": "Dapi",
"Body": "This is a test from Twilio"
}
}
],
"throughput": {
"voice": {
"mps": "1",
"mpm": "10"
},
"sms": {
"mps": "10"
}
}
}
requests.put("https://api.dapi.io/v1/invokes",
auth=('USER_ID', 'USER_SECRET'), json=payload)
A new invoke can be created with this API. The following parameters can be passed as argument.
Key | Description |
---|---|
list_id | The id of the list that should be started |
providers | The list of providers that are available to handle this invoke |
The providers are message delivery providers that based on their delivery services like type of messages they will send and/or the geographical delivery , are able to handle this invoke
. For each provider
the correct parameters need to be added so that when the system is creating the
message, the message delivery will not fail.
Optionally you can specify the throughput for the list that has been invoked. By default it is set at the maximum throughput rate as specified in the account limits.
If, for some reason, you want to reduce the throughput for a particular invoke, you can use the throughput parameter. Add the throughput parameter to your API-request, and specify for each message type how many mps (messages per second) or mpm (messages per minute) Dapi needs to handle. Once the invoke is created, all the contacts will be contacted as quickly as possible via the message types as defined, in the order as specified with the throughput as specified.
Get the details for an invoke
$ curl https://api.dapi.io/v1/invokes/1 \
-u "USER_ID:USER_SECRET" \
-X GET
{
"id": "1",
"status": "running",
"contacts": [
{
"type": "sms",
"provider": "twilio",
"order": "1",
"contact": "+31612345678"
},
{
"type": "email",
"provider": "mailgun",
"order": "2",
"contact": "support@dapi.io"
}
]
}
import requests
requests.get("https://api.dapi.io/v1/invokes/1",
auth=('USER_ID', 'USER_SECRET'))
Once an invoke is created, this API can be used to retrieve all details of an invoke. The following information will be returned.
Key | Description |
---|---|
id | The unique identifier of the invoke |
status | The current status of the invoke (see table below) |
contacts | The list of contacts in the list |
Each invoke will have one of the following status
options.
Status | Description |
---|---|
running | The invoke is still running |
completed | The invoke has completed |
stopped | The invoke has been stopped manually |
Stop a running invoke
$ curl https://api.dapi.io/v1/invokes/1 \
-u "USER_ID:USER_SECRET" \
-H "Content-Type: application/json" \
-X POST \
-d '{
"status": "stopped"
}'
import requests
payload = {
"status": "stopped"
}
requests.post("https://api.dapi.io/v1/invokes/1",
auth=('USER_ID', 'USER_SECRET'), json=payload)
This API is used to stop a running invoke. In case you started a wrong list, or if you don’t want the invoke to continue with the next messages, this is going to stop the running invoke and the next messages will never be started.
Delete an invoke
$ curl https://api.dapi.io/v1/invokes/1 \
-u "USER_ID:USER_SECRET" \
-X DELETE
import requests
requests.delete("https://api.dapi.io/v1/invokes/1",
auth=('USER_ID', 'USER_SECRET'))
This API is used to delete an invoke. If the invoke is not completed or stopped, it can not be deleted, and this API call will return an error. When an invoke is not running anymore, it can be deleted, and all the informations will be removed from the system.
Get a list of all invokes
$ curl https://api.dapi.io/v1/invokes \
-u "USER_ID:USER_SECRET" \
-X GET
{
"page": "0",
"invokes": [
{
"id": "1",
"status": "completed",
"contacts": [
{
"type": "sms",
"provider": "twilio",
"order": "1",
"contact": "+31612345678"
},
{
"type": "email",
"provider": "mailgun",
"order": "2",
"contact": "support@dapi.io"
}
]
}
]
}
import requests
requests.get("https://api.dapi.io/v1/invokes",
auth=('USER_ID', 'USER_SECRET'))
This API will return a list of all the invokes including their details, in the system.