curl --request POST \
--url https://api.politicalcomms.com/v1/projects/{id}/schedule \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"scheduled_at": "2026-05-01T13:00:00-04:00",
"scheduled_timezone": "America/New_York",
"daily_cap_bypass": false
}
'import requests
url = "https://api.politicalcomms.com/v1/projects/{id}/schedule"
payload = {
"scheduled_at": "2026-05-01T13:00:00-04:00",
"scheduled_timezone": "America/New_York",
"daily_cap_bypass": False
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
scheduled_at: '2026-05-01T13:00:00-04:00',
scheduled_timezone: 'America/New_York',
daily_cap_bypass: false
})
};
fetch('https://api.politicalcomms.com/v1/projects/{id}/schedule', 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.politicalcomms.com/v1/projects/{id}/schedule",
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([
'scheduled_at' => '2026-05-01T13:00:00-04:00',
'scheduled_timezone' => 'America/New_York',
'daily_cap_bypass' => false
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$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.politicalcomms.com/v1/projects/{id}/schedule"
payload := strings.NewReader("{\n \"scheduled_at\": \"2026-05-01T13:00:00-04:00\",\n \"scheduled_timezone\": \"America/New_York\",\n \"daily_cap_bypass\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
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.politicalcomms.com/v1/projects/{id}/schedule")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"scheduled_at\": \"2026-05-01T13:00:00-04:00\",\n \"scheduled_timezone\": \"America/New_York\",\n \"daily_cap_bypass\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.politicalcomms.com/v1/projects/{id}/schedule")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"scheduled_at\": \"2026-05-01T13:00:00-04:00\",\n \"scheduled_timezone\": \"America/New_York\",\n \"daily_cap_bypass\": false\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"project_id": "8a3f5c7e-2d91-4b64-ae08-6f1c9d3e7b52",
"status": "scheduled",
"scheduled_at": "2025-07-10T09:00:00-04:00",
"scheduled_timezone": "America/New_York",
"daily_cap_bypass": false
}
}Schedule Project
Transition a project to scheduled status. The project must be in ready or paused status; scheduling a paused project resumes it. When a project pauses with pause_reason brand_daily_cap (the brand’s T-Mobile daily cap; it resets at midnight Pacific), do not resume at midnight. Schedule it for the next day during sending hours (the project’s sending window: 8 AM to 10 PM in the time zone of most recipients, or 8 AM Eastern to 10 PM Pacific when no zone holds a majority) with a morning scheduled_at, or resume now with daily_cap_bypass: true (T-Mobile messages over the cap may fail and are still billed). At the cap, recipients on known other carriers keep sending; T-Mobile recipients and recipients with an unknown carrier wait, and the project pauses when only those remain. Running list analysis first means only T-Mobile recipients wait. See Carrier throughput limits. A project cannot be created, updated with, or scheduled on a list whose analysis is in progress; the request fails with 409 LIST_ANALYSIS_IN_PROGRESS.
curl --request POST \
--url https://api.politicalcomms.com/v1/projects/{id}/schedule \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"scheduled_at": "2026-05-01T13:00:00-04:00",
"scheduled_timezone": "America/New_York",
"daily_cap_bypass": false
}
'import requests
url = "https://api.politicalcomms.com/v1/projects/{id}/schedule"
payload = {
"scheduled_at": "2026-05-01T13:00:00-04:00",
"scheduled_timezone": "America/New_York",
"daily_cap_bypass": False
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
scheduled_at: '2026-05-01T13:00:00-04:00',
scheduled_timezone: 'America/New_York',
daily_cap_bypass: false
})
};
fetch('https://api.politicalcomms.com/v1/projects/{id}/schedule', 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.politicalcomms.com/v1/projects/{id}/schedule",
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([
'scheduled_at' => '2026-05-01T13:00:00-04:00',
'scheduled_timezone' => 'America/New_York',
'daily_cap_bypass' => false
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$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.politicalcomms.com/v1/projects/{id}/schedule"
payload := strings.NewReader("{\n \"scheduled_at\": \"2026-05-01T13:00:00-04:00\",\n \"scheduled_timezone\": \"America/New_York\",\n \"daily_cap_bypass\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
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.politicalcomms.com/v1/projects/{id}/schedule")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"scheduled_at\": \"2026-05-01T13:00:00-04:00\",\n \"scheduled_timezone\": \"America/New_York\",\n \"daily_cap_bypass\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.politicalcomms.com/v1/projects/{id}/schedule")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"scheduled_at\": \"2026-05-01T13:00:00-04:00\",\n \"scheduled_timezone\": \"America/New_York\",\n \"daily_cap_bypass\": false\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"project_id": "8a3f5c7e-2d91-4b64-ae08-6f1c9d3e7b52",
"status": "scheduled",
"scheduled_at": "2025-07-10T09:00:00-04:00",
"scheduled_timezone": "America/New_York",
"daily_cap_bypass": false
}
}Authorizations
Authenticate every request by passing your API key in the X-API-Key header. Keys are scoped to your organization hierarchy.
Headers
Optional idempotency key: a unique string of 16-200 printable ASCII characters (a UUID is recommended). Retrying the write with the same key within 24 hours returns the stored response of the first call with an X-Idempotent-Replayed: true response header instead of executing it again. Reusing a key with a different request body returns 422 (IDEMPOTENCY_MISMATCH); a duplicate sent while the first call is still running returns 409 with a Retry-After header. Keys are scoped per endpoint and organization.
16 - 200Path Parameters
Resource ID
Body
ISO 8601 date-time including a timezone offset (e.g. 2025-07-10T09:00:00-04:00). May be now or in the past - the project starts sending as soon as audience compilation finishes (no minimum lead time).
US time zone the scheduled time is displayed in. Must be one of the six supported IANA zones.
America/New_York, America/Chicago, America/Denver, America/Los_Angeles, America/Anchorage, Pacific/Honolulu "America/New_York"
Run the whole project past the brand daily carrier limit instead of pausing at it. Only applies to brands that have a T-Mobile daily limit on file (political brands do not today); such a project otherwise pauses at the cap each Pacific day and must be started again to continue. Ignored for brands with no cap. Setting this accepts that messages to T-Mobile recipients over the limit may fail and are still billed: carrier is not reliably known before sending, so only those recipients cannot be skipped. Holds until the next schedule or resume call, which rewrites it, so send it on every schedule or resume call you want it to apply to.
