---
title: "Initiate carousel creation from your own slide content"
method: POST
path: "/post/initiate/import"
---

# Initiate carousel creation from your own slide content

`POST /post/initiate/import`

## Request

- Base URL: `https://embed-api.postnitro.ai`
- URL: `https://embed-api.postnitro.ai/post/initiate/import`
- Auth: API key in header `embed-api-key`

Creates a carousel post from caller-provided slide content. Slide order rules: exactly one starting_slide first, at least one body_slide in the middle, exactly one ending_slide last. Returns immediately with an embedPostId; poll GET /post/status/{embedPostId} until COMPLETED, then call GET /post/output/{embedPostId}. Content import costs 1 credit per slide. Docs: https://postnitro.ai/docs/embed/api/initiate/import.md

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `postType` 'CAROUSEL' | 'IMAGE' | 'VIDEO', required: Type of post to create. Must be uppercase. CAROUSEL and VIDEO take an array of slides (for VIDEO each slide is a scene); IMAGE takes a single slide object
  - `requestorId` string: Optional custom identifier for tracking
  - `templateId` string, required: ID of the design template to use
  - `brandId` string, required: ID of the brand configuration to apply
  - `responseType` 'DESIGN' | 'PDF' | 'PNG' | 'MP4': Output format. DESIGN (default) creates and saves the design without rendering a file. PNG produces one image per slide. PDF produces a single document. MP4 produces a single video and is valid only for postType VIDEO, which in turn accepts only MP4 or DESIGN. Send a rendering format explicitly if you need a file
  - `slides` union, required: For CAROUSEL and VIDEO: an array of slides in display order (exactly 1 starting_slide first, 1+ body_slide, exactly 1 ending_slide last). For IMAGE: a single slide object (no array, no type field). The shape is strictly enforced per postType — sending the wrong one returns a 422
    - Slide[]
      - `type` 'starting_slide' | 'body_slide' | 'ending_slide', required: Slide role. Exactly 1 starting_slide (must be first), at least 1 body_slide, exactly 1 ending_slide (must be last)
      - `heading` string, required: Main heading text
      - `sub_heading` string: Subtitle text
      - `description` string: Description / body text
      - `image` string, uri: Image URL. Ignored when layoutType is 'infographic'
      - `background_image` string, uri: Background image URL
      - `cta_button` string: Call-to-action button text
      - `layoutType` 'default' | 'infographic': 'infographic' renders structured column data instead of the image. Available on both CAROUSEL and IMAGE slides
      - `layoutConfig` LayoutConfig: Infographic configuration, used when layoutType is 'infographic'. All fields are optional; any omitted field uses its default. If layoutType is 'infographic' but layoutConfig is missing, the slide falls back to the default layout
        - `hasHeader` boolean: Whether to show a header for each column
        - `columnCount` 1 | 2 | 3: Number of columns (max 3)
        - `displayCounterAs` 'none' | 'counter': Whether to show numbered counters
        - `columnDisplay` 'cycle' | 'grid': 'cycle' for sequential/step-by-step, 'grid' for comparative layout. With 'cycle', put ALL data in the first columnData entry only
        - `columnData` object[]: The columns to render
          - `id` string, required: Unique id for the column. Caller-provided — stored as-is, not auto-generated
          - `header` string: Column header text (shown when hasHeader is true)
          - `content` object[], required
            - `id` string, required: Unique id for the item. Caller-provided — stored as-is, not auto-generated
            - `icon` string, nullable: Optional icon
            - `title` string, required
            - `description` string, required: Description as an HTML string, e.g. '<p dir="ltr">Description</p>'
            - `titleEnabled` boolean: Whether to show the title
            - `descriptionEnabled` boolean: Whether to show the description
    - Slide
      - `type` 'starting_slide' | 'body_slide' | 'ending_slide', required: Slide role. Exactly 1 starting_slide (must be first), at least 1 body_slide, exactly 1 ending_slide (must be last)
      - `heading` string, required: Main heading text
      - `sub_heading` string: Subtitle text
      - `description` string: Description / body text
      - `image` string, uri: Image URL. Ignored when layoutType is 'infographic'
      - `background_image` string, uri: Background image URL
      - `cta_button` string: Call-to-action button text
      - `layoutType` 'default' | 'infographic': 'infographic' renders structured column data instead of the image. Available on both CAROUSEL and IMAGE slides
      - `layoutConfig` LayoutConfig: Infographic configuration, used when layoutType is 'infographic'. All fields are optional; any omitted field uses its default. If layoutType is 'infographic' but layoutConfig is missing, the slide falls back to the default layout
        - `hasHeader` boolean: Whether to show a header for each column
        - `columnCount` 1 | 2 | 3: Number of columns (max 3)
        - `displayCounterAs` 'none' | 'counter': Whether to show numbered counters
        - `columnDisplay` 'cycle' | 'grid': 'cycle' for sequential/step-by-step, 'grid' for comparative layout. With 'cycle', put ALL data in the first columnData entry only
        - `columnData` object[]: The columns to render
          - `id` string, required: Unique id for the column. Caller-provided — stored as-is, not auto-generated
          - `header` string: Column header text (shown when hasHeader is true)
          - `content` object[], required
            - `id` string, required: Unique id for the item. Caller-provided — stored as-is, not auto-generated
            - `icon` string, nullable: Optional icon
            - `title` string, required
            - `description` string, required: Description as an HTML string, e.g. '<p dir="ltr">Description</p>'
            - `titleEnabled` boolean: Whether to show the title
            - `descriptionEnabled` boolean: Whether to show the description
  - `generateImages` GenerateImages: Opt-in AI image generation. Presence of this object enables it; omit it entirely for no images. Images are generated after the design is created and before rendering, and baked into the design (observable in the rendered file or via editorUrl) — the output shape is unchanged. Best-effort: if generation fails or isn't permitted (e.g. free plan or over the org's AI-image quota) the post still completes without images, and a GENERATE_IMAGES step is recorded in the status logs. Post credits are unchanged; AI images bill against the org's separate AI-image quota. editorType, image model, and copy config are resolved server-side and must not be sent
    - `context` string: Topic/brief that guides the image prompts. On generate, defaults to aiGeneration.context; on import, defaults to an empty string
    - `imagePlacement` 'auto' | 'background' | 'in-line': 'auto' lets the AI decide per slide, 'background' generates slide backgrounds, 'in-line' generates images placed inside the slide content
    - `imageStrategy` 'strategic' | 'all': 'strategic' lets the AI pick which slides get images (capped at ~50% of slides), 'all' gives every eligible slide an image (capped by credits)
  - `videoSettings` VideoSettings: How a VIDEO post moves, its music and its voiceover; rejected with a 422 for any other postType. All of it is optional: with no videoSettings, the video moves as its template does, or in the Clean style. A video runs as long as its slides, motion and narration take, up to 2:00: a longer MP4 fails with its design kept (see the output's 400). The backgroundMusicId is the same field as the postSettings object on the scheduling API. Docs: https://postnitro.ai/docs/embed/api/initiate/video-motion.md
    - `motionStyle` string: How every slide moves: a built-in style's name (none, minimal, clean, slideshow, editorial, cinematic, luxe, story, typewriter, snap, bold, playful, kinetic, glitch) or the id of a style saved in the workspace (GET /motion-style lists both). Checked at request time: an unknown one returns a 422. Replaces the template's motion
    - `sequenceId` string: The id of a sequence saved in the workspace (GET /motion-sequence): its animations on every slide, element by element, over the style's; each slide keeps its own length and transition. Checked at request time: an unknown id returns a 422
    - `backgroundMusicId` string: Media id (not a URL) of an audio file to play under the video — list them with GET /audio. Verified at request time: the media must exist, belong to the API key's workspace, and be an audio file, otherwise the request is rejected with a 422. Kept on the design with its volume, so the editor and the MP4 play it alike: a new track starts at its beginning and fades out over the last second. Lowered to 30% while a voiceover plays. Replaces audioId; send one or the other, not both. Omit for no music. Docs: https://postnitro.ai/docs/embed/api/initiate/import.md
    - `backgroundMusicVolume` number: The music's volume in percent, as the editor's slider shows it. A new track plays at 100 unless this says otherwise; a different track picked over an existing one keeps that one's volume and fade. On a new video it needs backgroundMusicId (422 otherwise); on an edit, it alone sets the volume of the music the video already has
    - `voiceover` union: An AI voiceover, { voice, tone, captions }, all optional. On an edit, false takes the video's narration off; a narrated video's new slides are narrated again in its voice and tone, and the fields given change just those
      - Voiceover: A voiceover the AI writes and records, as the editor's does: one spoken line per slide, written from the slides in the tone and recorded in the voice. No script is taken: a script field is rejected with a 422. Each slide lasts as long as its narration needs, and the AI keeps the whole narration within the 2:00 limit. {} gives every default. Charged from the plan's AI tokens (the tokens the script took, plus 5,000 per minute of audio), not API credits. Best-effort: with the AI tokens used up, or the narration failing, the video is made without it, and the VOICEOVER status step says why. Docs: https://postnitro.ai/docs/embed/api/initiate/voiceover.md
        - `voice` 'alloy' | 'ash' | 'ballad' | 'coral' | 'echo' | 'fable' | 'nova' | 'onyx' | 'sage' | 'shimmer' | 'verse': Who reads it: one of OpenAI's voices, the same as the editor's
        - `tone` string: How it's written and read: upbeat, calm, professional, storyteller, or your own words, up to 80 characters
        - `captions` boolean: true shows the narration's words as captions on the video; false hides them
      - unknown
    - `motion` SlideMotion[]: Advanced: each slide's own motion, one entry per slide in order; null leaves a slide to the style. Most videos don't need it. Checked at request time: a mistake returns a 422 that says where it is. A step for an element a slide doesn't show, and entries past the last slide, are left out, and the COMPOSE_MOTION status step says so. Docs: https://postnitro.ai/docs/embed/api/initiate/video-motion-advanced.md
      - `steps` MotionStep[]: The slide's animations, in the order they play; each starts after the one before unless it has together. Replaces the style's animations on this slide; [] keeps the slide still
        - `element` 'title' | 'subtitle' | 'description' | 'cta' | 'image' | 'backgroundImage' | 'infographics' | 'infographicHeader' | 'infographicAndGridTitle' | 'infographicAndGridDescription' | 'avatar' | 'name' | 'handle' | 'slideCount' | 'swipeIndicator' | 'bookmark' | 'backgroundPattern', required: What moves. title is the heading, subtitle the sub_heading, cta the cta_button and backgroundImage the background_image; avatar, name and handle are the brand's
        - `preset` 'fade' | 'rise' | 'slide' | 'zoom' | 'pop' | 'bounce' | 'spring' | 'blur' | 'rotate' | 'flash' | 'split' | 'glitch' | 'shimmer' | 'typewriter' | 'wave' | 'jump' | 'wipe' | 'sweep' | 'count' | 'pulse' | 'float' | 'wiggle' | 'kenburns', required: How it moves. pulse, float and wiggle are emphases, which loop until the slide ends unless repeat says otherwise; kenburns, a slow zoom and drift of a picture or background, plays once over the rest of its slide; sweep draws a text's highlighted words in, like a marker; count counts a text's numbers up from zero; the others bring an element in or take it out
        - `kind` 'enter' | 'emphasis' | 'exit': enter (the default) brings the element in, emphasis (the default for pulse, float, wiggle and kenburns) plays while it stays, and exit takes it out, playing the preset backwards
        - `together` boolean: Start with the previous step instead of after it
        - `delay` number: Seconds to wait before it starts
        - `seconds` number: How long it plays; for text played by line, word or letter, how long each part plays. Omit for the preset's own pace
        - `split` 'line' | 'word' | 'letter': Text only: play it by line, word or letter
        - `direction` 'left' | 'right' | 'up' | 'down': The direction of travel
        - `repeat` union: Emphasis only: how many times it plays, or until the slide ends, the default
          - integer
          - 'until-end'
      - `transition` SlideTransition: How a slide arrives
        - `type` 'none' | 'fade' | 'slide' | 'push' | 'zoom' | 'wipe' | 'blur', required: none cuts
        - `direction` 'left' | 'right' | 'up' | 'down': For slide, push and wipe
        - `seconds` number: How long it takes. Defaults to 0.5
      - `hold` number: Seconds the slide stays on screen after its animations
    - `audioId` string: The older name of backgroundMusicId, still accepted so that older requests keep working. Sending both is rejected with a 422
    - `videoDuration` unknown

## Response `200`

Generation initiated

- InitiateResponse
  - `success` boolean
  - `message` string
  - `data` object
    - `embedPostId` string: Use this ID to poll status and fetch output
    - `status` 'PENDING' | 'COMPLETED' | 'FAILED': PENDING = queued or generating (keep polling), COMPLETED = fetch output, FAILED = inspect status logs

## Other responses

- `409`: A request with this Idempotency-Key is still in progress; retry after `Retry-After` seconds to get its result.

---

[API](https://skmtc.dev/postnitro/apis/postnitro-embed-api.md) - [All operations](https://skmtc.dev/postnitro/apis/postnitro-embed-api/llms.txt) - [OpenAPI document](https://skmtc.dev/postnitro/apis/postnitro-embed-api/revisions/428cb3ea3f6a?raw)
