Переезжай на Whapi · от 500 ₽/мес Наш WhatsApp API работает штатно Регистрация
Chat routing · WhatsApp API use case

Assign a qualified WhatsApp chat to one sales owner

A buyer gets one sales owner after qualification, instead of waiting on a number where nobody is responsible. When your rules finish qualification, your backend marks that chat for the chosen owner and sends the handoff through Whapi.Cloud. This use case shows integrators how to implement that flow through the WhatsApp API.

Chat id arrives on the inbound message event Your backend picks the sales owner
A WhatsApp chat on a phone after qualification, with one sales owner marked and a short handoff ready to send.
Use case

When to use this flow

Qualification is already done

Use this flow when your rules mark the direct chat qualified and it still has no owner, so you can assign that chat to one sales owner.

Each owner is a label

Use this flow when a sales person or a department is a label on the same connected number.

The buyer must be told

Use this flow when the buyer should receive the handoff in that same direct chat.

A phone screen showing a WhatsApp chat where the buyer has just received a message naming their sales owner.
Customer experience

The buyer meets a named owner

Before this flow, a qualified chat sits on the number until someone notices it, and the buyer does not know who is responsible.

The buyer receives a message that names who continues the conversation, and that chat is no longer unowned. Integrators build this result with the WhatsApp API.

Workflow

Route the chat to a sales owner

1

Qualification finishes

Your rules mark this direct chat as qualified. Webhook events tell your backend the chat is ready, without polling.

2

Match the owner to a label

GET /labels

List the labels on the connected number and keep the one that matches the sales person or department your backend chose.

3

Put the label on the chat

POST /labels/{LabelID}/{AssociationID}

Attach that label to this chat so the owner is visible on the same number.

4

Tell the buyer who continues

POST /messages/text

Send the handoff text your backend wrote for this buyer into the same chat.

Need delivery tracking? If the handoff stays pending, it was not delivered. Later changes arrive on statuses.post and statuses.put. Learn about delivery status →

Prerequisites

Before you run the flow

The connected number is the one the buyer already wrote to. The API token lets your backend read labels on that number and send the handoff from it.

Optional — go deeper for this flow

API implementation

Calls that set the owner label

These calls run only after your backend has already chosen the sales person or department. They read labels, mark this chat, and send the handoff text.

Get your API token for free after you register on whapi.cloud, and use that token in the code instead of Your_Token from the examples.

Match the owner to a label

Find the label that stands for the owner your backend selected.

curl --request GET \
     --url https://gate.whapi.cloud/labels \
     --header 'accept: application/json' \
     --header 'authorization: Bearer Your_Token'
$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://gate.whapi.cloud/labels",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_HTTPHEADER => [
    "accept: application/json",
    "authorization: Bearer Your_Token"
  ],
]);

$response = curl_exec($curl);
curl_close($curl);
echo $response;
import requests

url = "https://gate.whapi.cloud/labels"
headers = {
    "accept": "application/json",
    "authorization": "Bearer Your_Token"
}

response = requests.get(url, headers=headers)
print(response.text)
const response = await fetch('https://gate.whapi.cloud/labels', {
  method: 'GET',
  headers: {
    accept: 'application/json',
    authorization: 'Bearer Your_Token',
  },
});

console.log(await response.text());
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://gate.whapi.cloud/labels")
  .method("GET", null)
  .addHeader("accept", "application/json")
  .addHeader("authorization", "Bearer Your_Token")
  .build();

Response response = client.newCall(request).execute();
using RestSharp;

var options = new RestClientOptions("https://gate.whapi.cloud/labels");
var client = new RestClient(options);
var request = new RestRequest("");
request.AddHeader("accept", "application/json");
request.AddHeader("authorization", "Bearer Your_Token");
var response = await client.GetAsync(request);

Console.WriteLine("{0}", response.Content);
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://gate.whapi.cloud/labels", nil)
	req.Header.Set("accept", "application/json")
	req.Header.Set("authorization", "Bearer Your_Token")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(string(out))
}

Put the label on the chat

Attach that label to this chat on the same number.

curl --request POST \
     --url https://gate.whapi.cloud/labels/3/[email protected] \
     --header 'accept: application/json' \
     --header 'authorization: Bearer Your_Token'
$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://gate.whapi.cloud/labels/3/[email protected]",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_HTTPHEADER => [
    "accept: application/json",
    "authorization: Bearer Your_Token"
  ],
]);

$response = curl_exec($curl);
curl_close($curl);
echo $response;
import requests

url = "https://gate.whapi.cloud/labels/3/[email protected]"
headers = {
    "accept": "application/json",
    "authorization": "Bearer Your_Token"
}

response = requests.post(url, headers=headers)
print(response.text)
const response = await fetch('https://gate.whapi.cloud/labels/3/[email protected]', {
  method: 'POST',
  headers: {
    accept: 'application/json',
    authorization: 'Bearer Your_Token',
  },
});

console.log(await response.text());
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
  .url("https://gate.whapi.cloud/labels/3/[email protected]")
  .method("POST", null)
  .addHeader("accept", "application/json")
  .addHeader("authorization", "Bearer Your_Token")
  .build();

Response response = client.newCall(request).execute();
using RestSharp;

var options = new RestClientOptions("https://gate.whapi.cloud/labels/3/[email protected]");
var client = new RestClient(options);
var request = new RestRequest("");
request.AddHeader("accept", "application/json");
request.AddHeader("authorization", "Bearer Your_Token");
var response = await client.PostAsync(request);

Console.WriteLine("{0}", response.Content);
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("POST", "https://gate.whapi.cloud/labels/3/[email protected]", nil)
	req.Header.Set("accept", "application/json")
	req.Header.Set("authorization", "Bearer Your_Token")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(string(out))
}

Tell the buyer who continues

Send the buyer a text that names who continues the conversation.

curl --request POST \
     --url https://gate.whapi.cloud/messages/text \
     --header 'accept: application/json' \
     --header 'authorization: Bearer Your_Token' \
     --header 'content-type: application/json' \
     --data '
{
  "to": "61371989950",
  "body": "Thanks for your answers \u2014 Alex from Sales will continue this chat with you here."
}
'
$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://gate.whapi.cloud/messages/text",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "{\"to\": \"61371989950\", \"body\": \"Thanks for your answers \\u2014 Alex from Sales will continue this chat with you here.\"}",
  CURLOPT_HTTPHEADER => [
    "accept: application/json",
    "authorization: Bearer Your_Token",
    "content-type: application/json"
  ],
]);

$response = curl_exec($curl);
curl_close($curl);
echo $response;
import requests

url = "https://gate.whapi.cloud/messages/text"
payload = {
    "to": "61371989950",
    "body": "Thanks for your answers \u2014 Alex from Sales will continue this chat with you here."
}
headers = {
    "accept": "application/json",
    "authorization": "Bearer Your_Token",
    "content-type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)
print(response.text)
const response = await fetch('https://gate.whapi.cloud/messages/text', {
  method: 'POST',
  headers: {
    accept: 'application/json',
    authorization: 'Bearer Your_Token',
    'content-type': 'application/json',
  },
  body: JSON.stringify({
    "to": "61371989950",
    "body": "Thanks for your answers \u2014 Alex from Sales will continue this chat with you here."
}),
});

console.log(await response.text());
OkHttpClient client = new OkHttpClient();

MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\"to\": \"61371989950\", \"body\": \"Thanks for your answers \\u2014 Alex from Sales will continue this chat with you here.\"}");
Request request = new Request.Builder()
  .url("https://gate.whapi.cloud/messages/text")
  .post(body)
  .addHeader("accept", "application/json")
  .addHeader("authorization", "Bearer Your_Token")
  .addHeader("content-type", "application/json")
  .build();

Response response = client.newCall(request).execute();
using RestSharp;

var options = new RestClientOptions("https://gate.whapi.cloud/messages/text");
var client = new RestClient(options);
var request = new RestRequest("");
request.AddHeader("accept", "application/json");
request.AddHeader("authorization", "Bearer Your_Token");
request.AddHeader("content-type", "application/json");
request.AddJsonBody(new { to = "61371989950", body = "Thanks for your answers — Alex from Sales will continue this chat with you here." });
var response = await client.PostAsync(request);

Console.WriteLine("{0}", response.Content);
package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
)

func main() {
	body := []byte(`{"to": "61371989950", "body": "Thanks for your answers \u2014 Alex from Sales will continue this chat with you here."}`)
	req, _ := http.NewRequest("POST", "https://gate.whapi.cloud/messages/text", bytes.NewReader(body))
	req.Header.Set("accept", "application/json")
	req.Header.Set("authorization", "Bearer Your_Token")
	req.Header.Set("content-type", "application/json")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(string(out))
}
Delivery

See when the handoff message arrives

The first status on an API send can be pending. A handoff that stays pending was not delivered. sent, delivered, and read arrive later on statuses.post and statuses.put.

  • A status that stays pending means the handoff was not delivered.

  • Watch statuses.post and statuses.put for sent, delivered, and read.

  • Do not treat the buyer as informed until the handoff moves past pending.

What to read on delivery and webhooks

Contact our support if something went wrong
When things break

Handle failures at each step

If no owner is resolved, the matching label is missing, the label is not applied, or the handoff is not delivered, the chat is still unowned.

Do not leave the chat without an owner

Retry or alert when the owner cannot be resolved, the label is missing, the label is not applied, or the handoff is not delivered. If that handoff still fails, contact Whapi support with the chat and the label you tried to set.

Contact our support if something went wrong

Troubleshoot by API step

Status What it means What to do
400 Wrong request parameters
500 Internal Error
Status What it means What to do
400 Wrong request parameters
401 Need channel authorization for add label association
404 Specified chat or message not found
409 Label association already exists
500 Internal Error
Status What it means What to do
400 Wrong request parameters
401 Need channel authorization for send message
402 Trial version limit exceeded
403 It is forbidden to send to this group/recipient
429 Too many requests
500 Internal Error
FAQ

Questions about chat ownership

If no eligible owner is resolved, the matching label is missing, the label is not applied, or the handoff is not delivered, retry or alert. Do not leave that chat unowned.
No. The chat stays on the number the buyer already wrote to. A label marks the owner, and the handoff names who continues the chat.
Your backend chooses. It can use your own rules. This page does not pick the owner for you.
No. Those questions happen earlier. This flow starts after qualification and assigns the chat to one owner.
A normal text in the same chat. The wording comes from your backend, so the handoff names who continues the chat.
Поддерживаемые функции WhatsApp

Всё, что нужно для создания автоматизации WhatsApp

Whapi.Cloud предоставляет доступ к полному набору функций WhatsApp — сообщениям, медиа, группам, каналам, вебхукам и не только. Создавайте ботов, автоматизации и интеграции без функциональных ограничений.

Выбор разработчиков

Нам доверяют 3 300+ разработчиков и SaaS-команд

Разработчики по всему миру используют Whapi.Cloud для создания автоматизаций, ботов, CRM-интеграций, массовых рассылок и продвинутых WhatsApp-воркфлоу. Наша инфраструктура обрабатывает миллионы API-запросов с высокой стабильностью — и этот показатель растёт каждый месяц.

Иконка функции

5,5K+

активных API-каналов

Иконка функции

21M+

API-запросов в месяц

«Всё просто, интуитивно и легко. Документация понятная, и вся нужная информация всегда под рукой. Отличная работа.»

Roberto K. / Web-разработчик

«Мы подключили WhatsApp к нашим процессам через n8n всего за несколько минут. Без кода, без сложностей — всё заработало с первого раза.»

Martin P. / Разработчик

«Whapi.Cloud стал важной частью нашей коммуникации с клиентами. Мы автоматизировали обновления по продуктам, уведомления о заказах и поддержку — без шаблонов и модерации.»

Oscar T. / CTO

Декоративный пузырь