Send Typing Indicator
curl --request POST \
--url https://api.flowiq.live/send-whatsapp \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"phone_number": "+27123456789",
"message_type": "typing",
"typing": {
"message_id": "<string>"
}
}
'import requests
url = "https://api.flowiq.live/send-whatsapp"
payload = {
"phone_number": "+27123456789",
"message_type": "typing",
"typing": { "message_id": "<string>" }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
phone_number: '+27123456789',
message_type: 'typing',
typing: {message_id: '<string>'}
})
};
fetch('https://api.flowiq.live/send-whatsapp', 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://api.flowiq.live/send-whatsapp",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'phone_number' => '+27123456789',
'message_type' => 'typing',
'typing' => [
'message_id' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.flowiq.live/send-whatsapp"
payload := strings.NewReader("{\n \"phone_number\": \"+27123456789\",\n \"message_type\": \"typing\",\n \"typing\": {\n \"message_id\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.flowiq.live/send-whatsapp")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"phone_number\": \"+27123456789\",\n \"message_type\": \"typing\",\n \"typing\": {\n \"message_id\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.flowiq.live/send-whatsapp")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"phone_number\": \"+27123456789\",\n \"message_type\": \"typing\",\n \"typing\": {\n \"message_id\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"message": "Typing indicator shown to 27123456789 for up to 25 seconds or until you reply",
"data": {
"message_type": "typing",
"contact_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"whatsapp_id": "27123456789",
"message_id": "wamid.HBgLMjc4MTIzNDU2NzgVAgASGBQzRUI...",
"message_id_source": "request",
"marked_read": true,
"expires_in_seconds": 25
}
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>",
"meta_error_code": 123
}Send Messages
Send Typing Indicator
Show “typing…” in the customer’s WhatsApp chat while you prepare a reply. WhatsApp attaches it to one message the customer sent: that message is marked read, and the indicator shows until you reply or about 25 seconds pass. Nothing is stored as a message. Needs the send permission.
POST
/
send-whatsapp
Send Typing Indicator
curl --request POST \
--url https://api.flowiq.live/send-whatsapp \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"phone_number": "+27123456789",
"message_type": "typing",
"typing": {
"message_id": "<string>"
}
}
'import requests
url = "https://api.flowiq.live/send-whatsapp"
payload = {
"phone_number": "+27123456789",
"message_type": "typing",
"typing": { "message_id": "<string>" }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
phone_number: '+27123456789',
message_type: 'typing',
typing: {message_id: '<string>'}
})
};
fetch('https://api.flowiq.live/send-whatsapp', 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://api.flowiq.live/send-whatsapp",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'phone_number' => '+27123456789',
'message_type' => 'typing',
'typing' => [
'message_id' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.flowiq.live/send-whatsapp"
payload := strings.NewReader("{\n \"phone_number\": \"+27123456789\",\n \"message_type\": \"typing\",\n \"typing\": {\n \"message_id\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.flowiq.live/send-whatsapp")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"phone_number\": \"+27123456789\",\n \"message_type\": \"typing\",\n \"typing\": {\n \"message_id\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.flowiq.live/send-whatsapp")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"phone_number\": \"+27123456789\",\n \"message_type\": \"typing\",\n \"typing\": {\n \"message_id\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"message": "Typing indicator shown to 27123456789 for up to 25 seconds or until you reply",
"data": {
"message_type": "typing",
"contact_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"whatsapp_id": "27123456789",
"message_id": "wamid.HBgLMjc4MTIzNDU2NzgVAgASGBQzRUI...",
"message_id_source": "request",
"marked_read": true,
"expires_in_seconds": 25
}
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>",
"meta_error_code": 123
}Show “typing…” in the customer’s WhatsApp chat while your code prepares a reply, for example while it looks up an order or waits on an AI model.
WhatsApp attaches the indicator to one message the customer sent: that message is marked as read (blue ticks), and “typing…” shows until you send your reply or about 25 seconds pass, whichever comes first. Nothing is stored in the chat.
Without a
The API key needs the
Basic Usage
curl -X POST "https://api.flowiq.live/send-whatsapp" \
-H "Authorization: Bearer fiq_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+27123456789",
"message_type": "typing"
}'
message_id, FlowIQ uses the customer’s latest WhatsApp message. To answer a specific message, pass its id (the whatsapp_message_id of the message_received webhook):
{
"phone_number": "+27123456789",
"message_type": "typing",
"typing": {
"message_id": "wamid.HBgLMjc4MTIzNDU2NzgVAgASGBQzRUI..."
}
}
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
phone_number | string | Yes | The customer’s WhatsApp number with country code. The contact must exist in FlowIQ |
message_type | string | Yes | Must be "typing" |
typing.message_id | string | No | A message the customer sent (wamid.…). Default: their latest message |
send permission.
Response
Success (200)
{
"success": true,
"message": "Typing indicator shown to 27123456789 for up to 25 seconds or until you reply",
"data": {
"message_type": "typing",
"contact_id": "4f1c2a3b-…",
"whatsapp_id": "27123456789",
"message_id": "wamid.HBgLMjc4MTIzNDU2NzgVAgASGBQzRUI...",
"message_id_source": "latest_inbound",
"marked_read": true,
"expires_in_seconds": 25
}
}
Errors
| Status | When |
|---|---|
400 | typing.message_id is not a WhatsApp message id |
403 | The API key has no send permission |
404 | No contact with that number |
409 | The customer has never sent you a WhatsApp message, so there is nothing to answer |
502 | WhatsApp refused it (for example a message id it does not know); message and meta_error_code carry its reason |
Integration Example
Show the indicator as soon as a message arrives, then send the reply when it is ready:async function replyWithTyping(apiKey, phoneNumber, incomingMessageId, buildReply) {
const headers = { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" };
await fetch("https://api.flowiq.live/send-whatsapp", {
method: "POST",
headers,
body: JSON.stringify({
phone_number: phoneNumber,
message_type: "typing",
typing: { message_id: incomingMessageId },
}),
});
const text = await buildReply(); // keep it under ~25 seconds, or send typing again
const response = await fetch("https://api.flowiq.live/send-whatsapp", {
method: "POST",
headers,
body: JSON.stringify({ phone_number: phoneNumber, message_type: "text", text }),
});
const data = await response.json();
if (!response.ok) throw new Error(data.message);
return data;
}
The indicator also marks the customer’s message as read. Only send it when you are about to reply.
Authorizations
Your FlowIQ API key (from Settings → Profile → API Keys), sent as a bearer token. Format: Bearer fiq_YOUR_API_KEY
Body
application/json

