Generate Slideshow
curl --request POST \
--url https://api.example.com/api/partner/v1/slideshows/generate \
--header 'Content-Type: application/json' \
--data '
{
"prompt": "<string>",
"product_id": {},
"pack_id": {},
"slide_count": 123,
"slideshow_type": "<string>",
"aspect_ratio": "<string>",
"language": "<string>",
"advanced_settings": {
"font_size": {},
"text_preset": "<string>",
"text_width": "<string>"
},
"skip_ai": true,
"slide_config": {
"total_slides": 123,
"slide_types": [
{}
],
"custom_images": {},
"pinned_images": {},
"slide_texts": {},
"slide_text_elements": {},
"pack_assignments": {}
}
}
'import requests
url = "https://api.example.com/api/partner/v1/slideshows/generate"
payload = {
"prompt": "<string>",
"product_id": {},
"pack_id": {},
"slide_count": 123,
"slideshow_type": "<string>",
"aspect_ratio": "<string>",
"language": "<string>",
"advanced_settings": {
"font_size": {},
"text_preset": "<string>",
"text_width": "<string>"
},
"skip_ai": True,
"slide_config": {
"total_slides": 123,
"slide_types": [{}],
"custom_images": {},
"pinned_images": {},
"slide_texts": {},
"slide_text_elements": {},
"pack_assignments": {}
}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
prompt: '<string>',
product_id: {},
pack_id: {},
slide_count: 123,
slideshow_type: '<string>',
aspect_ratio: '<string>',
language: '<string>',
advanced_settings: {font_size: {}, text_preset: '<string>', text_width: '<string>'},
skip_ai: true,
slide_config: {
total_slides: 123,
slide_types: [{}],
custom_images: {},
pinned_images: {},
slide_texts: {},
slide_text_elements: {},
pack_assignments: {}
}
})
};
fetch('https://api.example.com/api/partner/v1/slideshows/generate', 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.example.com/api/partner/v1/slideshows/generate",
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([
'prompt' => '<string>',
'product_id' => [
],
'pack_id' => [
],
'slide_count' => 123,
'slideshow_type' => '<string>',
'aspect_ratio' => '<string>',
'language' => '<string>',
'advanced_settings' => [
'font_size' => [
],
'text_preset' => '<string>',
'text_width' => '<string>'
],
'skip_ai' => true,
'slide_config' => [
'total_slides' => 123,
'slide_types' => [
[
]
],
'custom_images' => [
],
'pinned_images' => [
],
'slide_texts' => [
],
'slide_text_elements' => [
],
'pack_assignments' => [
]
]
]),
CURLOPT_HTTPHEADER => [
"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.example.com/api/partner/v1/slideshows/generate"
payload := strings.NewReader("{\n \"prompt\": \"<string>\",\n \"product_id\": {},\n \"pack_id\": {},\n \"slide_count\": 123,\n \"slideshow_type\": \"<string>\",\n \"aspect_ratio\": \"<string>\",\n \"language\": \"<string>\",\n \"advanced_settings\": {\n \"font_size\": {},\n \"text_preset\": \"<string>\",\n \"text_width\": \"<string>\"\n },\n \"skip_ai\": true,\n \"slide_config\": {\n \"total_slides\": 123,\n \"slide_types\": [\n {}\n ],\n \"custom_images\": {},\n \"pinned_images\": {},\n \"slide_texts\": {},\n \"slide_text_elements\": {},\n \"pack_assignments\": {}\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
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.example.com/api/partner/v1/slideshows/generate")
.header("Content-Type", "application/json")
.body("{\n \"prompt\": \"<string>\",\n \"product_id\": {},\n \"pack_id\": {},\n \"slide_count\": 123,\n \"slideshow_type\": \"<string>\",\n \"aspect_ratio\": \"<string>\",\n \"language\": \"<string>\",\n \"advanced_settings\": {\n \"font_size\": {},\n \"text_preset\": \"<string>\",\n \"text_width\": \"<string>\"\n },\n \"skip_ai\": true,\n \"slide_config\": {\n \"total_slides\": 123,\n \"slide_types\": [\n {}\n ],\n \"custom_images\": {},\n \"pinned_images\": {},\n \"slide_texts\": {},\n \"slide_text_elements\": {},\n \"pack_assignments\": {}\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/partner/v1/slideshows/generate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"prompt\": \"<string>\",\n \"product_id\": {},\n \"pack_id\": {},\n \"slide_count\": 123,\n \"slideshow_type\": \"<string>\",\n \"aspect_ratio\": \"<string>\",\n \"language\": \"<string>\",\n \"advanced_settings\": {\n \"font_size\": {},\n \"text_preset\": \"<string>\",\n \"text_width\": \"<string>\"\n },\n \"skip_ai\": true,\n \"slide_config\": {\n \"total_slides\": 123,\n \"slide_types\": [\n {}\n ],\n \"custom_images\": {},\n \"pinned_images\": {},\n \"slide_texts\": {},\n \"slide_text_elements\": {},\n \"pack_assignments\": {}\n }\n}"
response = http.request(request)
puts response.read_bodySlideshows
Generate Slideshow
Generate AI-powered slideshows for TikTok photo carousels, Instagram carousels, Pinterest pins, and more. Supports AI generation from prompts, manual slide configuration, and mixed mode. The core content creation endpoint for OpenClaw agents.
POST
/
api
/
partner
/
v1
/
slideshows
/
generate
Generate Slideshow
curl --request POST \
--url https://api.example.com/api/partner/v1/slideshows/generate \
--header 'Content-Type: application/json' \
--data '
{
"prompt": "<string>",
"product_id": {},
"pack_id": {},
"slide_count": 123,
"slideshow_type": "<string>",
"aspect_ratio": "<string>",
"language": "<string>",
"advanced_settings": {
"font_size": {},
"text_preset": "<string>",
"text_width": "<string>"
},
"skip_ai": true,
"slide_config": {
"total_slides": 123,
"slide_types": [
{}
],
"custom_images": {},
"pinned_images": {},
"slide_texts": {},
"slide_text_elements": {},
"pack_assignments": {}
}
}
'import requests
url = "https://api.example.com/api/partner/v1/slideshows/generate"
payload = {
"prompt": "<string>",
"product_id": {},
"pack_id": {},
"slide_count": 123,
"slideshow_type": "<string>",
"aspect_ratio": "<string>",
"language": "<string>",
"advanced_settings": {
"font_size": {},
"text_preset": "<string>",
"text_width": "<string>"
},
"skip_ai": True,
"slide_config": {
"total_slides": 123,
"slide_types": [{}],
"custom_images": {},
"pinned_images": {},
"slide_texts": {},
"slide_text_elements": {},
"pack_assignments": {}
}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
prompt: '<string>',
product_id: {},
pack_id: {},
slide_count: 123,
slideshow_type: '<string>',
aspect_ratio: '<string>',
language: '<string>',
advanced_settings: {font_size: {}, text_preset: '<string>', text_width: '<string>'},
skip_ai: true,
slide_config: {
total_slides: 123,
slide_types: [{}],
custom_images: {},
pinned_images: {},
slide_texts: {},
slide_text_elements: {},
pack_assignments: {}
}
})
};
fetch('https://api.example.com/api/partner/v1/slideshows/generate', 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.example.com/api/partner/v1/slideshows/generate",
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([
'prompt' => '<string>',
'product_id' => [
],
'pack_id' => [
],
'slide_count' => 123,
'slideshow_type' => '<string>',
'aspect_ratio' => '<string>',
'language' => '<string>',
'advanced_settings' => [
'font_size' => [
],
'text_preset' => '<string>',
'text_width' => '<string>'
],
'skip_ai' => true,
'slide_config' => [
'total_slides' => 123,
'slide_types' => [
[
]
],
'custom_images' => [
],
'pinned_images' => [
],
'slide_texts' => [
],
'slide_text_elements' => [
],
'pack_assignments' => [
]
]
]),
CURLOPT_HTTPHEADER => [
"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.example.com/api/partner/v1/slideshows/generate"
payload := strings.NewReader("{\n \"prompt\": \"<string>\",\n \"product_id\": {},\n \"pack_id\": {},\n \"slide_count\": 123,\n \"slideshow_type\": \"<string>\",\n \"aspect_ratio\": \"<string>\",\n \"language\": \"<string>\",\n \"advanced_settings\": {\n \"font_size\": {},\n \"text_preset\": \"<string>\",\n \"text_width\": \"<string>\"\n },\n \"skip_ai\": true,\n \"slide_config\": {\n \"total_slides\": 123,\n \"slide_types\": [\n {}\n ],\n \"custom_images\": {},\n \"pinned_images\": {},\n \"slide_texts\": {},\n \"slide_text_elements\": {},\n \"pack_assignments\": {}\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
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.example.com/api/partner/v1/slideshows/generate")
.header("Content-Type", "application/json")
.body("{\n \"prompt\": \"<string>\",\n \"product_id\": {},\n \"pack_id\": {},\n \"slide_count\": 123,\n \"slideshow_type\": \"<string>\",\n \"aspect_ratio\": \"<string>\",\n \"language\": \"<string>\",\n \"advanced_settings\": {\n \"font_size\": {},\n \"text_preset\": \"<string>\",\n \"text_width\": \"<string>\"\n },\n \"skip_ai\": true,\n \"slide_config\": {\n \"total_slides\": 123,\n \"slide_types\": [\n {}\n ],\n \"custom_images\": {},\n \"pinned_images\": {},\n \"slide_texts\": {},\n \"slide_text_elements\": {},\n \"pack_assignments\": {}\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/partner/v1/slideshows/generate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"prompt\": \"<string>\",\n \"product_id\": {},\n \"pack_id\": {},\n \"slide_count\": 123,\n \"slideshow_type\": \"<string>\",\n \"aspect_ratio\": \"<string>\",\n \"language\": \"<string>\",\n \"advanced_settings\": {\n \"font_size\": {},\n \"text_preset\": \"<string>\",\n \"text_width\": \"<string>\"\n },\n \"skip_ai\": true,\n \"slide_config\": {\n \"total_slides\": 123,\n \"slide_types\": [\n {}\n ],\n \"custom_images\": {},\n \"pinned_images\": {},\n \"slide_texts\": {},\n \"slide_text_elements\": {},\n \"pack_assignments\": {}\n }\n}"
response = http.request(request)
puts response.read_bodyCreate a new slideshow in the authenticated key scope. This is the core content creation endpoint - your OpenClaw agent or automation script generates slideshows here, then publishes them to media-capable accounts via Create Post.
Manual mode (
generate supports:
- AI generation from a prompt/product context
- manual initial slide setup (
skip_ai=true) - mixed setup with explicit
slide_config
Body Parameters
Prompt used for AI text generation. Required unless
skip_ai=true or product_id is provided.Optional product reference. Must exist in the authenticated key scope.
Optional global image pack ID. Required whenever any generated slide uses
image_pack and no
per-slide pack_assignments are provided.Optional target slide count (
1-10). Default: 5.Optional:
educational or personal. Default: educational.Optional:
9:16, 1:1, or 4:5. Default: 4:5.Optional language hint (2-32 chars).
Optional text styling defaults.
Show advanced_settings object
Show advanced_settings object
default, small, or a numeric size (8-200). Preset mapping for generated slides:
default = title/single 48px, body 40px; small = title/single 40px, body 33px
(rounded from 0.83x). If users ask for “a bit bigger than small”, use a numeric midpoint
such as 44.Text style preset (for example
tiktok).default or narrow.Optional. When
true, generation skips AI text creation and uses your slide_config input.Optional explicit per-slide setup.
Show slide_config object
Show slide_config object
Integer
1-10.Exact-length array matching
total_slides. Values: image_pack or
custom_image.Map of slide index -> custom image payload. Required for every
custom_image slide.Optional map of slide index -> pinned image URL.
Optional map of slide index -> text string.
Optional map of slide index -> text element array
(
content, x, y, optional id, font_size, width).Optional map of slide index -> pack UUID. Valid only for
image_pack
slides.All
slide_config map keys must be 0-based numeric indices in range. image_pack slides must
resolve a pack via pack_id or pack_assignments[index].Examples
AI mode (prompt + global pack)
cURL
curl --request POST \
--url https://www.genviral.io/api/partner/v1/slideshows/generate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"prompt": "5 discipline quotes",
"pack_id": "11111111-1111-1111-1111-111111111111",
"slide_count": 1,
"slideshow_type": "educational",
"aspect_ratio": "4:5",
"language": "en",
"advanced_settings": {
"font_size": 44,
"text_preset": "tiktok",
"text_width": "default"
}
}'
Manual mode (skip_ai=true)
cURL
curl --request POST \
--url https://www.genviral.io/api/partner/v1/slideshows/generate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"skip_ai": true,
"slide_config": {
"total_slides": 2,
"slide_types": ["custom_image", "image_pack"],
"custom_images": {
"0": {
"image_url": "https://cdn.example.com/custom-0.jpg",
"image_id": "hero_0"
}
},
"slide_text_elements": {
"0": [
{
"content": "Hook text",
"x": 50,
"y": 25
}
]
},
"pack_assignments": {
"1": "11111111-1111-1111-1111-111111111111"
}
}
}'
Response
Returns201 with the full slideshow object (same structure as
Get Slideshow).
Response
{
"ok": true,
"code": 201,
"message": "Slideshow generated",
"data": {
"id": "2ab58bb0-0c39-45c0-a4d5-b6852f9d7fc0",
"title": "5 discipline quotes",
"status": "draft",
"slideshow_type": "educational",
"product_id": null,
"original_prompt": "5 discipline quotes",
"preview_image_url": null,
"created_at": "2026-02-14T09:20:00.000Z",
"updated_at": "2026-02-14T09:20:00.000Z",
"last_rendered_at": null,
"slide_count": 1,
"settings": {
"image_pack_id": "11111111-1111-1111-1111-111111111111",
"aspect_ratio": "4:5",
"slideshow_type": "educational",
"advanced_settings": {
"font_size": 44,
"text_preset": "tiktok",
"text_width": "default"
},
"pack_assignments": null
},
"slides": [
{
"index": 0,
"image_url": "https://cdn.example.com/slides/discipline-1.jpg",
"rendered_image_url": null,
"text_elements": [
{
"id": "9fd0b2bd-a95a-4488-8b7a-bf1d18d2bcdf",
"content": "Discipline beats motivation",
"x": 50,
"y": 25,
"font_size": 48,
"width": 70,
"height": null,
"editable": true,
"style_preset": "tiktok",
"font_family": null,
"background_color": null,
"text_color": null,
"border_radius": null
}
],
"grid_images": null,
"grid_type": null,
"background_filters": null,
"image_overlays": null
}
]
}
}
Error Responses
400 invalid_json- body is not valid JSON422 invalid_payload- schema/validation failed404 pack_not_found- referenced pack is missing or outside key scope422 pack_empty- selected pack has no images422 pack_required- one or moreimage_packslides are missing pack resolution404 product_not_found-product_iddoes not exist403 forbidden_product_access-product_idexists but is outside key scope401- authentication failed (missing/invalid/revoked token)402 subscription_required- active Creator/Professional/Business plan required403 tier_not_allowed- Scheduler tier cannot use Partner API500 generate_failed- unexpected generation failure
⌘I
