List message templates
Returns the templates you can send, from Kai’s mirror of the channel’s library. A template is sendable when Meta approved it and all of its variables are plain text. A template with an image header or with a variable link in a button is not sendable.
Titles. A template can have a title above the message, and the
title can have its own variables. Kai fills them. WhatsApp numbers
and names the variables of the title and of the message separately,
so {{1}} in the title and {{1}} in the message are two values.
To keep them apart, each variable has an address: a message variable
keeps its plain name, and a title variable gets header. in front of
it. The variables field lists these addresses in the order that a
send fills them, the title first.
Omit channel_id when the workspace has one WhatsApp channel. Send
status=all to also see pending and rejected templates.
Hints. Each variable carries a binding and a value. Send
agent and one of contact_id or phone to fill the values, then
prefill your own form with them. A value of null means that Kai
cannot fill this variable. Ask the person for it.
The hints are advice. POST /conversations/outbound still needs
every value, because your form is what the person reads before the
message goes out. Your user can also change a filled value.
curl --request GET \
--url https://kaisupport.com/api/v1/templates \
--header 'Authorization: Bearer <token>'import requests
url = "https://kaisupport.com/api/v1/templates"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://kaisupport.com/api/v1/templates', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://kaisupport.com/api/v1/templates",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://kaisupport.com/api/v1/templates"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://kaisupport.com/api/v1/templates")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://kaisupport.com/api/v1/templates")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"channel_id": "7c1f4a80-2b6e-4f5d-9a3c-8e2d1b0c9f44",
"agent": {
"member_id": "2c9a0d51-6f4b-4b0d-8f2a-1d3c5e7a9b11",
"name": "Baran Demir",
"email": "baran@example.com"
},
"contact": {
"contact_id": "4f1d6f2a-6a1e-4a0b-9c53-2a9a1f0c77d1",
"name": "Gülsüm Bodur"
},
"data": [
{
"name": "consultation_request_cant_be_reached_reschedule_tr",
"language": "tr",
"category": "UTILITY",
"status": "approved",
"header": "Derece Kampüsü · {{konu}}",
"body": "Selamlar {{customer_name}} ben Derece Kampüsü’nden {{consultant_name}}, ön görüşme talep etmişsin ancak sana ulaşamadım.",
"variables": [
"header.konu",
"customer_name",
"consultant_name"
],
"variable_hints": [
{
"address": "header.konu",
"key": "konu",
"part": "header",
"binding": "free",
"value": null,
"source": null
},
{
"address": "customer_name",
"key": "customer_name",
"part": "body",
"binding": "customer_name",
"value": "Gülsüm Bodur",
"source": "contact"
},
{
"address": "consultant_name",
"key": "consultant_name",
"part": "body",
"binding": "agent_name",
"value": "Baran Demir",
"source": "member"
}
],
"sendable": true
}
]
}{
"error": {
"type": "invalid_request",
"message": "Send at least one of \"external_id\", \"email\", \"phone\" or \"identities\" so the contact can be matched."
}
}{
"error": {
"type": "unauthorized",
"message": "That API key is not valid."
}
}{
"error": {
"type": "forbidden",
"message": "This key does not have the \"contacts:write\" permission."
}
}{
"error": {
"type": "not_found",
"message": "No such contact."
}
}Authorizations
Send your API key as Authorization: Bearer kai_live_....
Make, edit and revoke keys in Kai, under Settings → API. Kai stores only a hash of the key, so the full key is shown one time. You can change the name and the permissions of a key later without a new key.
Query Parameters
A WhatsApp channel id from GET /channels.
Send all to include templates that are not sendable.
all The email address or the member id of the teammate who sends the
message. It fills the agent_name bindings. An address that no
member holds returns agent: null and empty hints.
A contact id. It fills the customer_name bindings.
A phone number, as an alternative to contact_id. Kai finds the
contact of this number.
The name that your own system holds for this customer. It wins
over the name in Kai, and it fills a customer_first_name
binding for a customer that Kai does not know yet.
curl --request GET \
--url https://kaisupport.com/api/v1/templates \
--header 'Authorization: Bearer <token>'import requests
url = "https://kaisupport.com/api/v1/templates"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://kaisupport.com/api/v1/templates', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://kaisupport.com/api/v1/templates",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://kaisupport.com/api/v1/templates"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://kaisupport.com/api/v1/templates")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://kaisupport.com/api/v1/templates")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"channel_id": "7c1f4a80-2b6e-4f5d-9a3c-8e2d1b0c9f44",
"agent": {
"member_id": "2c9a0d51-6f4b-4b0d-8f2a-1d3c5e7a9b11",
"name": "Baran Demir",
"email": "baran@example.com"
},
"contact": {
"contact_id": "4f1d6f2a-6a1e-4a0b-9c53-2a9a1f0c77d1",
"name": "Gülsüm Bodur"
},
"data": [
{
"name": "consultation_request_cant_be_reached_reschedule_tr",
"language": "tr",
"category": "UTILITY",
"status": "approved",
"header": "Derece Kampüsü · {{konu}}",
"body": "Selamlar {{customer_name}} ben Derece Kampüsü’nden {{consultant_name}}, ön görüşme talep etmişsin ancak sana ulaşamadım.",
"variables": [
"header.konu",
"customer_name",
"consultant_name"
],
"variable_hints": [
{
"address": "header.konu",
"key": "konu",
"part": "header",
"binding": "free",
"value": null,
"source": null
},
{
"address": "customer_name",
"key": "customer_name",
"part": "body",
"binding": "customer_name",
"value": "Gülsüm Bodur",
"source": "contact"
},
{
"address": "consultant_name",
"key": "consultant_name",
"part": "body",
"binding": "agent_name",
"value": "Baran Demir",
"source": "member"
}
],
"sendable": true
}
]
}{
"error": {
"type": "invalid_request",
"message": "Send at least one of \"external_id\", \"email\", \"phone\" or \"identities\" so the contact can be matched."
}
}{
"error": {
"type": "unauthorized",
"message": "That API key is not valid."
}
}{
"error": {
"type": "forbidden",
"message": "This key does not have the \"contacts:write\" permission."
}
}{
"error": {
"type": "not_found",
"message": "No such contact."
}
}