curl --request POST \
--url https://api.tella.com/v1/sources \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"duration": 1,
"height": 4503599627370495,
"width": 4503599627370495
}
'import requests
url = "https://api.tella.com/v1/sources"
payload = {
"duration": 1,
"height": 4503599627370495,
"width": 4503599627370495
}
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({duration: 1, height: 4503599627370495, width: 4503599627370495})
};
fetch('https://api.tella.com/v1/sources', 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/sources",
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([
'duration' => 1,
'height' => 4503599627370495,
'width' => 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/sources"
payload := strings.NewReader("{\n \"duration\": 1,\n \"height\": 4503599627370495,\n \"width\": 4503599627370495\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/sources")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"duration\": 1,\n \"height\": 4503599627370495,\n \"width\": 4503599627370495\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tella.com/v1/sources")
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 \"duration\": 1,\n \"height\": 4503599627370495,\n \"width\": 4503599627370495\n}"
response = http.request(request)
puts response.read_body{
"expiresAt": "2023-11-07T05:31:56Z",
"sourceId": "<string>",
"uploadUrl": "<string>"
}{
"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."
}Create a source upload (video, audio, image, or LUT)
Returns a sourceId and a pre-signed S3 URL. PUT the file bytes to uploadUrl, then reference sourceId from clips, layouts (b-roll media), overlays, or backgrounds. For a 3D .cube LUT use kind: "lut", omit dimensions and duration, upload unchanged, then save it with POST /v1/library and apply the returned item id with PATCH /v1/videos/{id}/clips/{clipId}/filters. Use kind: "image" for images (no duration); Tella hosts the bytes for rendering, so you never deal with raw image URLs. To reuse an uploaded source in other videos, save it to the workspace library with POST /v1/library (scope: "workspace"); GET /v1/library then finds it from any video.
curl --request POST \
--url https://api.tella.com/v1/sources \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"duration": 1,
"height": 4503599627370495,
"width": 4503599627370495
}
'import requests
url = "https://api.tella.com/v1/sources"
payload = {
"duration": 1,
"height": 4503599627370495,
"width": 4503599627370495
}
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({duration: 1, height: 4503599627370495, width: 4503599627370495})
};
fetch('https://api.tella.com/v1/sources', 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/sources",
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([
'duration' => 1,
'height' => 4503599627370495,
'width' => 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/sources"
payload := strings.NewReader("{\n \"duration\": 1,\n \"height\": 4503599627370495,\n \"width\": 4503599627370495\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/sources")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"duration\": 1,\n \"height\": 4503599627370495,\n \"width\": 4503599627370495\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tella.com/v1/sources")
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 \"duration\": 1,\n \"height\": 4503599627370495,\n \"width\": 4503599627370495\n}"
response = http.request(request)
puts response.read_body{
"expiresAt": "2023-11-07T05:31:56Z",
"sourceId": "<string>",
"uploadUrl": "<string>"
}{
"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
Body
Create a new source upload (video, audio, image, 3D .cube LUT, or font). Returns a pre-signed S3 URL to PUT the bytes to, plus a sourceId to reference from clips, layouts, overlays, backgrounds, and sound effects. For a LUT, upload the .cube unchanged and save it with POST /v1/library; use the returned library item id with PATCH /v1/videos/{id}/clips/{clipId}/filters. For a font, upload the .ttf or .otf unchanged and save it with POST /v1/library; use the returned library item id as a text overlay's fontId.
Duration in seconds. Required for video and audio; omit for image, lut and font.
x > 0Height in pixels. Required for video and image; omit for audio, lut and font.
0 < x <= 9007199254740991Source kind: video (default), audio (e.g. sound effects), image, lut (a 3D .cube LUT), or font (a .ttf or .otf file).
video, audio, image, lut, font Width in pixels. Required for video and image; omit for audio, lut and font.
0 < x <= 9007199254740991Response
OK
ISO-8601 timestamp at which uploadUrl stops accepting uploads.
^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$ID of the new source.
Pre-signed S3 URL. PUT the file bytes here (single PUT, max ~5GB). Upload the file as-is: any common container is accepted (MP4, MOV, WebM, MP3, WAV, M4A, …) — the .mp4 in the URL path is just the storage key, not a container requirement.
Was this page helpful?