> ## Documentation Index
> Fetch the complete documentation index at: https://docs.genviral.io/llms.txt
> Use this file to discover all available pages before exploring further.

# 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.

Create 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](/api-reference/create-post).

`generate` supports:

* AI generation from a prompt/product context
* manual initial slide setup (`skip_ai=true`)
* mixed setup with explicit `slide_config`
* recreating the format of a [Viral Library](/api-reference/search-viral-library) post for your
  product (`reference`)

Generation runs on the same engine as the Genviral app and Vira. The request stays open until the
deck is finished (usually one to three minutes) and then returns it. If the deck is still generating
after about five minutes, the request answers `504 generation_timeout` with the `slideshow_id`; poll
[Get Slideshow](/api-reference/get-slideshow) until `generation_status` is `complete` or `failed`,
or retry with the same `Idempotency-Key` to wait on the same deck again.

## Idempotency

Send a unique `Idempotency-Key` header for each slideshow you intend to create. Retrying the same
key with the same body replays the original result. When the header is omitted, Genviral derives a
stable key from the credential and request body for backward compatibility, so an identical
headerless request is treated as a retry rather than a new generation.

## Body Parameters

<ParamField body="prompt" type="string">
  Prompt used for AI text generation. Required unless `skip_ai=true` or `product_id` is provided.
</ParamField>

<ParamField body="product_id" type="string (UUID)">
  Optional product reference. Must exist in the authenticated key scope.
</ParamField>

<ParamField body="pack_id" type="string (UUID)">
  Optional global image pack ID. Required whenever any generated slide uses `image_pack` and no
  per-slide `pack_assignments` are provided, unless `image_sourcing` allows Pinterest sourcing.
</ParamField>

<ParamField body="image_sourcing" type="string">
  Optional image sourcing mode. Default: `pack` (backward compatible).

  * `pack` — shuffle backgrounds from `pack_id` or per-slide `pack_assignments` only
  * `pinterest_auto` — run the whole-deck Pinterest agent after text generation; `pack_id` optional
  * `pinterest_then_pack` — image search like `pinterest_auto`; a slide the search cannot fill
    takes an image from its `pack_assignments` pack or `pack_id` instead (no extra charge). Without
    a pack it behaves exactly like `pinterest_auto`, where an unfilled slide fails the request
</ParamField>

<ParamField body="reference" type="object">
  Optional Viral Library post to recreate for your product or prompt, as
  `{ "viral_post_id": "<post id>" }`. Genviral analyzes the post once (the first request for a
  post can take 15–40 seconds longer; that time is part of the same wait) and builds one slide per
  analyzed source slide: each keeps the source slide's kind of shot, subject, copy role, copy
  pattern, and length. The reference is style only: new words are written for your product and every
  image is sourced by search. The source post's text and images are never reused.

  Requires `prompt` or `product_id`. Not accepted together with `slide_config`, `slide_count`,
  `pack_id`, `skip_ai: true`, or an `image_sourcing` other than `pinterest_auto`. Reading the post
  counts against your Viral Library `get` rate limit.
</ParamField>

<ParamField body="slide_count" type="number">
  Optional target slide count (`1-10`). Default: `5`.
</ParamField>

<ParamField body="slideshow_type" type="string">
  Optional: `educational` or `personal`. Default: `educational`.
</ParamField>

<ParamField body="aspect_ratio" type="string">
  Optional: `9:16`, `1:1`, or `4:5`. Default: `4:5`.
</ParamField>

<ParamField body="language" type="string">
  Optional language hint (2-32 chars).
</ParamField>

<ParamField body="advanced_settings" type="object">
  Optional text styling defaults.

  <Expandable title="advanced_settings object">
    <ParamField body="font_size" type="string | number">
      `default`, `small`, or a number from `8` to `200`. Presets: `default` = title/single
      `48px`, body `40px`; `small` = title/single `40px`, body `33px`. A number sets that exact
      size for every text element on every slide.
    </ParamField>

    <ParamField body="text_preset" type="string">
      Text style preset (for example `tiktok`).
    </ParamField>

    <ParamField body="text_width" type="string">
      `default` or `narrow`.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="skip_ai" type="boolean">
  Optional. When `true`, no AI copy is written: slides with text in `slide_config.slide_texts` or
  `slide_config.slide_text_elements` keep it verbatim, and every other slide is image-only.
  Images are still sourced from your packs, custom images, or Pinterest.
</ParamField>

<ParamField body="slide_config" type="object">
  Optional explicit per-slide setup.

  <Expandable title="slide_config object">
    <ParamField body="total_slides" type="number" required>
      Integer `1-10`.
    </ParamField>

    <ParamField body="slide_types" type="array" required>
      Exact-length array matching `total_slides`. Values: `image_pack` or
      `custom_image`.
    </ParamField>

    <ParamField body="custom_images" type="object">
      Map of slide index -> custom image payload. Required for every
      `custom_image` slide.
    </ParamField>

    <ParamField body="pinned_images" type="object">
      Optional map of slide index -> pinned image URL.
    </ParamField>

    <ParamField body="slide_texts" type="object">
      Optional map of slide index -> text string.
    </ParamField>

    <ParamField body="slide_text_elements" type="object">
      Optional map of slide index -> text element array
      (`content`, `x`, `y`, optional `id`, `font_size`, `width`). Elements render verbatim at
      their `x`/`y` (percent of the slide, `0`–`100`), with `font_size` (`8`–`200`) and `width`
      (`1`–`100`) when given and the deck's text settings otherwise. Out-of-range values are
      refused with `422 invalid_payload`.
    </ParamField>

    <ParamField body="pack_assignments" type="object">
      Optional map of slide index -> pack UUID. Valid only for `image_pack`
      slides.
    </ParamField>
  </Expandable>
</ParamField>

<Warning>
  All `slide_config` map keys must be 0-based numeric indices in range. `image_pack` slides must
  resolve a pack via `pack_id`, `pack_assignments[index]`, or an `image_sourcing` mode that allows
  Pinterest sourcing (`pinterest_auto`, `pinterest_then_pack`).
</Warning>

## Examples

### AI mode (prompt + global pack)

```bash cURL theme={null}
curl --request POST \
  --url https://www.genviral.io/api/partner/v1/slideshows/generate \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: slideshow-discipline-quotes-v1' \
  --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"
  }
}'
```

### Pinterest auto mode (`image_sourcing=pinterest_auto`)

```bash cURL theme={null}
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 morning routine tips for busy parents",
  "product_id": "22222222-2222-2222-2222-222222222222",
  "image_sourcing": "pinterest_auto",
  "slide_count": 5,
  "slideshow_type": "educational",
  "aspect_ratio": "4:5"
}'
```

### Recreate a Viral Library post for a product (`reference`)

```bash cURL theme={null}
curl --request POST \
  --url https://www.genviral.io/api/partner/v1/slideshows/generate \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: meal-planner-like-viral-post-v1' \
  --data '{
  "product_id": "22222222-2222-2222-2222-222222222222",
  "prompt": "Show how the app stops weekly grocery waste",
  "reference": { "viral_post_id": "onthecarte-7510079309214731526" },
  "aspect_ratio": "4:5"
}'
```

### Manual mode (`skip_ai=true`)

```bash cURL theme={null}
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
        }
      ]
    },
    "slide_texts": {
      "1": "Second slide text"
    },
    "pack_assignments": {
      "1": "11111111-1111-1111-1111-111111111111"
    }
  }
}'
```

## Response

Returns `201` with the full slideshow object (same structure as
[Get Slideshow](/api-reference/get-slideshow)).

```json Response theme={null}
{
  "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 JSON
* `422 invalid_payload` - schema/validation failed
* `422 pack_empty` - a referenced pack is missing, outside key scope, or has no images
* `404 viral_reference_not_found` - the `reference` post does not exist or is not visible to this
  credential
* `422 viral_reference_has_no_images` - the `reference` post has no slide images to analyze
* `429 rate_limited` - a `reference` request hit the Viral Library `get` rate limit; see `retry_after_seconds`
* `503 viral_reference_analysis_unavailable` - the `reference` post could not be analyzed right now
  (`retryable: true`); nothing was charged
* `403 forbidden_product_access` - `product_id` does not exist or is outside key scope
* `409 conflict` - the `Idempotency-Key` is in use by a running request (`retryable: true`) or was
  used for a different request (`retryable: false`)
* `401` - authentication failed (missing/invalid/revoked token)
* `402 subscription_required` - active Creator/Professional/Business plan required
* `402 insufficient_credits` - buy a credit pack at `https://www.genviral.io/billing?tab=credits`, then retry
* `403 tier_not_allowed` - Scheduler tier cannot use Partner API
* `500 generate_failed` - generation failed; includes `slideshow_id` when the deck was started
* `504 generation_timeout` - the deck is still generating; poll `slideshow_id` with Get Slideshow


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.