Introduction:
Welcome to the Campaign Verloop API. Verloop API lets you send messages to your users on WhatsApp and other channels (coming soon)
API Version:
The current version of the API V1.0
Reference:
Following are the use cases of Verloop Campaign API.
- Get the list of templates (live)
- Get a template (live)
- Get the list of campaigns (live)
- Get a campaign (live)
- Trigger a template message as a part of a campaign (live)
- Callbacks (live)
Postman collection: https://www.getpostman.com/collections/8e64c8f29c726d4e9dc2
Concepts:
Client ID
<client_id> can be found in the verloop dashboard URL (the part before verloop.io). for example, in https:/clientID.verloop.io, the client id would be “bigbasket”
So the endpoint URL for Send Message would be: https://clientID.verloop.io/api/v1/Campaign/SendMessage
API Errors:
We use Twirp for serving, so overall status codes can be found in this document.
Errors specific to this API can be “unauthenticated”, “not_found”, “internal” or “invalid_argument” type
Auth Token
A valid auth token will be necessary to send campaign messages. It’ll be shared separately over email/UI. This token must be sent in the `Authorization` header with all requests.
If you send an incorrect/ expired/revoked auth token, the API will respond with status 401 and the following body
{
"code": "unauthenticated",
"msg": "Authentication required"
}
Meta:
Every object in Verloop across all APIs has meta information in this field.
Id | String (Id of the object) |
CreatedAt | Unix timestamp of create time |
UpdatedAt | Unix timestamp of last updated time |
List Templates:
Request:
Method: POST
URL: https://<client_id>.verloop.io/api/v1/Campaign/ListTemplates
Headers:
Authorization: <auth_token>
Content-Type: application/json
Body:
{
"ListOption": {
"Limit": 10,
"Offset": 0
},
"Type": "TYPE_WHATSAPP"
}
Response:
Success:
{
"ListOption": {
"Limit": 10,
"Offset": 0
},
"Count": 2,
"Templates": [
{
"Meta": {
"Id": "1234",
"CreatedAt": 1564996815,
"UpdatedAt": 1564996815
},
"Name": "Order Confirmed WA",
"WhatsAppTemplate": {
"TemplateID": "order_confirmed1"
},
"Block": {
"MessageBlock": {
"Type": "TYPE_MESSAGE",
"LeadingMessage": {
"TextMessage": "Your order {{order_number}} for {{amount}} has been confirmed"
}
}
},
"Parameters": ["order_number", "amount"]
},
{
"Meta": {
"Id": "4567",
"CreatedAt": 1564996800,
"UpdatedAt": 1564996800
},
"Name": "Happy birthday WA",
"WhatsAppTemplate": {
"TemplateID": "happy_birthday1"
},
"Block": {
"MessageBlock": {
"Type": "TYPE_MESSAGE",
"LeadingMessage": {
"TextMessage": "Happy birthday!\n\nAvail {{discount}} off on your birthday, use coupon code {{coupon_code}}"
}
}
},
"Parameters": ["discount", "coupon code"]
}
]
}
Error:
Status: 400
{
"code": "invalid_argument",
"msg": "ListOption.Limit is capped at 100",
"meta": {
"argument": "ListOption.Limit"
}
}
Get Template:
Request:
Method: POST
URL: https://<client_id>.verloop.io/api/v1/Campaign/GetTemplate
Headers:
Authorization: <auth_token>
Body:
{
"ID": "1234"
}
Response:
Success:
{
"Template": {
"Meta": {
"Id": "1234",
"CreatedAt": 1564996815,
"UpdatedAt": 1564996815
},
"Name": "Order Confirmed WA",
"WhatsAppTemplate": {
"TemplateID": "order_confirmed1"
},
"Block": {
"MessageBlock": {
"Type": "TYPE_MESSAGE",
"LeadingMessage": {
"TextMessage": "Your order {{order_number}} for {{amount}} has been confirmed"
}
}
},
"Parameters": ["order_number", "amount"]
}
}
Error:
Status: 404
{
"code": "not_found",
"msg": "Template not found"
}
List Campaigns:
Request:
Method: POST
URL: https://<client_id>.verloop.io/api/v1/Campaign/ListCampaigns
Headers:
Authorization: <auth_token>
Content-Type: application/json
Body:
{
"ListOption": {
"Limit": 10,
"Offset": 0
},
"Type": "TYPE_WHATSAPP"
}
Response:
Success:
{
"ListOption": {
"Limit": 10,
"Offset": 0
},
"Count": 2,
"Campaigns": [
{
"Meta": {
"Id": "abcd",
"CreatedAt": 1564996815,
"UpdatedAt": 1564996815
},
"Name": "Order update",
"Type": "TYPE_WHATSAPP",
"TemplateID": "1234",
"Status": "STATUS_DRAFT"
},
{
"Meta": {
"Id": "defg",
"CreatedAt": 1564996805,
"UpdatedAt": 1564996813
},
"Name": "Birthday discount",
"Type": "TYPE_WHATSAPP",
"TemplateID": "4567",
"Status": "STATUS_PUBLISHED"
}
]
}
Error:
Status: 400
{
"code": "invalid_argument",
"msg": "ListOption.Limit is capped at 100",
"meta": {
"argument": "ListOption.Limit"
}
}
Get Campaign:
Request:
Method: POST
URL: https://<client_id>.verloop.io/api/v1/Campaign/GetCampaign
Headers:
Authorization: <auth_token>
Content-Type: application/json
Body:
{
“ID”: “abcd”
}
Response:
Success:
{
"Campaign": {
"Meta": {
"Id": "abcd",
"CreatedAt": 1564996815,
"UpdatedAt": 1564996819
},
"Name": "My updated campaign name",
"Type": "TYPE_WHATSAPP",
"TemplateID": "4567",
"Status": "STATUS_PUBLISHED"
}
}
Error:
Status: 400
{
"code": "invalid_argument",
"msg": "Campaign.Meta.Id is required",
"meta": {
"argument": "Campaign.Meta.Id"
}
}
Send Message
Request:
Method: POST
URL: https://<client_id>.verloop.io/api/v1/Campaign/SendMessage
Headers:
Authorization: <auth_token>
Content-Type: application/json
Body:
{
"CampaignID": "abcd",
"To": {
"PhoneNumber": "919916564955"
},
"Parameters": {
"order_number": "#1234",
"amount": "$100"
},
"Variables": {
"order_number": "1234",
"customer_id": "my_customer_id"
},
"Callback": {
"URL": "https://example.com/msg_callback",
"State": {
"a": "b",
"c": "d"
}
}
}
Response:
Success:
{
"MessageID": "some_message_id"
}
Error:
Status: 400
{
"code": "invalid_argument",
"msg": "Callback.URL not a valid HTTPS URL",
"meta": {
"argument": "Callback.URL"
}
}
Possible Errors:
- CampaignID is not valid
- CampaignID is not published
- CallbackURL is not a valid HTTPS URL
- CallbackURL only HTTPS callback URLs are allowed
- WhatsAppCampaignParameters are not present or valid
- Couldn’t send campaign message, please retry in some time
CampaignID: As of now, you cannot send a templated whatsapp message without a campaign id. When you create a campaign, you get a campaign id, you have to pass that here.
PhoneNumber: PhoneNumber is with the 91 India code, so you have to use the number of the customer as WhatsApp saves it, with preceding country code without 0 or +. E.g. 919689639098
Parameters: Template Messages have parameters that will be dynamically incorporated into the message. These parameters will be passed in Parameters in the form of a dictionary of string key value pairs.
- Note: Sending more or fewer params than a template expects will result in a silent failure as we don’t know that status from Kaleyra yet.
- In the example above, `$100` has no meaning outside of passing straight to WhatsApp/ any channel we support in the future.
- Parameter values being sent must be in stringified format. i.e. even if `amount` was supposed to be an integer, it must be sent to the API as a string
Variables: These are the Verloop variables that will be associated with the user when the user engages with the template message. These variables will be available during recipe for interpolation/webhook block and exports, this is where you can send variables. These are completely independent of `LocalizableParams`.
- In the example above, `$100` is not available in the recipe. If you want to use it in the recipe, you can send it in Variables.
- Variables being sent must be defined beforehand from the UI, this allows us to parse and validate them later. Any variables not set on the UI will be dropped completely.
- Variables being sent must be in stringified format. i.e. even if `order_number` was supposed to be an integer, it must be sent to the API as a string.
CallbackURL: If you need status updates for Messages, you can send a https URL in this parameter. We’ll make a POST request with in application/json format with the following body
Sample body:
{
"MessageID": "some_message_id",
"Status": "STATUS_READ",
"Timestamp": 1564996815,
"Parameters": {
"order_number": "#1234",
"amount": "$100"
},
"Variables": {
"order_number": "1234",
"customer_id": "my_customer_id"
},
"State": {
"a": "b",
"c": "d"
}
}
MessageID:
Id of the message as sent in response to the SendMessage API.
Status:
Status | Meaning |
STATUS_PENDING | Initial status of every message (not sent over callback) |
STATUS_SENT | Message was sent to the user |
STATUS_DELIVERED | Message delivered to user |
STATUS_READ | Message read by user |
STATUS_REPLIED | User replied to the message |
STATUS_EXPIRED | A new campaign message expired old campaign messages (future: campaign had an expiry which lapsed) |
STATUS_FAILED | Message could not be sent to the user. |
Note: In a future version of the callback API, we will start adding a field for “Reason” of failure in case of STATUS_FAILED.
Timestamp:
Time of status event in seconds since unix epoch.
Parameters and Variables:
Same as above.
SendMessage gotchas:
- In this initial version, the API accepts any campaign ID and variable name/value you’re sending and will silently drop it without warning. In a future version, we will add checks and return an error in the `SendMessage` API itself.
- You can only send messages after a campaign has been published. An unpublished Campaign will silently drop messages for now, in a later version `SendMessage` will return an error. (We might need to implement testing endpoints and/or UI senders with rate budgets to test unpublished campaigns)
Campaign ⇒ Template + Associated workflow
Collect Moviefeedback_1 ⇒ collect_NPS_movie_1 + Collect NPS
Collect MF_2 ⇒ collect_NPS_movie_2 + Collect NPS
Send_20_discount ⇒ whatsapp_template_discount_20 + default