Generate from a prompt
Instead of building a timeline yourself, you can describe the video and let Rendley’s agent do the work. The agent searches stock, generates media, and edits the project’s timeline to match your request. You then export the project to a file.
The agent runs on a thread tied to a project. You start a session with a message and read the result back as a Server-Sent Events (SSE) stream. The same Authorization: Bearer key authorizes it.
1. Create a project and a thread
Create a project (see Render a video), then open a thread on it.
/v1/agent/threads curl -X POST https://api.rendley.com/v1/agent/threads \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "project_id": "PROJECT_ID" }'
Keep the returned thread_id. You can also fetch the most recent thread for a project with GET /v1/agent/threads/last?project_id=....
2. Start a session
/v1/agent/sessions Send your prompt as message. The response is a text/event-stream, not JSON, so read it as a stream.
| Field | Type | Notes |
|---|---|---|
thread_id | string, required | The thread from step 1. |
project_id | string, required | The project the agent edits. |
message | string, required | What you want, in plain language. Up to 500,000 characters. |
attachments | array, optional | Your own media to use, each { "media_id": "..." }, from an upload. Up to 20. |
curl -N -X POST https://api.rendley.com/v1/agent/sessions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"thread_id": "THREAD_ID",
"project_id": "PROJECT_ID",
"message": "Edit this interview into a 3-minute reel with captions and music."
}'
3. Read the stream
The stream emits named events. Read until completed (success) or error.
| Event | Meaning |
|---|---|
token | A chunk of the agent’s text reply. data is { "content": "..." }. |
token_done | The text reply is finished. |
interrupt | The agent is pausing for a decision (see step 4). |
completed | The agent finished. The project is now edited. |
error | The agent stopped. data carries the reason. |
const res = await fetch("https://api.rendley.com/v1/agent/sessions", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
thread_id: "THREAD_ID",
project_id: "PROJECT_ID",
message: "Edit this interview into a 3-minute reel with captions and music.",
}),
});
const reader = res.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
while (true) {
const { value, done } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const chunks = buffer.split("\n\n");
buffer = chunks.pop();
for (const chunk of chunks) {
const event = /event: (.*)/.exec(chunk)?.[1];
const data = /data: (.*)/.exec(chunk)?.[1];
if (event === "token") process.stdout.write(JSON.parse(data).content);
if (event === "interrupt") { /* resume, see step 4 */ }
if (event === "completed") console.log("\nDone");
if (event === "error") throw new Error(data);
}
} import json, requests
with requests.post(
"https://api.rendley.com/v1/agent/sessions",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"thread_id": "THREAD_ID",
"project_id": "PROJECT_ID",
"message": "Edit this interview into a 3-minute reel with captions and music.",
},
stream=True,
) as res:
event = None
for line in res.iter_lines(decode_unicode=True):
if line.startswith("event: "):
event = line[7:]
elif line.startswith("data: "):
data = line[6:]
if event == "token":
print(json.loads(data)["content"], end="")
elif event == "completed":
print("\nDone")
elif event == "error":
raise RuntimeError(data) 4. Approve or stop (interrupts)
The agent can pause and emit an interrupt event when it wants a decision, for example to approve a plan or a tool. Continue (or stop) by posting to the resume endpoint, then read the new stream the same way.
/v1/agent/sessions/resume curl -N -X POST https://api.rendley.com/v1/agent/sessions/resume \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"thread_id": "THREAD_ID",
"interrupt_id": "INTERRUPT_ID",
"response": "approve"
}'
response is approve, reject, or free text answering the agent’s question. For an unattended backend, resume every interrupt with approve to let the agent run to completion.
5. Export
When the session completes, the project is edited but not yet rendered. Export it and poll the job to get a downloadable file.