Carousels & Infographics
Create carousel
Creates an editable multi-slide carousel draft from a structured content outline (never HTML). LinkedIn only: an X account returns 400 linkedin_only. Omit integrationId to use the selected template or default styling without profile branding; supply a connected LinkedIn profile or company page for profile branding. Created with no rendered preview.
/api/public/carouselscurl -X POST https://postiv.ai/api/public/carousels \
-H "Authorization: Bearer pk_postiv_..." \
-H "Content-Type: application/json" \
-d '{
"title": "Launch lessons"
}'{
"success": true,
"carousel": {
"id": "car1...",
"title": "5 Content Mistakes",
"status": "draft",
"integrationId": 1234,
"planItemId": null,
"createdAt": "2026-07-19T09:10:00.000Z"
},
"versionId": "cv1...",
"versionNumber": 1,
"slideCount": 6,
"slides": [
{
"index": 0,
"title": "5 Content Mistakes",
"textPreview": "Most B2B content fails because..."
}
],
"openInPostivUrl": "https://postiv.ai/app/create?carouselId=car1...",
"warnings": []
}Authorization
Requires an organization API key with the posts:write scope, sent as Authorization: Bearer or x-api-key.
Body parameters
titlestringrequired1-240 chars, internal library title.
integrationIdintOptional positive LinkedIn profile or company page ID for branding (LinkedIn only: an X account returns 400 linkedin_only). Omit for an unassigned draft using the selected template or default styling; null is not accepted. Required when planItemId is supplied. Scheduling and publishing require a connected profile.
styleIdstringExact styleId from list_visual_templates (format carousel). global:freeform has no template: a designer draws every slide around the outline copy in the Brand Kit, with images only from outline.slides[].assetHints.
outline.topicstringrequiredoutline.targetAudiencestringoutline.contentTypestringe.g. educational, listicle, case study, story.
outline.objectivestringoutline.narrativeArcstringoutline.styleInstructionsstringFreeform visual direction layered on the saved brand style. With styleId global:freeform, the look the designer follows.
outline.backgroundStylestringnonegriddotsdiagonalwavessubtle-noisegradient-onlyoutline.themeOverride.backgroundColorstringHex; overrides the saved brand theme for this carousel only.
outline.themeOverride.textColorstringoutline.themeOverride.primaryColorstringoutline.themeOverride.accentColorstringoutline.slides[]arrayrequired1-10 slides (10 max enforced; app-level guidance says 5-8 is the LinkedIn sweet spot).
outline.slides[].slideTypestringrequirede.g. cover, content, list, quote, stats, comparison, cta.
outline.slides[].headlinestringrequiredoutline.slides[].subheadlinestringoutline.slides[].bodystringoutline.slides[].calloutstringoutline.slides[].items[]arrayMax 8, each { label, description? }.
outline.slides[].dataPointobject{ value, label } hero stat.
outline.slides[].imageUrls[]string[]Max 3 public URLs.
outline.slides[].assetHints[]arrayFreeform (styleId global:freeform) only; templates ignore them. Max 4, each { kind: logo | image | screenshot | website-screenshot, topic, label?, scope?: any | library | web }. Search-only, never AI generated; topic {asset=ID} uses that media-library image directly. Unresolved assets come back in warnings.
outline.slides[].layoutstringoutline.slides[].designNotesstringplanItemIduuidLinks to a Bob plan item and marks it drafted.
Response
The created carousel with slide text summaries.
carousel.id / title / status / integrationId / planItemId / createdAtmixedversionIduuidversionNumberint1 for a new carousel.
slideCountintslides[].index / title / textPreviewmixedtextPreview is HTML-stripped, truncated to 200 chars.
appliedStyleobjectFreeform only: { styleId: 'global:freeform', name: 'Freeform', explicitlySelected: true }.
openInPostivUrlstringwarningsstring[]Profile-branding notices and per-slide generation warnings, e.g. 'slide 3: ...'.
Errors
| 400 | missing_title / invalid_outline (0 slides or >10 slides) |
| 400 | missing_integration_id: planItemId was supplied without integrationId |
| 400 | linkedin_only: integrationId is an X account |
| 404 | integration_not_found: integrationId is not an account in this workspace / linkedin_profile_not_found: the LinkedIn profile is not active |
| 502 | carousel_generation_failed: generation produced zero slides, or the Freeform designer failed |
Good to know
- Status is 201 Created. Always call render-carousel next: no preview images exist yet. The model must supply CONTENT only; Postiv's shared slide generator fills editable canvas templates.