curl --request POST \
--url https://api.tella.com/v1/videos/{id}/clips/{clipId}/layouts/auto \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"instructions": "Keep the camera visible the whole time",
"style": "product-demo-round"
}
'import requests
url = "https://api.tella.com/v1/videos/{id}/clips/{clipId}/layouts/auto"
payload = {
"instructions": "Keep the camera visible the whole time",
"style": "product-demo-round"
}
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({
instructions: 'Keep the camera visible the whole time',
style: 'product-demo-round'
})
};
fetch('https://api.tella.com/v1/videos/{id}/clips/{clipId}/layouts/auto', 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}/layouts/auto",
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([
'instructions' => 'Keep the camera visible the whole time',
'style' => 'product-demo-round'
]),
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}/layouts/auto"
payload := strings.NewReader("{\n \"instructions\": \"Keep the camera visible the whole time\",\n \"style\": \"product-demo-round\"\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}/layouts/auto")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"instructions\": \"Keep the camera visible the whole time\",\n \"style\": \"product-demo-round\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tella.com/v1/videos/{id}/clips/{clipId}/layouts/auto")
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 \"instructions\": \"Keep the camera visible the whole time\",\n \"style\": \"product-demo-round\"\n}"
response = http.request(request)
puts response.read_body{
"layouts": [
{
"id": "<string>",
"media": [
{
"type": "image",
"height": 0,
"imageUrl": "<string>",
"slot": "screen",
"sourceId": "<string>",
"width": 0
}
],
"crop": {
"bottom": 1,
"left": 1,
"right": 1,
"top": 1
},
"durationMs": 5000,
"followsBase": true,
"layout": {
"kind": "fullscreen",
"screenFit": "cover",
"style": "regular"
},
"popOut": {
"amount": 0.25,
"background": "original",
"color": "<string>",
"outlineColor": "<string>",
"outlineWidth": 0.025
},
"startTimeMs": 0,
"transitionStyle": "spring"
}
],
"editingStyle": "product-demo-round"
}{
"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": "conflict",
"message": "The request conflicts with the resource's current state, e.g. an Idempotency-Key whose first request is still in progress. Retry once it settles."
}{
"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."
}{
"docsUrl": "https://docs.tella.com/",
"error": "unavailable",
"message": "A dependency was unavailable and the request was not executed. Safe to resend unchanged after the Retry-After delay."
}Auto-generate layouts with AI
Lets AI watch the clip and lay it out — the API twin of the editor’s “Auto layouts”. The clip’s existing layouts are replaced: the AI picks an editing style (or follows style), sets the clip’s base layout, and adds time-ranged layout changes. Generation watches the actual video, so expect the request to take on the order of a minute for longer clips.
curl --request POST \
--url https://api.tella.com/v1/videos/{id}/clips/{clipId}/layouts/auto \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"instructions": "Keep the camera visible the whole time",
"style": "product-demo-round"
}
'import requests
url = "https://api.tella.com/v1/videos/{id}/clips/{clipId}/layouts/auto"
payload = {
"instructions": "Keep the camera visible the whole time",
"style": "product-demo-round"
}
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({
instructions: 'Keep the camera visible the whole time',
style: 'product-demo-round'
})
};
fetch('https://api.tella.com/v1/videos/{id}/clips/{clipId}/layouts/auto', 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}/layouts/auto",
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([
'instructions' => 'Keep the camera visible the whole time',
'style' => 'product-demo-round'
]),
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}/layouts/auto"
payload := strings.NewReader("{\n \"instructions\": \"Keep the camera visible the whole time\",\n \"style\": \"product-demo-round\"\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}/layouts/auto")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"instructions\": \"Keep the camera visible the whole time\",\n \"style\": \"product-demo-round\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tella.com/v1/videos/{id}/clips/{clipId}/layouts/auto")
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 \"instructions\": \"Keep the camera visible the whole time\",\n \"style\": \"product-demo-round\"\n}"
response = http.request(request)
puts response.read_body{
"layouts": [
{
"id": "<string>",
"media": [
{
"type": "image",
"height": 0,
"imageUrl": "<string>",
"slot": "screen",
"sourceId": "<string>",
"width": 0
}
],
"crop": {
"bottom": 1,
"left": 1,
"right": 1,
"top": 1
},
"durationMs": 5000,
"followsBase": true,
"layout": {
"kind": "fullscreen",
"screenFit": "cover",
"style": "regular"
},
"popOut": {
"amount": 0.25,
"background": "original",
"color": "<string>",
"outlineColor": "<string>",
"outlineWidth": 0.025
},
"startTimeMs": 0,
"transitionStyle": "spring"
}
],
"editingStyle": "product-demo-round"
}{
"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": "conflict",
"message": "The request conflicts with the resource's current state, e.g. an Idempotency-Key whose first request is still in progress. Retry once it settles."
}{
"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."
}{
"docsUrl": "https://docs.tella.com/",
"error": "unavailable",
"message": "A dependency was unavailable and the request was not executed. Safe to resend unchanged after the Retry-After delay."
}Authorizations
API key obtained from your Tella account settings
Path Parameters
Video identifier
"vid_abc123def456"
Clip identifier
"cl_xyz789ghi012"
Body
Let AI watch the clip and lay it out — the API twin of the editor's "Auto layouts". Replaces the clip's existing layouts with the generated ones.
Free-form guidance for the AI, e.g. "keep the camera visible the whole time" or "punch in whenever a menu is opened".
2000"Keep the camera visible the whole time"
Editing style guiding the AI's layout choices. Omit to let the AI pick one based on the clip's content.
product-demo-portrait, product-demo-round, product-demo-square, product-demo-wide, presentation-tv-show, presentation-portrait, tutorial-round, tutorial-square, intro, outro, intro-and-outro "product-demo-round"
Response
OK
Layouts generated by AI for the clip
The generated time-ranged layouts. The clip's base layout is also updated; fetch it via the layouts list endpoint.
Hide child attributes
Hide child attributes
Layout ID
B-roll media on this layout — one entry per filled slot (screen and/or camera). Empty on the base layout and on layouts whose underlying section carries no media. Each entry's slot says which slot it fills.
Hide child attributes
Hide child attributes
image, video Image height in pixels (image media only).
-9007199254740991 <= x <= 9007199254740991Hosted image URL, for image media. Read-only: not accepted as input — pass sourceId instead.
Which slot the media fills: screen (the subject/main frame, the default) or camera (the bubble/presentation slot — a media bubble over the recording behind it). A camera slot requires a layout that renders the camera (e.g. camera-bubble, side-by-side, tv-presenter).
screen, camera Source ID the media was created from. Absent for image media added in the editor.
Image width in pixels (image media only).
-9007199254740991 <= x <= 9007199254740991The crop of the clip's screen recording while this layout shows — the layout's own crop, else the clip's. Absent when the recording is uncropped.
Hide child attributes
Hide child attributes
Pixels of the screen recording removed from its bottom edge
x >= 0Pixels of the screen recording removed from its left edge
x >= 0Pixels of the screen recording removed from its right edge
x >= 0Pixels of the screen recording removed from its top edge
x >= 0Layout duration in ms. Omitted for clip-spanning layouts.
x >= 05000
True when this layout follows the clip's base layout: updating the base layout changes it too, so it needs no update of its own. False when it has its own layout. Absent on the base layout itself.
Structured layout for this section. Custom layouts, whether arranged in the editor or written through the API, report their geometry as kind: custom. Null only for internal layouts outside the public vocabulary.
- Fullscreen
- Middle
- Side by Side
- TV Presenter
- Cut Out
- Camera Bubble
- Camera Only
- Screen Only
- Custom
Hide child attributes
Hide child attributes
fullscreen Only honoured for basic-subject clips (Tella renders the screen fullscreen). Defaults to cover.
cover, letterbox Only honoured for camera-subject clips: regular (default) is plain fullscreen, stretch stretches the subject. Ignored on basic-subject clips.
regular, stretch The camera's pop-out while this layout shows. Absent when it is off.
Hide child attributes
Hide child attributes
How far the frame shrinks below the presenter, as a fraction of the camera slot (0–0.5). Defaults to 0.22.
0 <= x <= 0.5What fills the frame behind the presenter: original keeps the camera feed, color paints color. Defaults to original.
original, color Frame fill when background is color, as #RRGGBB or #RRGGBBAA. Defaults to #6366F1.
^#[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$Outline colour as #RRGGBB or #RRGGBBAA. Defaults to #FFFFFF.
^#[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$Outline around the frame as a fraction of its width (0–0.05); 0 draws none. Defaults to 0.
0 <= x <= 0.05Layout start time in ms on the clip's playback timeline (cuts applied). Omitted for clip-spanning layouts.
x >= 00
Transition into this layout. Omitted on the base layout, or when the section uses an internal style not exposed via the public API.
spring, hardCut The editing style the AI chose (or was told to use).
product-demo-portrait, product-demo-round, product-demo-square, product-demo-wide, presentation-tv-show, presentation-portrait, tutorial-round, tutorial-square, intro, outro, intro-and-outro "product-demo-round"
Was this page helpful?