curl --request POST \
--url https://api.chatsailer.com/v1/campaigns/{campaign_id}/participants \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"contact_ids": [
"con_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4"
]
}
'import requests
url = "https://api.chatsailer.com/v1/campaigns/{campaign_id}/participants"
payload = { "contact_ids": ["con_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({contact_ids: ['con_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4']})
};
fetch('https://api.chatsailer.com/v1/campaigns/{campaign_id}/participants', 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/campaigns/{campaign_id}/participants",
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([
'contact_ids' => [
'con_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/campaigns/{campaign_id}/participants"
payload := strings.NewReader("{\n \"contact_ids\": [\n \"con_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4\"\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.chatsailer.com/v1/campaigns/{campaign_id}/participants")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"contact_ids\": [\n \"con_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.chatsailer.com/v1/campaigns/{campaign_id}/participants")
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 \"contact_ids\": [\n \"con_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"added": 123,
"already_present": 123,
"object": "enrolment_result"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"ctx": {},
"input": "<unknown>"
}
]
}Add contacts to a campaign
This causes real messages to be sent to real people. The contacts you add here are messaged on the campaign’s own schedule.
Takes ids of contacts that already exist — create them first if they do not. Contacts already in the campaign are counted in already_present and are not enrolled twice.
There is no way to request an immediate send. Enrolment and sending are separate decisions.
curl --request POST \
--url https://api.chatsailer.com/v1/campaigns/{campaign_id}/participants \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"contact_ids": [
"con_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4"
]
}
'import requests
url = "https://api.chatsailer.com/v1/campaigns/{campaign_id}/participants"
payload = { "contact_ids": ["con_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({contact_ids: ['con_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4']})
};
fetch('https://api.chatsailer.com/v1/campaigns/{campaign_id}/participants', 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/campaigns/{campaign_id}/participants",
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([
'contact_ids' => [
'con_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/campaigns/{campaign_id}/participants"
payload := strings.NewReader("{\n \"contact_ids\": [\n \"con_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4\"\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.chatsailer.com/v1/campaigns/{campaign_id}/participants")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"contact_ids\": [\n \"con_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.chatsailer.com/v1/campaigns/{campaign_id}/participants")
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 \"contact_ids\": [\n \"con_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"added": 123,
"already_present": 123,
"object": "enrolment_result"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"ctx": {},
"input": "<unknown>"
}
]
}Authorizations
A workspace API token. Create one in Settings → API. Send it as Authorization: Bearer sk_live_....
Path Parameters
Unique identifier for a campaign.
^camp_[0-9a-f]{32}$"camp_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4"
Body
Body for adding contacts to a campaign or an audience.
Takes ids of contacts that already exist, rather than contact details. This endpoint is not an import: creating people and messaging them should not be the same call, because the failure modes are different and only one of them is reversible.
Contacts to add. They must already exist in this workspace.
1 - 1000 elementsUnique identifier for a contact.
^con_[0-9a-f]{32}$