Introduction
.' '. __
. . . (__\_
. . . -{{_(|8)
' . . ' ' . . ' (__/
Welcome to the Sendbee REST API documentation.
Use our APIs to seamlessly integrate Sendbee functionalities into your website or application.
Client libraries
Sendbee has official libraries that are available in several languages:
Supported channels
WhatsApp Business
You can send and receive WhatsApp messages for customer support, alerts and notifications. Currently you don’t need to specify WhatsApp channel as a destination when making Sendbee API calls, as it’s the only channel we support.
WhatsApp Opt-In Requirements
WhatsApp requires that a contact must first consent to receive messages in WhatsApp by opting into them via a third-party channel. This can be any channel your business uses to communicate with people today — your website, app, email, SMS, retail location, etc. Sending users messages without an opt-in may result in users blocking your business and suspension of your WhatsApp business account.
To learn more, please visit WhatsApp Business API guide
Notifications (Message Templates)
WhatsApp requires that any initiated messages sent by your business must be a pre-approved templated message. These messages are called Message Templates, with the exception of messages sent as a reply to a contact-initiated message (see the Customer Care Messages section below for more details). Currently only text messages can be sent as Message Templates.
To learn more, please visit our guide for sending WhatsApp notifications using message templates.
Customer Care Messages
To have a 2-way conversation with a contact, you need to receive messages from them. Contacts can send you a message in response to a Message Template or directly via WhatsApp click-to-chat link (see WhatsApp click-to-chat link section below).
WhatsApp 24-hour customer care window
A WhatsApp 24-hour customer care window begins when a contact-initiated message was sent to your business. Sessions are valid for 24 hours after the most recently received message, during which time you can communicate with contacts using free form messages. These messages are called Customer Care Messages. In order to send a message outside the 24-hour custom care window, you must use a pre-approved Message Template (see the Notifications section above for more details).
WhatsApp click-to-chat link
WhatsApp’s click to chat feature allows your customers to begin a chat with your business on WhatsApp without having your phone number saved in their phone’s address book. By clicking the link, a chat with your business automatically opens. Click to chat link works on WhatsApp mobile apps and WhatsApp Web.
To create your link use https://wa.me/
Examples:
Use: https://wa.me/15551234567
Don’t use: https://wa.me/+001-(555)1234567–
To learn more, please visit WhatsApp click to chat link guide.
How to make a request
Every request to the API should be made with the following data in headers:
{
"X-Auth-Token": "...",
"X-Api-Key": "...",
"Accept": "application/json",
"Content-Type": "application/json"
}
In order to use Sendbee APIs, you need to have an active Sendbee business account. Create your account at www.sendbee.io.
Base API URL is https://api-v2.sendbee.io
To authenticate a request to the API, you must create an Auth token as described in Authentication section and send it in authorization header using X-Auth-Token key. Also, API key should be added in header mapped with X-Api-Key key.
Request header name | Request header value |
---|---|
X-Api-Key | Your API key (available in Sendbee dashboard) |
X-Auth-Token | Generated auth token. See Authentication for information on how to generate auth tokens. |
Accept | application/json |
Content-Type | application/json |
Response
The response may contain data
, meta
, links
, warning
or error
elements.
Response with pagination elements
Response with pagination elements:
{
"data": {...},
"meta": {
"current_page": ...,
"from": ...,
"to": ...,
"total": ...,
"per_page": ...,
"last_page": ...
},
"links": {
"first": "...",
"last": "...",
"next": "...",
"prev": "..."
}
}
When you’re making calls to the Sendbee API, in some cases API endpoints could return a list of data consisting of a larger amount of elements. For that reason, we paginate the results to make sure responses are easier to handle. Paginated responses are usually returned when making GET or any other request that returns a list of data in the response. The paginated response contains data, meta and links elements.
Response without pagination elements
Response without pagination elements:
{
"data": {...}
}
Responses without pagination are usually returned when making POST, PUT, DELETE or any other request that doesn’t return a list of data in the response. The unpaginated response contains only a data element.
Warnings
Warning in response:
{
"warning": "...",
"data": {...},
...
}
If something goes wrong in an API request, an error or a warning will be returned. Warnings are usually returned for non-fatal conditions indicating the issues that should be addressed, whereas errors are only returned for fatal conditions.
Errors
Error in response:
{
"error": {
"detail": "...",
"type": "..."
}
}
In case of an error, the response will not contain any other data then the error data. Errors usually occur when a parameter is missing, is invalid or when you try to update a contact using a contact ID that doesn’t exist.
Authentication
import hmac, base64, hashlib
from datetime import datetime, timezone
API_SECRET = '...'
# step 1: get current timestamp
timestamp = str(int(
datetime.now(timezone.utc).timestamp()
)).encode('utf-8')
# step 2: encrypt timestamp with your API secret to get a hash
encrypted = hmac.new(
API_SECRET, data, hashlib.sha256
).hexdigest()
# step 3: concatenate timestamp and hash
timestamp_encrypt = '{}.{}'.format(
timestamp.decode("utf-8"), encrypted.decode("utf-8")
).encode('utf-8')
# step 5: translate concatenated string into base64
auth_token = base64.b64encode(ts_encrypt).decode("utf-8")
<?php
// your API secret
$API_SECRET = '...';
// preferred method: using PHP API
$requestIsValid = \Sendbee\Api\Client::generateToken($API_SECRET);
// manual method (if you don't want to use the PHP API library)
// step 1: get current timestamp
$timestamp = time();
// step 2: encrypt timestamp with your API secret
$hashedData = hash_hmac('sha256', $timestamp, $API_SECRET, false);
// step 3: concatenate timestamp and encrypted_b64
$timestamp_encrypt = $timestamp . '.' . $hashedData;
// step 4: translate concatenated string into base64
$auth_token = base64_encode($timestamp_encrypt);
?>
using System;
using System.Security.Cryptography;
using System.Text;
public class Program
{
public static void Main()
{
Console.WriteLine(getAuthKey());
}
public static string getAuthKey()
{
string apiSecret = "...";
Int32 timestamp = (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
string hashedData = HashHmac(timestamp.ToString(), apiSecret);
return Base64Encode(timestamp.ToString() + "." + hashedData);
}
private static string HashHmac(string data, string key)
{
using (HMACSHA256 hmac = new HMACSHA256(Encoding.ASCII.GetBytes(key)))
{
byte[] a2 = hmac.ComputeHash(Encoding.ASCII.GetBytes(data));
return String.Concat(Array.ConvertAll(a2, x => x.ToString("x2")));
}
}
public static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
}
Every request to the API should be made with the following data in headers:
{
"X-Auth-Token": "...",
"X-Api-Key": "...",
"Accept": "application/json",
"Content-Type": "application/json"
}
The Sendbee API uses the Auth token to authenticate requests.
To create an Auth token for every request, you need API Secret.
Follow these steps to create an authentication token:
1. get current timestamp (in seconds)
2. encrypt the timestamp with your API secret key using HMAC sha256 encrypt algorithm (the output should be lowercase hexadecimal)
3. concatenate timestamp and encrypted timestamp separated by a .
(dot)
4. translate the concatenated string into base64
Check out official Sendbee API client libraries.
If you are using some of those languages it is highly recommended
to use our client library because in that case you don’t need to worry
about authentication, the library does it for you.
If you’re using programing language other then the ones we provide client libraries for, please consider using these examples on how to create a valid auth token:
Step-by-step tutorial
If you’re having trouble writing code that successfully generates an authentication token, please try following this step-by-step tutorial and test your code.
For this tutorial we will be using predefined values for Secret key and Current timestamp.
Step 1: get current timestamp (in seconds)
Step result is:
1586286575
Step 2: encrypt the timestamp with your API secret key using HMAC sha256 encrypt algorithm
Step result is (lowercase hexadecimal):
675ff7bd7674f940aec62dadad81fbf79d1f92876d79145ad25af2bf64faee41
Step 3: concatenate timestamp and encrypted timestamp separated by a . (dot)
Step result is:
1586286575.675ff7bd7674f940aec62dadad81fbf79d1f92876d79145ad25af2bf64faee41
Step 4: translate the concatenated string into base64
Step result is (scroll to the right):
MTU4NjI4NjU3NS42NzVmZjdiZDc2NzRmOTQwYWVjNjJkYWRhZDgxZmJmNzlkMWY5Mjg3NmQ3OTE0NWFkMjVhZjJiZjY0ZmFlZTQx
Authentication resources
Timestamp:
- Unix timestamp is a system for describing a point in time. It is the number of seconds that have elapsed since the Unix epoch, that is the time 00:00:00 UTC on 1 January 1970, minus leap seconds: https://en.wikipedia.org/wiki/Unix_time
- Timestamp converter: https://www.unixtimestamp.com/
HMAC:
- HMAC is a specific type of message authentication code (MAC) involving a cryptographic hash function and a secret cryptographic key: https://en.wikipedia.org/wiki/HMAC
- HMAC generator: https://www.freeformatter.com/hmac-generator.html
- HMAC-Sha256 using Java: https://sorenpoulsen.com/calculate-hmac-sha256-with-java
- HMAC-Sha256 using Ruby: https://stackoverflow.com/questions/34855049/using-hmac-sha256-in-ruby
- HMAC-Sha256 using Go: https://golangcode.com/generate-sha256-hmac/
- HMAC-Sha256 using C++: https://stackoverflow.com/questions/37737857/generate-hmac-sha256-hash-using-key-in-c
- some more HMAC-Sha256 examples https://github.com/danharper/hmac-examples
base64:
- Base64 is a scheme designed to carry data stored in binary formats across channels that only reliably support text content: https://en.wikipedia.org/wiki/Base64
- base64 decoder/encoder: https://www.base64decode.org/
Rate Limit
A rate limit is the number of API calls a business number can make within a given time period. If this limit is exceeded, API requests are throttled, and will fail with 429 error response.
No matter how many API keys you make in your Sendbee account, rate limit will always be counted within a business number.
Error response
Response body:
{
"detail": "Request was throttled. Expected available in 5 seconds.",
"error": true,
"type": "throttled"
}
If an API call is throttled, server will return error response:
429 Too Many Requests
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429
Response headers:
Key | Value |
---|---|
Retry-After | 5 |
How to handle throttled request
When using Sendbee API, you should be prepared to handle possible 429 error responses.
Once you experience a 429 error response, you should look for the Retry-After
key in the response headers, which gives you an information on how long you
should wait until making your next API call.
Sendbee API allows you to make a maximum of 60 calls per minute. It means if
you make 60 API calls in 30 seconds, next API call will be throttled,
and you will receive 429 error response with Retry-After
key in response
headers with value of 30, which means you should wait for 30 seconds until
making your next API call.
Error test endpoint
curl -X GET -G "https://api-v2.sendbee.io/rate-limit/error-test" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json"
Error test response:
{
"detail": "Request was throttled. Expected available in 5 seconds.",
"error": true,
"type": "throttled"
}
This endpoint doesn’t do anything, it just returns 429 error response. With this endpoint you always have all the data necessary to know how to implement your solution on how to handle 429 error response.
Requests to this endpoint doesn’t add to your rate limit counting, meaning you can freely query it as much as you want without fearing your app will hit the rate limit error.
HTTP Request
GET https://api-v2.sendbee.io/rate-limit/error-test
Request test endpoint
curl -X GET -G "https://api-v2.sendbee.io/rate-limit/request-test" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json"
Request test response:
{
"detail": "Request was throttled. Expected available in 5 seconds.",
"error": true,
"type": "throttled"
}
This endpoint doesn’t do anything, it will return 429 error response once you query it in rate higher than 60 call per minute. With this endpoint you can test your 429 error response handle implementation in real life environment.
Requests to this endpoint add to your rate limit counting, meaning you need to be careful and not to use this endpoint once your app is in the production.
HTTP Request
GET https://api-v2.sendbee.io/rate-limit/request-test
Teams
A team on Sendbee platform is a group of people working for your company using the platform to communicate with customers. Each team consists of members. You can have more then one team and each team can have a number of team members.
Fetch teams
curl -X GET -G "https://api-v2.sendbee.io/teams/teams" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json"
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
teams = api.teams([member_id='...'])
for team in teams:
team.id
team.name
for member in team.members:
member.id
member.name
member.role
member.online
member.available
Teams fetch response:
{
"data":[
{
"id": "...",
"name": "...",
"members": [
{
"id": "...",
"name": "...",
"online": true|false,
"available": true|false,
"role": "owner|admin|team_leader|member"
},
...
]
},
...
],
"meta": {
"current_page": ...,
"from": ...,
"to": ...,
"total": ...,
"per_page": ...,
"last_page": ...
},
"links": {
"first": "...",
"last": "...",
"next": "...",
"prev": "...",
}
}
Fetch teams within your account on Sendbee platform.
With this endpoint you can fetch a list of your teams, and every team in the list contains a list of members.
If you send member_id
parameter, you will get all teams where that person is a member.
HTTP Request
GET https://api-v2.sendbee.io/teams/teams
URI Parameters
Parameter | Default | Required | Description |
---|---|---|---|
member_id | Provide a member ID in order to get only teams where that person is a member |
Fetch team members
curl -X PUT -G "https://api-v2.sendbee.io/teams/members" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json"
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
members = api.team_members([team_id='...'])
for member in members:
member.id
member.name
member.role
member.online
member.available
for team in member.teams:
team.id
team.name
Chatbot status settings response:
{
"data":[
{
"id": "...",
"name": "...",
"online": true|false,
"available": true|false,
"role": "owner|admin|team_leader|member",
"teams":[
{
"id": "...",
"name": "..."
},
...
]
},
...
],
"meta": {
"current_page": ...,
"from": ...,
"to": ...,
"total": ...,
"per_page": ...,
"last_page": ...
},
"links": {
"first": "...",
"last": "...",
"next": "...",
"prev": "...",
}
}
Fetch team members within your account on Sendbee platform.
With this endpoint you can fetch a list of users from your company (team members) using Sendbee platform, and every member in the list contains a list of teams where he or she is a member.
If you send team_id
parameter, you will get a list of members for that team.
HTTP Request
PUT https://api-v2.sendbee.io/teams/members
URI Parameters
Parameter | Default | Required | Description |
---|---|---|---|
team_id | Provide a team ID in order to get team members only for that team |
Contacts
A contact is a person/entity with whom you have communicated or that subscribed to receive messages from your business. The Sendbee API gives you the ability to subscribe, fetch or update your contacts.
Subscribe contact
curl -X POST -G "https://api-v2.sendbee.io/contacts/subscribe" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json" \
-d '{"phone": "...", "name": "..."}'
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
contact = api.subscribe_contact(
phone='+...',
# this is mandatory the most important information
# about the subscribing contact
[tags=['...', ...]],
# tag new contact
# if tag doesn't exist, it will be created
[name='...'],
[notes=[...]],
# write notes about your new subscriber
[contact_fields={'__field_name__': '__field_value__', ...}],
# fill contact fields with your data (value part)
# contact fields must be pre-created in Sendbee Dashboard
# any non-existent field will be ignored
[block_notifications=[True|False]],
# prevent sending browser push notification and email
# notification to agents, when new contact subscribes
# (default is True)
[block_automation=[True|False]]
# prevent sending automated template messages to newly
# subscribed contact (if any is set in Sendbee Dashboard)
# (default is True)
)
contact.id
contact.status
contact.folder
contact.created_at
contact.name
contact.phone
for tag in contact.tags:
tag.id
tag.name
for note in contact.notes:
note.value
for contact_field in contact.contact_fields:
contact_field.key
contact_field.value
<?php
$sendbeeApi = new \Sendbee\Api\Client($public_key, $secret);
$contactData = [
// contact phone number, MANDATORY
'phone' => '+...',
// feel free to specify other optional contact data here
// ...
];
try {
$response = $sendbeeApi->subscribeContact($contactData);
} catch (\Sendbee\Api\Support\DataException $ex) {
// handle missing data
// this happens when required data was not provided
echo "Could not subscribe a contact. ", $ex->getMessage();
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
/**
* @var $contact \Sendbee\Api\Models\Contact
*/
$contact = $response->getData();
// contact is now subscribed (created)
// $contact contains the newly created contact data
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
// handle error
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Subscribe contact response:
{
"data": {
"id": "...",
"name": "...",
"phone": "...",
"created_at": "...",
"tags": ["...", ...],
"status": "...",
"folder": "...",
"contact_fields": [
{
"key": "...",
"value": "..."
},
...
],
"notes": ["...", ...]
}
}
By subscribing a contact, you create a new contact as well.
But to be in compliance with WhatsApp Opt-In rules, you should subscribe/create only contacts who consent to receive your messages in WhatsApp.
Contact consent could be received in form of the web form on your website,
having some kind of “Receive your purchase information on WhatsApp” checkbox.
It means contacts are subscribing to your business WhatsApp
communication channel.
Read more about WhatsApp Opt-In rules.
HTTP Request
POST https://api-v2.sendbee.io/contacts/subscribe
Data Parameters
Parameter | Default | Required | Description |
---|---|---|---|
phone | yes | Contact phone number. Number must be passed in the E.164 format: +/country code/area code/phone number, UK number example: +442071838750. | |
tags | Tags for this contact (if passed tag name doesn’t match any existing tag name, it will be created as a new one). | ||
name | Contact name. | ||
notes | Custom notes about the contact. | ||
contact_fields | Contact fields defined in your contact fields list. A contact field must be pre-created via the Sendbee Dashboard or Sendbee API. Any non-existent field will be ignored. Send it in the following format: {“[field_name]”: “[field_value]”, …}. | ||
block_notifications | True | Prevent sending browser push notification and email notification to agents when new contact subscribes. | |
block_automation | True | Prevent sending automated template messages to newly subscribed contact (applicable only if an automation rule was created in the Sendbee Dashboard). |
Fetch contacts
curl -X GET -G "https://api-v2.sendbee.io/contacts" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json"
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
contacts = api.contacts(
[tags=['...', ...]], [status='subscribed|unsubscribed'],
[search_query='...'], [page=...], [limit=...]
)
for contact in contacts:
contact.id
contact.status
contact.folder
contact.created_at
contact.name
contact.phone
for tag in contact.tags:
tag.id
tag.name
for note in contact.notes:
note.value
for contact_field in contact.contact_fields:
contact_field.key
contact_field.value
<?php
$sendbeeApi = new \Sendbee\Api\Client($public_key, $secret);
// optional parameters
$params = [
'tags' => '', // Filter contacts by tag
'status' => '', // Filter contacts by status
'search_query' => '', // Filter contacts by query string
'page' => 1 // Page number for pagination
];
try {
$response = $sendbeeApi->getContacts($params);
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
// everything is OK
$data = $response->getData();
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Fetch contacts response:
{
"data": [
{
"id": "...",
"name": "...",
"phone": "...",
"created_at": "...",
"tags": ["...", ...],
"status": "subscribed|unsubscribed",
"folder": "open|done|spam",
"contact_fields": [
{
"key": "...",
"value": "..."
},
...
],
"notes": ["...", ...]
},
...
],
"meta": {
"current_page": ...,
"from": ...,
"to": ...,
"total": ...,
"per_page": ...,
"last_page": ...
},
"links": {
"first": "...",
"last": "...",
"next": "...",
"prev": "..."
}
}
HTTP Request
GET https://api-v2.sendbee.io/contacts
URI Parameters
Parameter | Default | Required | Description |
---|---|---|---|
phone | Contact phone number. Number must be passed in the E.164 format: +/country code/area code/phone number, UK number example: +442071838750. | ||
tags | Filter contacts by tags. | ||
status | Filter contacts by subscription status. Use subscribed or unsubscribed value. | ||
search_query | Filter contacts by string. The query will search through name and phone number fields. | ||
page | 1 | Page number for pagination. | |
limit | 10 | Number of items per page. Maximum is 100. |
Update contact
curl -X PUT -G "https://api-v2.sendbee.io/contacts" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json" \
-d '{"id": "...", ...}'
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
contact = api.update_contact(
id='...',
# contact is identified with ID
[phone='+...'],
# this is the most important information
# about the subscribing contact
[tags=['...', ...]],
# tag a contact
# if tag doesn't exist, it will be created
# if you want to remove a tag from a contact, put "-" before the tag name
# example: tags=['-tag1'] # this will remove a "tag1" tag from a contact
[name='...'],
[notes=[...]],
# write notes about your new subscriber
# if there are notes already saved for this contact
# new notes will be appended
[contact_fields={'__field_name__': '__field_value__', ...}],
# fill contact fields with your data (value part)
# contact fields must be pre-created in Sendbee Dashboard
# any non-existent field will be ignored
# if there are fields already filled with data for this contact
# it will be overwritten with new data
)
contact.id
contact.status
contact.folder
contact.created_at
contact.name
contact.phone
for tag in contact.tags:
tag.id
tag.name
for note in contact.notes:
note.value
for contact_field in contact.contact_fields:
contact_field.key
contact_field.value
<?php
$contactData = [
// contact id, MANDATORY
'id' => '...',
// feel free to specify other optional contact data here
// ...
];
try {
$response = $sendbeeApi->updateContact($contactData);
} catch (\Sendbee\Api\Support\DataException $ex) {
// handle missing data
// this happens when required data was not provided
echo "Could not update a contact. ", $ex->getMessage();
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
/**
* @var $contact \Sendbee\Api\Models\Contact
*/
$contact = $response->getData();
// contact is now updated
// $contact contains the updated contact data
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
// handle error
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Update contacts response:
{
"data": {
"id": "...",
"name": "...",
"phone": "...",
"created_at": "...",
"tags": ["...", ...],
"status": "subscribed|unsubscribed",
"folder": "open|done|spam",
"contact_fields": [
{
"key": "...",
"value": "..."
},
...
],
"notes": ["...", ...]
}
}
HTTP Request
PUT https://api-v2.sendbee.io/contacts
Data Parameters
Parameter | Default | Required | Description |
---|---|---|---|
id | Yes | Contact ID | |
phone | Contact phone number. Number must be passed in the E.164 format: +/country code/area code/phone number, UK number example: +442071838750. | ||
tags | Tag a contact, if tag doesn’t exist, it will be created. If you want to remove a tag from the contact, put “-” (without quotations) before the tag name. (add tag example: tags=[“new_customer”] - this will add a “new_customer” tag to the contact) (remove tag example: tags=[“-new_customer”] - this will remove a “new_customer” tag from the contact) | ||
name | Contact name | ||
notes | Custom notes about the contact. Take care, notes are not replaced but are instead appended to existing notes when updating a contact. | ||
contact_fields | Contact fields defined in your contact fields list. A contact field must be pre-created in the Sendbee Dashboard or via Sendbee API. Any non-existent field will be ignored. Send it in the following format: {“[field_name]”: “[field_value]”, …}. |
Contact tags
A contact tag is a label that can be used to classify contacts. The Sendbee API gives you the ability to fetch, create, update or delete your contact tags.
Fetch contact tags
curl -X GET -G "https://api-v2.sendbee.io/contacts/tags" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json"
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
tags = api.tags([name='...'], [page=...], [limit=...])
for tag in tags:
tag.id
tag.name
<?php
$sendbeeApi = new \Sendbee\Api\Client($public_key, $secret);
// optional parameters
$params = [
'name' => '...', // Name of the tag
'page' => 1 // Page number for pagination
];
try {
$response = $sendbeeApi->getTags($params);
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
// everything is OK
$data = $response->getData();
foreach ($data as $tag) {
/**
* @var $tag \Sendbee\Api\Models\ContactTag
*/
echo "\n ID: ", $tag->id;
echo "\n name: ", $tag->name;
}
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Fetch tags response:
{
"data": [
{
"id": "...",
"name": "...",
},
...
],
"meta": {
"current_page": ...,
"from": ...,
"to": ...,
"total": ...,
"per_page": ...,
"last_page": ...
},
"links": {
"first": "...",
"last": "...",
"next": "...",
"prev": "..."
}
}
HTTP Request
GET https://api-v2.sendbee.io/contacts/tags
URI Parameters
Parameter | Default | Required | Description |
---|---|---|---|
name | Tag name | ||
page | 1 | Page number for pagination. | |
limit | 10 | Number of items per page. Maximum is 100. |
Create contact tag
curl -X POST -G "https://api-v2.sendbee.io/contacts/tags" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json" \
-d '{"name": "..."}'
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
tag = api.create_tag(name='...')
tag.id
tag.name
<?php
$sendbeeApi = new \Sendbee\Api\Client($public_key, $secret);
$data = [
// tag name, MANDATORY
'name' => '...'
];
try {
$response = $sendbeeApi->createTag($data);
} catch (\Sendbee\Api\Support\DataException $ex) {
// handle missing data
// this happens when required data was not provided
echo "Missing required data. ", $ex->getMessage();
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
/**
* @var $tag \Sendbee\Api\Models\ContactTag
*/
$tag = $response->getData();
// tag is now created
// $tag contains the newly created tag data
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
// handle error
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Create contact tag response:
{
"data": {
"id": "...",
"name": "..."
}
}
HTTP Request
POST https://api-v2.sendbee.io/contacts/tags
Data Parameters
Parameter | Default | Required | Description |
---|---|---|---|
name | yes | Tag name |
Update contact tag
curl -X PUT -G "https://api-v2.sendbee.io/contacts/tags" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json" \
-d '{"id": "...", "name": "..."}'
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
tag = api.update_tag(id='...', name='...')
tag.id
tag.name
<?php
$sendbeeApi = new \Sendbee\Api\Client($public_key, $secret);
$data = [
// tag id, MANDATORY
'id' => '...',
// tag name, MANDATORY
'name' => '...'
];
try {
$response = $sendbeeApi->updateTag($data);
} catch (\Sendbee\Api\Support\DataException $ex) {
// handle missing data
// this happens when required data was not provided
echo "Missing required data. ", $ex->getMessage();
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
/**
* @var $tag \Sendbee\Api\Models\ContactTag
*/
$tag = $response->getData();
// tag is now updated
// $tag contains the updated tag data
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
// handle error
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Update contact tag response:
{
"data": {
"id": "...",
"name": "..."
}
}
HTTP Request
PUT https://api-v2.sendbee.io/contacts/tags
Data Parameters
Parameter | Default | Required | Description |
---|---|---|---|
id | yes | Tag ID | |
name | yes | Tag name |
Delete contact tag
curl -X DELETE -G "https://api-v2.sendbee.io/contacts/tags?id=..." \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json"
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
response = api.delete_tag(id='...')
response.message
<?php
$sendbeeApi = new \Sendbee\Api\Client($public_key, $secret);
$data = [
// tag id, MANDATORY
'id' => '...'
];
try {
$response = $sendbeeApi->deleteTag($data);
} catch (\Sendbee\Api\Support\DataException $ex) {
// handle missing data
// this happens when required data was not provided
echo "Missing required data. ", $ex->getMessage();
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
/**
* @var $message \Sendbee\Api\Models\ServerMessage
*/
$message = $response->getData();
// record is now deleted
// $message contains server info message
print_r($message);
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
// handle error
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Delete contact tag response:
{
"data": {
"message": "Tag deleted"
}
}
HTTP Request
DELETE https://api-v2.sendbee.io/contacts/tags
URI Parameters
Parameter | Default | Required | Description |
---|---|---|---|
id | yes | Tag ID |
Contact fields
A contact field is a property associated with a contact, that can be populated with specific information such as job title, company details, website, and so on. The Sendbee API gives you the ability to fetch, create, update or delete your contact fields.
Each contact field has a specified data type. Ensure the data you submit when updating a contact field’s value is formatted correctly:
Type | Example | Value |
---|---|---|
String | Zagreb, Croatia. | String values |
Boolean | true | Boolean true/false values |
Number | 50 | Integers |
Datetime | 2020-01-15 03:04:05 | YYYY-MM-DD HH:MM:SS |
List | [‘option1’, ‘option2’, …] | List of options |
Fetch contact fields
curl -X GET -G "https://api-v2.sendbee.io/contacts/fields" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json"
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
contact_fields = api.contact_fields([search_query='...'], [page=...], [limit=...])
for contact_field in contact_fields:
contact_field.name
contact_field.type
if contact_field.type == 'list':
contact_field.options
<?php
$sendbeeApi = new \Sendbee\Api\Client($public_key, $secret);
$params = [
'search_query' => '', // Filter by query string
'page' => 1 // Page number for pagination
];
try {
$response = $sendbeeApi->getContactFields($params);
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
// everything is OK
$data = $response->getData();
foreach ($data as $field) {
/**
* @var $tag \Sendbee\Api\Models\ContactField
*/
echo "\n ID: ", $field->id;
echo "\n type: ", $field->type;
echo "\n name: ", $field->name;
foreach ($field->options as $option) {
/**
* @var $option string
*/
echo "\n field -> option: ", $option;
}
}
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Fetch contact fields response:
{
"data": [
{
"id": "...",
"type": "...",
"name": "...",
"options": ["...", ...]
},
...
],
"meta": {
"current_page": ...,
"from": ...,
"to": ...,
"total": ...,
"per_page": ...,
"last_page": ...
},
"links": {
"first": "...",
"last": "...",
"next": "...",
"prev": "..."
}
}
HTTP Request
GET https://api-v2.sendbee.io/contacts/fields
URI Parameters
Parameter | Default | Required | Description |
---|---|---|---|
search_query | Filter contact fields by string. The query will search for name. | ||
page | 1 | Page number for pagination. | |
limit | 10 | Number of items per page. Maximum is 100. |
Create contact field
curl -X POST -G "https://api-v2.sendbee.io/contacts/fields" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json" \
-d '{"name": "...", "type": "text|number|list|date|boolean"}'
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
contact_field = api.create_contact_field(
name='...', type='text|number|list|date|boolean'
)
contact_field.id
contact_field.name
contact_field.type
if contact_field.type == 'list':
contact_field.options
<?php
$sendbeeApi = new \Sendbee\Api\Client($public_key, $secret);
$data = [
// name, MANDATORY
'name' => 'field name',
// type, one of ['text', 'number', 'list', 'date', 'boolean'], MANDATORY
'type' => 'text',
// List of options. Send it only if the field type is a list.
// values are strings
'options' => []
];
try {
$response = $sendbeeApi->createContactField($data);
} catch (\Sendbee\Api\Support\DataException $ex) {
// handle missing data
// this happens when required data was not provided
echo "Missing required data. ", $ex->getMessage();
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
/**
* @var $contactField \Sendbee\Api\Models\ContactField
*/
$contactField = $response->getData();
// contact field is now created
// $contactField contains the newly created contact field data
print_r($contactField);
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
// handle error
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Create contact field response:
{
"data": {
"id": "...",
"type": "...",
"name": "...",
"options": ["...", ...]
}
}
When you subscribe or update a contact, use contact field name to link a field value to a contact.
If a contact field type is a list, then you need to send the options
parameter.
Options parameter is a list of option names: ['option1', 'option2', ...]
HTTP Request
POST https://api-v2.sendbee.io/contacts/fields
Data Parameters
Parameter | Default | Required | Description |
---|---|---|---|
name | yes | Field name. | |
type | yes | Field type. Can be string, number, list, date or boolean. | |
options | List of options. Send it only if the field type is a list. |
Update contact field
When you subscribe or update a contact, use contact field name to link a field value to a contact.
If a contact field type is a list, then you need to send the options
parameter.
Options parameter is a list of option names: ['option1', 'option2', ...]
curl -X PUT -G "https://api-v2.sendbee.io/contacts/fields" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json" \
-d '{"id": "..."}'
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
contact_field = api.update_contact_field(
id='...', [name='...'], [type='text|number|list|date|boolean']
)
contact_field.id
contact_field.name
contact_field.type
if contact_field.type == 'list':
contact_field.options
<?php
$sendbeeApi = new \Sendbee\Api\Client($public_key, $secret);
$data = [
// id, MANDATORY
'id' => '...',
// name, MANDATORY
'name' => 'field name update',
// type, one of ['text', 'number', 'list', 'date', 'boolean'], MANDATORY
'type' => 'text',
// List of options. Send it only if the field type is a list.
// values are strings
'options' => []
];
try {
$response = $sendbeeApi->updateContactField($data);
} catch (\Sendbee\Api\Support\DataException $ex) {
// handle missing data
// this happens when required data was not provided
echo "Missing required data. ", $ex->getMessage();
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
/**
* @var $contactField \Sendbee\Api\Models\ContactField
*/
$contactField = $response->getData();
// contact field is now updated
// $contactField contains the updated contact field data
print_r($contactField);
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
// handle error
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Update contact field response:
{
"data": {
"id": "...",
"type": "...",
"name": "..."
}
}
HTTP Request
PUT https://api-v2.sendbee.io/contacts/fields
Data Parameters
Parameter | Default | Required | Description |
---|---|---|---|
id | yes | Contact field id. | |
name | Field name. | ||
type | Field type. Can be text, number, list, date, boolean. | ||
options | List of options. Send it only if the field type is a list. |
Delete contact field
curl -X DELETE -G "https://api-v2.sendbee.io/contacts/fields?id=..." \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json"
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
response = api.delete_contact_field(id='...')
response.message
<?php
$sendbeeApi = new \Sendbee\Api\Client($public_key, $secret);
$data = [
// id, MANDATORY
'id' => '...',
];
try {
$response = $sendbeeApi->deleteContactField($data);
} catch (\Sendbee\Api\Support\DataException $ex) {
// handle missing data
// this happens when required data was not provided
echo "Missing required data. ", $ex->getMessage();
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
/**
* @var $message \Sendbee\Api\Models\ServerMessage
*/
$message = $response->getData();
// record is now deleted
// $message contains server info message
print_r($message);
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
// handle error
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Delete contact field response:
{
"data": {
"message": "Contact field deleted"
}
}
HTTP Request
DELETE https://api-v2.sendbee.io/contacts/fields
URI Parameters
Parameter | Default | Required | Description |
---|---|---|---|
id | yes | Contact field id |
Conversations
A conversation is a unique thread of messages that can include Notifications (Message Templates) and Customer Care messages. The Sendbee API gives you the ability to fetch conversations, conversation messages, message templates and send message templates or customer care messages.
Fetch conversation list
curl -X GET -G "https://api-v2.sendbee.io/conversations" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json"
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
conversations = api.conversations(
[folder='open|done|spam'], [search_query='...'],
[date_from=__timestamp__], [date_to=__timestamp__],
[limit=...], [page=...]
)
for conversation in conversations:
conversation.id
conversation.folder
conversation.chatbot_active
conversation.platform
conversation.created_at
conversation.contact.id
conversation.contact.name
conversation.contact.phone
conversation.last_message.direction
conversation.last_message.status
conversation.last_message.inbound_sent_at
conversation.last_message.outbound_sent_at
<?php
// optional parameters
$params = [
// Filter conversations by folder. Specify open, done or spam
'folder' => '',
// Any kind of string that will be used to perform filtering
'search_query' => '',
// Page number for pagination
'page' => 1
];
try {
$response = $sendbeeApi->getConversations($params);
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
// everything is OK
$data = $response->getData();
foreach ($data as $conversation) {
/**
* @var $conversation \Sendbee\Api\Models\Conversation
*/
echo "\n ID: ", $conversation->id;
echo "\n folder: ", $conversation->folder;
echo "\n chatbot_active: ", $conversation->chatbot_active;
echo "\n platform: ", $conversation->platform;
echo "\n created_at: ", $conversation->created_at;
echo "\n contact -> id: ", $conversation->contact->id;
echo "\n contact -> name: ", $conversation->contact->name;
echo "\n contact -> phone: ", $conversation->contact->phone;
echo "\n last_message -> direction: ", $conversation->last_message->direction;
echo "\n last_message -> status: ", $conversation->last_message->status;
echo "\n last_message -> inbound_sent_at: ", $conversation->last_message->inbound_sent_at;
echo "\n last_message -> outbound_sent_at: ", $conversation->last_message->outbound_sent_at;
}
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Fetch conversations response:
{
"data": [
{
"id": "...",
"folder": "open|done|spam",
"last_message": {
"direction": "inbound|outbound",
"status": "sent|received|delivered|read|failed",
"inbound_sent_at": "...",
"outbound_sent_at": "..."
},
"contact":{
"id": "...",
"phone": "...",
"name": "..."
},
"chatbot_active": true|false,
"platform": "whatsapp",
"created_at": "2020-01-14 21:56:49"
},
...
],
"meta": {
"current_page": ...,
"from": ...,
"to": ...,
"total": ...,
"per_page": ...,
"last_page": ...
},
"links": {
"first": "...",
"last": "...",
"next": "...",
"prev": "..."
}
}
HTTP Request
GET https://api-v2.sendbee.io/conversations
URI Parameters
Parameter | Default | Required | Description |
---|---|---|---|
folder | open, done or spam | ||
search_query | Filter conversations by string. The query will search through contact name and phone number fields. | ||
date_from | Filter conversations to the ones with the last message (inbound or outbound) AFTER this date and time. Should be UNIX timestamp. | ||
date_to | Filter conversations to the ones with the last message (inbound or outbound) BEFORE this date and time. Should be UNIX timestamp. | ||
page | 1 | Page number for pagination. | |
limit | 10 | Number of items per page. Maximum is 100. |
Fetch one conversation
curl -X GET -G "https://api-v2.sendbee.io/conversation" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json"
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
conversation = api.get_conversation(conversation_id='__conversation__id__')
conversation.id
conversation.folder
conversation.chatbot_active
conversation.platform
conversation.created_at
conversation.contact.id
conversation.contact.name
conversation.contact.phone
conversation.last_message.direction
conversation.last_message.status
conversation.last_message.inbound_sent_at
conversation.last_message.outbound_sent_at
<?php
// parameters
$params = [
// Conversation UUID, MANDATORY
'conversation_id' => '...'
];
try {
$response = $sendbeeApi->getConversation($params);
} catch (\Sendbee\Api\Support\DataException $ex) {
// handle missing data
// this happens when required data was not provided
echo "Missing required data. ", $ex->getMessage();
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
// everything is OK
/**
* @var $conversation \Sendbee\Api\Models\Conversation
*/
$conversation = $response->getData();
echo "\n ID: ", $conversation->id;
echo "\n folder: ", $conversation->folder;
echo "\n chatbot_active: ", $conversation->chatbot_active;
echo "\n platform: ", $conversation->platform;
echo "\n created_at: ", $conversation->created_at;
echo "\n contact -> id: ", $conversation->contact->id;
echo "\n contact -> name: ", $conversation->contact->name;
echo "\n contact -> phone: ", $conversation->contact->phone;
echo "\n last_message -> direction: ", $conversation->last_message->direction;
echo "\n last_message -> status: ", $conversation->last_message->status;
echo "\n last_message -> inbound_sent_at: ", $conversation->last_message->inbound_sent_at;
echo "\n last_message -> outbound_sent_at: ", $conversation->last_message->outbound_sent_at;
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Fetch conversation response:
[
{
"id": "...",
"folder": "open|done|spam",
"last_message": {
"direction": "inbound|outbound",
"status": "sent|received|delivered|read|failed",
"inbound_sent_at": "...",
"outbound_sent_at": "..."
},
"contact":{
"id": "...",
"phone": "...",
"name": "..."
},
"chatbot_active": true|false,
"platform": "whatsapp",
"created_at": "2020-01-14 21:56:49"
}
]
HTTP Request
GET https://api-v2.sendbee.io/conversation
URI Parameters
Parameter | Default | Required | Description |
---|---|---|---|
conversation_id | yes | conversation UUID |
Update conversation
curl -X PUT -G "https://api-v2.sendbee.io/conversation" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json" \
-d '{"conversation_id": ..., "folder": ...}'
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
conversations = api.update_conversation(
conversation_id='__conversation__id__'
folder='open|done|spam'
)
conversation.id
conversation.folder
conversation.chatbot_active
conversation.platform
conversation.created_at
conversation.contact.id
conversation.contact.name
conversation.contact.phone
conversation.last_message.direction
conversation.last_message.status
conversation.last_message.inbound_sent_at
conversation.last_message.outbound_sent_at
<?php
// parameters
$params = [
// Conversation UUID, MANDATORY
'conversation_id' => '...',
// Assigned "folder" - 'open', 'done' or 'spam'
'folder' => 'open|done|spam'
];
try {
$response = $sendbeeApi->updateConversation($params);
} catch (\Sendbee\Api\Support\DataException $ex) {
// handle missing data
// this happens when required data was not provided
echo "Missing required data. ", $ex->getMessage();
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
// everything is OK
$data = $response->getData();
foreach ($data as $message) {
/**
* @var $message \Sendbee\Api\Models\Message
*/
echo "\n body: ", $message->body;
echo "\n media_type: ", $message->media_type;
echo "\n media_url: ", $message->media_url;
echo "\n status: ", $message->status;
echo "\n direction: ", $message->direction;
echo "\n sent_at: ", $message->sent_at;
}
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Update conversation response:
{
"id": "...",
"folder": "open|done|spam",
"last_message": {
"direction": "inbound|outbound",
"status": "sent|received|delivered|read|failed",
"inbound_sent_at": "...",
"outbound_sent_at": "..."
},
"contact":{
"id": "...",
"phone": "...",
"name": "..."
},
"chatbot_active": true|false,
"platform": "whatsapp",
"created_at": "2020-01-14 21:56:49"
}
HTTP Request
GET https://api-v2.sendbee.io/conversation
Data Parameters
Parameter | Default | Required | Description |
---|---|---|---|
conversation_id | yes | conversation UUID | |
folder | open, done or spam |
Fetch conversation messages
curl -X GET -G "https://api-v2.sendbee.io/conversations/messages?conversation_id=..." \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json"
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
messages = api.messages(conversation_id='...')
for message in messages:
message.body
message.media_type
message.media_url
message.status
message.direction
message.sent_at
<?php
// parameters
$params = [
// Conversation UUID, MANDATORY
'conversation_id' => '...',
// Page number for pagination
'page' => 1
];
try {
$response = $sendbeeApi->getMessages($params);
} catch (\Sendbee\Api\Support\DataException $ex) {
// handle missing data
// this happens when required data was not provided
echo "Missing required data. ", $ex->getMessage();
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
// everything is OK
$data = $response->getData();
foreach ($data as $message) {
/**
* @var $message \Sendbee\Api\Models\Message
*/
echo "\n body: ", $message->body;
echo "\n media_type: ", $message->media_type;
echo "\n media_url: ", $message->media_url;
echo "\n status: ", $message->status;
echo "\n direction: ", $message->direction;
echo "\n sent_at: ", $message->sent_at;
}
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Fetch conversation messages response:
{
"data": [
{
"body": "...",
"media_type": "...",
"media_url": "...",
"status": "sent|received|delivered|read|failed",
"direction": "inbound|outbound|template_message|bot",
"sent_at": "..."
},
...
],
"meta": {
"current_page": ...,
"from": ...,
"to": ...,
"total": ...,
"per_page": ...,
"last_page": ...
},
"links": {
"first": "...",
"last": "...",
"next": "...",
"prev": "..."
}
}
HTTP Request
GET https://api-v2.sendbee.io/conversations/messages
URI Parameters
Parameter | Default | Required | Description |
---|---|---|---|
conversation_id | yes | Conversation UUID | |
page | 1 | Page number for pagination. |
Message Type
Type | Description |
---|---|
text | Text in message |
file | Document in message (PDF, DOC, DOCX, PPT, PPTX, XLS, XLSX) |
image | Image in message (JPG/JPEG, PNG) |
audio | Audio in message (AAC, M4A, AMR, MP3, OGG OPUS) |
video | Video in message (MP4, 3GPP) |
Message Status
Status | Description |
---|---|
sent | Message is sent but not yet delivered to contact’s device |
delivered | Message is delivered but not yet read by contact |
read | Contact read the message |
received | Contact sent the message and the message has been received to your business number |
failed | Message failed to be sent |
Message Direction
Direction | Description |
---|---|
inbound | Message is sent by contact |
outbound | Message is sent by your agent or API and is regular message |
template_message | Message is sent by your agent or API and is message template |
bot | Message is sent by your chatbot |
Send message
curl -X POST -G "https://api-v2.sendbee.io/conversations/messages/send" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json" \
-d '{"phone": "...", ...'
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
response = api.send_message(
phone='+...', [text='...'], [media_url='...'], [agent_id='...'], [live_inbox=True|False]
)
response.status
response.id
response.message_reference_id
<?php
$data = [
// phone number to send the message to, MANDATORY
'phone' => '+...',
// message text, MANDATORY
'text' => '...',
// Media URL for media message
'media_url' => '',
// Set to true to disable turning-off chatbot
'prevent_bot_off' => true|false,
// trigger real-time events after sending
'live_inbox => true|false,
// assigned agent for the conversation
'agent_id' => '...'
];
try {
$response = $sendbeeApi->sendMessage($data);
} catch (\Sendbee\Api\Support\DataException $ex) {
// handle missing data
// this happens when required data was not provided
echo "Missing required data. ", $ex->getMessage();
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
/**
* @var $messageInfo \Sendbee\Api\Models\SentMessage
*/
$messageInfo = $response->getData();
// $messageInfo contains message information
print_r($messageInfo);
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
// handle error
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Send message response:
{
"data": {
"status": "sent|queued",
// save this id, and when you get sent message status requests on
// your webhook, you'll get this same id to identify the conversation
"id": "__conversation_id__",
// save this id, and when you get sent message status requests on
// your webhook, you'll get this same id to identify message
"message_reference_id": "__message_id__"
}
}
When a message is sent using API to an existing conversation, it is viewable in the web UI, but the conversation doesn’t appear at the top.
Supported media formats
Category | Formats |
---|---|
Audio | AAC, M4A, AMR, MP3, OGG OPUS |
Video | MP4, 3GPP |
Image | JPG/JPEG, PNG |
Document | PDF, DOC, DOCX, PPT, PPTX, XLS, XLSX |
HTTP Request
POST https://api-v2.sendbee.io/conversations/messages/send
Data Parameters
Parameter | Default | Required | Description |
---|---|---|---|
phone | yes | Contact phone number. Number must be passed in the E.164 format: +/country code/area code/phone number, UK number example: +442071838750. | |
text | Text content of the message or caption if you use media_url. | ||
media_url | A publicly accessible url to the media file. The url must serve appropriate Content-Length and Content-Type headers for the file being sent. | ||
prevent_bot_off | If there is an active bot running on your Sendbee account, it will be turned off with every message sent using API. Use this parameter to prevent the bot from turning off. Set this parameter to “true”. | ||
agent_id | ID of an agent (team member) to whom the conversation will be assigned. Don’t include this parameter if you don’t want to change assigned agent. If the conversation is unassigned, it will stay unassigned if this parameters isn’t included. Learn more how to get an agent ID. | ||
live_inbox | false | If you want to display a message sent via API in your inbox in real-time, set this parameter to “true”. If the parameter is set to “false” a message will not be displayed and your existing conversation list will remain unchanged. |
Whatsapp Message Templates
Fetch message templates
curl -X GET -G "https://api-v2.sendbee.io/conversations/messages/templates" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json"
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
templates = api.message_templates(
[status="pending|approved|rejected"], [search_query='...'],
[page=...], [limit=...]
)
for template in templates:
template.id
template.text
template.tags
template.buttons # available for all Sendbee users onboarded after 11th of December 2020
template.button_tags # available for all Sendbee users onboarded after 11th of December 2020
template.keyword
template.language
template.status
template.rejected_reason
<?php
// optional parameters
$params = [
'status' => 'pending|approved|rejected', // Fetch approved or unapproved templates
'search_query' => '', // Filter by query string
'page' => 1 // Page number for pagination
];
try {
$response = $sendbeeApi->getMessageTemplates($params);
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
// everything is OK
$data = $response->getData();
foreach ($data as $messageTemplate) {
/**
* @var $messageTemplate \Sendbee\Api\Models\MessageTemplate
*/
echo "\n ID: ", $messageTemplate->id;
echo "\n status: ", $messageTemplate->status;
echo "\n attachment: ", $messageTemplate->attachment;
echo "\n keyword: ", $messageTemplate->keyword;
echo "\n text: ", $messageTemplate->text;
echo "\n language: ", $messageTemplate->language;
echo "\n rejected_reason: ", $messageTemplate->rejected_reason;
foreach ($messageTemplate->tags as $tag) {
/**
* @var $tag \Sendbee\Api\Models\MessageTemplateTag
*/
echo "\n tag -> name: ", $tag->name;
}
foreach ($messageTemplate->buttons as $button) {
/**
* @var $tag \Sendbee\Api\Models\MessageTemplateButton
*/
echo "\n button -> index: ", $tag->index;
echo "\n button -> type: ", $tag->type;
echo "\n button -> title: ", $tag->title;
echo "\n button -> value: ", $tag->value;
}
}
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Fetch message templates response:
{
"data": [
{
"id": "...",
"text": "...",
"tags": ["...", ...],
"buttons": [...], # available for all Sendbee users onboarded after 11th of December 2020,
"button_tags": [...], # available for all Sendbee users onboarded after 11th of December 2020
"keyword": "...",
"language": "...",
"attachment": null|"image"|"video"|"document",
"status": "pending|approved|rejected",
"rejected_reason": "..."
},
...
],
"meta": {
"current_page": ...,
"from": ...,
"to": ...,
"total": ...,
"per_page": ...,
"last_page": ...
},
"links": {
"first": "...",
"last": "...",
"next": "...",
"prev": "..."
}
}
Message templates must be sent to Facebook for approval.
Therefor every message template has status
field which can have 3 different values:
Status | Description |
---|---|
pending | Template is sent for approval and is waiting to be approved or rejected |
approved | Template is approved and is ready to be used |
rejected | Template is rejected and cannot be used |
If the template is rejected, rejected reason should come in rejected_reason
field.
There are a number of reasons why a template can be rejected:
Reason key | Description |
---|---|
FORMATTING | Formatting is incorrect |
COMMERCE_VIOLATION | The message template(s) contain content that violates WhatsApp’s Commerce Policy |
BUSINESS_VIOLATION | The message template(s) contain content that violates WhatsApp’s Business Policy |
PROMOTIONAL | The message template(s) are considered promotional |
ABUSIVE | The message template(s) contain potentially abusive or threatening content |
Message template can also have attachment.
That means you can send image, video or document URL together with text.
Learn more how to send attachment in Send Message Template section.
HTTP Request
GET https://api-v2.sendbee.io/conversations/messages/templates
URI Parameters
Parameter | Default | Required | Description |
---|---|---|---|
status | Filter templates by status: “pending” or “approved” or “rejected” | ||
search_query | Filter message templates by string. The query will search through keywords and template texts. | ||
page | 1 | Page number for pagination. | |
limit | 10 | Number of items per page. Maximum is 100. |
Send message template
curl -X POST -G "https://api-v2.sendbee.io/conversations/messages/templates/send" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json" \
-d '{"phone": "...", "template_keyword": "...", "language": "...", "tags": {...}}'
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
response = api.send_template_message(
phone='+...',
template_keyword='...',
language='...',
tags={'__tag_key__': '__tag_value__', ...},
[agent_id='...'],
[live_inbox=True|False]
)
response.status
response.id
response.message_reference_id
<?php
$data = [
// phone number to send the message to, MANDATORY
'phone' => '+...',
// keyword of an existing message template you are using, MANDATORY
'template_keyword' => '...',
// language code of an existing message template you are using, MANDATORY
'language' => 'en',
// tags, key-value pairs of data that is injected in placeholders, MANDATORY
// example:
// message template is 'Your order {{order}} has been dispatched. Please expect delivery by {{date}}'
// tags are ['order' => 55, 'date' => '2020-12-12']
// final message will be 'Your order 55 has been dispatched. Please expect delivery by 2020-12-12'
'tags' => [],
// Set to true to disable turning-off chatbot
'prevent_bot_off' => true,
// send attachment url for media template mesages
'attachment' => 'http...',
// trigger real-time events after sending
'live_inbox => true|false,
// assigned agent for the conversation
'agent_id' => '...'
];
try {
$response = $sendbeeApi->sendMessageTemplate($data);
} catch (\Sendbee\Api\Support\DataException $ex) {
// handle missing data
// this happens when required data was not provided
echo "Missing required data. ", $ex->getMessage();
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
/**
* @var $messageInfo \Sendbee\Api\Models\SentMessage
*/
$messageInfo = $response->getData();
// $messageInfo contains message information
print_r($messageInfo);
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
// handle error
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Send message template response:
{
"data": {
"status": "sent|queued",
// save this id, and when you get sent message status requests on
// your webhook, you'll get this same id to identify the conversation
"id": "__conversation_id__",
// save this id, and when you get sent message status requests on
// your webhook, you'll get this same id to identify message
"message_reference_id": "__message_id__"
}
}
When a message template is sent using API to a contact for the first time and
using live_inbox=false
, it will not be visible in the web UI.
But when a message template is sent using API to an existing conversation and
using live_inbox=false
,
it is viewable in the web UI, but the conversation doesn’t appear at the top.
But if you use live_inbox=true
everything is visible in real-time.
Also, you need to be aware when you are sending a WhatsApp message template, you are using someone’s phone number as a destination. If that contact isn’t already in our database, we will save it automatically, but this contact will then be saved with the phone number only and without any other details like name, tags, email, etc.
If you want to update the contact after sending the message, please use this endpoint:
https://developer.sendbee.io/#update-contact
If you want to create the contact before sending the message, please use this endpoint:
https://developer.sendbee.io/#subscribe-contact
HTTP Request
POST https://api-v2.sendbee.io/conversations/messages/templates/send
Data Parameters
Parameter | Default | Required | Description |
---|---|---|---|
phone | yes | Contact phone number. Number must be passed in the E.164 format: +/country code/area code/phone number, UK number example: +442071838750. | |
template_keyword | yes | Every pre-created and approved message template is identified with a keyword. | |
language | yes | Language keyword, example: en (for english). | |
tags | Message templates use placeholder values (tags) that can be replaced with your custom data inside the curly braces {{…}}. Example: message template: “Welcome {{1}}! How can we help you?”, tags: {“1”: “John”} | ||
prevent_bot_off | If there is an active bot running on your Sendbee account, it will be turned off with every message sent using API. Use this parameter to prevent the bot from turning off. Set this parameter to “true”. | ||
agent_id | ID of an agent (team member) to whom the conversation will be assigned. Don’t include this parameter if you don’t want to change assigned agent. If the conversation is unassigned, it will stay unassigned if this parameters isn’t included. Learn more how to get an agent ID. | ||
live_inbox | false | If you want to display a message sent via API in your inbox in real-time, set this parameter to “true”. If the parameter is set to “false” a message will not be displayed and your existing conversation list will remain unchanged. |
Send media message template
curl -X POST -G "https://api-v2.sendbee.io/conversations/messages/templates/send" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json" \
-d '{"phone": "...", "template_keyword": "...",
"language": "...", "tags": {...}, "attachment": "..."}'
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
response = api.send_template_message(
phone='+...',
template_keyword='...',
language='...',
tags={'__tag_key__': '__tag_value__', ...},
[attachment='...'],
[agent_id='...']
)
response.status
response.conversation_id
# save this id, and when you get sent message status requests on
# your webhook, you'll get this same id to identify the conversation
<?php
$data = [
// phone number to send the message to, MANDATORY
'phone' => '+...',
// keyword of an existing message template you are using, MANDATORY
'template_keyword' => '...',
// language code of an existing message template you are using, MANDATORY
'language' => 'en',
// tags, key-value pairs of data that is injected in placeholders, MANDATORY
// example:
// message template is 'Your order {{order}} has been dispatched. Please expect delivery by {{date}}'
// tags are ['order' => 55, 'date' => '2020-12-12']
// final message will be 'Your order 55 has been dispatched. Please expect delivery by 2020-12-12'
'tags' => [],
// Set to true to disable turning-off chatbot
'prevent_bot_off' => true,
// send attachment url for media template mesages
'attachment' => 'http...'
];
try {
$response = $sendbeeApi->sendMessageTemplate($data);
} catch (\Sendbee\Api\Support\DataException $ex) {
// handle missing data
// this happens when required data was not provided
echo "Missing required data. ", $ex->getMessage();
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
/**
* @var $messageInfo \Sendbee\Api\Models\SentMessage
*/
$messageInfo = $response->getData();
// $messageInfo contains message information
print_r($messageInfo);
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
// handle error
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Send message template response:
{
"data": {
"status": "sent|queued",
"conversation_id": "..."
// save this id, and when you get sent message status requests on
// your webhook, you'll get this same id to identify the conversation
}
}
Media message template can have attachment.
That means you can send image, video or document URL together with text.
When you get a list of message templates, every template in that list has attachment
field with it’s value.
Attachment field value defines which type of attachment can be sent with message template:
Value | Description |
---|---|
image | Message template can be sent with image URL: JPG/JPEG, PNG |
video | Message template can be sent with video URL: MP4, 3GPP |
document | Message template can be sent with document URL: PDF, DOC, DOCX, PPT, PPTX, XLS, XLSX |
null | Message template does not support attachment URL |
HTTP Request
POST https://api-v2.sendbee.io/conversations/messages/templates/send
Data Parameters
Parameter | Default | Required | Description |
---|---|---|---|
phone | yes | Contact phone number. Number must be passed in the E.164 format: +/country code/area code/phone number, UK number example: +442071838750. | |
template_keyword | yes | Every pre-created and approved message template is identified with a keyword. | |
language | yes | Language keyword, example: en (for english). | |
tags | Message templates use placeholder values (tags) that can be replaced with your custom data inside the curly braces {{…}}. Example: message template: “Welcome {{1}}! How can we help you?”, tags: {“1”: “John”} | ||
prevent_bot_off | If there is an active bot running on your Sendbee account, it will be turned off with every message sent using API. Use this parameter to prevent the bot from turning off. Set this parameter to “true”. | ||
agent_id | ID of an agent (team member) to whom the conversation will be assigned. Don’t include this parameter if you don’t want to change assigned agent. If the conversation is unassigned, it will stay unassigned if this parameters isn’t included. Learn more how to get an agent ID. | ||
attachment | Message template supports attachment. Value of this field should be URL of uploaded image, video or document. Sendbee API does not support attachment upload or hosting, you should upload it your self and provide an URL here. |
Send interactive message template
curl -X POST -G "https://api-v2.sendbee.io/conversations/messages/templates/send" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json" \
-d '{"phone": "...", "template_keyword": "...",
"language": "...", "tags": {...}, "button_tags": {...}}'
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
response = api.send_template_message(
phone='+...',
template_keyword='...',
language='...',
tags={'__tag_name__': '__tag_value__', ...},
button_tags={'__tag_name__': '__tag_value__', ...},
[agent_id='...']
)
response.status
response.conversation_id
# save this id, and when you get sent message status requests on
# your webhook, you'll get this same id to identify the conversation
<?php
$data = [
// phone number to send the message to, MANDATORY
'phone' => '+...',
// keyword of an existing message template you are using, MANDATORY
'template_keyword' => '...',
// language code of an existing message template you are using, MANDATORY
'language' => 'en',
// tags, key-value pairs of data that is injected in placeholders, MANDATORY
// example:
// message template is 'Your order {{order}} has been dispatched. Please expect delivery by {{date}}'
// tags are ['order' => 55, 'date' => '2020-12-12']
// final message will be 'Your order 55 has been dispatched. Please expect delivery by 2020-12-12'
'tags' => [],
'button_tags' => [],
// Set to true to disable turning-off chatbot
'prevent_bot_off' => true,
// send attachment url for media template mesages
'attachment' => 'http...'
];
try {
$response = $sendbeeApi->sendMessageTemplate($data);
} catch (\Sendbee\Api\Support\DataException $ex) {
// handle missing data
// this happens when required data was not provided
echo "Missing required data. ", $ex->getMessage();
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
/**
* @var $messageInfo \Sendbee\Api\Models\SentMessage
*/
$messageInfo = $response->getData();
// $messageInfo contains message information
print_r($messageInfo);
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
// handle error
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Send message template response:
{
"data": {
"status": "sent|queued",
"conversation_id": "..."
// save this id, and when you get sent message status requests on
// your webhook, you'll get this same id to identify the conversation
}
}
Interactive message templates expand the content you can send recipients beyond the standard message template and media messages template types to include interactive buttons.
There are two types of predefined buttons offered:
Value | Description |
---|---|
Call-to-Action | Allows your customer to call a phone number or visit a website. |
Quick Reply | Allows your customer to return a simple text message. |
These buttons can be attached to text message templates or media message templates.
Once your interactive message templates have been created and approved,
you can use them in notification messages as well as customer service/care messages.
This is an example of message template with quick reply buttons:
When your customer clicks on a quick reply button, a response is sent.
A customer may not click a button and either reply to the interactive message or just send you a message.
This is an example of message template with call-to-action buttons:
Call-to-action button can have dynamic URL suffix: https://example.com/{{1}}
{{1}} is a placeholder which can be replaced with the last part of the URL: page/123
Finally the result is: https://example.com/page/123
Call-to-action button dynamic URL suffix works the same way as message template tag.
They are both placeholder which can be replaced with an actual content.
Use button_tags
API parameter to replace dynamic suffix in call-to-action URL button.
HTTP Request
POST https://api-v2.sendbee.io/conversations/messages/templates/send
Data Parameters
Parameter | Default | Required | Description |
---|---|---|---|
phone | yes | Contact phone number. Number must be passed in the E.164 format: +/country code/area code/phone number, UK number example: +442071838750. | |
template_keyword | yes | Every pre-created and approved message template is identified with a keyword. | |
language | yes | Language keyword, example: en (for english). | |
tags | Message templates use placeholder values (tags) that can be replaced with your custom data inside the curly braces {{…}}. Example: message template: “Welcome {{1}}! How can we help you?”, tags: {“1”: “John”} | ||
button_tags | If you’re using call to action URL buttons in message templates with dynamic suffix use placeholder values (tags) that can be replaced with your custom data inside the curly braces {{…}}. Example: call to action URL button: “https://example.com/{{1}}”, button_tags: {“1”: “page/123?param=value”} | ||
prevent_bot_off | If there is an active bot running on your Sendbee account, it will be turned off with every message sent using API. Use this parameter to prevent the bot from turning off. Set this parameter to “true”. | ||
agent_id | ID of an agent (team member) to whom the conversation will be assigned. Don’t include this parameter if you don’t want to change assigned agent. If the conversation is unassigned, it will stay unassigned if this parameters isn’t included. Learn more how to get an agent ID. |
Automation
The Sendbee API gives you the ability to manage the status settings of automated replies (chatbot). More automation features to come in the future.
Automated replies status check
curl -X GET -G "https://api-v2.sendbee.io/automation/chatbot/activity/status?conversation_id=..." \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json"
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
api.chatbot_activity_status(conversation_id='...')
<?php
$data = [
// conversation_id, MANDATORY
'conversation_id' => '...'
];
try {
$response = $sendbeeApi->getChatbotActivity($data);
} catch (\Sendbee\Api\Support\DataException $ex) {
// handle missing data
// this happens when required data was not provided
echo "Missing required data. ", $ex->getMessage();
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
/**
* @var $status \Sendbee\Api\Models\ChatbotStatus
*/
$status = $response->getData();
echo "\n conversation_id: ", $status->text;
echo "\n chatbot_active: ", $status->chatbot_active ? 'ON' : 'OFF';
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
// handle error
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Chatbot status settings response:
{
"data": {
"conversation_id": "...",
"chatbot_status": true|false
}
}
Automated replies (chatbot) are messages that would be automatically triggered based on the keywords that were received in the inbound message. Automated replies can be created in the Sendbee Dashboard.
Use automated replies status check to check if the bot for the conversation is active or not. Every contact is linked to a conversation. Automated replies would automatically turn OFF if a message was sent to a contact by an agent via the Sendbee Dashboard or via the API unless prevent_bot_off parameter is used.
You can turn the chatbot on or off for a certain conversation.
HTTP Request
GET https://api-v2.sendbee.io/automation/chatbot/activity/status
URI Parameters
Parameter | Default | Required | Description |
---|---|---|---|
conversation_id | yes | Conversation UUID |
Automated replies status settings
curl -X PUT -G "https://api-v2.sendbee.io/automation/chatbot/activity" \
-H "X-Auth-Token: ..." \
-H "X-Api-Key: ..." \
-H "Accept: application/json" \
-H "Content-Type": "application/json" \
-d '{"conversation_id": "...", "active": true|false}'
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
response = api.chatbot_activity(conversation_id='...', active=True|False)
response.conversation_id
response.chatbot_active # True/False
<?php
$sendbeeApi = new \Sendbee\Api\Client($public_key, $secret);
$data = [
// conversation_id, MANDATORY
'conversation_id' => '...',
// boolean value, true to enable chatbot, false to disable, MANDATORY
'active' => true | false
];
try {
$response = $sendbeeApi->chatbotActivity($data);
} catch (\Sendbee\Api\Support\DataException $ex) {
// handle missing data
// this happens when required data was not provided
echo "Missing required data. ", $ex->getMessage();
} catch (\Exception $ex) {
// handle exception thrown by GuzzleHttp
// this is most likely due to a network issue
echo "Could not contact backend endpoint. ", $ex->getMessage();
}
if ($response->isSuccess()) {
/**
* @var $tag \Sendbee\Api\Models\ServerMessage
*/
$message = $response->getData();
// chatbot activity is now set
// $message contains server info message
print_r($message);
} else {
/**
* @var $error \Sendbee\Api\Transport\ResponseError
*/
$error = $response->getError();
if ($error) {
// handle error
echo "\n error type: ", $error->type;
echo "\n error details: ", $error->detail;
}
}
?>
Chatbot status settings response:
{
"data": {
"message": "Chatbot turned on/off"
}
}
Automated replies (chatbot) are messages that would be automatically triggered based on the keywords that were received in the inbound message. Automated replies can be created in the Sendbee Dashboard.
Use automated replies status settings to turn automated replies ON or OFF for a certain conversation. Every contact is linked to a conversation. Automated replies would automatically turn OFF if a message was sent to a contact by an agent via the Sendbee Dashboard or via the API unless prevent_bot_off parameter is used.
You can turn the chatbot on or off for a certain conversation.
HTTP Request
PUT https://api-v2.sendbee.io/automation/chatbot/activity
Data Parameters
Parameter | Default | Required | Description |
---|---|---|---|
conversation_id | yes | Conversation UUID | |
active | yes | True of False |
Webhooks
Webhook request headers section:
{
"X-Auth-Token": "...",
"Accept": "application/json",
"Content-Type": "application/json"
}
A webhook allows you to be automatically notified when something happens in Sendbee without having to constantly poll the API. Webhooks can be activated in the Sendbee Dashboard.
Supported webhooks:
Keyword | Category | Description |
---|---|---|
contact.created | Contacts | New contact has been created |
contact.subscription_created | Contacts | New contact has been subscribed |
contact.subscription_updated | Contacts | Contact subscription has been updated |
contact.subscription_unsubscribed | Contacts | Contact unsubscribed from receiving messages |
message.received | Messages | Message has been received from WhatsApp contact |
message.sent | Messages | Message has been sent by agent or API |
message.sent_status | Messages | Message has been updated with a new status (delivered or read) |
whatsapp.message.template.sent_status | WhatsApp template message has been updated with a new status (delivered or read) | |
whatsapp.message.session.sent_status | WhatsApp session message has been updated with a new status (delivered or read) | |
whatsapp.message.template.approval_status | WhatsApp message template approval status has been updated (delivered or read) |
Every request to a webhook URL consists of body
and headers
elements.
Webhook authentication
from sendbee_api import SendbeeApi
api = SendbeeApi(
'__your_api_key_here__', '__your_secret_key_here__'
)
token = '...' # taken from the request header
if not api.auth.check_auth_token(token):
# error! authentication failed!
<?php
// Your API secret
$API_SECRET = '...';
// Received token
$token_from_request_header = '...';
// preferred method: using PHP API
$requestIsValid = \Sendbee\Api\Client::verifyToken($API_SECRET, $token_from_request_header);
// manual method (if you don't want to use the PHP API library)
function verifySendbeeToken($apiSecret, $token, $expirationSeconds = 0)
{
// sanity check - token should be a non-empty string
if(!is_string($token) || !$token)
{
return false;
}
// step 1: decode token using base64 encoding
$decoded = base64_decode($token);
// step 2: split encoded string by dot (.) to get timestamp (left part)
// separated from encrypted string (right part)
$parts = explode('.', $decoded);
// sanity check - there should be 2 values
if(count($parts) != 2)
{
return false;
}
$receivedTimestamp = $parts[0];
$receivedHash = $parts[1];
if($expirationSeconds < 1)
{
// set how old can the token be to 15 minutes
// (or whatever period you think is acceptable for you)
$expirationSeconds = 60 * 15;
}
// step 3: check if the timestamp is not older then specified $expirationSeconds
if($receivedTimestamp < (time() - $expirationSeconds))
{
return false;
}
// step 4: encrypt timestamp with your API secret using hmac sha256 and get a hash
$hash = hash_hmac('sha256', $receivedTimestamp, $apiSecret, false);
// step 5: compare the hash we received with the one we generated in step 2
// they need to be equal
return ($hash == $receivedHash);
}
$requestIsValid = verifySendbeeToken($API_SECRET, $token_from_request_header);
?>
It is highly recommended to authorize every request that Sendbee
sends to a webhook, just to be sure that the request indeed is
coming from Sendbee on behalf of your account.
To authorize a request coming from Sendbee, use X-Auth-Token
token in headers of the request.
To check if the token is valid, please follow these steps:
1. decode token using base64 encoding
2. split encoded string by dot (.) to get timestamp (left part) separated from encrypted string (right part)
3. check if the timestamp is not older then 15 minutes (or whatever period you think is acceptable for you)
5. encrypt timestamp from split string (step 2) with your API secret using hmac sha256
6. compare this encrypted timestamp with encrypted part (step 2), they need to be equal
contact.created
Request body for
contact.created
{
"business": {
"id": "...",
"name": "...",
},
"contact": {
"created_at": 123456789,
"id": "...",
"name": "...",
"phone": "...",
},
"type": "contact.created",
}
Every time a contact is created Sendbee sends a request to your webhook URL.
Contact can be created in various ways:
- Contact sends you a message
- Contact subscribes for receiving messages via the custom opt-in source
- You subscribe a contact via Sendbee API
contact.subscription_created
Request body for
contact.subscription_created
{
"business": {
"id": "...",
"name": "...",
},
"contact": {
"created_at": 123456789,
"id": "...",
"name": "...",
"phone": "...",
},
"subscribed_at": 123456789,
"subscribed_via": "API",
"subscription_updated_at": 123456789,
"type": "contact.subscription_created",
}
Every time a contact subscribes Sendbee sends a request to your webhook URL.
Contact can be subscribed in various ways:
- Contact subscribes for receiving messages via the custom opt-in source
- You subscribe a contact via Sendbee API
contact.subscription_updated
Request body for
contact.subscription_updated
{
"business": {
"id": "...",
"name": "...",
},
"contact": {
"created_at": 123456789,
"id": "...",
"name": "...",
"phone": "...",
},
"subscribed_at": 123456789,
"subscribed_via": "API",
"subscription_updated_at": 123456789,
"type": "contact.subscription_updated",
}
Every time a contact re-subscribes Sendbee sends a request to your webhook URL.
Contact can be re-subscribed in various ways:
- Existing contact subscribes for receiving messages via the custom opt-in source
- You subscribe an existing contact via Sendbee API
contact.unsubscribed
Request body for
contact.unsubscribed
{
"business": {
"id": "...",
"name": "...",
},
"contact": {
"created_at": 123456789,
"id": "...",
"name": "...",
"phone": "...",
},
"type": "contact.unsubscribed",
}
Every time a contact unsubscribes from receiving notifications by sending a STOP keyword to your business, Sendbee will send a request to your webhook URL.
message.received
Request body for
message.received
(text message)
{
"business": {
"id": "...",
"name": "...",
},
"contact": {
"created_at": 123456789,
"id": "...",
"name": "...",
"phone": "...",
},
"channel": "whatsapp",
"content": {
"text": "...",
},
"content_type": "text",
"conversation_id": "...",
"destination": "...", // your business phone number
"direction": "inbound",
"error": null,
"sent_at": 123456789,
"source": "...", // contact phone number
"type": "message.received",
}
Request body for
message.received
(media message)
{
"business": {
"id": "...",
"name": "...",
},
"contact": {
"created_at": 123456789,
"id": "...",
"name": "...",
"phone": "...",
},
"channel": "whatsapp",
"content": {
"media": {
"caption": '',
"type": "image|video|document",
"url": "...",
},
},
"content_type": "media",
"conversation_id": "...",
"destination": "...", // your business phone number
"direction": "inbound",
"error": null,
"sent_at": 123456789,
"source": "...", // contact phone number
"type": "message.received",
}
Every time a contact sends a message to your business, Sendbee will send a message to your webhook URL.
message.sent
Request body for
message.sent
(text message)
{
"business": {
"id": "...",
"name": "...",
},
"contact": {
"created_at": 123456789,
"id": "...",
"name": "...",
"phone": "...",
},
"channel": "whatsapp",
"content": {
"text": "...",
},
"content_type": "text",
"conversation_id": "...",
"destination": "...", // contact phone number
"direction": "inbound",
"error": null,
"sent_at": 123456789,
"source": "...", // your business phone number
"type": "message.sent",
}
Request body for
message.sent
(media message)
{
"business": {
"id": "...",
"name": "...",
},
"contact": {
"created_at": 123456789,
"id": "...",
"name": "...",
"phone": "...",
},
"channel": "whatsapp",
"content": {
"media": {
"caption": '',
"type": "image|video|document",
"url": "...",
},
},
"content_type": "media",
"conversation_id": "...",
"destination": "...", // contact phone number
"direction": "inbound",
"error": null,
"sent_at": 123456789,
"source": "...", // your business phone number
"type": "message.sent",
}
Every time your agent sends a message to contact, or a message has been sent using API, Sendbee will send a message to your webhook URL.
message.sent_status
Request body for
message.sent_status
{
"business": {
"id": "...",
"name": "...",
},
"contact": {
"created_at": 123456789,
"id": "...",
"name": "...",
"phone": "...",
},
"channel": "whatsapp",
"content": {...},
"content_type": "...",
"conversation_id": "...",
"message_id": "...",
"destination": "...", // contact phone number
"direction": "outbound",
"error": null,
"sent_at": "2020-01-01 12:00:00",
"source": "...", // your business phone number
"status": "sent|delivered|read",
"type": "message.sent_status",
}
Every time your business sends a message to a contact, Sendbee will send a message to your webhook URL indicating the status of the sent message.
whatsapp.message.template.sent_status
Request body for
whatsapp.message.template.sent_status
{
"business": {
"id": "...",
"name": "...",
},
"contact": {
"created_at": 123456789,
"id": "...",
"name": "...",
"phone": "...",
},
"channel": "whatsapp",
"content": {...},
"content_type": "...",
"conversation_id": "...",
"message_id": "...",
"destination": "...", // contact phone number
"direction": "outbound",
"error": null,
"sent_at": "2020-01-01 12:00:00",
"source": "...", // your business phone number
"status": "sent|delivered|read",
"type": "whatsapp.message.template.sent_status",
}
Every time your business sends a WhatsApp template message to a contact, Sendbee will send a message to your webhook URL indicating the status of the sent message.
whatsapp.message.session.sent_status
Request body for
whatsapp.message.session.sent_status
{
"business": {
"id": "...",
"name": "...",
},
"contact": {
"created_at": 123456789,
"id": "...",
"name": "...",
"phone": "...",
},
"channel": "whatsapp",
"content": {...},
"content_type": "...",
"conversation_id": "...",
"message_id": "...",
"destination": "...", // contact phone number
"direction": "outbound",
"error": null,
"sent_at": "2020-01-01 12:00:00",
"source": "...", // your business phone number
"status": "sent|delivered|read",
"type": "whatsapp.message.session.sent_status",
}
Every time your business sends a WhatsApp session message to a contact, Sendbee will send a message to your webhook URL indicating the status of the sent message.
whatsapp.message.template.approval_status
Request body for
whatsapp.message.template.approval_status
{
"template_id": "...",
"keyword": "...",
"status": "approved|rejected",
"type": "whatsapp.message.template.approval_status",
}
Every time your pending WhatsApp message template changes its approval state into approved or rejected, Sendbee will send a message to your webhook URL indicating the new state of your template.