curl --request PATCH \
--url https://platform.crescendo.ai/api/v1/cxm/tenants/{tenantId}/conversations/{conversationId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"changes": {
"status": "pending",
"pendingOn": "customer"
}
}
'import requests
url = "https://platform.crescendo.ai/api/v1/cxm/tenants/{tenantId}/conversations/{conversationId}"
payload = { "changes": {
"status": "pending",
"pendingOn": "customer"
} }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({changes: {status: 'pending', pendingOn: 'customer'}})
};
fetch('https://platform.crescendo.ai/api/v1/cxm/tenants/{tenantId}/conversations/{conversationId}', 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://platform.crescendo.ai/api/v1/cxm/tenants/{tenantId}/conversations/{conversationId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'changes' => [
'status' => 'pending',
'pendingOn' => 'customer'
]
]),
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://platform.crescendo.ai/api/v1/cxm/tenants/{tenantId}/conversations/{conversationId}"
payload := strings.NewReader("{\n \"changes\": {\n \"status\": \"pending\",\n \"pendingOn\": \"customer\"\n }\n}")
req, _ := http.NewRequest("PATCH", 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.patch("https://platform.crescendo.ai/api/v1/cxm/tenants/{tenantId}/conversations/{conversationId}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"changes\": {\n \"status\": \"pending\",\n \"pendingOn\": \"customer\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://platform.crescendo.ai/api/v1/cxm/tenants/{tenantId}/conversations/{conversationId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"changes\": {\n \"status\": \"pending\",\n \"pendingOn\": \"customer\"\n }\n}"
response = http.request(request)
puts response.read_body{
"conversation": {
"id": "<string>",
"status": "open",
"priority": "low",
"pendingOn": "<string>",
"pendingReason": "<string>",
"assignee": {
"type": "agent",
"id": "<string>"
},
"teamId": "<string>"
}
}{
"code": "BadRequest",
"message": "Invalid fields, unknown properties, or a disallowed status transition."
}{
"code": "Unauthenticated",
"message": "The API key is missing, invalid, or expired."
}{
"code": "PermissionDenied",
"message": "The API key does not authorize this tenant or operation."
}{
"code": "NotFound",
"message": "The customer Conversation or active assignee is unavailable in this tenant."
}{
"code": "Conflict",
"message": "The Conversation is merged/Closed, a lock is held, or lifecycle/realtime ownership constraints reject the operation."
}{
"code": "PayloadTooLarge",
"message": "The JSON body exceeds 32768 bytes."
}{
"code": "RateLimitExceeded",
"message": "The request exceeds the API rate limit."
}{
"code": "BadGateway",
"message": "The downstream request failed; the write may already have completed."
}{
"code": "ServiceUnavailable",
"message": "A required service is unavailable; the write may already have completed."
}{
"code": "GatewayTimeout",
"message": "The request timed out; the write may already have completed."
}Update a conversation
Update status, priority, Pending On, or Pending Reason. Normal lifecycle and required custom-field rules apply. A Closed Conversation requires an explicit valid transition to Open, which may include other allowed metadata in the same update. Pending fields omitted while Pending are preserved; leaving Pending clears them. Requires a tenant API key with cxm:conversations.write or an existing broader write scope. The complete JSON body must not exceed 32768 bytes. Each invocation executes independently, with no request deduplication, version precondition, preparation step, or retry protection. A timeout may follow a successful commit. Merged and non-customer records are rejected.
curl --request PATCH \
--url https://platform.crescendo.ai/api/v1/cxm/tenants/{tenantId}/conversations/{conversationId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"changes": {
"status": "pending",
"pendingOn": "customer"
}
}
'import requests
url = "https://platform.crescendo.ai/api/v1/cxm/tenants/{tenantId}/conversations/{conversationId}"
payload = { "changes": {
"status": "pending",
"pendingOn": "customer"
} }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({changes: {status: 'pending', pendingOn: 'customer'}})
};
fetch('https://platform.crescendo.ai/api/v1/cxm/tenants/{tenantId}/conversations/{conversationId}', 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://platform.crescendo.ai/api/v1/cxm/tenants/{tenantId}/conversations/{conversationId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'changes' => [
'status' => 'pending',
'pendingOn' => 'customer'
]
]),
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://platform.crescendo.ai/api/v1/cxm/tenants/{tenantId}/conversations/{conversationId}"
payload := strings.NewReader("{\n \"changes\": {\n \"status\": \"pending\",\n \"pendingOn\": \"customer\"\n }\n}")
req, _ := http.NewRequest("PATCH", 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.patch("https://platform.crescendo.ai/api/v1/cxm/tenants/{tenantId}/conversations/{conversationId}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"changes\": {\n \"status\": \"pending\",\n \"pendingOn\": \"customer\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://platform.crescendo.ai/api/v1/cxm/tenants/{tenantId}/conversations/{conversationId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"changes\": {\n \"status\": \"pending\",\n \"pendingOn\": \"customer\"\n }\n}"
response = http.request(request)
puts response.read_body{
"conversation": {
"id": "<string>",
"status": "open",
"priority": "low",
"pendingOn": "<string>",
"pendingReason": "<string>",
"assignee": {
"type": "agent",
"id": "<string>"
},
"teamId": "<string>"
}
}{
"code": "BadRequest",
"message": "Invalid fields, unknown properties, or a disallowed status transition."
}{
"code": "Unauthenticated",
"message": "The API key is missing, invalid, or expired."
}{
"code": "PermissionDenied",
"message": "The API key does not authorize this tenant or operation."
}{
"code": "NotFound",
"message": "The customer Conversation or active assignee is unavailable in this tenant."
}{
"code": "Conflict",
"message": "The Conversation is merged/Closed, a lock is held, or lifecycle/realtime ownership constraints reject the operation."
}{
"code": "PayloadTooLarge",
"message": "The JSON body exceeds 32768 bytes."
}{
"code": "RateLimitExceeded",
"message": "The request exceeds the API rate limit."
}{
"code": "BadGateway",
"message": "The downstream request failed; the write may already have completed."
}{
"code": "ServiceUnavailable",
"message": "A required service is unavailable; the write may already have completed."
}{
"code": "GatewayTimeout",
"message": "The request timed out; the write may already have completed."
}Authorizations
Tenant API key with cxm:conversations.write, cxm:conversations.*, cxm:write, or cxm:* scope. Keep it in a trusted backend; do not expose it in browser code.
Path Parameters
Exact tenant-authorized ID without path separators.
1 - 128Exact tenant-authorized ID without path separators.
1 - 512Body
Show child attributes
Show child attributes
Response
Committed operation result; notification delivery is not implied.
Show child attributes
Show child attributes

