curl --request POST \
--url https://dally.ai/v1/previs.keep \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"previs_id": "bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1",
"index": 1,
"template": {
"format": "9:16",
"layers": [
{
"kind": "picture",
"id": "setting",
"picture": {
"kind": "drawn",
"url": "https://media.withdally.com/generated/previs/7d3f2a1b-4c5e-4f6a-8b9c-0d1e2f3a4b5c/bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1.png",
"panel": 1,
"columns": 2,
"rows": 2,
"format": "9:16",
"previs_id": "bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1"
},
"fit": "cover",
"x": 0,
"y": 0,
"w": 100,
"h": 100
},
{
"kind": "text",
"id": "caption",
"text": "I made a schedule for avoiding my camera.",
"font": "classic",
"box": "black",
"x": 6,
"w": 88,
"y": 10,
"anchor": "top",
"align": "center",
"size": "xl"
}
]
},
"request_key": "keep-b-1"
}
'import requests
url = "https://dally.ai/v1/previs.keep"
payload = {
"previs_id": "bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1",
"index": 1,
"template": {
"format": "9:16",
"layers": [
{
"kind": "picture",
"id": "setting",
"picture": {
"kind": "drawn",
"url": "https://media.withdally.com/generated/previs/7d3f2a1b-4c5e-4f6a-8b9c-0d1e2f3a4b5c/bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1.png",
"panel": 1,
"columns": 2,
"rows": 2,
"format": "9:16",
"previs_id": "bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1"
},
"fit": "cover",
"x": 0,
"y": 0,
"w": 100,
"h": 100
},
{
"kind": "text",
"id": "caption",
"text": "I made a schedule for avoiding my camera.",
"font": "classic",
"box": "black",
"x": 6,
"w": 88,
"y": 10,
"anchor": "top",
"align": "center",
"size": "xl"
}
]
},
"request_key": "keep-b-1"
}
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({
previs_id: 'bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1',
index: 1,
template: {
format: '9:16',
layers: [
{
kind: 'picture',
id: 'setting',
picture: {
kind: 'drawn',
url: 'https://media.withdally.com/generated/previs/7d3f2a1b-4c5e-4f6a-8b9c-0d1e2f3a4b5c/bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1.png',
panel: 1,
columns: 2,
rows: 2,
format: '9:16',
previs_id: 'bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1'
},
fit: 'cover',
x: 0,
y: 0,
w: 100,
h: 100
},
{
kind: 'text',
id: 'caption',
text: 'I made a schedule for avoiding my camera.',
font: 'classic',
box: 'black',
x: 6,
w: 88,
y: 10,
anchor: 'top',
align: 'center',
size: 'xl'
}
]
},
request_key: 'keep-b-1'
})
};
fetch('https://dally.ai/v1/previs.keep', 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://dally.ai/v1/previs.keep",
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([
'previs_id' => 'bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1',
'index' => 1,
'template' => [
'format' => '9:16',
'layers' => [
[
'kind' => 'picture',
'id' => 'setting',
'picture' => [
'kind' => 'drawn',
'url' => 'https://media.withdally.com/generated/previs/7d3f2a1b-4c5e-4f6a-8b9c-0d1e2f3a4b5c/bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1.png',
'panel' => 1,
'columns' => 2,
'rows' => 2,
'format' => '9:16',
'previs_id' => 'bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1'
],
'fit' => 'cover',
'x' => 0,
'y' => 0,
'w' => 100,
'h' => 100
],
[
'kind' => 'text',
'id' => 'caption',
'text' => 'I made a schedule for avoiding my camera.',
'font' => 'classic',
'box' => 'black',
'x' => 6,
'w' => 88,
'y' => 10,
'anchor' => 'top',
'align' => 'center',
'size' => 'xl'
]
]
],
'request_key' => 'keep-b-1'
]),
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://dally.ai/v1/previs.keep"
payload := strings.NewReader("{\n \"previs_id\": \"bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1\",\n \"index\": 1,\n \"template\": {\n \"format\": \"9:16\",\n \"layers\": [\n {\n \"kind\": \"picture\",\n \"id\": \"setting\",\n \"picture\": {\n \"kind\": \"drawn\",\n \"url\": \"https://media.withdally.com/generated/previs/7d3f2a1b-4c5e-4f6a-8b9c-0d1e2f3a4b5c/bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1.png\",\n \"panel\": 1,\n \"columns\": 2,\n \"rows\": 2,\n \"format\": \"9:16\",\n \"previs_id\": \"bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1\"\n },\n \"fit\": \"cover\",\n \"x\": 0,\n \"y\": 0,\n \"w\": 100,\n \"h\": 100\n },\n {\n \"kind\": \"text\",\n \"id\": \"caption\",\n \"text\": \"I made a schedule for avoiding my camera.\",\n \"font\": \"classic\",\n \"box\": \"black\",\n \"x\": 6,\n \"w\": 88,\n \"y\": 10,\n \"anchor\": \"top\",\n \"align\": \"center\",\n \"size\": \"xl\"\n }\n ]\n },\n \"request_key\": \"keep-b-1\"\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://dally.ai/v1/previs.keep")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"previs_id\": \"bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1\",\n \"index\": 1,\n \"template\": {\n \"format\": \"9:16\",\n \"layers\": [\n {\n \"kind\": \"picture\",\n \"id\": \"setting\",\n \"picture\": {\n \"kind\": \"drawn\",\n \"url\": \"https://media.withdally.com/generated/previs/7d3f2a1b-4c5e-4f6a-8b9c-0d1e2f3a4b5c/bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1.png\",\n \"panel\": 1,\n \"columns\": 2,\n \"rows\": 2,\n \"format\": \"9:16\",\n \"previs_id\": \"bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1\"\n },\n \"fit\": \"cover\",\n \"x\": 0,\n \"y\": 0,\n \"w\": 100,\n \"h\": 100\n },\n {\n \"kind\": \"text\",\n \"id\": \"caption\",\n \"text\": \"I made a schedule for avoiding my camera.\",\n \"font\": \"classic\",\n \"box\": \"black\",\n \"x\": 6,\n \"w\": 88,\n \"y\": 10,\n \"anchor\": \"top\",\n \"align\": \"center\",\n \"size\": \"xl\"\n }\n ]\n },\n \"request_key\": \"keep-b-1\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://dally.ai/v1/previs.keep")
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 \"previs_id\": \"bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1\",\n \"index\": 1,\n \"template\": {\n \"format\": \"9:16\",\n \"layers\": [\n {\n \"kind\": \"picture\",\n \"id\": \"setting\",\n \"picture\": {\n \"kind\": \"drawn\",\n \"url\": \"https://media.withdally.com/generated/previs/7d3f2a1b-4c5e-4f6a-8b9c-0d1e2f3a4b5c/bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1.png\",\n \"panel\": 1,\n \"columns\": 2,\n \"rows\": 2,\n \"format\": \"9:16\",\n \"previs_id\": \"bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1\"\n },\n \"fit\": \"cover\",\n \"x\": 0,\n \"y\": 0,\n \"w\": 100,\n \"h\": 100\n },\n {\n \"kind\": \"text\",\n \"id\": \"caption\",\n \"text\": \"I made a schedule for avoiding my camera.\",\n \"font\": \"classic\",\n \"box\": \"black\",\n \"x\": 6,\n \"w\": 88,\n \"y\": 10,\n \"anchor\": \"top\",\n \"align\": \"center\",\n \"size\": \"xl\"\n }\n ]\n },\n \"request_key\": \"keep-b-1\"\n}"
response = http.request(request)
puts response.read_body{
"request_id": "req_previs_example",
"previs": {
"previs_id": "bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1",
"kind": "hooks",
"title": "The plan that made me stop filming",
"format": "9:16",
"frames": [
{
"say": "I spent longer choosing a font than filming.",
"see": "The creator closes a laptop at a kitchen table, looking quietly amused.",
"skeleton": "I spent longer ___ than ___",
"on_screen": "I spent longer ___ than ___",
"other_words": [
"I spent longer choosing a font than filming",
"I spent longer naming the file than filming",
"I spent longer picking a thumbnail than filming"
],
"seconds": 4,
"place": "lower",
"box": "none",
"borrowed_from": []
},
{
"say": "I spent longer choosing a font than filming.",
"see": "The creator closes a laptop at a kitchen table, looking quietly amused.",
"skeleton": "Day ___ of ___",
"on_screen": "Day ___ of ___",
"other_words": [
"Day three of choosing the font",
"Day three of not filming",
"Day three of the same font"
],
"seconds": 4,
"place": "lower",
"box": "none",
"borrowed_from": []
},
{
"say": "I spent longer choosing a font than filming.",
"see": "The creator closes a laptop at a kitchen table, looking quietly amused.",
"skeleton": "Nobody asked but I ___",
"on_screen": "Nobody asked but I ___",
"other_words": [
"Nobody asked but I picked the font",
"Nobody asked but I named the reel",
"Nobody asked but I chose the serif"
],
"seconds": 4,
"place": "lower",
"box": "none",
"borrowed_from": []
},
{
"say": "I spent longer choosing a font than filming.",
"see": "The creator closes a laptop at a kitchen table, looking quietly amused.",
"skeleton": "I finished ___ before I started ___",
"on_screen": "I finished ___ before I started ___",
"other_words": [
"I finished the font before I started filming",
"I finished the plan before I started the reel",
"I finished the intro card before I started the script"
],
"seconds": 4,
"place": "lower",
"box": "none",
"borrowed_from": []
}
],
"receipts": [],
"status": "ready",
"picked_index": null,
"verdicts": [
{
"index": 1,
"verdict": "kept",
"template": {
"format": "9:16",
"layers": [
{
"kind": "picture",
"id": "setting",
"picture": {
"kind": "drawn",
"url": "https://media.withdally.com/generated/previs/7d3f2a1b-4c5e-4f6a-8b9c-0d1e2f3a4b5c/bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1.png",
"panel": 1,
"columns": 2,
"rows": 2,
"format": "9:16",
"previs_id": "bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1"
},
"fit": "cover",
"x": 0,
"y": 0,
"w": 100,
"h": 100
},
{
"kind": "text",
"id": "caption",
"text": "I made a schedule for avoiding my camera.",
"font": "classic",
"box": "black",
"x": 6,
"w": 88,
"y": 10,
"anchor": "top",
"align": "center",
"size": "xl"
}
]
}
}
],
"revision": 1,
"revisions": [
{
"revision": 1,
"made_by": "chat",
"what": "Four hooks authored",
"forked_from": null,
"created_at": "2026-09-10T19:00:00.000Z",
"frames": [
{
"on_screen": "I spent longer ___ than ___",
"place": "lower",
"box": "none"
},
{
"on_screen": "Day ___ of ___",
"place": "lower",
"box": "none"
},
{
"on_screen": "Nobody asked but I ___",
"place": "lower",
"box": "none"
},
{
"on_screen": "I finished ___ before I started ___",
"place": "lower",
"box": "none"
}
]
}
],
"result": {
"image_url": "https://media.withdally.com/generated/previs/7d3f2a1b-4c5e-4f6a-8b9c-0d1e2f3a4b5c/bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1.png",
"width": 864,
"height": 1536,
"artist": "openai/gpt-image-2",
"quality": "low",
"provider": "openrouter",
"cost_usd": 0.04,
"latency_ms": 21000,
"provider_request_id": null,
"usage": {}
},
"error": null,
"created_at": "2026-09-10T19:00:00.000Z"
},
"show": {
"kind": "previs"
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {}
},
"request_id": "<string>"
}previs.keep
Access: public. Send a JSON body; unknown keys are rejected with 400 invalid_request (inputs are strict). Responses may gain fields additively — never remove or repurpose; ignore unknown response fields.
curl --request POST \
--url https://dally.ai/v1/previs.keep \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"previs_id": "bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1",
"index": 1,
"template": {
"format": "9:16",
"layers": [
{
"kind": "picture",
"id": "setting",
"picture": {
"kind": "drawn",
"url": "https://media.withdally.com/generated/previs/7d3f2a1b-4c5e-4f6a-8b9c-0d1e2f3a4b5c/bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1.png",
"panel": 1,
"columns": 2,
"rows": 2,
"format": "9:16",
"previs_id": "bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1"
},
"fit": "cover",
"x": 0,
"y": 0,
"w": 100,
"h": 100
},
{
"kind": "text",
"id": "caption",
"text": "I made a schedule for avoiding my camera.",
"font": "classic",
"box": "black",
"x": 6,
"w": 88,
"y": 10,
"anchor": "top",
"align": "center",
"size": "xl"
}
]
},
"request_key": "keep-b-1"
}
'import requests
url = "https://dally.ai/v1/previs.keep"
payload = {
"previs_id": "bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1",
"index": 1,
"template": {
"format": "9:16",
"layers": [
{
"kind": "picture",
"id": "setting",
"picture": {
"kind": "drawn",
"url": "https://media.withdally.com/generated/previs/7d3f2a1b-4c5e-4f6a-8b9c-0d1e2f3a4b5c/bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1.png",
"panel": 1,
"columns": 2,
"rows": 2,
"format": "9:16",
"previs_id": "bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1"
},
"fit": "cover",
"x": 0,
"y": 0,
"w": 100,
"h": 100
},
{
"kind": "text",
"id": "caption",
"text": "I made a schedule for avoiding my camera.",
"font": "classic",
"box": "black",
"x": 6,
"w": 88,
"y": 10,
"anchor": "top",
"align": "center",
"size": "xl"
}
]
},
"request_key": "keep-b-1"
}
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({
previs_id: 'bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1',
index: 1,
template: {
format: '9:16',
layers: [
{
kind: 'picture',
id: 'setting',
picture: {
kind: 'drawn',
url: 'https://media.withdally.com/generated/previs/7d3f2a1b-4c5e-4f6a-8b9c-0d1e2f3a4b5c/bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1.png',
panel: 1,
columns: 2,
rows: 2,
format: '9:16',
previs_id: 'bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1'
},
fit: 'cover',
x: 0,
y: 0,
w: 100,
h: 100
},
{
kind: 'text',
id: 'caption',
text: 'I made a schedule for avoiding my camera.',
font: 'classic',
box: 'black',
x: 6,
w: 88,
y: 10,
anchor: 'top',
align: 'center',
size: 'xl'
}
]
},
request_key: 'keep-b-1'
})
};
fetch('https://dally.ai/v1/previs.keep', 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://dally.ai/v1/previs.keep",
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([
'previs_id' => 'bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1',
'index' => 1,
'template' => [
'format' => '9:16',
'layers' => [
[
'kind' => 'picture',
'id' => 'setting',
'picture' => [
'kind' => 'drawn',
'url' => 'https://media.withdally.com/generated/previs/7d3f2a1b-4c5e-4f6a-8b9c-0d1e2f3a4b5c/bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1.png',
'panel' => 1,
'columns' => 2,
'rows' => 2,
'format' => '9:16',
'previs_id' => 'bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1'
],
'fit' => 'cover',
'x' => 0,
'y' => 0,
'w' => 100,
'h' => 100
],
[
'kind' => 'text',
'id' => 'caption',
'text' => 'I made a schedule for avoiding my camera.',
'font' => 'classic',
'box' => 'black',
'x' => 6,
'w' => 88,
'y' => 10,
'anchor' => 'top',
'align' => 'center',
'size' => 'xl'
]
]
],
'request_key' => 'keep-b-1'
]),
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://dally.ai/v1/previs.keep"
payload := strings.NewReader("{\n \"previs_id\": \"bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1\",\n \"index\": 1,\n \"template\": {\n \"format\": \"9:16\",\n \"layers\": [\n {\n \"kind\": \"picture\",\n \"id\": \"setting\",\n \"picture\": {\n \"kind\": \"drawn\",\n \"url\": \"https://media.withdally.com/generated/previs/7d3f2a1b-4c5e-4f6a-8b9c-0d1e2f3a4b5c/bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1.png\",\n \"panel\": 1,\n \"columns\": 2,\n \"rows\": 2,\n \"format\": \"9:16\",\n \"previs_id\": \"bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1\"\n },\n \"fit\": \"cover\",\n \"x\": 0,\n \"y\": 0,\n \"w\": 100,\n \"h\": 100\n },\n {\n \"kind\": \"text\",\n \"id\": \"caption\",\n \"text\": \"I made a schedule for avoiding my camera.\",\n \"font\": \"classic\",\n \"box\": \"black\",\n \"x\": 6,\n \"w\": 88,\n \"y\": 10,\n \"anchor\": \"top\",\n \"align\": \"center\",\n \"size\": \"xl\"\n }\n ]\n },\n \"request_key\": \"keep-b-1\"\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://dally.ai/v1/previs.keep")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"previs_id\": \"bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1\",\n \"index\": 1,\n \"template\": {\n \"format\": \"9:16\",\n \"layers\": [\n {\n \"kind\": \"picture\",\n \"id\": \"setting\",\n \"picture\": {\n \"kind\": \"drawn\",\n \"url\": \"https://media.withdally.com/generated/previs/7d3f2a1b-4c5e-4f6a-8b9c-0d1e2f3a4b5c/bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1.png\",\n \"panel\": 1,\n \"columns\": 2,\n \"rows\": 2,\n \"format\": \"9:16\",\n \"previs_id\": \"bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1\"\n },\n \"fit\": \"cover\",\n \"x\": 0,\n \"y\": 0,\n \"w\": 100,\n \"h\": 100\n },\n {\n \"kind\": \"text\",\n \"id\": \"caption\",\n \"text\": \"I made a schedule for avoiding my camera.\",\n \"font\": \"classic\",\n \"box\": \"black\",\n \"x\": 6,\n \"w\": 88,\n \"y\": 10,\n \"anchor\": \"top\",\n \"align\": \"center\",\n \"size\": \"xl\"\n }\n ]\n },\n \"request_key\": \"keep-b-1\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://dally.ai/v1/previs.keep")
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 \"previs_id\": \"bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1\",\n \"index\": 1,\n \"template\": {\n \"format\": \"9:16\",\n \"layers\": [\n {\n \"kind\": \"picture\",\n \"id\": \"setting\",\n \"picture\": {\n \"kind\": \"drawn\",\n \"url\": \"https://media.withdally.com/generated/previs/7d3f2a1b-4c5e-4f6a-8b9c-0d1e2f3a4b5c/bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1.png\",\n \"panel\": 1,\n \"columns\": 2,\n \"rows\": 2,\n \"format\": \"9:16\",\n \"previs_id\": \"bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1\"\n },\n \"fit\": \"cover\",\n \"x\": 0,\n \"y\": 0,\n \"w\": 100,\n \"h\": 100\n },\n {\n \"kind\": \"text\",\n \"id\": \"caption\",\n \"text\": \"I made a schedule for avoiding my camera.\",\n \"font\": \"classic\",\n \"box\": \"black\",\n \"x\": 6,\n \"w\": 88,\n \"y\": 10,\n \"anchor\": \"top\",\n \"align\": \"center\",\n \"size\": \"xl\"\n }\n ]\n },\n \"request_key\": \"keep-b-1\"\n}"
response = http.request(request)
puts response.read_body{
"request_id": "req_previs_example",
"previs": {
"previs_id": "bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1",
"kind": "hooks",
"title": "The plan that made me stop filming",
"format": "9:16",
"frames": [
{
"say": "I spent longer choosing a font than filming.",
"see": "The creator closes a laptop at a kitchen table, looking quietly amused.",
"skeleton": "I spent longer ___ than ___",
"on_screen": "I spent longer ___ than ___",
"other_words": [
"I spent longer choosing a font than filming",
"I spent longer naming the file than filming",
"I spent longer picking a thumbnail than filming"
],
"seconds": 4,
"place": "lower",
"box": "none",
"borrowed_from": []
},
{
"say": "I spent longer choosing a font than filming.",
"see": "The creator closes a laptop at a kitchen table, looking quietly amused.",
"skeleton": "Day ___ of ___",
"on_screen": "Day ___ of ___",
"other_words": [
"Day three of choosing the font",
"Day three of not filming",
"Day three of the same font"
],
"seconds": 4,
"place": "lower",
"box": "none",
"borrowed_from": []
},
{
"say": "I spent longer choosing a font than filming.",
"see": "The creator closes a laptop at a kitchen table, looking quietly amused.",
"skeleton": "Nobody asked but I ___",
"on_screen": "Nobody asked but I ___",
"other_words": [
"Nobody asked but I picked the font",
"Nobody asked but I named the reel",
"Nobody asked but I chose the serif"
],
"seconds": 4,
"place": "lower",
"box": "none",
"borrowed_from": []
},
{
"say": "I spent longer choosing a font than filming.",
"see": "The creator closes a laptop at a kitchen table, looking quietly amused.",
"skeleton": "I finished ___ before I started ___",
"on_screen": "I finished ___ before I started ___",
"other_words": [
"I finished the font before I started filming",
"I finished the plan before I started the reel",
"I finished the intro card before I started the script"
],
"seconds": 4,
"place": "lower",
"box": "none",
"borrowed_from": []
}
],
"receipts": [],
"status": "ready",
"picked_index": null,
"verdicts": [
{
"index": 1,
"verdict": "kept",
"template": {
"format": "9:16",
"layers": [
{
"kind": "picture",
"id": "setting",
"picture": {
"kind": "drawn",
"url": "https://media.withdally.com/generated/previs/7d3f2a1b-4c5e-4f6a-8b9c-0d1e2f3a4b5c/bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1.png",
"panel": 1,
"columns": 2,
"rows": 2,
"format": "9:16",
"previs_id": "bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1"
},
"fit": "cover",
"x": 0,
"y": 0,
"w": 100,
"h": 100
},
{
"kind": "text",
"id": "caption",
"text": "I made a schedule for avoiding my camera.",
"font": "classic",
"box": "black",
"x": 6,
"w": 88,
"y": 10,
"anchor": "top",
"align": "center",
"size": "xl"
}
]
}
}
],
"revision": 1,
"revisions": [
{
"revision": 1,
"made_by": "chat",
"what": "Four hooks authored",
"forked_from": null,
"created_at": "2026-09-10T19:00:00.000Z",
"frames": [
{
"on_screen": "I spent longer ___ than ___",
"place": "lower",
"box": "none"
},
{
"on_screen": "Day ___ of ___",
"place": "lower",
"box": "none"
},
{
"on_screen": "Nobody asked but I ___",
"place": "lower",
"box": "none"
},
{
"on_screen": "I finished ___ before I started ___",
"place": "lower",
"box": "none"
}
]
}
],
"result": {
"image_url": "https://media.withdally.com/generated/previs/7d3f2a1b-4c5e-4f6a-8b9c-0d1e2f3a4b5c/bc3c7b36-7ac7-433d-82ef-58bc2d1fe1d1.png",
"width": 864,
"height": 1536,
"artist": "openai/gpt-image-2",
"quality": "low",
"provider": "openrouter",
"cost_usd": 0.04,
"latency_ms": 21000,
"provider_request_id": null,
"usage": {}
},
"error": null,
"created_at": "2026-09-10T19:00:00.000Z"
},
"show": {
"kind": "previs"
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {}
},
"request_id": "<string>"
}Authorizations
A WorkOS-dashboard-issued internal API key on Authorization: Bearer.
Body
The completed hooks' Previs id.
^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$Zero-based frame: A=0, B=1, C=2, D=3.
0 <= x <= 3The document in front when they kept it: the frame's drawn picture as its setting and its words as text layers, as the card painted it or as they edited it.
Show child attributes
Show child attributes
One key for this one keep; send the same key again and nothing is kept twice.
1 - 128Response
Success. request_id is present on every response.
The stored previs and its current state; dally_show kind previs takes this whole response.
Show child attributes
Show child attributes
How it is shown: dally_write renders this kind on this very answer with this whole response as its data, so the creator already sees it; do not render it again.
Show child attributes
Show child attributes
Server-minted id for this request. Present on every response, success and error — quote it when reporting a problem.
1