skills/orshot/SKILL.md
Generate images, PDFs, and videos programmatically using the Orshot API. Use when building visual content automation, marketing image generation, certificate/invoice PDFs, social media carousels, or video generation from templates.
npx skillsauth add orshot-hq/orshot-agent-skills orshotInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Orshot is an automated image, PDF, and video generation platform. Design templates in Orshot Studio (or import from Canva/Figma), then generate renders via REST API, SDKs, or no-code integrations.
Use this skill when:
Any page on orshot.com can be fetched as clean markdown by appending .md to the URL or sending Accept: text/markdown header. Use this to get detailed, up-to-date information on demand without relying solely on this skill file.
Examples:
https://orshot.com/docs/api-reference.md
https://orshot.com/docs/sdks/node.md
https://orshot.com/docs/publish/publish-from-api.md
https://orshot.com/docs/developers/oauth-overview.md
https://orshot.com/docs/orshot-embed/introduction.md
https://orshot.com/blog/bannerbear-api-alternative.md
Key documentation pages:
| Topic | URL |
|-------|-----|
| API Reference | https://orshot.com/docs/api-reference.md |
| Node.js SDK | https://orshot.com/docs/sdks/node.md |
| Python SDK | https://orshot.com/docs/sdks/python.md |
| PHP SDK | https://orshot.com/docs/sdks/php.md |
| Ruby SDK | https://orshot.com/docs/sdks/ruby.md |
| Studio Templates | https://orshot.com/docs/orshot-studio/introduction.md |
| Style Parameters | https://orshot.com/docs/orshot-studio/style-parameters.md |
| Setting Parameters | https://orshot.com/docs/orshot-studio/setting-parameters.md |
| Image Generation | https://orshot.com/docs/image-generation.md |
| Video Generation | https://orshot.com/docs/video-generation.md |
| PDF Generation | https://orshot.com/docs/pdf-generation.md |
| Social Publishing | https://orshot.com/docs/publish/introduction.md |
| OAuth / Developer Apps | https://orshot.com/docs/developers.md |
| White-Label Embed | https://orshot.com/docs/orshot-embed/introduction.md |
| Integrations | https://orshot.com/docs/integrations.md |
| Dynamic URLs | https://orshot.com/docs/integrations/dynamic-urls.md |
| Webhooks | https://orshot.com/docs/integrations/webhooks.md |
| Error Reference | https://orshot.com/docs/error-reference.md |
When a user asks about a specific topic, fetch the relevant .md URL for the latest details.
All API requests require a Bearer token in the Authorization header:
Authorization: Bearer <ORSHOT_API_KEY>
Get your API key from Workspace Settings → API Keys in the Orshot dashboard.
npm install orshot
import { Orshot } from "orshot";
const orshot = new Orshot("<ORSHOT_API_KEY>");
// Render from template
const response = await orshot.renderFromTemplate({
templateId: "open-graph-image-1",
modifications: { title: "Hello World" },
responseType: "base64", // "base64" | "url" | "binary"
responseFormat: "png", // "png" | "webp" | "jpg" | "pdf"
});
// Generate signed URL
const signedUrl = await orshot.generateSignedUrl({
templateId: "open-graph-image-1",
modifications: { title: "Hello" },
expiresAt: 1744276943,
renderType: "images",
responseFormat: "png",
});
pip install orshot
import orshot
os = orshot.Orshot('<ORSHOT_API_KEY>')
response = os.render_from_template({
'template_id': 'open-graph-image-1',
'modifications': {'title': 'Hello World'},
'response_type': 'base64',
'response_format': 'png'
})
composer require nicholasgriffintn/orshot-phpgem install orshotThis section describes the complete structure of an Orshot template for MCP tools and AI agents.
An Orshot template consists of pages, each containing a canvas and elements.
Template
├── id: number | string
├── name: string
├── description: string
├── width: number
├── height: number
├── pages_data: Array
└── Page
├── id: string (UUID)
├── name: string
├── canvas: CanvasConfig
├── width: number
├── height: number
├── backgroundColor: string
├── backgroundImage: string
├── elements: Element[]
├── modifications: Modification[] (API parameters)
├── id: string
├── type: string
├── element: Element
├── description: string
└── thumbnail_url: string | null
| Property | Type | Default | Description |
| ----------------- | ------ | --------------- | ----------------------------------------- |
| width | number | 800 | Canvas width in pixels (max: 5000) |
| height | number | 800 | Canvas height in pixels (max: 5000) |
| backgroundColor | string | "#ffffff" | Background color (hex, rgba, or gradient) |
| backgroundImage | string | "" | URL to background image |
| borderWidth | number | 0 | Border width in pixels |
| borderColor | string | "rgba(0,0,0,1)" | Border color |
| borderStyle | string | "solid" | Border style (solid, dashed, etc) |
| Name | Dimensions | Use Case | | -------------------- | ---------- | ------------------------------- | | Square | 1080×1080 | Instagram posts, general social | | Instagram Story | 1080×1920 | Stories, Reels, TikTok | | Slide/Presentation | 1920×1080 | Presentations, slides | | YouTube Thumbnail | 1280×720 | Video thumbnails | | Twitter Post | 1600×900 | X/Twitter posts | | Open Graph | 1200×630 | Link previews, Facebook | | Pinterest Pin | 1000×1500 | Pinterest | | A4 Document | 2480×3508 | Print documents | | App Store Screenshot | 1290×2796 | iOS app screenshots |
All elements share these base properties:
| Property | Type | Description |
| ------------------- | ------- | -------------------------------------------- |
| id | string | Unique identifier (UUID) |
| name | string | Display name in layer list (was layerName) |
| type | string | "text", "image", "shape", "video" |
| position | object | { x: number, y: number } from top-left |
| dimensions | object | { width: number, height: number } |
| rotation | number | Rotation in degrees (0-360) |
| zIndex | number | Layer order (higher = on top) |
| aspectRatioLocked | boolean | Lock aspect ratio during resize |
| isHidden | boolean | Hide element from render |
| skewX | number | Horizontal skew angle |
| skewY | number | Vertical skew angle |
Content Types:
"Hello World" - Standard text string\n for line breaks: "Line 1\nLine 2".prompt modifier for AI-generated text{
type: "text",
content: string, // Plain text string
layerName: string, // Display name
zIndex: number,
rotation: number,
position: { x: number, y: number },
dimensions: { width: number, height: number },
style: {
// Typography
fontFamily: string, // e.g., "Inter", "Prata", "SF Pro"
fontSize: string, // e.g., "48px"
fontWeight: string | number, // "400", "700", 700
fontStyle: string, // "normal", "italic"
lineHeight: number, // e.g., 1.2
letterSpacing: string, // e.g., "0px", "2px"
// Appearance
fill: string, // Color or gradient
color: string, // Hex or rgba
opacity: number, // 0-1
stroke: string, // Stroke color
strokeWidth: string, // e.g., "0px"
// Alignment & Layout
textAlign: string, // "left", "center", "right"
verticalAlign: string, // "flex-start", "center", "flex-end"
textTransform: string, // "none", "uppercase"
textDecoration: string, // "none", "underline"
textMode: string, // "overflow", "fit"
paddingX: string,
paddingY: string,
// Borders & Backgrounds
borderColor: string,
borderWidth: string,
borderRadius: string,
textBackgroundColor: string,
textBackgroundRadius: string,
textStrokeColor: string,
textStrokeWidth: string,
// Effects
minFontSize: string, // For "fit" mode
filter: string, // e.g., "blur(0px)"
mixBlendMode: string, // "normal", "multiply", etc.
boxShadowX: string,
boxShadowY: string,
boxShadowBlur: string,
boxShadowColor: string,
dropShadowX: string,
dropShadowY: string,
dropShadowBlur: string,
dropShadowColor: string
},
// Parameterization
parameterizable: boolean,
parameterId: string,
parameterType: "text"
}
Gradient text:
color: "linear-gradient(90deg, #FF6B6B 0%, #4ECDC4 100%)";
Content Types:
"https://example.com/image.png" - Best for dynamic content"data:image/png;base64,iVBORw0KGgo..." - For embedded images{
type: "image",
content: string, // URL (preferred), base64, or binary
isSvg: boolean,
layerName: string,
style: {
// Sizing & Positioning
objectFit: string, // "contain", "cover", "fill"
objectPosition: string, // "center", "top left"
// Appearance
opacity: number,
fill: string, // Background fill
stroke: string, // Border stroke
// Borders
borderRadius: string, // "0px", "12px", "50%"
borderWidth: string,
borderColor: string,
// Effects
filter: string, // "blur(2px)", "grayscale(100%)"
mixBlendMode: string,
boxShadowX: string,
boxShadowY: string,
boxShadowBlur: string,
boxShadowColor: string,
dropShadowX: string,
dropShadowY: string,
dropShadowBlur: string,
dropShadowColor: string,
svgColor: string // Recolor monochrome SVGs
},
parameterType: "imageUrl"
}
{
type: "shape",
shapeType: string, // "rectangle", "circle", "arrow"
layerName: string,
style: {
// Fill & Stroke
fill: string, // Color or gradient
stroke: string,
strokeWidth: string, // e.g. "0px"
// Dimensions
borderRadius: string, // Rectangle only
borderWidth: string,
borderColor: string,
borderStyle: string,
// Appearance
opacity: number,
filter: string,
mixBlendMode: string,
// Shadows
boxShadowX: string,
boxShadowY: string,
boxShadowBlur: string,
boxShadowColor: string,
dropShadowX: string,
dropShadowY: string,
dropShadowBlur: string,
dropShadowColor: string
},
parameterType: "fill"
}
Gradient fills:
fill: "linear-gradient(180deg, rgba(0,0,0,0.7) 0%, transparent 100%)";
fill: "radial-gradient(circle at center, #FF6B6B 0%, #4ECDC4 100%)";
Content Types:
"https://example.com/video.mp4" - Must be a publicly accessible URL{
type: "video",
content: string, // Video URL (must be publicly accessible)
videoOptions: {
loop: boolean,
muted: boolean,
trim_start_time: string,
trim_end_time: string,
duration: number | null
},
style: {
// Sizing & Positioning
objectFit: string, // "contain", "cover", "fill"
objectPosition: string,
// Appearance
opacity: number,
filter: string,
mixBlendMode: string,
// Borders & Shadows
borderRadius: string,
borderWidth: string,
borderColor: string,
elementBoxShadowX: string,
elementBoxShadowY: string,
elementBoxShadowBlur: string,
elementBoxShadowColor: string
},
parameterType: "videoUrl"
}
When creating or updating templates, always ensure all text, image, and video elements are parameterizable with unique IDs. This enables dynamic content replacement via the API.
Every dynamic element MUST have:
{
parameterizable: true,
parameterId: "unique_id", // Unique across template, lowercase with underscores
parameterType: "text" | "imageUrl" | "videoUrl"
}
| Element Type | parameterId Examples | parameterType |
| ------------ | ------------------------------------------- | ------------- |
| Text | headline, subtitle, cta_text, price | "text" |
| Image | product_image, logo, background_image | "imageUrl" |
| Video | hero_video, background_video | "videoUrl" |
product_title not text1card_title, card_image)Before finalizing any template update:
parameterizable: true and unique parameterIdparameterizable: true and unique parameterIdparameterizable: true and unique parameterIdPopular font pairings:
Prata + InterInstrument Serif + DM SansPlayfair Display + LatoMontserrat + Open SansPlatform-specific fonts:
SF Pro Display, SF Pro TextGoogle Sans, RobotoLuxury/Gold palette:
#D4AF37#B8860B#F5E7A3iOS system colors:
#007AFF#8E8E93#F5F5F7Professional dark:
#0F172A#1E293B, #334155#64748B, #94A3B8Best practices:
zIndex ordering:
Add text element:
addElement("text", {
content: "Hello World",
fontFamily: "Inter",
fontSize: 48,
fontWeight: "700",
color: "#FFFFFF",
x: 100,
y: 100,
width: 400,
height: 60,
});
Add shape backdrop:
addElement("rectangle", {
fill: "rgba(0,0,0,0.5)",
width: 1080,
height: 200,
x: 0,
y: 800,
borderRadius: "0px",
});
Batch update multiple elements:
batchUpdate([
{
elementId: "heading",
type: "ORSHOT_UPDATE_ELEMENT",
updates: { style: { fontSize: 72 } },
},
{
elementId: "subtitle",
type: "ORSHOT_UPDATE_ELEMENT",
updates: { style: { color: "#94A3B8" } },
},
{ type: "ORSHOT_UPDATE_CANVAS", updates: { backgroundColor: "#0F172A" } },
]);
Generate images/PDFs/videos from templates designed in Orshot Studio.
POST https://api.orshot.com/v1/studio/render
await fetch("https://api.orshot.com/v1/studio/render", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer <ORSHOT_API_KEY>",
},
body: JSON.stringify({
templateId: 123, // Integer - your studio template ID
modifications: {
title: "Hello World",
imageUrl: "https://example.com/photo.jpg",
canvasBackgroundColor: "#eff2fa",
},
response: {
type: "base64", // "base64" | "url" | "binary"
format: "png", // "png" | "webp" | "jpg" | "pdf" | "mp4" | "webm" | "gif"
scale: 1, // 1 = original size, 2 = double
includePages: [1, 3], // optional – only for multi-page templates
fileName: "my-render", // optional – custom filename (without extension)
},
pdfOptions: {
// optional – only when format is "pdf"
margin: "20px",
rangeFrom: 1,
rangeTo: 2,
colorMode: "rgb", // "rgb" or "cmyk"
dpi: 300,
},
}),
});
Response (single page):
{
"data": {
"content": "data:image/png;base64,iVBORw0.....",
"format": "png",
"type": "base64",
"responseTime": 325.22
}
}
Response (multi-page/carousel):
{
"data": [
{ "page": 1, "content": "https://storage.orshot.com/.../image1.png" },
{ "page": 2, "content": "https://storage.orshot.com/.../image2.png" }
],
"format": "png",
"type": "url",
"responseTime": 3166.01,
"totalPages": 2,
"renderedPages": 2
}
Generate renders from Orshot's pre-built utility templates (e.g., website screenshots, tweet images).
POST https://api.orshot.com/v1/generate/{renderType}
renderType: images or pdfsawait fetch("https://api.orshot.com/v1/generate/images", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer <ORSHOT_API_KEY>",
},
body: JSON.stringify({
templateId: "website-screenshot", // String ID for utility templates
response: {
format: "png",
type: "base64",
},
modifications: {
websiteUrl: "https://example.com",
fullCapture: false,
delay: 500,
width: 1200,
height: 1000,
},
}),
});
Create publicly accessible render URLs without exposing your API key.
POST https://api.orshot.com/v1/signed-url/create
await fetch("https://api.orshot.com/v1/signed-url/create", {
method: "POST",
headers: {
Authorization: "Bearer <ORSHOT_API_KEY>",
"Content-Type": "application/json",
},
body: JSON.stringify({
templateId: "website-screenshot",
expiresAt: 1744550160505, // UNIX timestamp, or null for no expiry
renderType: "images",
modifications: {
websiteUrl: "https://example.com",
},
}),
});
GET https://api.orshot.com/v1/studio/templates/all?page=1&limit=10
Response includes data array of templates and pagination object with page, limit, total, totalPages.
GET https://api.orshot.com/v1/studio/templates/:templateId
Returns the template metadata including available modifications.
DELETE https://api.orshot.com/v1/studio/templates/:templateId
POST https://api.orshot.com/v1/studio/templates/:templateId/duplicate
GET https://api.orshot.com/v1/profile/workspace
Returns workspace details, plan info, and render usage.
POST https://api.orshot.com/v1/brand-assets/upload
Upload as multipart/form-data with a file field. Max 5MB, supports PNG, JPG, JPEG, SVG, WEBP, GIF.
GET https://api.orshot.com/v1/brand-assets
DELETE https://api.orshot.com/v1/brand-assets/:assetId
These endpoints require an Enterprise plan.
POST https://api.orshot.com/v1/studio/templates/create
{
name: "Product Banner", // required, max 255 chars
description: "Banner template", // optional
canvas_width: 1200, // required, 1-5000
canvas_height: 628, // required, 1-5000
pages_data: [...] // optional - array of page objects with elements
}
POST https://api.orshot.com/v1/studio/templates/bulk-create
Create multiple templates at once via CSV or JSON.
PATCH https://api.orshot.com/v1/studio/templates/:templateId
Update template name and description.
PATCH https://api.orshot.com/v1/studio/templates/:templateId/update-modifications
Update text and image content in template layers.
POST https://api.orshot.com/v1/studio/templates/:templateId/generate-variants
Generate multiple size variants of a template using AI.
Generate images directly from URL parameters:
https://api.orshot.com/v1/studio/dynamic-url/my-image?title=Hello%20World&title.fontSize=48px&title.color=%23ff0000
URL-encode special characters (e.g., # → %23).
Override template styles, content, and behavior at render time using dot notation.
Format: parameterId.property
{
"modifications": {
"title": "Hello World",
"title.fontSize": "48px",
"title.color": "#ff0000",
"title.fontFamily": "Roboto",
"title.textAlign": "center",
"logo.borderRadius": "50%",
"logo.objectFit": "cover"
}
}
Text properties: fontSize, fontWeight, fontStyle, fontFamily, lineHeight, letterSpacing, textAlign, verticalAlign, textDecoration, textTransform, color, backgroundColor, backgroundRadius, textStrokeWidth, textStrokeColor, opacity, filter, dropShadowX/Y/Blur/Color
Image properties: objectFit, objectPosition, borderRadius, borderWidth, borderColor, boxShadowX/Y/Blur/Color, opacity, filter
Shape properties: fill, stroke, strokeWidth, borderRadius, opacity
Position/Size (all elements): x, y, width, height
Property names are case-insensitive.
Prefix modifications with page number:
{
"modifications": {
"page1@title": "Page 1 Title",
"page2@title": "Page 2 Title",
"[email protected]": "48px"
}
}
Generate text or images using AI:
{
"modifications": {
"headline.prompt": "Write a catchy headline about coffee",
"background.prompt": "A serene mountain landscape at sunset"
}
}
openai/gpt-5-nanogoogle/nano-bananaAdd clickable links in PDF outputs:
{
"modifications": {
"cta_button.href": "https://example.com/signup",
"logo.href": "https://company.com"
},
"response": { "format": "pdf" }
}
Control video elements dynamically:
{
"modifications": {
"bgVideo": "https://example.com/video.mp4",
"bgVideo.trimStart": 5,
"bgVideo.trimEnd": 15,
"bgVideo.muted": false,
"bgVideo.loop": true
},
"response": { "format": "mp4" }
}
Render templates with video elements as MP4, WebM, or GIF:
await fetch("https://api.orshot.com/v1/studio/render", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer <ORSHOT_API_KEY>",
},
body: JSON.stringify({
templateId: 123,
modifications: {
videoElement: "https://example.com/custom-video.mp4",
"videoElement.trimStart": 0,
"videoElement.trimEnd": 10,
"videoElement.muted": false,
"videoElement.loop": true,
},
videoOptions: {
trimStart: 0,
trimEnd: 20,
muted: true,
loop: true,
},
response: {
type: "url",
format: "mp4",
},
}),
});
| Type | Description |
| -------- | ----------------------------------------------- |
| url | Returns a hosted URL to the rendered file |
| base64 | Returns base64-encoded content as a string |
| binary | Returns binary file content for custom handling |
| Format | Type | Notes |
| ------ | ----- | ------------------------------------------ |
| png | Image | Best quality, larger size |
| webp | Image | Smaller size, good quality |
| jpg | Image | Compressed, no transparency |
| pdf | Doc | Supports multi-page, clickable links, CMYK |
| mp4 | Video | H.264, requires video elements in template |
| webm | Video | VP9, web-optimized |
| gif | Video | Animated, no audio support |
| Output | Cost | | -------------------- | -------------------- | | Image (PNG/JPG/WebP) | 2 renders per image | | PDF | 2 renders per page | | Video (MP4/WebM/GIF) | 2 renders per second |
Multi-page templates: each page counts separately.
Orshot connects with:
npx orshot-cli for terminal-based generation| Code | Error | Fix |
| ---- | ------------------------------ | -------------------------------------------- |
| 400 | templateId missing | Add templateId to request body |
| 400 | Invalid API Key | Generate new key from dashboard |
| 403 | Authorization header missing | Add Authorization: Bearer <KEY> header |
| 403 | Subscription inactive | Check usage or upgrade plan |
| 403 | Template not found | Verify template ID belongs to your workspace |
| 403 | Video on free plan | Upgrade to paid plan for video generation |
url response type for production – avoids large base64 payloadswebp format for smaller file sizes with good qualitypx for sizespage1@paramId format for carousel templates?cache=false query param to bypass cache when neededPublish rendered images/videos directly to 13+ social platforms via API. Supports Twitter/X, Instagram, LinkedIn, Pinterest, Facebook, TikTok, YouTube, Threads, Bluesky, Reddit, Telegram, Snapchat, and Google Business.
For detailed setup: fetch https://orshot.com/docs/publish/introduction.md
Connect social accounts in Workspace Settings → Social Accounts in the Orshot dashboard. Each connected account gets a numeric ID used in API calls.
Add the publish object to any render request:
await fetch("https://api.orshot.com/v1/studio/render", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer <ORSHOT_API_KEY>",
},
body: JSON.stringify({
templateId: 123,
modifications: { title: "New Post" },
response: { type: "url", format: "png" },
publish: {
accounts: [1, 3], // Social account IDs
content: "Check this out!", // Caption text (max 5000 chars)
isDraft: false, // true = save as draft
schedule: { // Optional: schedule for later
scheduledFor: "2026-04-25T14:00:00Z"
},
timezone: "America/New_York",
platformOptions: { // Per-account overrides (keyed by account ID)
"1": { firstComment: "https://example.com" }, // LinkedIn
"3": { title: "Pin Title", link: "https://..." } // Pinterest
}
}
}),
});
Response includes publish status:
{
"data": { "content": "https://storage.orshot.com/..." },
"publish": [
{ "platform": "twitter", "username": "acme", "status": "published", "url": "https://x.com/..." },
{ "platform": "linkedin", "username": "acme", "status": "scheduled" }
]
}
Format compatibility:
Build third-party integrations with Orshot using OAuth 2.0. Register apps, authenticate users, and access their workspaces programmatically.
For detailed setup: fetch https://orshot.com/docs/developers/oauth-overview.md
client_id and client_secretAuthorization Code Flow (web apps):
GET https://orshot.com/oauth/authorize?
response_type=code&
client_id=YOUR_CLIENT_ID&
redirect_uri=https://yourapp.com/callback&
scope=templates:read templates:write renders:write
Device Flow (CLI/headless):
POST https://orshot.com/oauth/device/code
client_id=YOUR_CLIENT_ID&
scope=templates:read renders:write
POST https://orshot.com/oauth/token
grant_type=authorization_code&
code=AUTH_CODE&
client_id=YOUR_CLIENT_ID&
client_secret=YOUR_CLIENT_SECRET&
redirect_uri=https://yourapp.com/callback
| Scope | Description |
|-------|-------------|
| templates:read | List and get templates |
| templates:write | Create, update, delete, duplicate templates |
| renders:write | Generate renders (images, PDFs, videos) |
| brand:read | Read brand assets (images, colors, fonts, videos) |
| brand:write | Upload, update, delete brand assets |
| social:read | List connected social accounts |
| social:write | Publish to social accounts |
| workspace:read | Read workspace profile and settings |
For endpoint details: fetch https://orshot.com/docs/developers/oauth-endpoints.md
Embed Orshot's template editor into your application as a white-label component. Users can design and customize templates directly in your app.
For detailed setup: fetch https://orshot.com/docs/orshot-embed/introduction.md
<iframe
src="https://orshot.com/embeds/YOUR_EMBED_ID?userId=USER_123"
width="100%"
height="600"
frameborder="0"
></iframe>
npm install @orshot/react
import { OrshotEmbed } from "@orshot/react";
<OrshotEmbed
embedId="YOUR_EMBED_ID"
userId="user_123"
token="JWT_TOKEN"
onRender={(data) => console.log("Rendered:", data)}
onSave={(data) => console.log("Saved:", data)}
/>
npm install @orshot/vue
<template>
<OrshotEmbed
embed-id="YOUR_EMBED_ID"
user-id="user_123"
@render="onRender"
@save="onSave"
/>
</template>
userId to give each user their own template copiesFor React SDK details: fetch https://orshot.com/docs/orshot-embed/react-sdk.md
For Vue SDK details: fetch https://orshot.com/docs/orshot-embed/vue-sdk.md
For webhook setup: fetch https://orshot.com/docs/orshot-embed/webhooks.md
This section provides accurate API mapping tables for migrating from competing image generation platforms to Orshot. Each subsection covers authentication, endpoint mapping, and request format translation.
For detailed comparison articles, fetch the corresponding blog post URL.
Blog: https://orshot.com/blog/bannerbear-api-alternative.md
Authentication:
| BannerBear | Orshot |
|------------|--------|
| Authorization: Bearer BB_API_KEY | Authorization: Bearer ORSHOT_API_KEY |
Endpoint Mapping:
| Action | BannerBear | Orshot |
|--------|-----------|--------|
| Generate image | POST /v2/images (async, returns 202) | POST /v1/studio/render (sync) |
| Generate image (sync) | POST sync.api.bannerbear.com/v2/images (10s timeout) | POST /v1/studio/render (sync by default) |
| List templates | GET /v2/templates | GET /v1/studio/templates/all?page=1&limit=10 |
| Get template | GET /v2/templates/:uid | GET /v1/studio/templates/:id |
| Generate video | POST /v2/videos | POST /v1/studio/render with format: "mp4" |
| Multi-template batch | POST /v2/collections | Loop POST /v1/studio/render per template |
Request Format Translation:
BannerBear uses a modifications array with named layers:
// BannerBear
{
"template": "TEMPLATE_UID",
"modifications": [
{ "name": "title", "text": "Hello World" },
{ "name": "hero", "image_url": "https://example.com/img.jpg" },
{ "name": "bg", "color": "#FF0000" }
]
}
// Orshot equivalent
{
"templateId": 123,
"modifications": {
"title": "Hello World",
"hero": "https://example.com/img.jpg",
"canvasBackgroundColor": "#FF0000"
},
"response": { "type": "url", "format": "png" }
}
Key differences:
image_url for images, Orshot uses the parameter ID directly with a URL valuetemplate is a UID string, Orshot templateId is an integer for studio templates"title.fontSize": "48px") — BannerBear does notBlog: https://orshot.com/blog/placid-api-alternative.md
Authentication:
| Placid | Orshot |
|--------|--------|
| Authorization: Bearer PLACID_TOKEN | Authorization: Bearer ORSHOT_API_KEY |
Endpoint Mapping:
| Action | Placid | Orshot |
|--------|--------|--------|
| Generate image | POST /api/rest/{template_uuid} | POST /v1/studio/render |
| Get image status | GET /api/rest/images/{id} | Not needed (sync response) |
| List templates | GET /api/rest/templates | GET /v1/studio/templates/all?page=1&limit=10 |
| Get template | GET /api/rest/templates/{uuid} | GET /v1/studio/templates/:id |
| Delete render | DELETE /api/rest/images/{id} | Not needed (renders don't expire) |
Request Format Translation:
Placid uses a layers object with type-specific properties:
// Placid
{
"layers": {
"title": {
"text": "Hello World",
"text_color": "#FF0000",
"font": "Arial"
},
"hero_image": {
"image": "https://example.com/img.jpg"
},
"background": {
"background_color": "#000000"
}
},
"modifications": {
"width": 1200,
"height": 630,
"image_format": "jpg"
}
}
// Orshot equivalent
{
"templateId": 123,
"modifications": {
"title": "Hello World",
"title.color": "#FF0000",
"title.fontFamily": "Arial",
"hero_image": "https://example.com/img.jpg",
"canvasBackgroundColor": "#000000"
},
"response": { "type": "url", "format": "jpg" }
}
Key differences:
layers (content) from modifications (output settings), Orshot combines both in modificationstext_color, Orshot uses dot notation parameterId.colorimage key for image URLs, Orshot uses the parameter ID directlyBlog: https://orshot.com/blog/creatomate-api-alternative.md
Authentication:
| Creatomate | Orshot |
|------------|--------|
| Authorization: Bearer CREATOMATE_KEY | Authorization: Bearer ORSHOT_API_KEY |
Endpoint Mapping:
| Action | Creatomate | Orshot |
|--------|-----------|--------|
| Generate render | POST /v1/renders | POST /v1/studio/render |
| Get render status | GET /v1/renders/:id | Not needed (sync response) |
| List templates | GET /v1/templates | GET /v1/studio/templates/all?page=1&limit=10 |
| Get template | GET /v1/templates/:id | GET /v1/studio/templates/:id |
Request Format Translation:
Creatomate uses a flat modifications object (closest to Orshot's format):
// Creatomate
{
"template_id": "TEMPLATE_UUID",
"modifications": {
"Title": "Hello World",
"Image-1": "https://example.com/img.jpg"
},
"output_format": "jpg",
"render_scale": 1,
"max_width": 1080
}
// Orshot equivalent
{
"templateId": 123,
"modifications": {
"title": "Hello World",
"image_1": "https://example.com/img.jpg"
},
"response": { "type": "url", "format": "jpg", "scale": 1 }
}
Key differences:
template_id is a UUID string, Orshot templateId is an integeroutput_format at root level, Orshot uses response.formatBlog: https://orshot.com/blog/renderform-api-alternative.md
Authentication:
| RenderForm | Orshot |
|------------|--------|
| X-API-KEY: RENDERFORM_KEY | Authorization: Bearer ORSHOT_API_KEY |
Endpoint Mapping:
| Action | RenderForm | Orshot |
|--------|-----------|--------|
| Generate image | POST /api/v2/render | POST /v1/studio/render |
| List templates | GET /api/v2/my-templates?page=1&size=50 | GET /v1/studio/templates/all?page=1&limit=10 |
| Get template | GET /api/v2/my-templates/:id | GET /v1/studio/templates/:id |
| URL-based render | GET /img/TEMPLATE.jpg?key=...¶m=... | GET /v1/studio/dynamic-url/TEMPLATE?param=... |
Request Format Translation:
RenderForm uses dot notation in a data object (similar to Orshot's style overrides):
// RenderForm
{
"template": "TEMPLATE_ID",
"data": {
"title.text": "Hello World",
"hero.src": "https://example.com/img.jpg",
"bg.color": "#FF0000"
},
"fileName": "output",
"width": 1200,
"height": 630
}
// Orshot equivalent
{
"templateId": 123,
"modifications": {
"title": "Hello World",
"hero": "https://example.com/img.jpg",
"canvasBackgroundColor": "#FF0000"
},
"response": { "type": "url", "format": "png", "fileName": "output" }
}
Key differences:
X-API-KEY header, Orshot uses Authorization: Bearerdata with componentId.property dot notation for everything, Orshot uses modifications with parameter IDs for content and dot notation only for style overridestemplate is a string ID, Orshot templateId is an integerBlog: https://orshot.com/blog/abyssale-api-alternative.md
Authentication:
| Abyssale | Orshot |
|----------|--------|
| x-api-key: ABYSSALE_KEY | Authorization: Bearer ORSHOT_API_KEY |
Endpoint Mapping:
| Action | Abyssale | Orshot |
|--------|---------|--------|
| Generate image | POST /async/banner-builder/{designId}/generate (async) | POST /v1/studio/render (sync) |
| Poll status | GET /generation-request/{requestId} | Not needed (sync response) |
| List designs | GET /designs | GET /v1/studio/templates/all?page=1&limit=10 |
| Get design | GET /designs/{designId} | GET /v1/studio/templates/:id |
| Multi-format render | template_format_names param | Loop POST /v1/studio/render per format, or use Variant Generation API |
Request Format Translation:
Abyssale uses an elements object with payload for text:
// Abyssale
{
"template_format_names": ["facebook-feed", "instagram-post"],
"elements": {
"title": { "payload": "Hello World" },
"hero_image": { "image_url": "https://example.com/img.jpg" },
"background": { "color": "#FF0000" }
},
"callback_url": "https://webhook.example.com"
}
// Orshot equivalent
{
"templateId": 123,
"modifications": {
"title": "Hello World",
"hero_image": "https://example.com/img.jpg",
"canvasBackgroundColor": "#FF0000"
},
"response": { "type": "url", "format": "png" }
}
Key differences:
payload for text content, Orshot uses the parameter ID directlyimage_url for images, Orshot uses the parameter ID with URL valuetemplate_format_names, Orshot requires separate calls or Variant Generation APIBlog: https://orshot.com/blog/dynapictures-api-alternative.md
Authentication:
| DynaPictures | Orshot |
|--------------|--------|
| Authorization: Bearer DYNA_KEY | Authorization: Bearer ORSHOT_API_KEY |
Endpoint Mapping:
| Action | DynaPictures | Orshot |
|--------|-------------|--------|
| Generate image | POST /designs/{id} | POST /v1/studio/render |
| List designs | GET /designs | GET /v1/studio/templates/all?page=1&limit=10 |
Key differences:
Blog: https://orshot.com/blog/contentdrips-api-alternative.md
Contentdrips is a social media design tool with API as a secondary feature. Migration is straightforward since Orshot is API-first.
Key differences:
| Feature | BannerBear | Placid | Creatomate | RenderForm | Abyssale | Orshot |
|---------|-----------|--------|------------|------------|----------|--------|
| Auth header | Authorization: Bearer | Authorization: Bearer | Authorization: Bearer | X-API-KEY | x-api-key | Authorization: Bearer |
| Modifications format | Array of objects | layers object | Flat object | data with dot notation | elements with payload | Flat object |
| Template ID type | UID string | UUID string | UUID string | String | UUID string | Integer (studio) |
| Response model | Async (poll) | Async (poll) | Async (poll) | Sync | Async (poll) | Sync |
| Render persistence | Permanent | 30 days | 7 days | 14 days | 7 days | Permanent |
| Style overrides | No | Limited | Via source JSON | Dot notation | No | Dot notation |
| Multi-page | No | No | No | No | No | Yes |
| Video support | Yes (extra cost) | Yes (5x cost) | Yes | No | Animated only | Yes (2 renders/sec) |
| White-label editor | No | No | $109/mo+ | No | No | All paid plans ($30/mo) |
| Social publishing | No | No | No | No | No | 13+ platforms |
tools
Use when work should span one or more detached tasks but still behave like one job with a single owner context. TaskFlow is the durable flow substrate under authoring layers like Lobster, ACPX, plugins, or plain code. Keep conditional logic in the caller; use TaskFlow for flow identity, child-task linkage, waiting state, revision-checked mutations, and user-facing emergence.
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------
tools
A CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.