curl --request POST \
--url https://api.tella.com/v1/videos/{id}/clips/{clipId}/text-overlays \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"durationMs": 5000,
"startTimeMs": 1000,
"text": "Welcome back",
"backgroundShape": "squircle",
"color": "#FFFFFFFF",
"fontFamily": "Inter",
"fontSize": 81,
"fontWeight": 500,
"fontWidth": 100,
"textAlign": "center"
}
'import requests
url = "https://api.tella.com/v1/videos/{id}/clips/{clipId}/text-overlays"
payload = {
"durationMs": 5000,
"startTimeMs": 1000,
"text": "Welcome back",
"backgroundShape": "squircle",
"color": "#FFFFFFFF",
"fontFamily": "Inter",
"fontSize": 81,
"fontWeight": 500,
"fontWidth": 100,
"textAlign": "center"
}
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({
durationMs: 5000,
startTimeMs: 1000,
text: 'Welcome back',
backgroundShape: 'squircle',
color: '#FFFFFFFF',
fontFamily: 'Inter',
fontSize: 81,
fontWeight: 500,
fontWidth: 100,
textAlign: 'center'
})
};
fetch('https://api.tella.com/v1/videos/{id}/clips/{clipId}/text-overlays', 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.tella.com/v1/videos/{id}/clips/{clipId}/text-overlays",
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([
'durationMs' => 5000,
'startTimeMs' => 1000,
'text' => 'Welcome back',
'backgroundShape' => 'squircle',
'color' => '#FFFFFFFF',
'fontFamily' => 'Inter',
'fontSize' => 81,
'fontWeight' => 500,
'fontWidth' => 100,
'textAlign' => 'center'
]),
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.tella.com/v1/videos/{id}/clips/{clipId}/text-overlays"
payload := strings.NewReader("{\n \"durationMs\": 5000,\n \"startTimeMs\": 1000,\n \"text\": \"Welcome back\",\n \"backgroundShape\": \"squircle\",\n \"color\": \"#FFFFFFFF\",\n \"fontFamily\": \"Inter\",\n \"fontSize\": 81,\n \"fontWeight\": 500,\n \"fontWidth\": 100,\n \"textAlign\": \"center\"\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.tella.com/v1/videos/{id}/clips/{clipId}/text-overlays")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"durationMs\": 5000,\n \"startTimeMs\": 1000,\n \"text\": \"Welcome back\",\n \"backgroundShape\": \"squircle\",\n \"color\": \"#FFFFFFFF\",\n \"fontFamily\": \"Inter\",\n \"fontSize\": 81,\n \"fontWeight\": 500,\n \"fontWidth\": 100,\n \"textAlign\": \"center\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tella.com/v1/videos/{id}/clips/{clipId}/text-overlays")
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 \"durationMs\": 5000,\n \"startTimeMs\": 1000,\n \"text\": \"Welcome back\",\n \"backgroundShape\": \"squircle\",\n \"color\": \"#FFFFFFFF\",\n \"fontFamily\": \"Inter\",\n \"fontSize\": 81,\n \"fontWeight\": 500,\n \"fontWidth\": 100,\n \"textAlign\": \"center\"\n}"
response = http.request(request)
puts response.read_body{
"textOverlay": {
"background": {
"color": "#5E51F8FF",
"type": "solid"
},
"backgroundShape": "squircle",
"color": "#FFFFFFFF",
"dimensions": {
"height": 540,
"width": 960
},
"durationMs": 5000,
"fontFamily": "Inter",
"fontSize": 81,
"fontWeight": 500,
"fontWidth": 100,
"id": "ly_abc123",
"point": {
"xPct": 30,
"yPct": 30
},
"startTimeMs": 1000,
"text": "Welcome back",
"textAlign": "center",
"transition": "hard_cut"
}
}{
"docsUrl": "https://docs.tella.com/",
"error": "bad_request",
"message": "The request was malformed or contained invalid parameters."
}{
"docsUrl": "https://docs.tella.com/",
"error": "unauthorized",
"message": "Authentication is required. Provide a valid API key."
}{
"docsUrl": "https://docs.tella.com/",
"error": "forbidden",
"message": "You don't have permission to access this resource."
}{
"docsUrl": "https://docs.tella.com/",
"error": "not_found",
"message": "The requested resource was not found."
}{
"docsUrl": "https://docs.tella.com/",
"error": "rate_limited",
"message": "You have exceeded the rate limit. Please slow down."
}{
"docsUrl": "https://docs.tella.com/",
"error": "server_error",
"message": "An unexpected error occurred"
}{
"docsUrl": "https://docs.tella.com/",
"error": "not_implemented",
"message": "The requested operation is not implemented."
}Add a text overlay to a clip
Adds a text overlay to a clip. Nothing needs uploading — pass the copy directly. Font, color, position and size all fall back to the editor’s defaults.
curl --request POST \
--url https://api.tella.com/v1/videos/{id}/clips/{clipId}/text-overlays \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"durationMs": 5000,
"startTimeMs": 1000,
"text": "Welcome back",
"backgroundShape": "squircle",
"color": "#FFFFFFFF",
"fontFamily": "Inter",
"fontSize": 81,
"fontWeight": 500,
"fontWidth": 100,
"textAlign": "center"
}
'import requests
url = "https://api.tella.com/v1/videos/{id}/clips/{clipId}/text-overlays"
payload = {
"durationMs": 5000,
"startTimeMs": 1000,
"text": "Welcome back",
"backgroundShape": "squircle",
"color": "#FFFFFFFF",
"fontFamily": "Inter",
"fontSize": 81,
"fontWeight": 500,
"fontWidth": 100,
"textAlign": "center"
}
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({
durationMs: 5000,
startTimeMs: 1000,
text: 'Welcome back',
backgroundShape: 'squircle',
color: '#FFFFFFFF',
fontFamily: 'Inter',
fontSize: 81,
fontWeight: 500,
fontWidth: 100,
textAlign: 'center'
})
};
fetch('https://api.tella.com/v1/videos/{id}/clips/{clipId}/text-overlays', 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.tella.com/v1/videos/{id}/clips/{clipId}/text-overlays",
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([
'durationMs' => 5000,
'startTimeMs' => 1000,
'text' => 'Welcome back',
'backgroundShape' => 'squircle',
'color' => '#FFFFFFFF',
'fontFamily' => 'Inter',
'fontSize' => 81,
'fontWeight' => 500,
'fontWidth' => 100,
'textAlign' => 'center'
]),
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.tella.com/v1/videos/{id}/clips/{clipId}/text-overlays"
payload := strings.NewReader("{\n \"durationMs\": 5000,\n \"startTimeMs\": 1000,\n \"text\": \"Welcome back\",\n \"backgroundShape\": \"squircle\",\n \"color\": \"#FFFFFFFF\",\n \"fontFamily\": \"Inter\",\n \"fontSize\": 81,\n \"fontWeight\": 500,\n \"fontWidth\": 100,\n \"textAlign\": \"center\"\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.tella.com/v1/videos/{id}/clips/{clipId}/text-overlays")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"durationMs\": 5000,\n \"startTimeMs\": 1000,\n \"text\": \"Welcome back\",\n \"backgroundShape\": \"squircle\",\n \"color\": \"#FFFFFFFF\",\n \"fontFamily\": \"Inter\",\n \"fontSize\": 81,\n \"fontWeight\": 500,\n \"fontWidth\": 100,\n \"textAlign\": \"center\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tella.com/v1/videos/{id}/clips/{clipId}/text-overlays")
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 \"durationMs\": 5000,\n \"startTimeMs\": 1000,\n \"text\": \"Welcome back\",\n \"backgroundShape\": \"squircle\",\n \"color\": \"#FFFFFFFF\",\n \"fontFamily\": \"Inter\",\n \"fontSize\": 81,\n \"fontWeight\": 500,\n \"fontWidth\": 100,\n \"textAlign\": \"center\"\n}"
response = http.request(request)
puts response.read_body{
"textOverlay": {
"background": {
"color": "#5E51F8FF",
"type": "solid"
},
"backgroundShape": "squircle",
"color": "#FFFFFFFF",
"dimensions": {
"height": 540,
"width": 960
},
"durationMs": 5000,
"fontFamily": "Inter",
"fontSize": 81,
"fontWeight": 500,
"fontWidth": 100,
"id": "ly_abc123",
"point": {
"xPct": 30,
"yPct": 30
},
"startTimeMs": 1000,
"text": "Welcome back",
"textAlign": "center",
"transition": "hard_cut"
}
}{
"docsUrl": "https://docs.tella.com/",
"error": "bad_request",
"message": "The request was malformed or contained invalid parameters."
}{
"docsUrl": "https://docs.tella.com/",
"error": "unauthorized",
"message": "Authentication is required. Provide a valid API key."
}{
"docsUrl": "https://docs.tella.com/",
"error": "forbidden",
"message": "You don't have permission to access this resource."
}{
"docsUrl": "https://docs.tella.com/",
"error": "not_found",
"message": "The requested resource was not found."
}{
"docsUrl": "https://docs.tella.com/",
"error": "rate_limited",
"message": "You have exceeded the rate limit. Please slow down."
}{
"docsUrl": "https://docs.tella.com/",
"error": "server_error",
"message": "An unexpected error occurred"
}{
"docsUrl": "https://docs.tella.com/",
"error": "not_implemented",
"message": "The requested operation is not implemented."
}Authorizations
API key obtained from your Tella account settings
Path Parameters
Video identifier
"vid_abc123def456"
Clip identifier
"cl_xyz789ghi012"
Body
Add a text overlay to a clip. Nothing needs uploading — pass the copy directly. When point/dimensions are omitted, a centered box 60% of the artboard wide and 25% tall is used.
0 < x <= 90071992547409915000
Start time. Milliseconds on the clip playback timeline (with cuts applied) — the same timeline as the cut transcript.
0 <= x <= 90071992547409911000
1"Welcome back"
Background behind the text. Defaults to transparent.
Show child attributes
Show child attributes
Defaults to none.
none, regular, squircle "squircle"
Defaults to white.
^#(?:[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$"#FFFFFFFF"
Overlay size in artboard pixels. Absolute (not a percentage) so the overlay shape never distorts when the artboard dimensions change. Both sides must be greater than 0 — the renderer lays the overlay out into this box, so a zero or negative side has no valid meaning.
Show child attributes
Show child attributes
One of Tella's catalog font families. Defaults to Inter. Anything outside the catalog is rejected rather than silently falling back.
Inter, Roboto Mono, Archivo, Barlow, Caveat, DM Sans, Figtree, Lora, Merriweather, Montserrat, Nunito Sans, Open Sans, Oswald, Playfair Display, Poppins, Raleway, Roboto, Roboto Flex, Source Sans 3, Space Grotesk "Inter"
Font size in artboard pixels. Defaults to 7.5% of the video's shorter side, which is the editor's default and readable at any canvas size.
x > 081
Variable-font weight axis — 100 (thin) to 900 (black), 500 by default. Values outside the chosen font's own axis range are clamped when rendered.
1 <= x <= 1000500
Variable-font width axis, as a percentage — 100 is normal, 50 ultra-condensed, 150 extra-expanded, 100 by default. Values outside the chosen font's own axis range are clamped when rendered.
x > 0100
Top-left corner of the overlay, as a percentage of the video canvas (0-100). Relative so the anchor survives video aspect ratio changes.
Show child attributes
Show child attributes
Defaults to center.
left, center, right "center"
Response
OK
A text overlay on a clip
A text overlay on a clip. Unlike image and video overlays it references no source — the copy and its font live on the overlay itself.
Show child attributes
Show child attributes
Related topics
List text overlays on a clipAdd an overlay to a clipModel Context Protocol (MCP)Overlays overviewRemove a text overlayWas this page helpful?