Rendley docs

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.

#List projects

List all projects in a workspace.

GEThttps://api.rendley.com/v1/projects

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.

POSThttps://api.rendley.com/v1/projects

Don't have one? Create an API key

Body

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"
  }
}

#Get a project

Retrieve a single project by its ID.

GEThttps://api.rendley.com/v1/projects/{id}

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

PATCHhttps://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

Body

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"]

#Delete a project

Delete a project by its ID.

DELETEhttps://api.rendley.com/v1/projects/{id}

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.

POSThttps://api.rendley.com/v1/projects/{id}/duplicate

Don'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.

GEThttps://api.rendley.com/v1/projects/{id}/version

Don'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"]