curl --request POST \
--url https://api.chatsailer.com/v1/conversations/{conversation_id}/handoff \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"assignee_id": "usr_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4"
}
'import requests
url = "https://api.chatsailer.com/v1/conversations/{conversation_id}/handoff"
payload = { "assignee_id": "usr_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4" }
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({assignee_id: 'usr_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4'})
};
fetch('https://api.chatsailer.com/v1/conversations/{conversation_id}/handoff', 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.chatsailer.com/v1/conversations/{conversation_id}/handoff",
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([
'assignee_id' => 'usr_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4'
]),
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.chatsailer.com/v1/conversations/{conversation_id}/handoff"
payload := strings.NewReader("{\n \"assignee_id\": \"usr_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4\"\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.chatsailer.com/v1/conversations/{conversation_id}/handoff")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"assignee_id\": \"usr_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.chatsailer.com/v1/conversations/{conversation_id}/handoff")
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 \"assignee_id\": \"usr_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4\"\n}"
response = http.request(request)
puts response.read_body{
"created_at": "2023-11-07T05:31:56Z",
"id": "conv_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4",
"status": "waiting",
"updated_at": "2023-11-07T05:31:56Z",
"channel": "whatsapp_api",
"channel_id": "chn_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4",
"contact_id": "con_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4",
"handler": {
"id": "<string>",
"kind": "user",
"name": "<string>",
"object": "owner"
},
"last_message_at": "2023-11-07T05:31:56Z",
"needs_human": true,
"object": "conversation",
"queue_name": "<string>"
}{
"error": {
"code": "<string>",
"message": "<string>",
"type": "invalid_request_error",
"detail": [
{
"field": "<string>",
"message": "<string>",
"code": "<string>"
}
],
"documentation_url": "<string>",
"param": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"type": "invalid_request_error",
"detail": [
{
"field": "<string>",
"message": "<string>",
"code": "<string>"
}
],
"documentation_url": "<string>",
"param": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"type": "invalid_request_error",
"detail": [
{
"field": "<string>",
"message": "<string>",
"code": "<string>"
}
],
"documentation_url": "<string>",
"param": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"type": "invalid_request_error",
"detail": [
{
"field": "<string>",
"message": "<string>",
"code": "<string>"
}
],
"documentation_url": "<string>",
"param": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"type": "invalid_request_error",
"detail": [
{
"field": "<string>",
"message": "<string>",
"code": "<string>"
}
],
"documentation_url": "<string>",
"param": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"type": "invalid_request_error",
"detail": [
{
"field": "<string>",
"message": "<string>",
"code": "<string>"
}
],
"documentation_url": "<string>",
"param": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"type": "invalid_request_error",
"detail": [
{
"field": "<string>",
"message": "<string>",
"code": "<string>"
}
],
"documentation_url": "<string>",
"param": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"type": "invalid_request_error",
"detail": [
{
"field": "<string>",
"message": "<string>",
"code": "<string>"
}
],
"documentation_url": "<string>",
"param": "<string>",
"request_id": "<string>"
}
}Hand a conversation from the AI agent to a person
The AI agent stops replying and a person takes over: the teammate in assignee_id, or, without one, whoever picks it up from its queue first. Nothing is sent to the contact.
Only for conversations the AI agent is handling (handler.kind is agent). Otherwise this answers 409 conversation_not_with_ai; use assign to move a conversation between people.
curl --request POST \
--url https://api.chatsailer.com/v1/conversations/{conversation_id}/handoff \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"assignee_id": "usr_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4"
}
'import requests
url = "https://api.chatsailer.com/v1/conversations/{conversation_id}/handoff"
payload = { "assignee_id": "usr_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4" }
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({assignee_id: 'usr_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4'})
};
fetch('https://api.chatsailer.com/v1/conversations/{conversation_id}/handoff', 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.chatsailer.com/v1/conversations/{conversation_id}/handoff",
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([
'assignee_id' => 'usr_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4'
]),
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.chatsailer.com/v1/conversations/{conversation_id}/handoff"
payload := strings.NewReader("{\n \"assignee_id\": \"usr_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4\"\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.chatsailer.com/v1/conversations/{conversation_id}/handoff")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"assignee_id\": \"usr_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.chatsailer.com/v1/conversations/{conversation_id}/handoff")
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 \"assignee_id\": \"usr_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4\"\n}"
response = http.request(request)
puts response.read_body{
"created_at": "2023-11-07T05:31:56Z",
"id": "conv_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4",
"status": "waiting",
"updated_at": "2023-11-07T05:31:56Z",
"channel": "whatsapp_api",
"channel_id": "chn_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4",
"contact_id": "con_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4",
"handler": {
"id": "<string>",
"kind": "user",
"name": "<string>",
"object": "owner"
},
"last_message_at": "2023-11-07T05:31:56Z",
"needs_human": true,
"object": "conversation",
"queue_name": "<string>"
}{
"error": {
"code": "<string>",
"message": "<string>",
"type": "invalid_request_error",
"detail": [
{
"field": "<string>",
"message": "<string>",
"code": "<string>"
}
],
"documentation_url": "<string>",
"param": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"type": "invalid_request_error",
"detail": [
{
"field": "<string>",
"message": "<string>",
"code": "<string>"
}
],
"documentation_url": "<string>",
"param": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"type": "invalid_request_error",
"detail": [
{
"field": "<string>",
"message": "<string>",
"code": "<string>"
}
],
"documentation_url": "<string>",
"param": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"type": "invalid_request_error",
"detail": [
{
"field": "<string>",
"message": "<string>",
"code": "<string>"
}
],
"documentation_url": "<string>",
"param": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"type": "invalid_request_error",
"detail": [
{
"field": "<string>",
"message": "<string>",
"code": "<string>"
}
],
"documentation_url": "<string>",
"param": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"type": "invalid_request_error",
"detail": [
{
"field": "<string>",
"message": "<string>",
"code": "<string>"
}
],
"documentation_url": "<string>",
"param": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"type": "invalid_request_error",
"detail": [
{
"field": "<string>",
"message": "<string>",
"code": "<string>"
}
],
"documentation_url": "<string>",
"param": "<string>",
"request_id": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"type": "invalid_request_error",
"detail": [
{
"field": "<string>",
"message": "<string>",
"code": "<string>"
}
],
"documentation_url": "<string>",
"param": "<string>",
"request_id": "<string>"
}
}Authorizations
A workspace API token (sk_live_...) or an OAuth access token (oat_live_...). Create workspace tokens in Settings > API. Send either as Authorization: Bearer <token>.
Headers
A unique value (a UUID works) that makes retrying this request safe. A repeat with the same key and body within 24 hours returns the original response instead of acting twice; the same key with a different body is a 409 idempotency_key_reused.
255Path Parameters
Unique identifier for a conversation.
^conv_[0-9a-f]{32}$"conv_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4"
Body
Body for handing a conversation from the AI agent to a person.
Unique identifier for an user.
^usr_[0-9a-f]{32}$"usr_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4"
Response
Successful Response
One thread with one contact on one channel.
Unique identifier for a conversation.
^conv_[0-9a-f]{32}$"conv_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4"
Where a conversation stands.
waiting: open, and nobody has picked it up yet — it is in a queue, or
assigned to a teammate who has not accepted it. active: open and being
handled, by the AI agent or by a teammate. closed: finished.
waiting, active, closed When anything about the conversation last changed, including who handles it and whether it is open.
Platform this thread runs on, e.g. whatsapp.
whatsapp_api, whatsapp, instagram, slack, web_widget, botconversa Unique identifier for a channel.
^chn_[0-9a-f]{32}$"chn_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4"
Unique identifier for a contact.
^con_[0-9a-f]{32}$"con_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4"
Who is handling it now: the AI agent (kind: agent) or a teammate (kind: user). Null while it waits in a queue for a teammate, and once it is closed.
Show child attributes
Show child attributes
Whether a person has been asked for: the AI agent asked for one, or a teammate was assigned or took it over. It does not say who has the conversation — one routed straight to a teammate can read false — so use handler for that. Null once closed.
"conversation"The queue it is in while open.