Initiate AI Generation
POST https://embed-api.postnitro.ai/post/initiate/generate
Generates a carousel, image or video post with AI, from a topic, an article or an X post, using one of your AI presets. For a video, see Video Posts. To send your own slides instead, use Import.
Headers
Content-Type: application/jsonembed-api-key: your-api-key-here(required)
Request Body
| Field | Type | Required | Description | Allowed Values |
|---|---|---|---|---|
postType | string | Yes | Type of post to generate | "CAROUSEL", "IMAGE", "VIDEO" |
requestorId | string | No | Custom identifier for tracking | Any string |
templateId | string | Yes | ID of the template to use: see Templates | Valid template ID |
brandId | string | Yes | ID of the brand configuration: see Brands | Valid brand ID |
presetId | string | Yes | ID of the AI configuration preset: see AI Presets | Valid preset ID |
responseType | string | No | Output format (default: “DESIGN”) | "DESIGN", "PDF", "PNG", "MP4" |
aiGeneration | object | Yes | AI generation configuration | See below |
generateImages | object | No | Opt-in AI image generation — generates images and bakes them into the design before rendering | See AI Image Generation |
videoSettings | object | No | How a video post moves, its music and its voiceover. A video is animated without it | See Video Posts |
AI Generation Object
| Field | Type | Required | Description | Allowed Values |
|---|---|---|---|---|
type | string | Yes | Type of AI generation | "text", "article", "x" |
context | string | Yes | Context/prompt for AI generation | Any string |
instructions | string | No | Additional instructions for AI | Any string |
How type and context work together:
"text"—contextis a plain-text topic or prompt describing what to create (e.g."Create a carousel about digital marketing tips")"article"—contextis the URL of an article to turn into a carousel"x"—contextis the URL of an X (Twitter) post to turn into a carousel
Video Posts
Set postType: "VIDEO" to produce a video. The AI writes slides exactly as it does for a carousel, and each slide becomes a scene in the rendered video. See the VIDEO example.
Everything else about video posts:
- Video Motion: how a video moves without asking, the built-in styles, saved styles and sequences, and its length
- Voiceover: narration the AI writes and records, in the voice and tone you pick
- Per-Slide Motion: each slide’s own animations
- Motion Styles and Motion Sequences: list and save the styles and sequences
videoSettingstakes by id - Audio: the
backgroundMusicIdfor its music - Read a Post and Edit a Post: a video’s settings read back, and its slides, template, brand, motion, music or voiceover changed later
Response types. A VIDEO post accepts only "MP4" — renders the video — or "DESIGN", which saves the design without rendering so you can finish it in the video maker via editorUrl. "PDF" and "PNG" are rejected for VIDEO, and "MP4" is rejected for every other post type.
videoSettings
All of it is optional. A video with no videoSettings is animated as its template is, or in the Clean style, and runs as long as its motion takes, up to 2:00. See Video Motion.
| Field | Type | Description |
|---|---|---|
motionStyle | string | How every slide moves: a built-in style’s name, such as "clean" or "bold", or the id of a style saved in your workspace. See Motion styles, and list yours with Motion Styles |
sequenceId | string | The id of a sequence saved in your workspace: its animations on every slide, over the style. See Saved styles and sequences, and list them with Motion Sequences |
backgroundMusicId | string | Music under the video: the id of an audio file in your workspace, from GET /audio. See Background music |
backgroundMusicVolume | number | The music’s volume in percent, 0 to 100, as the editor’s slider shows it. Default 100 |
voiceover | object | A voiceover the AI writes and records: { voice, tone, captions }, all optional. See Voiceover |
Three more fields are accepted: motion, each slide’s own animations, for per-slide motion; videoDuration, which is ignored, since a video runs as long as its motion takes (Length); and audioId, the older name of backgroundMusicId, so requests that send it keep working. Any other field returns a 422, and so does videoSettings on a CAROUSEL or IMAGE post.
Background music
backgroundMusicId is a media id, not a URL. Get one from the Audio API: upload happens in the PostNitro app, and GET /audio lists what the workspace has. It’s verified when you make the request: the media must exist, belong to your API key’s workspace, and be an audio file. Otherwise the request is rejected with a 422. audioId, its older name, is still accepted; send one or the other, not both.
The music is kept on the design with its volume, so the editor and the MP4 play it alike. A new track starts at its beginning, at 100 unless backgroundMusicVolume says otherwise, and fades out over the last second. It’s lowered to 30% while a voiceover plays. backgroundMusicVolume needs backgroundMusicId. The 422s are listed under Background music.
Voiceover
voiceover has the AI write a line for every slide it made and record it, charged in AI tokens, not API credits. See Voiceover.
The scheduling API’s
postSettingstakes the samebackgroundMusicId, so a track carries straight over from generating a video to scheduling it as a reel. A reel plays its design’s motion, and runs as long as it does.
AI Image Generation
Add an optional generateImages object to have the API generate AI images and bake them into the design before it’s rendered. Its presence is the opt-in — omit the field and no images are generated (existing behavior). Works for CAROUSEL, IMAGE, and VIDEO posts and with every responseType (PDF, PNG, MP4, DESIGN).
| Field | Type | Required | Default | Allowed Values |
|---|---|---|---|---|
context | string | No | Falls back to aiGeneration.context | Any string — topic/brief that guides the image prompts |
imagePlacement | string | No | "auto" | "auto", "background", "in-line" |
imageStrategy | string | No | "strategic" | "strategic", "all" |
These are the only accepted fields — any other key inside generateImages returns a 422. Everything else the image service needs (editorType, image model, and the AI copy config) is resolved server-side: editorType from postType, the platform image model, and socialPlatform/tone/audience/language from your AI preset.
On direct REST calls,
contextis optional (it falls back as shown above). Over the MCP server and CLI,contextis required — the AI agent composes it for the user. That is the only difference in howgenerateImagesbehaves across the two.
imagePlacement
| Value | Behavior |
|---|---|
auto | AI decides per slide whether an image is a background or placed in-line with the content. |
background | Images are generated for slide backgrounds. |
in-line | Images are generated to sit inside the slide content, alongside the text. |
imageStrategy
| Value | Behavior |
|---|---|
strategic | The AI picks which slides get images, capped at ~50% of slides for a balanced look. |
all | Every eligible slide gets an image, capped only by available credits. |
Behavior & limits:
- Image generation runs after the design is created and before rendering, so a rendered
PDF/PNGalready contains the images and aDESIGNresponse has them baked into the saved design (visible viaeditorUrl). The output shape is unchanged — no new fields. - Best-effort: if generation fails or isn’t permitted, the post still completes without images. A
GENERATE_IMAGESstep appears in the status logs —COMPLETEDon success,FAILED(with a skip reason) otherwise. - Free plan: AI image generation is not available — the step is skipped (logged as failed) and the post completes without images.
- Credits: the post’s reported
credits(slide-based) are unchanged. AI images bill against the organization’s separate AI-image quota. - Image generation adds latency — keep polling status until
COMPLETED.
On
generate,contextplussocialPlatform/tone/audience/languageare taken from the request/preset, sogenerateImagescan be as small as{ "imagePlacement": "auto" }— or{}to accept all defaults.
Example Requests
CAROUSEL
curl --location 'https://embed-api.postnitro.ai/post/initiate/generate' \
--header 'Content-Type: application/json' \
--header 'embed-api-key: pn-your-api-key' \
--data '{
"postType": "CAROUSEL",
"requestorId": "user123",
"templateId": "xtrnxgfgk9a08tmsz2601k1c",
"brandId": "cmdhb8oe10006v0pmh6a4no6t",
"presetId": "preset123",
"responseType": "PNG",
"aiGeneration": {
"type": "text",
"context": "Create a carousel about digital marketing tips",
"instructions": "Focus on actionable tips for small businesses"
}
}'CAROUSEL with AI images
curl --location 'https://embed-api.postnitro.ai/post/initiate/generate' \
--header 'Content-Type: application/json' \
--header 'embed-api-key: pn-your-api-key' \
--data '{
"postType": "CAROUSEL",
"requestorId": "user123",
"templateId": "xtrnxgfgk9a08tmsz2601k1c",
"brandId": "cmdhb8oe10006v0pmh6a4no6t",
"presetId": "preset123",
"responseType": "DESIGN",
"aiGeneration": {
"type": "text",
"context": "How our scheduling feature saves marketers time"
},
"generateImages": {
"imagePlacement": "auto",
"imageStrategy": "all"
}
}'VIDEO
The smallest video request: animated as its template is, or in the Clean style.
curl --location 'https://embed-api.postnitro.ai/post/initiate/generate' \
--header 'Content-Type: application/json' \
--header 'embed-api-key: pn-your-api-key' \
--data '{
"postType": "VIDEO",
"templateId": "xtrnxgfgk9a08tmsz2601k1c",
"brandId": "cmdhb8oe10006v0pmh6a4no6t",
"presetId": "preset123",
"responseType": "MP4",
"aiGeneration": {
"type": "text",
"context": "Three habits that make remote teams faster"
}
}'With a style, music at a quarter of its volume, and a voiceover:
"videoSettings": {
"motionStyle": "bold",
"backgroundMusicId": "cmqi7jyir0003v0m91hxnyyaq",
"backgroundMusicVolume": 25,
"voiceover": { "voice": "nova", "tone": "Hype and punchy" }
}Response
{
"success": true,
"message": "CAROUSEL generation initiated",
"data": {
"embedPostId": "post123",
"status": "PENDING"
}
}Generation is asynchronous. This endpoint returns immediately with an
embedPostIdwhile the post is generated in the background. Poll Check Post Status with theembedPostIduntil the status isCOMPLETED, then call Get Post Output to retrieve the final files.
Once it’s made, Read a Post gives its content back and Edit a Post changes it in place, by the same embedPostId.