Use this exact hook instead of generating one. It is used word for word. On quote-card decks a hook that promises a count (“7 different ways…”) sets the length when slideCount is omitted. On classic slideshows a hook that promises a count always sets the number of body slides (up to 33, what a 35-photo TikTok post can hold), so “7 swaps” gets seven complete swaps.
2–10, default 6. Total slides, the hook and the closing slide included. On classic slideshows a generated hook is written to count to it (slideCount minus the hook and the close).
soft | direct | none. On quote-card decks, none drops the CTA slide and every slide after the hook is advice; otherwise the CTA is the last slide of the count. On classic slideshows the soft mention (soft) or the CTA (direct) is its own last slide, after every body slide; it never replaces a body slide’s text.
Requires content:write and an Idempotency-Key header. Costs 1 credit for type: "slideshow", charged only on success.
type: "illustrated" or "hook_video" returns 201 with notice: "generation_not_wired" and status: "failed" — the row is created (so you can see the gap explicitly) but no generation runs. Their pipelines are asynchronous Durable-Object state machines not yet integrated with this API. Use type: "slideshow" today.
A plain slideshow’s result is text only — no rendered slide images — so POST /v1/schedules refuses it with 409 no_images. Create it with brief.templateId: "quote-card" to get finished slide images the API can post (see Schedules).
On insufficient credits: 402 with {"error": {"code": "insufficient_credits", "insufficient": true, ...}}.
POST /v1/content/{id}/approve and POST /v1/content/{id}/reject — requires content:approve. Approve fails with 409 not_ready if status isn’t "ready" yet. See The approval gate.
POST /v1/content/{id}/remix — not yet wired (returns 501 not_implemented), for the same reason illustrated/hook_video generation isn’t. Mirrors the app’s own free remix (re-pick images, keep text) once it lands.