curl --request GET \
--url https://api.cloudhumans.com/cloudchat/v1/accounts/{accountId}/campaigns/{campaignId} \
--header 'Authorization: Bearer <token>' \
--header 'cloudchat-instance: <cloudchat-instance>'import requests
url = "https://api.cloudhumans.com/cloudchat/v1/accounts/{accountId}/campaigns/{campaignId}"
headers = {
"cloudchat-instance": "<cloudchat-instance>",
"Authorization": "Bearer <token>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {'cloudchat-instance': '<cloudchat-instance>', Authorization: 'Bearer <token>'}
};
fetch('https://api.cloudhumans.com/cloudchat/v1/accounts/{accountId}/campaigns/{campaignId}', 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.cloudhumans.com/cloudchat/v1/accounts/{accountId}/campaigns/{campaignId}",
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>",
"cloudchat-instance: <cloudchat-instance>"
],
]);
$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://api.cloudhumans.com/cloudchat/v1/accounts/{accountId}/campaigns/{campaignId}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("cloudchat-instance", "<cloudchat-instance>")
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://api.cloudhumans.com/cloudchat/v1/accounts/{accountId}/campaigns/{campaignId}")
.header("cloudchat-instance", "<cloudchat-instance>")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.cloudhumans.com/cloudchat/v1/accounts/{accountId}/campaigns/{campaignId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["cloudchat-instance"] = '<cloudchat-instance>'
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"id": 176,
"title": "September reactivation",
"message": "reactivation_september",
"campaign_status": "completed",
"campaign_type": "one_off",
"created_at": "2026-09-19T17:34:12.881Z",
"updated_at": "2026-09-19T17:34:15.002Z",
"reachable_count": 1187,
"subject": "<string>",
"inbox_id": 60,
"email_campaign_sender_id": 123,
"sender_id": 895,
"conversation_label_id": 123,
"team_id": 123,
"recipients_count": 1240,
"scheduled_at": "2026-09-19T17:34:12.881Z",
"started_at": "2023-11-07T05:31:56Z",
"completed_at": "2026-09-19T17:34:15.002Z"
}{
"error": {
"code": "bad_request",
"message": "The request is malformed."
}
}{
"error": {
"code": "unauthorized",
"message": "Authentication is required. Send a valid Bearer token in the Authorization header."
}
}{
"error": {
"code": "forbidden",
"message": "You do not have permission to perform this action."
}
}{
"error": {
"code": "not_found",
"message": "Resource could not be found."
}
}{
"message": "API rate limit exceeded"
}{
"error": {
"code": "internal_error",
"message": "An unexpected error occurred. Please try again later."
}
}Get a campaign
Read one campaign back by the id you were given when it was created. No endpoint lists campaigns, so an id you did not keep cannot be recovered.
campaign_status is not a delivery report. completed means a worker took the campaign over, not that anything arrived: on WhatsApp the status is set before the audience is even resolved, and started_at stays null for the whole life of a WhatsApp campaign. For what was actually delivered, open the campaign dashboard in Cloud Chat.
reachable_count is not part of this response: reach is computed when the campaign is created and never stored.
curl --request GET \
--url https://api.cloudhumans.com/cloudchat/v1/accounts/{accountId}/campaigns/{campaignId} \
--header 'Authorization: Bearer <token>' \
--header 'cloudchat-instance: <cloudchat-instance>'import requests
url = "https://api.cloudhumans.com/cloudchat/v1/accounts/{accountId}/campaigns/{campaignId}"
headers = {
"cloudchat-instance": "<cloudchat-instance>",
"Authorization": "Bearer <token>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {'cloudchat-instance': '<cloudchat-instance>', Authorization: 'Bearer <token>'}
};
fetch('https://api.cloudhumans.com/cloudchat/v1/accounts/{accountId}/campaigns/{campaignId}', 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.cloudhumans.com/cloudchat/v1/accounts/{accountId}/campaigns/{campaignId}",
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>",
"cloudchat-instance: <cloudchat-instance>"
],
]);
$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://api.cloudhumans.com/cloudchat/v1/accounts/{accountId}/campaigns/{campaignId}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("cloudchat-instance", "<cloudchat-instance>")
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://api.cloudhumans.com/cloudchat/v1/accounts/{accountId}/campaigns/{campaignId}")
.header("cloudchat-instance", "<cloudchat-instance>")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.cloudhumans.com/cloudchat/v1/accounts/{accountId}/campaigns/{campaignId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["cloudchat-instance"] = '<cloudchat-instance>'
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"id": 176,
"title": "September reactivation",
"message": "reactivation_september",
"campaign_status": "completed",
"campaign_type": "one_off",
"created_at": "2026-09-19T17:34:12.881Z",
"updated_at": "2026-09-19T17:34:15.002Z",
"reachable_count": 1187,
"subject": "<string>",
"inbox_id": 60,
"email_campaign_sender_id": 123,
"sender_id": 895,
"conversation_label_id": 123,
"team_id": 123,
"recipients_count": 1240,
"scheduled_at": "2026-09-19T17:34:12.881Z",
"started_at": "2023-11-07T05:31:56Z",
"completed_at": "2026-09-19T17:34:15.002Z"
}{
"error": {
"code": "bad_request",
"message": "The request is malformed."
}
}{
"error": {
"code": "unauthorized",
"message": "Authentication is required. Send a valid Bearer token in the Authorization header."
}
}{
"error": {
"code": "forbidden",
"message": "You do not have permission to perform this action."
}
}{
"error": {
"code": "not_found",
"message": "Resource could not be found."
}
}{
"message": "API rate limit exceeded"
}{
"error": {
"code": "internal_error",
"message": "An unexpected error occurred. Please try again later."
}
}Authorizations
The id_token from POST /auth/v1/signin, sent as Authorization: Bearer <id_token>. Not the access_token — that one does not carry the identity Cloud Chat authorizes on.
Headers
Your Cloud Chat instance ID — an integer, fixed for your company, told at onboarding. The API overview explains how instances work, how to find yours, and the errors a wrong or missing value produces.
1
Path Parameters
Your Cloud Chat account. It has to be an account your token grants membership on, and it has to live on the instance in the cloudchat-instance header — the two travel together. Account numbers are only unique within an instance, so the same number is a different company on another instance. Usually a mismatched pair fails closed with a 401, because your user does not exist on the other instance — but if your identity happens to exist on both, the call succeeds against the other company's data, silently. Read it and you are looking at the wrong help center; write it and you have stored into the wrong account. Send the two values that were given to you together, and never try a number to see what answers.
1
The campaign display id — the id returned when it was created. It is the number Cloud Chat displays, never the internal database id, and it is sequential within the account rather than globally unique. No endpoint lists campaigns, so the response that created it is the only place this value comes from — keep it.
176
Response
The campaign as stored.
A one-off campaign as stored. reachable_count is present only in the create response.
The display id, sequential within the account. Keep it — no endpoint lists campaigns, so this is the only way back to it.
176
Internal name of the campaign.
"September reactivation"
The template name on a WhatsApp campaign, the message body on e-mail and widget.
"reactivation_september"
Where the campaign is in its lifecycle — not a delivery report. completed means a worker took it over, not that anything arrived: on WhatsApp it is set before the audience is even resolved. failed means a precondition stopped the dispatch and it will not be retried. What actually reached your contacts is in the Cloud Chat campaign dashboard.
The values in use are active, completed, running, draft, partially_completed and failed. The set is open and grows as new states are added, so read an unfamiliar value as a state you do not know yet rather than as an error.
"completed"
Campaigns created through the API are always one_off. A campaign built in Cloud Chat can be ongoing and fire on a trigger instead.
ongoing, one_off "one_off"
When the campaign was created.
"2026-09-19T17:34:12.881Z"
When it last changed.
"2026-09-19T17:34:15.002Z"
The reach the campaign was confirmed against. Returned only when the campaign is created: reach is computed, never stored, so reading a campaign back omits the field entirely.
1187
Subject line of an e-mail campaign; null on the other channels.
The inbox that sends. On an e-mail campaign it follows from the sender.
60
The verified sender of an e-mail campaign; null on WhatsApp and widget.
The user the campaign is attributed to. Through the API this is always the identity of the token that created it — authorship cannot be set in the payload.
895
Label applied to the conversations the campaign opens, when one was configured.
Team the resulting conversations are assigned to, when one was configured.
The raw audience size recorded on the campaign, before the reachability check. It is not what was delivered, and it is not what confirm_recipients is compared against.
1240
When the campaign is due out. A campaign created without one carries the moment it was created.
"2026-09-19T17:34:12.881Z"
When dispatch began. Always null on a WhatsApp campaign — only the e-mail path fills it — so its absence tells you nothing about whether the campaign ran.
When the campaign reached a terminal status; null while it is still open.
"2026-09-19T17:34:15.002Z"