API reference
Projects
Create, read, update and delete projects. A project holds the timeline the agent edits and the export renders, and can be duplicated or rolled back.
Don't have one? Create an API key
const res = await fetch("https://api.rendley.com/v1/projects", {
headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const { data } = await res.json();curl "https://api.rendley.com/v1/projects" \
-H "Authorization: Bearer YOUR_API_KEY"import requests
res = requests.get(
"https://api.rendley.com/v1/projects",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
data = res.json()["data"]$ch = curl_init("https://api.rendley.com/v1/projects");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY"]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.rendley.com/v1/projects", nil)
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
b, _ := io.ReadAll(res.Body)
fmt.Println(string(b))
}require "net/http"
require "json"
uri = URI("https://api.rendley.com/v1/projects")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]Response 200
{
"data": [
{
"agent_prompt": "string",
"created_at": "string",
"created_by": "string",
"deleted_at": "string",
"fit_duration": 0,
"id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70",
"last_viewed_at": "string",
"name": "string",
"project_json": "string",
"thumbnail_url": "string",
"updated_at": "string",
"version": 0,
"workspace_id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70"
}
]
}#Create a project
Create a new project, optionally from a template. workspace_id may be omitted when the account has exactly one workspace.
https://api.rendley.com/v1/projectsDon't have one? Create an API key
AgentPrompt, when set, is stored on the project and prefilled into the assistant when the editor opens (MCP draft handoff).
Max matches the projects.name column (VARCHAR(255)).
Optional when the account has exactly one workspace: the project is created there. Required once a second workspace exists.
const res = await fetch("https://api.rendley.com/v1/projects", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
body: JSON.stringify({
"name": "<name>"
}),
});
const { data } = await res.json();curl -X POST "https://api.rendley.com/v1/projects" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "<name>"
}'import requests
res = requests.post(
"https://api.rendley.com/v1/projects",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"name": "<name>"
},
)
data = res.json()["data"]$ch = curl_init("https://api.rendley.com/v1/projects");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY", "Content-Type: application/json"]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(["name" => "<name>"]));
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];package main
import (
"fmt"
"io"
"net/http"
"bytes"
)
func main() {
body := bytes.NewBufferString(`{
"name": "<name>"
}`)
req, _ := http.NewRequest("POST", "https://api.rendley.com/v1/projects", body)
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
b, _ := io.ReadAll(res.Body)
fmt.Println(string(b))
}require "net/http"
require "json"
uri = URI("https://api.rendley.com/v1/projects")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"
req["Content-Type"] = "application/json"
req.body = { name: "<name>" }.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]Response 200
{
"data": {
"agent_prompt": "string",
"created_at": "string",
"created_by": "string",
"deleted_at": "string",
"fit_duration": 0,
"id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70",
"last_viewed_at": "string",
"name": "string",
"project_json": "string",
"thumbnail_url": "string",
"updated_at": "string",
"version": 0,
"workspace_id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70"
}
}Don't have one? Create an API key
const res = await fetch("https://api.rendley.com/v1/projects/ID", {
headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const { data } = await res.json();curl "https://api.rendley.com/v1/projects/ID" \
-H "Authorization: Bearer YOUR_API_KEY"import requests
res = requests.get(
"https://api.rendley.com/v1/projects/ID",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
data = res.json()["data"]$ch = curl_init("https://api.rendley.com/v1/projects/ID");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY"]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.rendley.com/v1/projects/ID", nil)
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
b, _ := io.ReadAll(res.Body)
fmt.Println(string(b))
}require "net/http"
require "json"
uri = URI("https://api.rendley.com/v1/projects/ID")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]Response 200
{
"data": {
"agent_prompt": "string",
"created_at": "string",
"created_by": "string",
"deleted_at": "string",
"fit_duration": 0,
"id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70",
"last_viewed_at": "string",
"name": "string",
"project_json": "string",
"thumbnail_url": "string",
"updated_at": "string",
"version": 0,
"workspace_id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70"
}
}#Update a project
https://api.rendley.com/v1/projects/{id}Update a project's mutable fields. Send only the fields you want to change. Public API keys may update metadata but cannot persist project_json until SDK schema validation is available; browser sessions retain the editor save behavior.
Don't have one? Create an API key
AdoptFileHashes lists role=pending uploads to retag role=library in the same request, AFTER the project JSON is saved: the atomic "save project + adopt pending uploads" step of the library injection flow. Adoption is skipped when the save itself fails.
AgentPrompt updates the stored handoff prompt out of band from the version-guarded document save: "" clears it (on send), non-empty sets it, nil leaves it untouched.
const res = await fetch("https://api.rendley.com/v1/projects/ID", {
method: "PATCH",
headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
body: JSON.stringify({
"adopt_file_hashes": [
"string"
],
"agent_prompt": "<agent_prompt>",
"fit_duration": 0
}),
});
const { data } = await res.json();curl -X PATCH "https://api.rendley.com/v1/projects/ID" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"adopt_file_hashes": [
"string"
],
"agent_prompt": "<agent_prompt>",
"fit_duration": 0
}'import requests
res = requests.patch(
"https://api.rendley.com/v1/projects/ID",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"adopt_file_hashes": [
"string"
],
"agent_prompt": "<agent_prompt>",
"fit_duration": 0
},
)
data = res.json()["data"]$ch = curl_init("https://api.rendley.com/v1/projects/ID");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PATCH");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY", "Content-Type: application/json"]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(["adopt_file_hashes" => ["string"], "agent_prompt" => "<agent_prompt>", "fit_duration" => 0]));
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];package main
import (
"fmt"
"io"
"net/http"
"bytes"
)
func main() {
body := bytes.NewBufferString(`{
"adopt_file_hashes": [
"string"
],
"agent_prompt": "<agent_prompt>",
"fit_duration": 0
}`)
req, _ := http.NewRequest("PATCH", "https://api.rendley.com/v1/projects/ID", body)
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
b, _ := io.ReadAll(res.Body)
fmt.Println(string(b))
}require "net/http"
require "json"
uri = URI("https://api.rendley.com/v1/projects/ID")
req = Net::HTTP::Patch.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"
req["Content-Type"] = "application/json"
req.body = { adopt_file_hashes: ["string"], agent_prompt: "<agent_prompt>", fit_duration: 0 }.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]Don't have one? Create an API key
const res = await fetch("https://api.rendley.com/v1/projects/ID", {
method: "DELETE",
headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const { data } = await res.json();curl -X DELETE "https://api.rendley.com/v1/projects/ID" \
-H "Authorization: Bearer YOUR_API_KEY"import requests
res = requests.delete(
"https://api.rendley.com/v1/projects/ID",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
data = res.json()["data"]$ch = curl_init("https://api.rendley.com/v1/projects/ID");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY"]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("DELETE", "https://api.rendley.com/v1/projects/ID", nil)
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
b, _ := io.ReadAll(res.Body)
fmt.Println(string(b))
}require "net/http"
require "json"
uri = URI("https://api.rendley.com/v1/projects/ID")
req = Net::HTTP::Delete.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]#Duplicate a project
Create a copy of an existing project, including its media assets.
https://api.rendley.com/v1/projects/{id}/duplicateDon't have one? Create an API key
const res = await fetch("https://api.rendley.com/v1/projects/ID/duplicate", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const { data } = await res.json();curl -X POST "https://api.rendley.com/v1/projects/ID/duplicate" \
-H "Authorization: Bearer YOUR_API_KEY"import requests
res = requests.post(
"https://api.rendley.com/v1/projects/ID/duplicate",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
data = res.json()["data"]$ch = curl_init("https://api.rendley.com/v1/projects/ID/duplicate");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY"]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("POST", "https://api.rendley.com/v1/projects/ID/duplicate", nil)
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
b, _ := io.ReadAll(res.Body)
fmt.Println(string(b))
}require "net/http"
require "json"
uri = URI("https://api.rendley.com/v1/projects/ID/duplicate")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]Response 200
{
"data": {
"agent_prompt": "string",
"created_at": "string",
"created_by": "string",
"deleted_at": "string",
"fit_duration": 0,
"id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70",
"last_viewed_at": "string",
"name": "string",
"project_json": "string",
"thumbnail_url": "string",
"updated_at": "string",
"version": 0,
"workspace_id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70"
}
}#Get a project's version
Retrieve the current version number of a project. The version increments on every document save; poll it to detect edits made in the studio.
https://api.rendley.com/v1/projects/{id}/versionDon't have one? Create an API key
const res = await fetch("https://api.rendley.com/v1/projects/ID/version", {
headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const { data } = await res.json();curl "https://api.rendley.com/v1/projects/ID/version" \
-H "Authorization: Bearer YOUR_API_KEY"import requests
res = requests.get(
"https://api.rendley.com/v1/projects/ID/version",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
data = res.json()["data"]$ch = curl_init("https://api.rendley.com/v1/projects/ID/version");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY"]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.rendley.com/v1/projects/ID/version", nil)
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
b, _ := io.ReadAll(res.Body)
fmt.Println(string(b))
}require "net/http"
require "json"
uri = URI("https://api.rendley.com/v1/projects/ID/version")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]