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 status.
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 T-Mobile meters (Aegis-vetted, non-political), which carry a per-brand T-Mobile daily cap; 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. Persists for the life of the project.
