curl --request POST \
--url https://api.tella.com/v1/library \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"sourceId": "su_abc123def456",
"from": "pinterest",
"name": "Intro camera take",
"videoId": "vid_abc123def456"
}
'import requests
url = "https://api.tella.com/v1/library"
payload = {
"sourceId": "su_abc123def456",
"from": "pinterest",
"name": "Intro camera take",
"videoId": "vid_abc123def456"
}
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({
sourceId: 'su_abc123def456',
from: 'pinterest',
name: 'Intro camera take',
videoId: 'vid_abc123def456'
})
};
fetch('https://api.tella.com/v1/library', 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/library",
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([
'sourceId' => 'su_abc123def456',
'from' => 'pinterest',
'name' => 'Intro camera take',
'videoId' => 'vid_abc123def456'
]),
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/library"
payload := strings.NewReader("{\n \"sourceId\": \"su_abc123def456\",\n \"from\": \"pinterest\",\n \"name\": \"Intro camera take\",\n \"videoId\": \"vid_abc123def456\"\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/library")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"sourceId\": \"su_abc123def456\",\n \"from\": \"pinterest\",\n \"name\": \"Intro camera take\",\n \"videoId\": \"vid_abc123def456\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tella.com/v1/library")
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 \"sourceId\": \"su_abc123def456\",\n \"from\": \"pinterest\",\n \"name\": \"Intro camera take\",\n \"videoId\": \"vid_abc123def456\"\n}"
response = http.request(request)
puts response.read_body{
"item": {
"id": "media_abc123def456",
"name": "Intro camera take",
"scope": "private",
"type": "video",
"category": "Everyday",
"createdAt": "<string>",
"dimensions": {
"height": 0,
"width": 0
},
"durationMs": 4200,
"link": "<string>",
"presetId": "cha-ching",
"sourceId": "su_abc123def456",
"summary": "<string>",
"tags": [
"<string>"
],
"updatedAt": "<string>",
"url": "<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."
}Add a source to the library
Saves an uploaded source to the library so it can be listed and reused later, both here and in the editor’s media panels. Create the source via POST /v1/sources and upload the bytes first, then pass its sourceId. Without this a source is only reachable through the clips that already reference it. To bring in an image you saved in a connected Pinterest, Are.na or mymind account instead, pass from with the service and sourceId set to the item’s id from GET /v1/library?scope=<service>; Tella copies the image into your private library (default), the workspace library, or with scope: "video" the library of the video named by videoId. Only images can be brought in: Pinterest image pins, Are.na image blocks, and mymind images or the screenshot mymind took of a saved page.
curl --request POST \
--url https://api.tella.com/v1/library \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"sourceId": "su_abc123def456",
"from": "pinterest",
"name": "Intro camera take",
"videoId": "vid_abc123def456"
}
'import requests
url = "https://api.tella.com/v1/library"
payload = {
"sourceId": "su_abc123def456",
"from": "pinterest",
"name": "Intro camera take",
"videoId": "vid_abc123def456"
}
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({
sourceId: 'su_abc123def456',
from: 'pinterest',
name: 'Intro camera take',
videoId: 'vid_abc123def456'
})
};
fetch('https://api.tella.com/v1/library', 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/library",
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([
'sourceId' => 'su_abc123def456',
'from' => 'pinterest',
'name' => 'Intro camera take',
'videoId' => 'vid_abc123def456'
]),
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/library"
payload := strings.NewReader("{\n \"sourceId\": \"su_abc123def456\",\n \"from\": \"pinterest\",\n \"name\": \"Intro camera take\",\n \"videoId\": \"vid_abc123def456\"\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/library")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"sourceId\": \"su_abc123def456\",\n \"from\": \"pinterest\",\n \"name\": \"Intro camera take\",\n \"videoId\": \"vid_abc123def456\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tella.com/v1/library")
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 \"sourceId\": \"su_abc123def456\",\n \"from\": \"pinterest\",\n \"name\": \"Intro camera take\",\n \"videoId\": \"vid_abc123def456\"\n}"
response = http.request(request)
puts response.read_body{
"item": {
"id": "media_abc123def456",
"name": "Intro camera take",
"scope": "private",
"type": "video",
"category": "Everyday",
"createdAt": "<string>",
"dimensions": {
"height": 0,
"width": 0
},
"durationMs": 4200,
"link": "<string>",
"presetId": "cha-ching",
"sourceId": "su_abc123def456",
"summary": "<string>",
"tags": [
"<string>"
],
"updatedAt": "<string>",
"url": "<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
Save an uploaded source to the library so it can be listed and reused later, or, with from, bring in an image you saved in a connected Pinterest, Are.na or mymind account. LUT sources must be valid 3D .cube files with LUT_3D_SIZE at most 65. Apply a saved LUT using its item id in PATCH /v1/videos/{id}/clips/{clipId}/filters. Font sources must be .ttf or .otf files of at most 20 MB; the item is named after the font's family and its id is a text overlay's fontId.
Source ID from POST /v1/sources, with the bytes already uploaded to its uploadUrl. With from, the id of an item from GET /v1/library?scope=<from> instead.
"su_abc123def456"
Bring an image in from your connected Pinterest, Are.na or mymind account instead of saving an uploaded source. Tella copies the image, and the returned item's sourceId places it like any other image.
pinterest, arena, mymind "pinterest"
Display name shown in the library. Defaults to the item's type.
1 - 255"Intro camera take"
Where to save the item (default: private). workspace shares it with everyone in the workspace and requires an owner or member role; viewers get a 403. video, with from only, saves it to the library of the video named by videoId.
private, workspace, video Expected item type. Optional — the type is taken from the source's own kind; supplying a value that disagrees is an error.
image, video, sound-effect, lut, font With from and scope: "video": the video whose media library the image is saved to. Requires edit access to that video.
"vid_abc123def456"
Response
Created
The newly created library item
A placeable piece of media — either saved to a workspace's library, or an entry in Tella's curated catalog
Hide child attributes
Hide child attributes
Unique library item identifier
"media_abc123def456"
Display name shown in the library
"Intro camera take"
Where the item lives: a library scope, video for an image brought into one video's library, or pinterest, arena or mymind for an image still in the connected service
private, workspace, default, video, pinterest, arena, mymind "private"
The kind of media the item holds
image, video, sound-effect, music, lut, screenshot, font "video"
Catalog grouping, for default items only — the same grouping the editor's sound effects and background music panels show
"Everyday"
ISO-8601 creation timestamp. Absent for default catalog items, which are served from Tella's catalog rather than stored as rows.
Duration in milliseconds, for time-based media
4200
For pinterest, arena and mymind items: the page the pin or save links to
Preset ID, for default catalog items only. A preset has no source, so pass this instead of sourceId: a sound-effect preset goes to POST /v1/videos/{id}/clips/{clipId}/sound-effects (placing it copies the effect into a source owned by your workspace), a music preset to PUT /v1/videos/{id}/background-music.
"cha-ching"
Source ID. Pass it anywhere a sourceId is accepted — clips, layouts, overlays, sound effects. Present for every item added through this API, including images. Absent for items added in the editor, which have no source, for music, LUT and font items, and for default catalog items, which use presetId instead.
"su_abc123def456"
For mymind items: mymind's AI summary of the save
For mymind items: the save's tags
ISO-8601 update timestamp. Absent for default catalog items.
Hosted media URL, for image, screenshot, music, lut and font items, and for default catalog items, where it is a publicly fetchable preview of the audio (for music presets it is also the track the video will play). API-created images expose this alongside sourceId; use sourceId to place the image on a clip, since overlays and layout media do not accept URLs. Editor-created screenshot items have a URL but no sourceId; use POST /v1/library/screenshots to capture a new placeable image or video.
Was this page helpful?