Base URL: https://generatebot.com/api/v1
Authentication: Bearer token in the Authorization header.
text
Authorization: Bearer GENERATEBOT_API_KEY
All request and response bodies use JSON. Set Content-Type: application/json.
ActionEndpointCreditsTypeSearch contentPOST /agents/news-aggregator10syncFetch RSS feedsPOST /rss0syncManage RSS feedsGET/PUT/DELETE /rss0syncGenerate from URLPOST /pipelines (content-analyzer)100asyncGenerate from topicPOST /pipelines (topic-to-content)100asyncGenerate scriptsPOST /pipelines (script-generator)15asyncPoll statusGET /pipelines/{runId}0pollList runsGET /pipelines0syncSave contentPOST /content0syncList contentGET /content0syncGet/Update/DeleteGET/PATCH/DELETE /content/{id}0syncCheck creditsGET /credits0syncCredit transactionsGET /credits/transactions0sync
POST /api/v1/agents/news-aggregator (10 credits)
json
{
"topic": "sustainable architecture trends",
"category": "technology",
"searchConfig": {
"resultLimit": 10,
"countryCode": "us",
"freshness": "pw",
"searchBreadth": "wide",
"preferredDomains": ["techcrunch.com", "reuters.com"],
"excludeDomains": ["reddit.com"]
}
}
topic (required): What to search for
category (optional): technology, finance, health, realestate, marketing, etc.
searchConfig (optional):
resultLimit: number of results (default 10)countryCode: "us", "au", "gb", etc.freshness: "pd" (past day), "pw" (past week), "pm" (past month), "py" (past year)searchBreadth: "narrow", "balanced", "wide"preferredDomains / excludeDomains: arrays of domain stringsReturns: array of articles with url, title, description, source, publishedAt, category
Use the returned URLs with the pipeline endpoint below
Tip: RSS feeds (below) are a free alternative to the news aggregator.
All RSS operations cost 0 credits.
POST /api/v1/rss - Fetch and parse feeds
json
{
"feedUrls": ["https://techcrunch.com/feed/", "https://blog.example.com/rss"],
"maxItemsPerFeed": 10,
"keywords": ["AI", "marketing"],
"publishedAfter": "2026-04-01T00:00:00Z"
}
feedUrls (optional): Direct RSS/Atom feed URLs (max 50)urls (optional): Website URLs to auto-discover feeds (max 20)useSavedFeeds (optional): If true, includes your saved feed URLsmaxItemsPerFeed: 1-100keywords: Filter items by title + description match (max 20)publishedAfter: ISO 8601 date filterfeedFilter / feedExclude: Include/exclude feeds by patterndedup: Deduplicate items across runsskipUnhealthyFeeds: Skip feeds with 5+ consecutive failuresdigest: { "maxDigestItems": 20, "groupByTopic": true } for summarized outputurls, feedUrls, or useSavedFeedsGET /api/v1/rss - List saved feed URLs
{ "feedUrls": [...], "count": 3 }PUT /api/v1/rss - Save feed URLs (requires rss:write scope)
{ "feedUrls": ["https://example.com/feed.xml"] } (max 50)DELETE /api/v1/rss - Clear all saved feed URLs (requires rss:write scope)
POST /api/v1/pipelines (async)
Pipeline TypeCreditsRequiresPurposecontent-analyzer100urlGenerate articles, social posts, scripts, carousel from a URLfull-pipeline100query or queries[]Generate content from a topic or questionscript-generator15queryGenerate video scripts only
From a URL (most common):
json
{ "pipelineType": "content-analyzer", "url": "https://example.com/article" }
From a topic:
json
{ "pipelineType": "full-pipeline", "query": "How AI is transforming healthcare" }
Optional fields:
market: "au" or "us"resultLimit: 1-100businessProfile: object with company contextcarouselTemplate: { "prompt": "...", "username": "..." } (content-analyzer only)Response: { "pipelineRunId": "uuid", "status": "running", "creditsConsumed": 100, "statusUrl": "/api/v1/pipelines/{runId}" }
Save the pipelineRunId -- you need it later as sourcePipelineRunId when creating videos.
Polling: GET /api/v1/pipelines/{runId} every 10 seconds.
GET /api/v1/pipelines - List pipeline runs
?status=completed&pipelineType=content-analyzer&limit=10&offset=0When status is "completed", the response contains all generated content:
json
{
"status": "completed",
"results": {
"data": {
"agents": {
"aiContentGenerator": {
"generatedContent": {
"articles": [{ "title": "...", "introduction": "...", "sections": [{ "heading": "...", "content": "..." }], "wordCount": 1200 }],
"linkedInPosts": [{ "intro": "...", "mainContent": "...", "callToAction": "...", "hashtags": ["#AI"] }],
"instagramPosts": [{ "caption": "...", "hashtags": ["#AI"], "imageTextOverlay": "..." }]
}
},
"scriptGenerator": {
"scripts": [{
"hook": "Breaking news you need to know!",
"platform": "tiktok",
"mainContent": [
{ "scene": 1, "voiceOver": "Here is what happened...", "textOverlay": "Key Point 1" }
],
"callToAction": "Follow for more!",
"hashtags": ["#News"]
}]
},
"imageFinder": {
"foundImages": [
{ "imageUrl": "https://cdn.example.com/img1.jpg", "altText": "...", "suggestedUse": "hero" },
{ "imageUrl": "https://cdn.example.com/img2.jpg", "altText": "...", "suggestedUse": "supporting" }
]
},
"carouselGenerator": {
"carousel": {
"slides": [
{ "slideNumber": 1, "text": "Key takeaway from the article" },
{ "slideNumber": 2, "text": "Supporting point with context" },
{ "slideNumber": 3, "text": "Final thought and call to action" }
]
}
}
}
},
"totalImagesFound": 30,
"totalContentItems": 5
}
}
Key paths to extract:
results.data.agents.aiContentGenerator.generatedContent.articles[0]results.data.agents.scriptGenerator.scripts[0]results.data.agents.imageFinder.foundImagesresults.data.agents.carouselGenerator.carousel.slidesIMPORTANT: Pipeline results are NOT auto-saved. Save via POST /content before publishing.
POST /api/v1/content - Save content (required before CMS/social publishing)
json
{
"contentType": "article",
"title": "Article Title",
"contentData": {
"introduction": "Intro paragraph...",
"sections": [{ "heading": "Section", "content": "Body text..." }],
"metaDescription": "Short description"
},
"tags": ["ai", "marketing"]
}
contentType: "article" | "linkedin" | "instagram" | "tiktok" | "script" | "reel"contentData: JSON object (max 100KB)tags (optional): max 20 stringsnotes (optional): max 2000 chars{ "content": { "id": "uuid", ... } } -- save the id as contentIdGET /api/v1/content - List content
?contentType=article&status=draft&limit=10&offset=0&tags=ai,marketingGET /api/v1/content/{id} - Get single item with full contentData
PATCH /api/v1/content/{id} - Update (title, contentData, tags, notes, status)
DELETE /api/v1/content/{id} - Delete
GET /api/v1/credits (0 credits)
Returns: { "total": 500, "subscription": 400, "oneTime": 100, "adminGranted": 0, "quota": 1000 }
GET /api/v1/credits/transactions (0 credits) - Credit transaction history
?limit=20&offset=0HTTP StatusMeaning401Invalid or missing API key402Insufficient credits429Rate limit exceeded -- wait and retry400Invalid request body -- check error details404Resource not found
All errors: { "error": { "code": "ERROR_CODE", "message": "..." }, "requestId": "..." }
generatebot-video): Create video reels from pipeline data. Step-by-step tutorial for slides, image modes, captions, TTS.generatebot-publish): Post to social media, publish to CMS, enrich articles, brand voice, AI images.generatebot-templates): Design and render canvas-based post image templates.generatebot-workflows): End-to-end workflow examples, credit costs, usage patterns.Base URL: https://generatebot.com/api/v1
Authentication: Bearer token in the Authorization header.
text
Authorization: Bearer GENERATEBOT_API_KEY
All request and response bodies use JSON. Set Content-Type: application/json.
This skill creates short-form video reels (9:16 portrait, 1080x1920) with AI voiceover from content you have generated.
Before creating a video, you need completed pipeline results. Run a content pipeline first (see Core skill):
text
POST /api/v1/pipelines
{ "pipelineType": "content-analyzer", "url": "https://example.com/article" }
Poll until status is "completed", then extract these three things:
Carousel slides: results.data.agents.carouselGenerator.carousel.slides
json
[{ "slideNumber": 1, "text": "Key takeaway from the article" }, ...]
Images: results.data.agents.imageFinder.foundImages
json
[{ "imageUrl": "https://...", "altText": "...", "suggestedUse": "hero" }, ...]
Hook: results.data.agents.scriptGenerator.scripts[0].hook
json
"Breaking news you need to know!"
Pipeline Run ID: The pipelineRunId from the pipeline POST response.
Each carousel slide becomes one video slide. Map them like this:
json
{
"text": "<carousel slide text>",
"imageUrl": "<image URL from imageFinder>",
"highlight": ["key", "words"]
}
Pairing rules:
suggestedUse: "hero" image for slide 1imageUrl -- never reuse the same image across slidestext is max 200 charactersThe text field is both the on-screen caption AND the voiceover narration. Write it as spoken language:
The imageMode field controls how images appear in the 9:16 portrait frame:
ModeBehaviorBest For_(omit)_Auto-detect: landscape (w/h > 1.2) uses overlay, else backgroundMost cases -- recommended"overlay"Image shown as 16:9 PiP inset (top 12%) over blurred/darkened version of itselfLandscape images, real estate, group photos"background"Full-screen cover-crop fills the entire framePortrait images, close-ups"background_with_overlays"Primary image full-bleed + extraImages as PiP insetsMultiple detail shots over a main image
Recommendation: Omit imageMode in most cases. Auto-detection handles landscape vs portrait correctly. Only set it explicitly to override.
Add related images as overlays that appear synced to specific words in the narration:
json
{
"text": "A stunning property in Brisbane with a resort style pool",
"imageUrl": "https://cdn.example.com/mansion-exterior.jpg",
"extraImages": [
"https://cdn.example.com/mansion-aerial.jpg",
"https://cdn.example.com/mansion-pool.jpg"
],
"extraImageTimings": [
{ "showAtWordIndex": 2 },
{ "showAtWordIndex": 7 }
]
}
How word indexing works:
Count words in text starting from 0, split on whitespace. Punctuation stays attached.
For the text above: A(0) stunning(1) property(2) in(3) Brisbane(4) with(5) a(6) resort(7) style(8) pool(9)
When to use extraImages:
imageUrl in extraImages for blurred-bg + clear-overlay effectLimits: Max 5 extra images per slide. If you omit extraImageTimings, overlays distribute evenly (less precise).
The highlight field is an array of words from text to emphasize visually (rendered in accent color with glow effect):
json
"highlight": ["25 million", "mansion"]
textEach slide can override global styles:
FieldTypeRangefontSizenumber12-120fontWeightstring"normal" or "bold"textColorstringhex, e.g. "#FFFFFF"backgroundColorstringhex, e.g. "#000000"textAlignstring"left", "center", "right"textPositionstring"top", "center", "bottom"imageOpacitynumber0-1textWidthPercentnumber10-100imageScalenumber0.1-5 (zoom level)imagePositionXnumberhorizontal offsetimagePositionYnumbervertical offset
Advanced text styling ( textStyle object, all fields optional):
json
{
"textStyle": {
"fontFamily": "Inter",
"letterSpacing": 1.2,
"lineHeight": 1.4,
"textTransform": "uppercase",
"shadow": { "enabled": true, "offsetX": 2, "offsetY": 2, "blur": 4, "color": "#000000" },
"outline": { "enabled": true, "width": 2, "color": "#000000" },
"background": { "enabled": true, "color": "#000000", "opacity": 0.7, "paddingX": 12, "paddingY": 8, "borderRadius": 8 },
"glow": { "enabled": true, "blur": 10, "color": "#75F30F", "intensity": 0.8 }
}
}
textTransform: "none", "uppercase", "lowercase", "capitalize"shadow: Drop shadow behind textoutline: Stroke around text charactersbackground: Colored box behind text (like a caption box)glow: Colored glow effect around textjson
"hook": "<scriptGenerator.scripts[0].hook>"
script field needed -- the API auto-builds TTS narration from all slide textsjson
"style": {
"accentColor": "#FF5500",
"captionStyle": "outlined",
"captionPosition": "center",
"fontSize": 48,
"colorGrade": "cinematic",
"filmGrain": { "enabled": true, "opacity": 0.025, "fps": 8 }
}
FieldOptionsDefaultaccentColorHex color#75F30FcaptionStyle"default", "outlined", "boxed", "marker""outlined"captionPosition"center", "lower-third", "top""lower-third"fontSize24-9652colorGrade"cinematic", "warm", "cool", "vibrant", "none"nonefilmGrain``{ enabled, opacity (0-0.1), fps (1-30) }disabled
FieldDescriptionDefaultvoiceIdElevenLabs voice ID(default Australian male)ttsModel"eleven_v3", "eleven_flash_v2_5", "eleven_multilingual_v2", "eleven_turbo_v2_5""eleven_v3"speedFactor0.5-3.0, post-render speed multiplier1.35
POST /api/v1/videos (200 credits)
json
{
"hook": "$25M mansion hits the market!",
"slides": [
{
"text": "A 25 million dollar mansion in Brisbane is up for grabs.",
"imageUrl": "https://cdn.example.com/mansion-exterior.jpg",
"highlight": ["25 million", "mansion"],
"extraImages": ["https://cdn.example.com/mansion-aerial.jpg"],
"extraImageTimings": [{ "showAtWordIndex": 4 }]
},
{
"text": "Spanning 1400 square meters with five bedrooms and eight bathrooms.",
"imageUrl": "https://cdn.example.com/mansion-pool.jpg",
"highlight": ["1400", "bathrooms"]
}
],
"sourcePipelineRunId": "<pipelineRunId from pipeline POST>",
"style": {
"accentColor": "#75F30F",
"captionStyle": "outlined",
"captionPosition": "center"
}
}
Field constraints:
hook: 1-200 chars, requiredslides: 1-15 slides, required (4-7 recommended)slides[].text: 1-200 chars, requiredslides[].imageUrl: HTTPS URL, requiredslides[].highlight: max 10 items, optionalslides[].extraImages: max 5 URLs, optionalwatermark: small text in corner, max 100 chars, optionalwatermarkLogoUrl: HTTPS URL to a logo image for the watermark, optionalwatermarkPosition: position string (max 50 chars), optionalcta: { "text": "Follow for more!", "url": "example.com" }, optionalsourcePipelineRunId: UUID, strongly recommended -- links video to source contentResponse:
json
{
"jobId": "uuid",
"contentId": "uuid",
"status": "queued",
"creditsConsumed": 200,
"statusUrl": "/api/v1/videos/{jobId}"
}
GET /api/v1/videos/{jobId} every 5 seconds.
Status progression: queued -> generating_audio -> rendering -> uploading -> completed
videoUrl contains the download URL.error field contains the error message.Keep polling up to 5 minutes. Do NOT stop on intermediate statuses. Do NOT report failure until status is "failed" or you have polled the maximum duration.
The video response includes a contentId. Use it directly with POST /api/v1/social/post (see Publish skill):
json
{
"contentId": "<contentId from video response>",
"platforms": [{
"accountId": "<from GET /api/v1/social/accounts>",
"platform": "instagram",
"contentType": "video",
"caption": "Check out our latest video!"
}]
}
SlidesApproximate Time3-560-90 seconds6-1090-150 seconds11-15150-180 seconds
Audio generation adds 10-20 seconds. Upload adds 5-10 seconds.
HTTP StatusMeaning402Insufficient credits (need 200)429Too many concurrent renders (max 2) -- wait and retry400Invalid request body -- check error details
generatebot-core): Search for content, run pipelines, manage content library. Required before creating videos.generatebot-publish): Post completed videos to social media, publish articles to CMS.generatebot-templates): Design and render canvas-based post image templates.generatebot-workflows): End-to-end workflow examples and patterns.Base URL: https://generatebot.com/api/v1
Authentication: Bearer token in the Authorization header.
text
Authorization: Bearer GENERATEBOT_API_KEY
All request and response bodies use JSON. Set Content-Type: application/json.
ActionEndpointCreditsList social accountsGET /social/accounts0Post to socialPOST /social/post0Social post historyGET /social/history0List CMS accountsGET /cms/accounts0Publish to CMSPOST /cms/publish0CMS publish historyGET /cms/history0Create templatePOST /templates0List templatesGET /templates0Get/Update/DeleteGET/PATCH/DELETE /templates/{id}0Render templatePOST /templates/{id}/render20Enrich with linksPOST /enrich/internal-links20Enrich with imagesPOST /enrich/images20Brand voice rewritePOST /agents/brand-voice-rewriter5Generate imagesPOST /agents/ai-image-generator10Reddit repliesPOST /agents/reddit-replier10Business profilePOST /agents/business-profile-generator5
Most publish actions require a contentId:
id is your contentId.contentId automatically (see Video skill).Step 1: List connected accounts:
GET /api/v1/social/accounts
Returns: [{ "id": "uuid", "platform": "instagram", "username": "@handle", "isConnected": true }]
Step 2: Post content: POST /api/v1/social/post
json
{
"contentId": "uuid-of-saved-content",
"platforms": [
{
"accountId": "uuid-from-social-accounts",
"platform": "instagram",
"contentType": "video",
"caption": "Check out our latest video!"
},
{
"accountId": "uuid-linkedin",
"platform": "linkedin",
"contentType": "text",
"text": "Great insights on AI in healthcare..."
}
]
}
contentId (required): UUID from POST /content or POST /videosplatforms[].accountId (required): from GET /social/accountsplatforms[].platform: "instagram", "tiktok", "threads", "linkedin", "youtube"platforms[].contentType: "text", "image", "video", "carousel", "multi-image"caption (max 5000), text (max 5000), hashtags (max 30), mediaUrls (max 10), title (max 200)Step 1: List connected CMS platforms:
GET /api/v1/cms/accounts
Returns: [{ "id": "uuid", "platform": "wordpress", "siteUrl": "https://myblog.com", "isConnected": true }]
Step 2: Publish: POST /api/v1/cms/publish
json
{
"contentId": "uuid-from-post-content",
"cmsAccountId": "uuid-from-cms-accounts",
"title": "Article Title",
"content": "<p>Introduction paragraph...</p><h2>Section Heading</h2><p>Section content...</p>",
"excerpt": "Short description",
"featuredImageUrl": "https://cdn.example.com/hero.jpg",
"status": "published"
}
contentId (required): UUID from POST /contentcmsAccountId (required): from GET /cms/accountstitle: 1-500 charscontent: HTML string, 1-200,000 charsslug (max 200), excerpt (max 1000), featuredImageUrl, categories (max 10), tags (max 20), status ("draft" | "published"), scheduledAt (ISO 8601)HTML conversion tip: Wrap introduction in <p> tags, each section as <h2>heading</h2><p>content</p>.
POST /api/v1/enrich/internal-links
json
{
"article": {
"title": "Article title",
"introduction": "Intro text...",
"sections": [{ "heading": "Section heading", "content": "Section body..." }]
},
"businessProfile": {
"sitemapUrl": "https://example.com/sitemap.xml",
"websiteUrl": "https://example.com"
}
}
Returns: enriched article with relevant internal links inserted into the content.
POST /api/v1/enrich/images
json
{
"article": {
"title": "Article title",
"sections": [{ "heading": "Section heading", "content": "Section body..." }]
},
"images": [
{ "imageUrl": "https://...", "altText": "Description", "suggestedUse": "hero" }
]
}
suggestedUse: "hero", "supporting", "thumbnail", or "background"POST /api/v1/agents/brand-voice-rewriter
json
{
"articles": [{
"title": "Article Title",
"introduction": "Article intro...",
"sections": [{ "heading": "Section heading", "content": "Section body..." }],
"metaDescription": "Short description"
}],
"businessProfile": {
"companyName": "Acme Corp",
"brandVoice": "professional",
"targetAudience": "enterprise CTOs",
"industryCategory": "technology"
}
}
Returns: rewritten articles matching the brand voice.
POST /api/v1/agents/ai-image-generator
json
{
"prompts": ["Modern office workspace with natural lighting, minimalist design"],
"style": "natural",
"size": "1024x1024"
}
prompts (required): Array of 1-5 strings (min 10 chars each)style: "natural" or "vivid" (default: "natural")size: "1024x1024", "1536x1024", "1024x1536", "auto"quality: "low", "medium", "high"useCase: "thumbnail", "instagram", "carousel", "article" (auto-selects best size/quality){ "data": { "images": [{ "imageUrl": "https://cdn.generatebot.com/...", "prompt": "..." }] } }imageUrl values directly as slide images when creating video reelsPOST /api/v1/agents/reddit-replier
json
{
"redditPostUrl": "https://www.reddit.com/r/smallbusiness/comments/abc123/best_tools/"
}
redditPostUrl (required): Full URL to a Reddit postanalysisConfig: { "responseStyle": "professional" | "casual" | "educational" }POST /api/v1/agents/business-profile-generator
json
{
"websiteUrl": "https://example.com",
"companyName": "Example Corp"
}
websiteUrl (required): Company website to crawlcompanyName (required): Company nameuserDescription, industryHint, country (default: "Australia")Design and render social media post images using Fabric.js canvas templates.
POST /api/v1/templates - Create a template
json
{
"name": "LinkedIn Announcement",
"description": "Clean announcement card for LinkedIn",
"category": "linkedin",
"canvasJson": "{...Fabric.js canvas JSON...}",
"templateMetadata": {
"fields": [
{ "key": "headline", "objectName": "headline-text", "label": "Headline", "maxLength": 80, "required": true },
{ "key": "body", "objectName": "body-text", "label": "Body Text", "maxLength": 200 }
],
"imageSlots": [
{ "key": "logo", "objectName": "logo-image", "required": true }
]
}
}
category: "linkedin", "instagram", or "article"canvasJson: Valid Fabric.js JSON string (max 500KB). Must contain an objects array with a clip workspace object.templateMetadata.fields: Max 20 text fields. Each maps a key to a canvas objectName.templateMetadata.imageSlots: Max 10 image slots. Each maps a key to a canvas objectName.GET /api/v1/templates - List templates
?category=linkedin&limit=10&offset=0GET /api/v1/templates/{id} - Get template with full canvas JSON
PATCH /api/v1/templates/{id} - Update (name, description, category, canvasJson, templateMetadata, isActive)
DELETE /api/v1/templates/{id} - Delete template
POST /api/v1/templates/{id}/render (20 credits) - Render template to image
json
{
"fields": {
"headline": "We Just Launched!",
"body": "Our new AI-powered content platform is live."
},
"images": {
"logo": "https://cdn.example.com/logo.png"
},
"outputFormat": "jpeg",
"quality": 0.9
}
fields: Key-value map matching template field keysimages: Key-value map matching template image slot keys (HTTPS URLs only)outputFormat: "jpeg" (default) or "png"quality: 0.1-1.0 (default: 0.9){ "creditsConsumed": 20, "imageUrl": "https://cdn...", "width": 1080, "height": 1080 }GET /api/v1/social/history - View past social media posts
?platform=instagram&status=published&limit=20&offset=0platform: "instagram", "tiktok", "threads", "linkedin", "youtube"status: "pending", "uploading", "processing", "published", "failed", "expired", "cancelled"GET /api/v1/cms/history - View past CMS publications
?platform=wordpress&status=published&limit=20&offset=0platform: "wordpress", "ghost", "webflow", "wix", "shopify", "framer", "notion"status: "pending", "publishing", "published", "failed", "updated", "cancelled"HTTP StatusMeaning401Invalid or missing API key402Insufficient credits429Rate limit exceeded -- wait and retry400Invalid request body -- check error details404Resource not found
All errors: { "error": { "code": "ERROR_CODE", "message": "..." }, "requestId": "..." }
generatebot-core): Search for content, run pipelines, manage content library, RSS feeds.generatebot-video): Create video reels from pipeline data.generatebot-templates): Design and render canvas-based post image templates.generatebot-workflows): End-to-end workflow examples and patterns.Base URL: https://generatebot.com/api/v1
Authentication: Bearer token in the Authorization header.
text
Authorization: Bearer GENERATEBOT_API_KEY
All request and response bodies use JSON. Set Content-Type: application/json.
ActionMethodPathCreditsTypeCreate templatePOST/templates0syncList templatesGET/templates0syncGet templateGET/templates/{id}0syncUpdate templatePATCH/templates/{id}0syncDelete templateDELETE/templates/{id}0syncRender templatePOST/templates/{id}/render20sync
Templates are canvas JSON documents with dynamic text and image slots. When rendered, the system substitutes placeholder content with real text and images, auto-fits text to its bounding box, and smart-fits images to cover their target areas. The output is a high-quality image (JPEG or PNG) uploaded to CDN.
json
{
"version": "5.3.0",
"objects": [ ... ],
"clipPath": {
"type": "rect",
"version": "5.3.0",
"left": 0, "top": 0,
"width": 1080, "height": 1920,
"fill": "#0a0a0a",
"scaleX": 1, "scaleY": 1
}
}
version: Always "5.3.0"objects: Ordered array of canvas objects (back-to-front rendering order)clipPath: Canvas-level clip boundary -- MUST match the clip rect dimensions and fillEvery template MUST have a clip rect as its first object. This defines the artboard:
json
{
"type": "rect",
"version": "5.3.0",
"originX": "left", "originY": "top",
"left": 0, "top": 0,
"width": 1080, "height": 1920,
"fill": "#0a0a0a",
"stroke": null, "strokeWidth": 0,
"scaleX": 1, "scaleY": 1,
"opacity": 1, "visible": true,
"name": "clip",
"selectable": false, "hasControls": false
}
Common dimensions:
FormatWidthHeightUse CasePortrait / Story10801920Instagram Stories, LinkedIn StoriesSquare10801080Instagram Feed, LinkedIn FeedLandscape1200627LinkedIn Articles, Twitter/X
PatternTypeExamplePurpose{{key}}Dynamic{{title}}, {{primaryImage}}Replaced during renderingPlain nameStaticgradient_overlay_1, accent_lineFixed decorative elementsclipWorkspaceclipArtboard boundary (exactly one)
Image placeholders define where dynamic images appear. The src MUST use a 1x1 transparent pixel -- never an empty string.
json
{
"type": "image",
"version": "5.3.0",
"originX": "left", "originY": "top",
"left": 0, "top": 0,
"width": 1200, "height": 800,
"scaleX": 0.9, "scaleY": 2.4,
"opacity": 1, "visible": true,
"name": "{{primaryImage}}",
"selectable": true, "hasControls": true,
"src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=",
"crossOrigin": "anonymous",
"filters": []
}
Key rules:
src MUST be the 1x1 transparent pixel base64 shown above. Empty string "" causes rendering failures.crossOrigin MUST be "anonymous"filters MUST be [] (empty array)width/ height define unscaled dimensions; scaleX/ scaleY scale to visual target sizeCircular image crop (optional):
json
{
"type": "image",
"name": "{{secondaryImage}}",
"width": 300, "height": 300,
"scaleX": 1, "scaleY": 1,
"src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=",
"crossOrigin": "anonymous", "filters": [],
"clipPath": {
"type": "circle",
"version": "5.3.0",
"radius": 140,
"left": 0, "top": 0,
"originX": "center", "originY": "center",
"fill": "rgb(0,0,0)",
"inverted": false, "absolutePositioned": false
}
}
Use large fontSize directly -- never use scaleX/ scaleY to size text.
json
{
"type": "textbox",
"version": "5.3.0",
"originX": "left", "originY": "top",
"left": 70, "top": 1050,
"width": 940, "height": 350,
"fill": "rgba(255, 255, 255, 1)",
"stroke": null, "strokeWidth": 0,
"fontSize": 82, "fontFamily": "Arial", "fontWeight": 900,
"text": "Headline Goes Here in Bold White Text",
"textAlign": "left", "lineHeight": 1.08, "charSpacing": 0,
"scaleX": 1, "scaleY": 1,
"angle": 0, "opacity": 1, "visible": true,
"name": "{{title}}",
"selectable": true, "hasControls": true, "editable": true
}
Key rules:
fontSize MUST be the actual desired size. Do NOT use scaleX/scaleY to enlarge text -- this breaks auto-fit.scaleX and scaleY MUST be 1 on text objects.height defines the maximum bounding box -- set it generously. The renderer shrinks text to fit.width defines the text wrapping width.Recommended font sizes by role:
RolefontSizefontWeightNotesTitle / Headline62-82700-900Bold, high-impactDescription / Body32-42400Regular weightLabel / Tag24-28700Often with charSpacing: 80-150Website / URL22-26400-600Subtle, lower opacityCTA24-28600-700Right-aligned or centered
Gradient overlays create dark zones over images where text remains readable. Use a 400x400 base rect, scale it up with scaleX/ scaleY, and flip vertically with flipY: true so the solid color sits at the bottom.
json
{
"type": "rect",
"version": "5.3.0",
"originX": "left", "originY": "top",
"left": -20, "top": 540,
"width": 400, "height": 400,
"fill": {
"type": "linear",
"coords": {"x1": 200, "y1": 0, "x2": 200, "y2": 400},
"colorStops": [
{"offset": 0, "color": "rgba(0, 0, 0, 1)"},
{"offset": 0.6, "color": "rgba(0, 0, 0, 0.75)"},
{"offset": 0.9, "color": "rgba(0, 0, 0, 0)"}
],
"offsetX": 0, "offsetY": 0, "gradientUnits": "pixels"
},
"stroke": null, "strokeWidth": 0,
"scaleX": 2.85, "scaleY": 3.5,
"flipY": true,
"opacity": 1, "visible": true,
"name": "gradient_overlay_1", "selectable": true
}
Best practices:
flipY: true makes offset 0 (solid) appear at the bottom, offset 1 (transparent) at the topleft: -20 to ensure full-width coverage after scalingDescribes which objects are dynamic and how they appear in the editor:
json
{
"fields": [
{
"key": "title",
"objectName": "{{title}}",
"label": "Title",
"maxLength": 80,
"required": true,
"defaultValue": "Headline Goes Here in Bold White Text"
}
],
"imageSlots": [
{
"key": "primaryImage",
"objectName": "{{primaryImage}}",
"required": true
}
]
}
Rules:
{{key}} object in canvas JSON MUST have a matching entry in fields (text) or imageSlots (images)objectName MUST exactly match the object's name including {{ and }}defaultValue should match the text property of the corresponding textboxStandard variable names:
KeyTypePurposeTypical maxLengthtitlefieldMain headline60-100descriptionfieldSupporting text150-250labelfieldCategory tag (e.g., "BREAKING NEWS")20-30websitefieldURL or domain30ctafieldCall to action (e.g., "Read Below")20-30primaryImageimageSlotMain hero image-secondaryImageimageSlotSupporting image (headshot, logo)-
json
{
"name": "News Card Dark",
"description": "Dark cinematic news card with full-bleed hero image...",
"category": "linkedin",
"canvasJson": "{...stringified canvas JSON...}",
"templateMetadata": {
"fields": [...],
"imageSlots": [...]
}
}
Validation:
name: 1-200 characters, requireddescription: max 1000 characters, optionalcategory: "linkedin" | "instagram" | "article", requiredcanvasJson: stringified JSON, max 500KB, must contain a clip objecttemplateMetadata.fields: max 20 itemstemplateMetadata.imageSlots: max 10 itemsResponse (201):
json
{
"success": true,
"data": {
"template": {
"id": "uuid",
"name": "News Card Dark",
"description": "...",
"category": "linkedin",
"template_metadata": {...},
"thumbnail_url": null,
"created_at": "2026-04-10T..."
}
}
}
Query: ?category=linkedin&limit=10&offset=0
Returns lightweight metadata (no canvas_json). Use GET by ID for the full template.
json
{
"success": true,
"data": {
"templates": [...],
"pagination": { "total": 12, "limit": 10, "offset": 0, "hasMore": true }
}
}
Returns full template including canvas_json.
Partial updates. Send only the fields to change ( name, category, canvasJson, templateMetadata, isActive).
Returns { "success": true, "data": { "deleted": true } }.
json
{
"fields": {
"title": "Breaking: AI Reaches New Milestone",
"description": "Researchers announce breakthrough in reasoning capabilities.",
"label": "TECH NEWS",
"website": "technews.com"
},
"images": {
"primaryImage": "https://example.com/hero.jpg"
},
"outputFormat": "jpeg",
"quality": 0.9
}
fields: key-value pairs matching template field keys (all strings)images: key-value pairs matching template image slot keys (HTTPS URLs only)outputFormat: "jpeg" (default) or "png"quality: 0.1-1.0, default 0.9Response:
json
{
"success": true,
"data": {
"imageUrl": "https://generatebot.b-cdn.net/posts/...",
"width": 1080,
"height": 1920,
"creditsConsumed": 20,
"pipelineRunId": "uuid"
}
}
The renderer automatically shrinks text to fit within its bounding box:
height generously on textbox objects -- this is the max vertical spacefontSize -- the renderer shrinks if text is longer than placeholderscaleX/ scaleY for text sizing -- keep both at 1The renderer scales images to cover their target area without distortion:
width * scaleX by height * scaleYPattern 1: Hero Image with Gradient Overlay (Dark Theme) Best for news, dramatic stories. Full-bleed hero image, two stacked gradient rects, bold white title, subtle description, label at top, website/CTA at bottom.
Pattern 2: Square Card with Accent Line Best for feeds. 1080x1080, aggressive gradient, thin vertical accent line, large caps title, no description.
Pattern 3: Editorial Clean (Light Theme) Best for thought leadership. Light background, colored label badge, serif title, hero image in bottom half.
Pattern 4: Split Dual Image Best for comparisons. Two images separated by a colored title band.
src must NEVER be empty string. Always use: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=scaleX and scaleY must be 1. Use fontSize for sizing.clip rect must be the first object with name: "clip".clipPath must match the clip rect's dimensions and fill.crossOrigin: "anonymous" and filters: [].scaleX/ scaleY. Never use full canvas dimensions directly.height on textboxes -- this is the auto-fit bounding box."linkedin", "instagram", or "article".canvasJson max size is 500KB.{{key}} object must have a matching metadata entry.Arial, Arial Black, Verdana, Helvetica, Tahoma, Trebuchet MS, Times New Roman, Georgia, Garamond, Courier New, Brush Script MT, Palatino, Bookman, Comic Sans MS, Impact, Lucida Sans Unicode, Geneva, Lucida Console
Step 1: Create
bash
curl -X POST https://generatebot.com/api/v1/templates \
-H "Authorization: Bearer GENERATEBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "News Card Dark",
"description": "Dark cinematic news card",
"category": "linkedin",
"canvasJson": "{...stringified canvas JSON...}",
"templateMetadata": {
"fields": [
{"key": "title", "objectName": "{{title}}", "label": "Title", "maxLength": 80, "required": true, "defaultValue": "Your Headline"}
],
"imageSlots": [
{"key": "primaryImage", "objectName": "{{primaryImage}}", "required": true}
]
}
}'
Step 2: Render (20 credits)
bash
curl -X POST https://generatebot.com/api/v1/templates/TEMPLATE_ID/render \
-H "Authorization: Bearer GENERATEBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"fields": { "title": "AI Breakthrough Announced Today" },
"images": { "primaryImage": "https://example.com/hero.jpg" },
"outputFormat": "jpeg",
"quality": 0.9
}'
HTTP StatusMeaning401Invalid or missing API key402Insufficient credits429Rate limit exceeded -- wait and retry400Invalid request body -- check error details404Template not found
All errors: { "error": { "code": "ERROR_CODE", "message": "..." }, "requestId": "..." }
generatebot-core): Search, pipeline, RSS, content CRUD, and credits endpoints.generatebot-video): Detailed video creation tutorial with imageMode reference.generatebot-publish): Social posting, CMS publishing, enrichment, brand voice, AI images.generatebot-workflows): End-to-end workflow patterns and usage mapping.Base URL: https://generatebot.com/api/v1
Authentication: Bearer token in the Authorization header.
text
Authorization: Bearer GENERATEBOT_API_KEY
All request and response bodies use JSON. Set Content-Type: application/json.
ActionCreditsSkillSearch (news-aggregator)10CoreRSS feeds (all operations)0CoreContent pipeline (content-analyzer)100CoreTopic pipeline (full-pipeline)100CoreScript generator pipeline15CoreVideo reel200VideoTemplate render20PublishEnrich (links or images)20 eachPublishBrand voice rewrite5PublishAI image generation10PublishReddit replies10PublishBusiness profile5PublishSave/list content0CoreCredit transactions0CoreTemplate CRUD0PublishSocial media post0PublishSocial post history0PublishCMS publish0PublishCMS publish history0PublishCheck credits0Core
User RequestActionsCredits"search for [topic]"POST /agents/news-aggregator10"get RSS news"POST /rss0"write an article about [topic]"POST /pipelines (full-pipeline)100"create content from [url]"POST /pipelines (content-analyzer)100"make a video about [topic]"Pipeline (100) + Video (200)300"enrich with links/images"POST /enrich/*20 each"generate images"POST /agents/ai-image-generator10"rewrite in brand voice"POST /agents/brand-voice-rewriter5"create a post template"POST /templates0"render a template"POST /templates/{id}/render20"post to [platform]"POST /social/post (needs contentId)0"publish to [cms]"POST /cms/publish (needs contentId)0"show post history"GET /social/history or GET /cms/history0"check credits" / "transactions"GET /credits or GET /credits/transactions0
Step 1: Check credits -- GET /api/v1/credits (0 credits)
Step 2: Search for a topic -- POST /api/v1/agents/news-aggregator (10 credits)
{ "topic": "your topic here" }Step 3: Generate content -- POST /api/v1/pipelines (100 credits)
{ "pipelineType": "content-analyzer", "url": "<URL from step 2>" }Step 4: Extract content from completed pipeline
results.data.agents.aiContentGenerator.generatedContent.articles[0]results.data.agents.scriptGenerator.scripts[0]results.data.agents.imageFinder.foundImagesresults.data.agents.carouselGenerator.carousel.slidesStep 5: Save the article -- POST /api/v1/content (0 credits)
json
{
"contentType": "article",
"title": "<articles[0].title>",
"contentData": {
"introduction": "<articles[0].introduction>",
"sections": "<articles[0].sections>",
"metaDescription": "<articles[0].metaDescription>"
}
}
Save the returned contentId at response.content.id.
Step 6: Publish article to CMS -- POST /api/v1/cms/publish (0 credits)
cmsAccountId<p>introduction</p><h2>heading</h2><p>content</p>contentId and cmsAccountIdStep 7: Create video reel -- POST /api/v1/videos (200 credits)
sourcePipelineRunId from step 3Step 8: Post video to social media -- POST /api/v1/social/post (0 credits)
contentId from the video response with contentType: "video"Total: ~310 credits (10 search + 100 pipeline + 200 video). CMS and social posting are free.
Tip: Use RSS feeds (POST /rss, 0 credits) instead of the news aggregator (10 credits) to source article URLs for free. Save your feed URLs once with PUT /rss, then fetch with { "useSavedFeeds": true }.
{ "feedUrls": ["https://techcrunch.com/feed/"] }{ "useSavedFeeds": true, "keywords": ["AI"], "maxItemsPerFeed": 5 }sourcePipelineRunId.Pipelines: Poll every 10 seconds.
Videos: Poll every 5 seconds.
Images: Synchronous but slow (5-15 seconds per image). Wait for the response.
CRITICAL: Do NOT stop polling on intermediate statuses. Do NOT report failure until status is actually "failed" or you have polled for the maximum duration.
HTTP StatusMeaning401Invalid or missing API key402Insufficient credits429Rate limit exceeded -- wait and retry400Invalid request body -- check error details404Resource not found
All errors: { "error": { "code": "ERROR_CODE", "message": "..." }, "requestId": "..." }
generatebot-core): All search, pipeline, RSS, content CRUD, and credits endpoints.generatebot-video): Detailed video creation tutorial with imageMode reference.generatebot-publish): Social posting, CMS publishing, enrichment, brand voice, AI images.generatebot-templates): Design and render canvas-based post image templates.