Replace a video's chapters
curl --request PUT \
--url https://app.trackplay.io/api/v1/videos/{video}/chapters \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"chapters": [
{
"time_seconds": 1,
"title": "<string>",
"description": "<string>"
}
],
"enabled": true
}
'import requests
url = "https://app.trackplay.io/api/v1/videos/{video}/chapters"
payload = {
"chapters": [
{
"time_seconds": 1,
"title": "<string>",
"description": "<string>"
}
],
"enabled": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
chapters: [{time_seconds: 1, title: '<string>', description: '<string>'}],
enabled: true
})
};
fetch('https://app.trackplay.io/api/v1/videos/{video}/chapters', 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://app.trackplay.io/api/v1/videos/{video}/chapters",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'chapters' => [
[
'time_seconds' => 1,
'title' => '<string>',
'description' => '<string>'
]
],
'enabled' => true
]),
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://app.trackplay.io/api/v1/videos/{video}/chapters"
payload := strings.NewReader("{\n \"chapters\": [\n {\n \"time_seconds\": 1,\n \"title\": \"<string>\",\n \"description\": \"<string>\"\n }\n ],\n \"enabled\": true\n}")
req, _ := http.NewRequest("PUT", 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.put("https://app.trackplay.io/api/v1/videos/{video}/chapters")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"chapters\": [\n {\n \"time_seconds\": 1,\n \"title\": \"<string>\",\n \"description\": \"<string>\"\n }\n ],\n \"enabled\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.trackplay.io/api/v1/videos/{video}/chapters")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"chapters\": [\n {\n \"time_seconds\": 1,\n \"title\": \"<string>\",\n \"description\": \"<string>\"\n }\n ],\n \"enabled\": true\n}"
response = http.request(request)
puts response.read_body{
"chapters_options": {
"chapters": [
{
"time_seconds": 1,
"title": "<string>",
"description": "<string>"
}
],
"enabled": true
}
}{
"error": {
"code": "<string>",
"message": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>"
}
}{
"message": "No query results for model [App\\\\Models\\\\WorkspaceVideo] 481"
}{
"message": "The given data was invalid.",
"errors": {}
}Captions and chapters
Replace a video's chapters
Replaces the video’s entire chapter list. This is a full replace, not a merge: send every chapter you want to keep, including ones already saved, or they are removed. An empty chapters array turns chapters off. Recompiles the player.
Requires a token with the videos:write scope.
PUT
/
videos
/
{video}
/
chapters
Replace a video's chapters
curl --request PUT \
--url https://app.trackplay.io/api/v1/videos/{video}/chapters \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"chapters": [
{
"time_seconds": 1,
"title": "<string>",
"description": "<string>"
}
],
"enabled": true
}
'import requests
url = "https://app.trackplay.io/api/v1/videos/{video}/chapters"
payload = {
"chapters": [
{
"time_seconds": 1,
"title": "<string>",
"description": "<string>"
}
],
"enabled": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
chapters: [{time_seconds: 1, title: '<string>', description: '<string>'}],
enabled: true
})
};
fetch('https://app.trackplay.io/api/v1/videos/{video}/chapters', 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://app.trackplay.io/api/v1/videos/{video}/chapters",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'chapters' => [
[
'time_seconds' => 1,
'title' => '<string>',
'description' => '<string>'
]
],
'enabled' => true
]),
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://app.trackplay.io/api/v1/videos/{video}/chapters"
payload := strings.NewReader("{\n \"chapters\": [\n {\n \"time_seconds\": 1,\n \"title\": \"<string>\",\n \"description\": \"<string>\"\n }\n ],\n \"enabled\": true\n}")
req, _ := http.NewRequest("PUT", 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.put("https://app.trackplay.io/api/v1/videos/{video}/chapters")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"chapters\": [\n {\n \"time_seconds\": 1,\n \"title\": \"<string>\",\n \"description\": \"<string>\"\n }\n ],\n \"enabled\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.trackplay.io/api/v1/videos/{video}/chapters")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"chapters\": [\n {\n \"time_seconds\": 1,\n \"title\": \"<string>\",\n \"description\": \"<string>\"\n }\n ],\n \"enabled\": true\n}"
response = http.request(request)
puts response.read_body{
"chapters_options": {
"chapters": [
{
"time_seconds": 1,
"title": "<string>",
"description": "<string>"
}
],
"enabled": true
}
}{
"error": {
"code": "<string>",
"message": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>"
}
}{
"message": "No query results for model [App\\\\Models\\\\WorkspaceVideo] 481"
}{
"message": "The given data was invalid.",
"errors": {}
}Authorizations
A scoped token minted in Settings → API tokens. Send it as Authorization: Bearer tplt_… or X-API-Key: tplt_….
Path Parameters
The video's numeric ID.
Body
application/json
The complete chapter list. This is a full replace, not a merge: send every chapter you want to keep, including ones already saved. An empty array removes all chapters.
Show child attributes
Show child attributes
Turns chapters on or off in the player. Defaults to true when chapters is non-empty, false otherwise.
Response
The video's chapters.
Show child attributes
Show child attributes