PostNitro Carousel Generator
Verified@iAmMuneeb
npx machina-cli add skill @iAmMuneeb/postnitro-carousel --openclawPostNitro Carousel Generator
Create social media carousel posts via the PostNitro.ai Embed API. Two workflows:
- AI Generation — provide a topic, article, or text and let AI create the carousel
- Content Import — provide your own slide content with full control, including infographics
Prerequisites
Set the following environment variables:
POSTNITRO_API_KEY— Obtained from PostNitro.ai account settings under "Embed".POSTNITRO_TEMPLATE_ID— ID of a carousel template from the user's PostNitro account.POSTNITRO_BRAND_ID— ID of a brand profile from the user's PostNitro account.POSTNITRO_PRESET_ID— (Required for AI generation) An AI preset ID from the user's PostNitro account.
If the user doesn't have these, direct them to https://postnitro.ai to sign up (free plan: 5 credits/month).
API Overview
Base URL: https://embed-api.postnitro.ai
Authentication: All requests require the header embed-api-key: $POSTNITRO_API_KEY.
Content-Type: application/json (for POST requests).
Async Workflow
All carousel creation is asynchronous:
- Initiate —
POST /post/initiate/generateorPOST /post/initiate/import→ returnsembedPostId - Poll Status —
GET /post/status/{embedPostId}→ poll untilstatusis"COMPLETED" - Get Output —
GET /post/output/{embedPostId}→ download the finished carousel
Endpoint 1: AI-Powered Generation
POST /post/initiate/generate
Use when the user provides a topic, article URL, or text and wants AI to generate carousel content.
Request Body
| Field | Type | Required | Description | Allowed Values |
|---|---|---|---|---|
postType | string | Yes | Type of post | "CAROUSEL" |
requestorId | string | No | Custom tracking identifier | Any string |
templateId | string | Yes | Template ID | Valid template ID |
brandId | string | Yes | Brand configuration ID | Valid brand ID |
presetId | string | Yes | AI configuration preset ID | Valid preset ID |
responseType | string | No | Output format (default: "PDF") | "PDF", "PNG" |
aiGeneration | object | Yes | AI generation config | See below |
aiGeneration Object
| Field | Type | Required | Description | Allowed Values |
|---|---|---|---|---|
type | string | Yes | Type of AI generation | "text", "article", "x" |
context | string | Yes | For "text": the text content. For "article": an article URL. For "x": an X post/thread URL. | Any string |
instructions | string | No | Additional style/tone instructions | Any string |
aiGeneration.type values:
"text"— Generate from user-provided text content"article"— Generate from an article URL (pass the URL ascontext)"x"— Generate from an X (Twitter) post or thread URL
Example (from text)
curl -X POST 'https://embed-api.postnitro.ai/post/initiate/generate' \
-H 'Content-Type: application/json' \
-H "embed-api-key: $POSTNITRO_API_KEY" \
-d '{
"postType": "CAROUSEL",
"requestorId": "user123",
"templateId": "'"$POSTNITRO_TEMPLATE_ID"'",
"brandId": "'"$POSTNITRO_BRAND_ID"'",
"presetId": "'"$POSTNITRO_PRESET_ID"'",
"responseType": "PNG",
"aiGeneration": {
"type": "text",
"context": "Digital marketing tips for small businesses: 1. Focus on local SEO 2. Use social proof 3. Start email marketing early",
"instructions": "Focus on actionable tips that can be implemented immediately"
}
}'
Example (from article URL)
curl -X POST 'https://embed-api.postnitro.ai/post/initiate/generate' \
-H 'Content-Type: application/json' \
-H "embed-api-key: $POSTNITRO_API_KEY" \
-d '{
"postType": "CAROUSEL",
"requestorId": "user123",
"templateId": "'"$POSTNITRO_TEMPLATE_ID"'",
"brandId": "'"$POSTNITRO_BRAND_ID"'",
"presetId": "'"$POSTNITRO_PRESET_ID"'",
"responseType": "PNG",
"aiGeneration": {
"type": "article",
"context": "https://example.com/blog/digital-marketing-tips",
"instructions": "Focus on actionable tips for small businesses"
}
}'
Response
{
"success": true,
"message": "CAROUSEL generation initiated",
"data": {
"embedPostId": "post123",
"status": "PENDING"
}
}
Credit cost: 2 credits per slide.
Endpoint 2: Content Import
POST /post/initiate/import
Use when the user provides their own slide content.
Request Body
| Field | Type | Required | Description | Allowed Values |
|---|---|---|---|---|
postType | string | Yes | Type of post | "CAROUSEL" |
requestorId | string | No | Custom tracking identifier | Any string |
templateId | string | Yes | Template ID | Valid template ID |
brandId | string | Yes | Brand configuration ID | Valid brand ID |
responseType | string | No | Output format (default: "PDF") | "PDF", "PNG" |
slides | array | Yes | Array of slide objects | See below |
Slide Structure
| Field | Type | Required | Description | Allowed Values |
|---|---|---|---|---|
type | string | Yes | Slide type | "starting_slide", "body_slide", "ending_slide" |
heading | string | Yes | Main heading text | Any string |
sub_heading | string | No | Subtitle text | Any string |
description | string | No | Description text | Any string |
image | string | No | Foreground image URL | Valid URL |
background_image | string | No | Background image URL | Valid URL |
cta_button | string | No | Call-to-action button text | Any string |
layoutType | string | No | Slide layout type | "default", "infographics" |
layoutConfig | object | No | Infographics configuration | See below |
Slide Rules
- Exactly 1
starting_slide(required) - At least 1
body_slide(required) - Exactly 1
ending_slide(required)
Infographics Layout
Set layoutType to "infographic" on a body_slide to replace the image area with structured data.
layoutConfig object:
| Field | Type | Required | Description | Allowed Values |
|---|---|---|---|---|
columnCount | number | Yes | Number of columns | 1, 2, 3 |
columnDisplay | string | Yes | Layout mode | "cycle", "grid" |
displayCounterAs | string | Yes | Counter display | "none", "counter" |
hasHeader | boolean | Yes | Show column headers | true, false |
columnData | array | No | Column content | See below |
columnData items:
| Field | Type | Required | Description |
|---|---|---|---|
header | string | Yes | Column header text |
content | array | Yes | Array of {"title": "...", "description": "..."} objects |
Infographics notes:
layoutType: "infographic"replaces the slide image with the infographic- Column count must not exceed 3
- Cyclical display (
"cycle") only uses data from the first column - Grid display (
"grid") uses data from all columns
Example (Default Slides)
curl -X POST 'https://embed-api.postnitro.ai/post/initiate/import' \
-H 'Content-Type: application/json' \
-H "embed-api-key: $POSTNITRO_API_KEY" \
-d '{
"postType": "CAROUSEL",
"templateId": "'"$POSTNITRO_TEMPLATE_ID"'",
"brandId": "'"$POSTNITRO_BRAND_ID"'",
"responseType": "PNG",
"slides": [
{
"type": "starting_slide",
"sub_heading": "My Awesome Subtitle",
"heading": "Welcome to the Carousel!",
"description": "This is how you start with a bang.",
"cta_button": "Swipe to learn more"
},
{
"type": "body_slide",
"heading": "Section 1: The Core Idea",
"description": "Explain your first key point here."
},
{
"type": "body_slide",
"heading": "Section 2: Deeper Dive",
"description": "More details for the second point."
},
{
"type": "ending_slide",
"heading": "Get Started Today!",
"sub_heading": "Ready to Act?",
"description": "A final encouraging message.",
"cta_button": "Visit Our Website"
}
]
}'
Example (With Infographics)
curl -X POST 'https://embed-api.postnitro.ai/post/initiate/import' \
-H 'Content-Type: application/json' \
-H "embed-api-key: $POSTNITRO_API_KEY" \
-d '{
"postType": "CAROUSEL",
"templateId": "'"$POSTNITRO_TEMPLATE_ID"'",
"brandId": "'"$POSTNITRO_BRAND_ID"'",
"responseType": "PNG",
"slides": [
{
"type": "starting_slide",
"heading": "PostNitro Infographics",
"sub_heading": "Import API Feature",
"description": "Create stunning visual carousels with structured data."
},
{
"type": "body_slide",
"heading": "Grid Layout",
"description": "Display data in an organized grid format.",
"layoutType": "infographic",
"layoutConfig": {
"columnCount": 2,
"columnDisplay": "grid",
"displayCounterAs": "counter",
"hasHeader": true,
"columnData": [
{
"header": "Features",
"content": [
{"title": "Grid Display", "description": "Organized columns for comparison."},
{"title": "Counter Support", "description": "Numbered items for sequence."}
]
},
{
"header": "Options",
"content": [
{"title": "Column Headers", "description": "Enable/disable per column."},
{"title": "Flexible Columns", "description": "Choose 1, 2, or 3 columns."}
]
}
]
}
},
{
"type": "ending_slide",
"heading": "Try PostNitro Infographics",
"sub_heading": "Start Creating Today",
"cta_button": "Get Your API Key"
}
]
}'
Response
{
"success": true,
"message": "CAROUSEL generation initiated",
"data": {
"embedPostId": "post123",
"status": "PENDING"
}
}
Credit cost: 1 credit per slide.
Endpoint 3: Check Post Status
GET /post/status/{embedPostId}
No request body. Pass embedPostId as a path parameter.
Headers: embed-api-key: $POSTNITRO_API_KEY (required)
curl -X GET "https://embed-api.postnitro.ai/post/status/$EMBED_POST_ID" \
-H "embed-api-key: $POSTNITRO_API_KEY"
Response
{
"success": true,
"data": {
"embedPostId": "post123",
"embedPost": {
"id": "post123",
"postType": "CAROUSEL",
"status": "COMPLETED",
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:35:00Z"
},
"logs": [
{
"id": "log1",
"embedPostId": "post123",
"step": "INITIATED",
"status": "SUCCESS",
"message": "Post generation initiated",
"timestamp": "2024-01-15T10:30:00Z"
},
{
"id": "log2",
"embedPostId": "post123",
"step": "PROCESSING",
"status": "SUCCESS",
"message": "Content generated successfully",
"timestamp": "2024-01-15T10:32:00Z"
},
{
"id": "log3",
"embedPostId": "post123",
"step": "COMPLETED",
"status": "SUCCESS",
"message": "Post generation completed",
"timestamp": "2024-01-15T10:35:00Z"
}
]
}
}
Poll every 3–5 seconds. Check data.embedPost.status for completion. The logs array provides step-by-step progress.
Endpoint 4: Get Output
GET /post/output/{embedPostId}
No request body. Pass embedPostId as a path parameter.
Headers: embed-api-key: $POSTNITRO_API_KEY (required)
curl -X GET "https://embed-api.postnitro.ai/post/output/$EMBED_POST_ID" \
-H "embed-api-key: $POSTNITRO_API_KEY"
Response (PNG)
{
"success": true,
"data": {
"embedPost": {
"id": "post123",
"postType": "CAROUSEL",
"responseType": "PNG",
"status": "COMPLETED",
"credits": 4,
"createdAt": "2026-02-19T21:11:50.115Z",
"updatedAt": "2026-02-19T21:12:08.333Z"
},
"result": {
"id": "result123",
"name": "Welcome to the Carousel!",
"size": {
"id": "4:5",
"dimensions": { "width": 1080, "height": 1350 }
},
"type": "png",
"mimeType": "image/png",
"data": [
"https://...supabase.co/.../slide_0.png",
"https://...supabase.co/.../slide_1.png"
]
}
}
}
Response (PDF)
{
"success": true,
"data": {
"embedPost": {
"id": "post123",
"postType": "CAROUSEL",
"responseType": "PDF",
"status": "COMPLETED",
"credits": 10,
"createdAt": "2026-02-19T21:11:50.115Z",
"updatedAt": "2026-02-19T21:12:08.333Z"
},
"result": {
"id": "result123",
"name": "Welcome to the Carousel!",
"size": {
"id": "4:5",
"dimensions": { "width": 1080, "height": 1350 }
},
"type": "pdf",
"mimeType": "application/pdf",
"data": "https://...supabase.co/.../output.pdf"
}
}
}
Result Object
| Field | Type | Description |
|---|---|---|
id | string | Unique result identifier |
name | string | Design name (from template or "Untitled") |
size | object | { "id": "4:5", "dimensions": { "width": 1080, "height": 1350 } } |
type | string | File type ("png" or "pdf") |
mimeType | string | MIME type ("image/png" or "application/pdf") |
data | string or array | PNG: Array of URLs (one per slide). PDF: Single URL. |
Download the URLs directly to save the carousel files.
Step-by-Step Usage
AI-Generated Carousel
- Confirm
POSTNITRO_API_KEY,POSTNITRO_TEMPLATE_ID,POSTNITRO_BRAND_ID, andPOSTNITRO_PRESET_IDare set. - Ask the user for their generation type (
text,article, orx), the corresponding content (text, article URL, or X post URL), and any style instructions. - Send the generate request to
POST /post/initiate/generate. - Extract
embedPostIdfrom the response. - Poll
GET /post/status/{embedPostId}every 3–5 seconds untilstatusis"COMPLETED". - Call
GET /post/output/{embedPostId}to get the result. Download the URL(s) fromdatato save files.
Custom Content Carousel
- Confirm
POSTNITRO_API_KEY,POSTNITRO_TEMPLATE_ID, andPOSTNITRO_BRAND_IDare set. - Gather slide content from the user. Structure as: 1
starting_slide→ 1+body_slide→ 1ending_slide. - For data-heavy slides, use
layoutType: "infographic"with alayoutConfigobject. - Send the import request to
POST /post/initiate/import. - Follow the same poll → output flow.
Content Strategy Tips
- LinkedIn: Professional tone, actionable insights, 6–10 slides, clear CTA.
- Instagram: Visual-first, concise text, 5–8 slides, storytelling arc.
- TikTok: Trendy, punchy, 4–7 slides, hook on slide 1.
- X (Twitter): Data-driven, 3–6 slides, provocative opening.
Error Handling
- If the API returns an authentication error, verify
POSTNITRO_API_KEYis correct and the account is active. - If credits are exhausted, inform the user. Free plan: 5 credits/month. Paid plan: 250+ credits/month ($10/month base).
- If the status poll indicates failure, retry the initiation once before reporting the error.
- All endpoints are rate-limited per API key — space requests appropriately.
- Default
responseTypeis"PDF". Always specify"PNG"explicitly if individual slide images are needed.
Links
- Documentation: https://postnitro.ai/docs/embed/api
- Get API Key: https://postnitro.ai/app/embed
- Postman Collection: https://www.postman.com/postnitro/postnitro-embed-apis/overview
- Support: support@postnitro.ai
Overview
PostNitro Carousel Generator creates professional social media carousels via the PostNitro.ai Embed API. It supports AI-generated carousels from topics, articles, or text, and manual content imports for LinkedIn, Instagram, TikTok, and X, with outputs as PNG or PDF.
How This Skill Works
Two workflows are available: AI generation and content import. For either, initiate a POST to /post/initiate/generate or /post/initiate/import with templateId, brandId, and (for AI) presetId, then poll /post/status/{embedPostId} until status is COMPLETED and fetch the final carousel from /post/output/{embedPostId}. All requests require the embed-api-key header.
When to Use It
- Turn a topic, article URL, or text into a multi-slide carousel.
- Convert a blog post or long-form content into slides for LinkedIn, Instagram, TikTok, or X.
- Import your own slide content with infographics for full creative control.
- Automate social media content creation across LinkedIn, Instagram, TikTok, and X.
- Export carousels as PNG or PDF using a chosen template and brand.
Quick Start
- Step 1: Gather credentials and IDs: POSTNITRO_API_KEY, TEMPLATE_ID, BRAND_ID, and PRESET_ID (needed for AI).
- Step 2: Choose a workflow: AI generation (POST /post/initiate/generate) or content import (POST /post/initiate/import), including required fields like postType, templateId, brandId, and aiGeneration when applicable.
- Step 3: Initiate, poll /post/status/{embedPostId} until COMPLETED, then download the output from /post/output/{embedPostId} as PNG or PDF.
Best Practices
- Set and verify POSTNITRO_API_KEY, TEMPLATE_ID, BRAND_ID, and PRESET_ID when using AI generation.
- Choose aiGeneration.type carefully (text, article, or x) and provide the proper context.
- Associate a consistent TEMPLATE_ID and BRAND_ID to maintain branding across posts.
- Poll status actively and handle COMPLETED results before retrieval of output.
- Review the generated or imported slides for accessibility, alt text, and visual consistency before publishing.
Example Use Cases
- Turn a blog post into an Instagram or LinkedIn carousel by supplying the article URL and AI preset.
- Create a LinkedIn carousel from a topic by using AI generation with a structured template.
- Import a pre-written slide deck with infographics for a TikTok carousel.
- Generate an X carousel from a product launch thread for a multi-slide recap.
- Automate weekly brand updates across LinkedIn, Instagram, TikTok, and X using a single template.