curl --request PATCH \
--url https://api.tella.com/v1/videos/{id}/clips/{clipId}/layouts/{layoutId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"crop": {
"bottom": 1,
"left": 1,
"right": 1,
"top": 1
},
"durationMs": 4503599627370596,
"layout": {
"kind": "fullscreen"
},
"media": {
"sourceId": "<string>",
"type": "image"
},
"popOut": {
"amount": 0.25,
"color": "<string>",
"outlineColor": "<string>",
"outlineWidth": 0.025
},
"startTimeMs": 4503599627370495
}
'import requests
url = "https://api.tella.com/v1/videos/{id}/clips/{clipId}/layouts/{layoutId}"
payload = {
"crop": {
"bottom": 1,
"left": 1,
"right": 1,
"top": 1
},
"durationMs": 4503599627370596,
"layout": { "kind": "fullscreen" },
"media": {
"sourceId": "<string>",
"type": "image"
},
"popOut": {
"amount": 0.25,
"color": "<string>",
"outlineColor": "<string>",
"outlineWidth": 0.025
},
"startTimeMs": 4503599627370495
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
crop: {bottom: 1, left: 1, right: 1, top: 1},
durationMs: 4503599627370596,
layout: {kind: 'fullscreen'},
media: {sourceId: '<string>', type: 'image'},
popOut: {amount: 0.25, color: '<string>', outlineColor: '<string>', outlineWidth: 0.025},
startTimeMs: 4503599627370495
})
};
fetch('https://api.tella.com/v1/videos/{id}/clips/{clipId}/layouts/{layoutId}', 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/{layoutId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'crop' => [
'bottom' => 1,
'left' => 1,
'right' => 1,
'top' => 1
],
'durationMs' => 4503599627370596,
'layout' => [
'kind' => 'fullscreen'
],
'media' => [
'sourceId' => '<string>',
'type' => 'image'
],
'popOut' => [
'amount' => 0.25,
'color' => '<string>',
'outlineColor' => '<string>',
'outlineWidth' => 0.025
],
'startTimeMs' => 4503599627370495
]),
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/{layoutId}"
payload := strings.NewReader("{\n \"crop\": {\n \"bottom\": 1,\n \"left\": 1,\n \"right\": 1,\n \"top\": 1\n },\n \"durationMs\": 4503599627370596,\n \"layout\": {\n \"kind\": \"fullscreen\"\n },\n \"media\": {\n \"sourceId\": \"<string>\",\n \"type\": \"image\"\n },\n \"popOut\": {\n \"amount\": 0.25,\n \"color\": \"<string>\",\n \"outlineColor\": \"<string>\",\n \"outlineWidth\": 0.025\n },\n \"startTimeMs\": 4503599627370495\n}")
req, _ := http.NewRequest("PATCH", 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.patch("https://api.tella.com/v1/videos/{id}/clips/{clipId}/layouts/{layoutId}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"crop\": {\n \"bottom\": 1,\n \"left\": 1,\n \"right\": 1,\n \"top\": 1\n },\n \"durationMs\": 4503599627370596,\n \"layout\": {\n \"kind\": \"fullscreen\"\n },\n \"media\": {\n \"sourceId\": \"<string>\",\n \"type\": \"image\"\n },\n \"popOut\": {\n \"amount\": 0.25,\n \"color\": \"<string>\",\n \"outlineColor\": \"<string>\",\n \"outlineWidth\": 0.025\n },\n \"startTimeMs\": 4503599627370495\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tella.com/v1/videos/{id}/clips/{clipId}/layouts/{layoutId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"crop\": {\n \"bottom\": 1,\n \"left\": 1,\n \"right\": 1,\n \"top\": 1\n },\n \"durationMs\": 4503599627370596,\n \"layout\": {\n \"kind\": \"fullscreen\"\n },\n \"media\": {\n \"sourceId\": \"<string>\",\n \"type\": \"image\"\n },\n \"popOut\": {\n \"amount\": 0.25,\n \"color\": \"<string>\",\n \"outlineColor\": \"<string>\",\n \"outlineWidth\": 0.025\n },\n \"startTimeMs\": 4503599627370495\n}"
response = http.request(request)
puts response.read_body{
"layout": {
"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"
}
}{
"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."
}Update a layout
Update a layout’s shape, timing, transition style, or media. transitionStyle and media are only valid on time-ranged layouts, not on the base (clip-spanning) layout. Updating the base layout also changes every layout that reports followsBase: true.
curl --request PATCH \
--url https://api.tella.com/v1/videos/{id}/clips/{clipId}/layouts/{layoutId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"crop": {
"bottom": 1,
"left": 1,
"right": 1,
"top": 1
},
"durationMs": 4503599627370596,
"layout": {
"kind": "fullscreen"
},
"media": {
"sourceId": "<string>",
"type": "image"
},
"popOut": {
"amount": 0.25,
"color": "<string>",
"outlineColor": "<string>",
"outlineWidth": 0.025
},
"startTimeMs": 4503599627370495
}
'import requests
url = "https://api.tella.com/v1/videos/{id}/clips/{clipId}/layouts/{layoutId}"
payload = {
"crop": {
"bottom": 1,
"left": 1,
"right": 1,
"top": 1
},
"durationMs": 4503599627370596,
"layout": { "kind": "fullscreen" },
"media": {
"sourceId": "<string>",
"type": "image"
},
"popOut": {
"amount": 0.25,
"color": "<string>",
"outlineColor": "<string>",
"outlineWidth": 0.025
},
"startTimeMs": 4503599627370495
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
crop: {bottom: 1, left: 1, right: 1, top: 1},
durationMs: 4503599627370596,
layout: {kind: 'fullscreen'},
media: {sourceId: '<string>', type: 'image'},
popOut: {amount: 0.25, color: '<string>', outlineColor: '<string>', outlineWidth: 0.025},
startTimeMs: 4503599627370495
})
};
fetch('https://api.tella.com/v1/videos/{id}/clips/{clipId}/layouts/{layoutId}', 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/{layoutId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'crop' => [
'bottom' => 1,
'left' => 1,
'right' => 1,
'top' => 1
],
'durationMs' => 4503599627370596,
'layout' => [
'kind' => 'fullscreen'
],
'media' => [
'sourceId' => '<string>',
'type' => 'image'
],
'popOut' => [
'amount' => 0.25,
'color' => '<string>',
'outlineColor' => '<string>',
'outlineWidth' => 0.025
],
'startTimeMs' => 4503599627370495
]),
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/{layoutId}"
payload := strings.NewReader("{\n \"crop\": {\n \"bottom\": 1,\n \"left\": 1,\n \"right\": 1,\n \"top\": 1\n },\n \"durationMs\": 4503599627370596,\n \"layout\": {\n \"kind\": \"fullscreen\"\n },\n \"media\": {\n \"sourceId\": \"<string>\",\n \"type\": \"image\"\n },\n \"popOut\": {\n \"amount\": 0.25,\n \"color\": \"<string>\",\n \"outlineColor\": \"<string>\",\n \"outlineWidth\": 0.025\n },\n \"startTimeMs\": 4503599627370495\n}")
req, _ := http.NewRequest("PATCH", 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.patch("https://api.tella.com/v1/videos/{id}/clips/{clipId}/layouts/{layoutId}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"crop\": {\n \"bottom\": 1,\n \"left\": 1,\n \"right\": 1,\n \"top\": 1\n },\n \"durationMs\": 4503599627370596,\n \"layout\": {\n \"kind\": \"fullscreen\"\n },\n \"media\": {\n \"sourceId\": \"<string>\",\n \"type\": \"image\"\n },\n \"popOut\": {\n \"amount\": 0.25,\n \"color\": \"<string>\",\n \"outlineColor\": \"<string>\",\n \"outlineWidth\": 0.025\n },\n \"startTimeMs\": 4503599627370495\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tella.com/v1/videos/{id}/clips/{clipId}/layouts/{layoutId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"crop\": {\n \"bottom\": 1,\n \"left\": 1,\n \"right\": 1,\n \"top\": 1\n },\n \"durationMs\": 4503599627370596,\n \"layout\": {\n \"kind\": \"fullscreen\"\n },\n \"media\": {\n \"sourceId\": \"<string>\",\n \"type\": \"image\"\n },\n \"popOut\": {\n \"amount\": 0.25,\n \"color\": \"<string>\",\n \"outlineColor\": \"<string>\",\n \"outlineWidth\": 0.025\n },\n \"startTimeMs\": 4503599627370495\n}"
response = http.request(request)
puts response.read_body{
"layout": {
"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"
}
}{
"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 ID
Clip ID
Layout (section) ID
Body
Update an existing layout on a clip
Crop the clip's screen recording for this layout only — the editor's crop modal on “This layout only”. Other layouts keep following the clip's crop; null makes this layout follow it again. Masks that start in the layout stay anchored to their content, and a custom layout's screen box keeps its on-canvas scale unless the same request writes layout geometry. Needs a screen recording in the clip. To crop the recording across the whole clip use auto-crop.
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 >= 0200 <= x <= 9007199254740991Single-layer fullscreen. Camera-subject clips take an optional style (regular/stretch); basic-subject clips take an optional screenFit.
- 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 Replace the layout's media content. Only valid on time-ranged layouts; rejected on the base (clip-spanning) layout.
- ClipMediaImage
- ClipMediaVideo
Hide child attributes
Hide child attributes
Source ID from POST /v1/sources (kind: image).
1image 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 Switch the camera pop-out on (an object merges over the current settings) or off (null). Omitted leaves it as it is, except that a cut-out layout drops it. On the base layout this and crop are accepted without layout.
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.05Start time in ms on the clip's playback timeline (cuts applied)
0 <= x <= 9007199254740991Only valid on time-ranged layouts; rejected on the base (clip-spanning) layout.
spring, hardCut Response
OK
A layout on a clip
A layout attached to a clip. Times are in ms on the clip's playback timeline (cuts applied). Internally the layout stays anchored to the footage, so it doesn't drift when cuts change later.
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 Was this page helpful?