Scheduled Broadcasts
Create a Scheduled Broadcast
POST /2/broadcasts/scheduled creates a one-time or recurring scheduled broadcast, with automatic or manual publishing.
POST
/
2
/
broadcasts
/
scheduled
Create a scheduled broadcast
curl --request POST \
--url https://api.x.com/2/broadcasts/scheduled \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"scheduled_start_ms": "<string>",
"source_id": "<string>",
"available_for_replay": true,
"chat_option": "<string>",
"description": "<string>",
"is_locked": true,
"locale": "<string>",
"manual_publish": true,
"scheduled_end_ms": "<string>",
"telecast_id": "<string>",
"thumbnail_media_id": "<string>",
"title": "<string>"
}
'import requests
url = "https://api.x.com/2/broadcasts/scheduled"
payload = {
"scheduled_start_ms": "<string>",
"source_id": "<string>",
"available_for_replay": True,
"chat_option": "<string>",
"description": "<string>",
"is_locked": True,
"locale": "<string>",
"manual_publish": True,
"scheduled_end_ms": "<string>",
"telecast_id": "<string>",
"thumbnail_media_id": "<string>",
"title": "<string>"
}
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({
scheduled_start_ms: '<string>',
source_id: '<string>',
available_for_replay: true,
chat_option: '<string>',
description: '<string>',
is_locked: true,
locale: '<string>',
manual_publish: true,
scheduled_end_ms: '<string>',
telecast_id: '<string>',
thumbnail_media_id: '<string>',
title: '<string>'
})
};
fetch('https://api.x.com/2/broadcasts/scheduled', 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.x.com/2/broadcasts/scheduled",
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_start_ms' => '<string>',
'source_id' => '<string>',
'available_for_replay' => true,
'chat_option' => '<string>',
'description' => '<string>',
'is_locked' => true,
'locale' => '<string>',
'manual_publish' => true,
'scheduled_end_ms' => '<string>',
'telecast_id' => '<string>',
'thumbnail_media_id' => '<string>',
'title' => '<string>'
]),
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.x.com/2/broadcasts/scheduled"
payload := strings.NewReader("{\n \"scheduled_start_ms\": \"<string>\",\n \"source_id\": \"<string>\",\n \"available_for_replay\": true,\n \"chat_option\": \"<string>\",\n \"description\": \"<string>\",\n \"is_locked\": true,\n \"locale\": \"<string>\",\n \"manual_publish\": true,\n \"scheduled_end_ms\": \"<string>\",\n \"telecast_id\": \"<string>\",\n \"thumbnail_media_id\": \"<string>\",\n \"title\": \"<string>\"\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.x.com/2/broadcasts/scheduled")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"scheduled_start_ms\": \"<string>\",\n \"source_id\": \"<string>\",\n \"available_for_replay\": true,\n \"chat_option\": \"<string>\",\n \"description\": \"<string>\",\n \"is_locked\": true,\n \"locale\": \"<string>\",\n \"manual_publish\": true,\n \"scheduled_end_ms\": \"<string>\",\n \"telecast_id\": \"<string>\",\n \"thumbnail_media_id\": \"<string>\",\n \"title\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.x.com/2/broadcasts/scheduled")
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 \"scheduled_start_ms\": \"<string>\",\n \"source_id\": \"<string>\",\n \"available_for_replay\": true,\n \"chat_option\": \"<string>\",\n \"description\": \"<string>\",\n \"is_locked\": true,\n \"locale\": \"<string>\",\n \"manual_publish\": true,\n \"scheduled_end_ms\": \"<string>\",\n \"telecast_id\": \"<string>\",\n \"thumbnail_media_id\": \"<string>\",\n \"title\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"available_for_replay": true,
"broadcast_id": "<string>",
"chat_option": "<string>",
"description": "<string>",
"locale": "<string>",
"manual_publish": true,
"recurring_schedule_id": "<string>",
"scheduled_broadcast_id": "<string>",
"scheduled_end_ms": "<string>",
"scheduled_start_ms": "<string>",
"source_id": "<string>",
"state": "<string>",
"telecast_id": "<string>",
"thumbnail_media_id": "<string>",
"title": "<string>"
},
"errors": [
{
"detail": "<string>",
"resource_type": "<string>",
"title": "<string>",
"type": "https://api.x.com/2/problems/resource-not-found",
"parameter": "<string>",
"resource_id": "<string>",
"status": 123,
"value": "<string>"
}
]
}{
"code": 123,
"message": "<string>"
}Creates a one-time or recurring scheduled broadcast owned by the authenticated user. The response returns
The response returns the first scheduled occurrence. Use the list endpoint to retrieve all generated occurrences. Recurrence cannot be added or changed later through the update endpoint.
201 Created with the newly created broadcast; for a recurring series, the response is the first occurrence.
Required fields
| Field | Description |
|---|---|
source_id | Existing source ID, equal to the source’s rtmp_stream_key. See Stream Sources. |
scheduled_start_ms | Scheduled start time, Unix epoch milliseconds as a decimal string. |
Publishing behavior
Setmanual_publish to true when you want to publish explicitly with POST /2/broadcasts/scheduled/:id/live. Otherwise, the scheduler publishes automatically at scheduled_start_ms.
Optional fields
scheduled_end_mssets the scheduled end time as Unix epoch milliseconds. If omitted, the broadcast has no scheduled end and runs until it is stopped or ends manually.titleanddescriptionset the broadcast’s status text and description.thumbnail_media_idis a numeric media ID used as the pre-live slate image.chat_optioncontrols chat permissions and is a numeric string.available_for_replayenables replay after the broadcast ends.is_lockedlocks the broadcast.localesets the broadcast’s locale.telecast_idassociates the broadcast with an existing telecast (numeric string).recurrencecreates a recurring series — see below.
Example: one-time broadcast
{
"source_id": "c47khpz1zuq9",
"scheduled_start_ms": "1784000000000",
"scheduled_end_ms": "1784003600000",
"title": "Product launch",
"description": "Live from our launch event",
"available_for_replay": true,
"manual_publish": true
}
Save both
broadcast_id (alphanumeric, used in endpoint paths) and scheduled_broadcast_id (numeric, required in the body of update requests).Example: recurring schedule
Addrecurrence with a frequency (Daily or Weekly) and the number of repeats as a decimal string:
{
"source_id": "c47khpz1zuq9",
"scheduled_start_ms": "1784000000000",
"scheduled_end_ms": "1784003600000",
"title": "Weekly livestream",
"recurrence": {
"frequency": "Weekly",
"repeats": "4"
}
}
Authorizations
OAuth2UserTokenUserToken
The access token received from the authorization server in the OAuth 2.0 flow.
Body
application/json
Start time, ms since Unix epoch (decimal string).
Pattern:
^[0-9]{1,19}$Ingest / source id to bind (same as sources rtmp_stream_key).
Minimum string length:
1Enable replay.
Chat permission option (numeric string).
Pattern:
^[0-9]{1,19}$Description.
Lock the broadcast.
Locale.
If true, do not auto-publish at start; call POST .../live when ready.
If set, creates a recurring series.
Show child attributes
Show child attributes
Optional end time, ms since Unix epoch (decimal string). Omit for an open-ended broadcast.
Pattern:
^[0-9]{1,19}$Optional telecast id (numeric string).
Pattern:
^[0-9]{1,19}$Pre-live slate media id (numeric string).
Pattern:
^[0-9]{1,19}$Title / status text.
⌘I
Create a scheduled broadcast
curl --request POST \
--url https://api.x.com/2/broadcasts/scheduled \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"scheduled_start_ms": "<string>",
"source_id": "<string>",
"available_for_replay": true,
"chat_option": "<string>",
"description": "<string>",
"is_locked": true,
"locale": "<string>",
"manual_publish": true,
"scheduled_end_ms": "<string>",
"telecast_id": "<string>",
"thumbnail_media_id": "<string>",
"title": "<string>"
}
'import requests
url = "https://api.x.com/2/broadcasts/scheduled"
payload = {
"scheduled_start_ms": "<string>",
"source_id": "<string>",
"available_for_replay": True,
"chat_option": "<string>",
"description": "<string>",
"is_locked": True,
"locale": "<string>",
"manual_publish": True,
"scheduled_end_ms": "<string>",
"telecast_id": "<string>",
"thumbnail_media_id": "<string>",
"title": "<string>"
}
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({
scheduled_start_ms: '<string>',
source_id: '<string>',
available_for_replay: true,
chat_option: '<string>',
description: '<string>',
is_locked: true,
locale: '<string>',
manual_publish: true,
scheduled_end_ms: '<string>',
telecast_id: '<string>',
thumbnail_media_id: '<string>',
title: '<string>'
})
};
fetch('https://api.x.com/2/broadcasts/scheduled', 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.x.com/2/broadcasts/scheduled",
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_start_ms' => '<string>',
'source_id' => '<string>',
'available_for_replay' => true,
'chat_option' => '<string>',
'description' => '<string>',
'is_locked' => true,
'locale' => '<string>',
'manual_publish' => true,
'scheduled_end_ms' => '<string>',
'telecast_id' => '<string>',
'thumbnail_media_id' => '<string>',
'title' => '<string>'
]),
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.x.com/2/broadcasts/scheduled"
payload := strings.NewReader("{\n \"scheduled_start_ms\": \"<string>\",\n \"source_id\": \"<string>\",\n \"available_for_replay\": true,\n \"chat_option\": \"<string>\",\n \"description\": \"<string>\",\n \"is_locked\": true,\n \"locale\": \"<string>\",\n \"manual_publish\": true,\n \"scheduled_end_ms\": \"<string>\",\n \"telecast_id\": \"<string>\",\n \"thumbnail_media_id\": \"<string>\",\n \"title\": \"<string>\"\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.x.com/2/broadcasts/scheduled")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"scheduled_start_ms\": \"<string>\",\n \"source_id\": \"<string>\",\n \"available_for_replay\": true,\n \"chat_option\": \"<string>\",\n \"description\": \"<string>\",\n \"is_locked\": true,\n \"locale\": \"<string>\",\n \"manual_publish\": true,\n \"scheduled_end_ms\": \"<string>\",\n \"telecast_id\": \"<string>\",\n \"thumbnail_media_id\": \"<string>\",\n \"title\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.x.com/2/broadcasts/scheduled")
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 \"scheduled_start_ms\": \"<string>\",\n \"source_id\": \"<string>\",\n \"available_for_replay\": true,\n \"chat_option\": \"<string>\",\n \"description\": \"<string>\",\n \"is_locked\": true,\n \"locale\": \"<string>\",\n \"manual_publish\": true,\n \"scheduled_end_ms\": \"<string>\",\n \"telecast_id\": \"<string>\",\n \"thumbnail_media_id\": \"<string>\",\n \"title\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"available_for_replay": true,
"broadcast_id": "<string>",
"chat_option": "<string>",
"description": "<string>",
"locale": "<string>",
"manual_publish": true,
"recurring_schedule_id": "<string>",
"scheduled_broadcast_id": "<string>",
"scheduled_end_ms": "<string>",
"scheduled_start_ms": "<string>",
"source_id": "<string>",
"state": "<string>",
"telecast_id": "<string>",
"thumbnail_media_id": "<string>",
"title": "<string>"
},
"errors": [
{
"detail": "<string>",
"resource_type": "<string>",
"title": "<string>",
"type": "https://api.x.com/2/problems/resource-not-found",
"parameter": "<string>",
"resource_id": "<string>",
"status": 123,
"value": "<string>"
}
]
}{
"code": 123,
"message": "<string>"
}