Mockly API
Schema
Reference for the chat render request body. Every field, every type.
Request body
The body of POST /api/v1/render is a render payload, discriminated on mockupType. Nine mockup types are supported, each with its own props shape:
mockupType | props shape | Render kinds |
|---|---|---|
"chats" | Chat props | image + video |
"ai" | AI chat props | image + video |
"stories" | Story props | image + video |
"notifications" | Notification props | image + video |
"posts" | Post props | image only |
"comments" | Comment props | image only |
"emails" | Email props | image only |
"contribution-chart" | GitHub chart props | image only |
"dashboard-chart" | Stripe chart props | image only |
The two chart types (contribution-chart, dashboard-chart) are the free-tool charts — you don't send a platform (it's implied by the chart type — GitHub / Stripe); the whole card is described by props.
Top-level fields, common to every type:
| Field | Type | Required | Description |
|---|---|---|---|
mockupType | "chats" | "ai" | "stories" | "notifications" | "posts" | "comments" | "emails" | "contribution-chart" | "dashboard-chart" | yes | Selects the mockup type and which props shape is required. |
platform | string | conditional | One of the supported platforms for the chosen mockupType. Omit for contribution-chart and dashboard-chart — the platform (GitHub / Stripe) is implied by the chart type. |
renderKind | "image" | "video" | yes | Output kind. "video" is only valid for chats, ai, stories, and notifications. |
resolutionScale | "1x" | "2x" | "4x" | yes | Resolution multiplier — "2x" is the typical default. |
rendererVersion | string | yes | Use "mockup-remotion-v1". |
render3D | boolean | no | Render the mockup on a 3D phone in 3D space (chats, stories, and notifications). Default false. |
cameraPosition | [number, number, number] | no | Camera XYZ position for the 3D view (chats and stories only); omit for the default angle. |
props | object | yes | The mockup content and appearance — shape depends on mockupType (see the table above). |
canvas | { aspectRatio, background, padding } | no | Frame the export on a larger canvas: aspectRatio is "1:1", "4:5", "9:16", or "16:9"; background a preset ("white", "black", "brand", "green", "purple") or hex color; padding 0–200 base px of vertical breathing room (canvas height = content + 2×padding; width follows the ratio). Omit for the exact content size. Works for every export: image, video, and render3D (the 3D phone floats directly on the canvas background). |
The schema validates strictly. Unknown top-level fields are rejected with 400 validation_failed. The top-level platform must equal props.platform.
Chat props
For mockupType: "chats", props describes the conversation itself and how it should look:
| Field | Type | Default | Description |
|---|---|---|---|
platform | string | — | Must match the top-level platform. |
sender | User | — | The user whose messages render on the right (sender side). |
receivers | User[] | — | Other participants. One for direct, multiple for group. |
messages | Message[] | — | The conversation, in chronological order. |
conversationType | "direct-message" | "group-chat" | "direct-message" | |
groupChatSettings | { name: string, image?: string } | — | Required when conversationType: "group-chat". |
darkMode | boolean | false | Render in dark mode (where the platform supports it). |
floatingMessages | boolean | false | Message bubbles float outside the phone frame (the phone scales down inside the same canvas). Bubble-style platforms only; ignored elsewhere. In 3D renders bubbles stay on screen and get a lifted drop shadow instead. |
mobileView | boolean | true | Render in mobile aspect ratio. |
showDeviceFrame | boolean | false | Wrap the mockup in a phone-frame. |
showDeviceStatus | boolean | true | Show the iOS/Android status bar at the top. |
showHeader | boolean | true | Show the platform's chat header. |
showFooter | boolean | true | Show the platform's input bar at the bottom. |
showReceiver | boolean | false | Force-show the receiver's name above messages even in DMs. |
showDates | boolean | true | Show date dividers between messages on different days. |
batteryLevel | number 0–100 | 100 | Battery indicator in the status bar. |
statusBarTime | string | "9:41" | Time displayed in the status bar. |
timeNotation | "12h" | "24h" | "24h" | Format for message timestamps. |
timezone | string (IANA, e.g. "Europe/Amsterdam") | — | Timezone for displaying message timestamps. |
transparentBackground | boolean | false | Render with a transparent background (PNG with alpha for images, WebM for video). |
customTheme | CustomTheme | — | Required when platform: "custom". |
secondaryTextColor | string (CSS color) | — | Color override for secondary text outside bubbles (date dividers, read receipts, sender names). Omit for each platform's default. Handy with floatingMessages, where these labels can land outside the phone. |
chatWallpaper | string | — | Custom conversation wallpaper: an image URL/data URL, or a hex color (e.g. #0b141a) for a solid fill. Empty string removes the wallpaper; omit for the platform default. Applies to any platform. |
Messages
messages is an array of ChatMessage:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Unique within the array. |
userId | string | yes | Must match sender.id or one of receivers[].id. |
type | "text" | "image" | "mixed" | yes | Content discriminator. |
timestamp | string (ISO 8601, e.g. "2026-04-30T10:15:00Z") | yes | UTC instant. |
text | string | depends | Required for "text" and "mixed". |
images | Image[] | depends | Required for "image" and "mixed". |
status | "sent" | "delivered" | "read" | no | Delivery state — only rendered on platforms that show one (e.g. WhatsApp ticks, iMessage "Read"). |
Examples:
{ "id": "m1", "type": "text", "userId": "u1", "text": "Hey!", "timestamp": "2026-04-30T10:15:00Z" }
{
"id": "m2",
"type": "image",
"userId": "u1",
"timestamp": "2026-04-30T10:16:00Z",
"images": [
{
"id": "i1",
"filename": "beach.jpg",
"data": "https://cdn.example.com/beach.jpg",
"mimeType": "image/jpeg",
"size": 245760
}
]
}
{
"id": "m3",
"type": "mixed",
"userId": "u1",
"text": "Look at this!",
"timestamp": "2026-04-30T10:17:00Z",
"images": [/* ... */],
"status": "read"
}
Images
ChatMessageImage:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Unique within the message. |
filename | string | yes | Display name; used as the download filename suffix. |
data | string | yes | Either an https:// URL or a base64 data URL (data:image/jpeg;base64,...). |
mimeType | string | yes | MIME of the image (e.g. "image/jpeg", "image/png"). |
size | number | yes | Size in bytes (informational; not enforced). |
caption | string | no | Caption shown below the image, where the platform supports it (Telegram, Discord). |
thumbnail | string | no | Smaller preview, same encoding as data. Falls back to data if omitted. |
Recommendation: prefer https:// URLs over data URLs. Data URLs balloon the request body and easily push past the 10 MB cap if you have multiple image messages.
Users
ChatUser:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Unique within the conversation; referenced by messages[].userId. |
name | string | yes | Display name. |
image | string | no | Avatar URL or data URL. |
username | string | no | X only. The @handle on the X profile card. Omit to auto-derive from name (e.g. "Jane Doe" → @janedoe). |
verified | boolean | no | X only. Shows the blue verified seal in the X header and profile card. Defaults to true; set false to hide it. |
joinedDate | string | no | X only. "Joined" month on the X profile card, as YYYY-MM (e.g. "2011-03" renders "Joined March 2011"). Omit to auto-derive. |
Each conversation has exactly one sender and one or more receivers. The sender's messages render on the right side; receivers' messages render on the left.
The username, verified, and joinedDate fields are only rendered for platform: "x" (the X profile card and header) and are ignored by every other platform. On X they apply to the receivers[0] — the person whose profile the conversation shows.
"receivers": [
{
"id": "u2",
"name": "Jane Doe",
"username": "janedoe",
"verified": true,
"joinedDate": "2011-03"
}
]
Custom theme
When platform: "custom", supply a customTheme so the renderer knows how to color bubbles and the background:
| Field | Type | Required | Description |
|---|---|---|---|
backgroundColor | string (hex / CSS) | yes | Conversation background. |
backgroundImage | string (URL / data URL) | no | Optional background image; layered above backgroundColor. |
senderBubble | { background: string, foreground: string } | yes | Colors for the sender's message bubbles. |
receiverBubble | { background: string, foreground: string } | yes | Colors for receivers' bubbles. |
fontSize | "small" | "medium" | "large" | "xl" | no (default "medium") | Body text size. |
customTheme is ignored for non-custom platforms — those use the platform's official colors.
Story props
For mockupType: "stories", props describes the story and how it should look:
| Field | Type | Default | Description |
|---|---|---|---|
platform | string | — | "instagram" or "snapchat"; must match top-level platform. |
author | StoryAuthor | — | The story's author. |
slides | StorySlide[] | — | The story slides, in order. |
currentSlide | number | 0 | Index of the slide to render. |
timestamp | string (ISO 8601) | — | Story timestamp. |
batteryLevel | number 0–100 | 100 | Status-bar battery indicator. |
showDeviceFrame | boolean | false | Wrap in a phone frame. |
showDeviceStatus | boolean | true | Show the status bar. |
statusBarTime | string | "9:41" | Status-bar time. |
timeNotation | "12h" | "24h" | "24h" | Timestamp format. |
Notification props
For mockupType: "notifications", props describes a stack of fake iOS push notifications on a lock screen. Video exports show them arriving one by one:
| Field | Type | Default | Description |
|---|---|---|---|
platform | string | — | "ios"; must match top-level platform. |
notifications | NotificationItem[] | — | Newest first — index 0 renders on top and arrives last in video exports. |
wallpaper | string | — | Lock-screen wallpaper: #hex solid, image URL, or data URL. Omit for the default gradient. |
wallpaperIsDark | boolean | — | Whether the wallpaper reads as dark — drives adaptive text/material (dark wallpaper → dark cards with white text). Omit = dark. |
cardStyle | "classic" | "glass" | "classic" | Card material: iOS 17/18 frosted, or the iOS 26 Liquid Glass look. |
carrier | string | — | Carrier name in the lock-screen status bar. |
dateLabel | string | — | Overrides the date line under the clock; defaults to formatting timestamp. |
timestamp | string (ISO 8601) | — | Drives the default date line. |
batteryLevel | number 0–100 | 100 | Status-bar battery indicator. |
showDeviceFrame | boolean | false | Wrap in a phone frame. |
showDeviceStatus | boolean | true | Show the lock-screen status bar (carrier + signal/wifi/battery). |
statusBarTime | string | "9:41" | The big lock-screen clock. |
timeNotation | "12h" | "24h" | "24h" | Clock format. |
Notification items
notifications is an array of NotificationItem:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Stable unique id. |
title | string | yes | Bold first line — the app or sender name. |
text | string | yes | Body text. |
timeLabel | string | no | Relative time top-right (default "now"). |
iconPreset | string | no | Brand icon preset key; takes precedence over icon. Valid keys: discord, gmail, imessage, instagram, paypal, shopify, snapchat, spotify, stripe, telegram, tiktok, whatsapp, x, youtube. Unknown keys fall back to the monogram. |
icon | string | no | Custom app icon: image URL or data URL. Falls back to a monogram. |
thumbnail | string | no | Trailing image on the right of the card. |
Story author
StoryAuthor:
| Field | Type | Required | Description |
|---|---|---|---|
username | string | yes | The author's username. |
verified | boolean | yes | Show the verified badge. |
avatar | string | no | Avatar URL or data URL. |
Story slides
slides is an array of StorySlide, rendered in order:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Unique within the array. |
image | string | no | The slide's background image — a URL or data URL. |
AI chat props
For mockupType: "ai", props describes an AI assistant conversation (ChatGPT, Claude, etc.):
| Field | Type | Default | Description |
|---|---|---|---|
platform | string | — | One of the AI platforms; must match top-level platform. |
model | string | — | Model label shown in the header (e.g. "GPT-5.6 Sol", "Sonnet 5"). |
messages | AIChatMessage[] | — | The conversation, in order. |
input | string | "" | Placeholder text shown in the composer input at the bottom. |
darkMode | boolean | false | Render in dark mode. |
batteryLevel | number 0–100 | 100 | Status-bar battery indicator. |
showDeviceFrame | boolean | false | Wrap in a phone frame. |
showDeviceStatus | boolean | true | Show the status bar. |
showHeader | boolean | true | Show the app header (with the model name). |
showFooter | boolean | true | Show the composer input bar. |
statusBarTime | string | "9:41" | Status-bar time. |
timeNotation | "12h" | "24h" | "24h" | Time format. |
timezone | string (IANA) | — | Timezone for any displayed times. |
AI chat messages
messages is an array of AIChatMessage:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Unique within the array. |
role | "user" | "assistant" | yes | Who sent it. User messages render on the right; assistant answers render as formatted markdown. |
content | string | yes | Message text. Assistant content supports Markdown (headings, lists, code blocks, tables). |
images | Image[] | no | Attached images (same shape as chat images). Typically on "user" messages. |
Video renders (renderKind: "video") animate the conversation: each user prompt appears, the assistant pauses, then its answer streams in like a typewriter. Streaming speed scales with answer length. Duration is derived from the messages automatically.
Post props
For mockupType: "posts", props describes a single social post:
| Field | Type | Default | Description |
|---|---|---|---|
platform | string | — | One of the post platforms; must match top-level. |
post | Post | — | The post content, author, and metrics. |
darkMode | boolean | false | Render in dark mode. |
transparentBackground | boolean | false | Render with a transparent background (PNG with alpha). |
Post object
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Unique id for the post. |
author | PostAuthor | yes | Who posted it. |
content | string | yes | The post body text. |
title | string | no | Title/headline, where the platform has one (e.g. Reddit). |
image | string | no | An attached image — URL or data URL. |
timestamp | string (ISO 8601) | yes | When the post was made. |
metrics | PostMetrics | yes | Engagement counts. Provide only the ones the platform shows. |
Post author
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Display name. |
username | string | no | Handle, where the platform shows one. |
subtitle | string | no | Secondary line (e.g. a LinkedIn headline). |
community | string | no | Community/subreddit name (e.g. Reddit r/...). |
image | string | no | Avatar URL or data URL. |
verified | boolean | no | Show a verified badge where supported. |
Post metrics
All fields are optional numbers — include only what the target platform displays: likes, comments, reposts, shares, views, bookmarks, saves, reactions, upvotes, downvotes.
Comment props
For mockupType: "comments", props describes a post's comment thread:
| Field | Type | Default | Description |
|---|---|---|---|
platform | string | — | One of the comment platforms; must match top-level. |
postAuthor | CommentUser | — | Author of the post the comments belong to. |
currentUser | CommentUser | — | The "you" user (used for the composer row). |
users | CommentUser[] | — | All users referenced by comments[].userId. |
comments | Comment[] | — | The comment thread, in order. |
commentCount | number | — | Total count shown in the header (can exceed the rendered list). |
videoImage | string | — | YouTube only: video frame shown above the comments panel (URL or data URL, cropped to 16:9). |
darkMode | boolean | false | Render in dark mode. |
batteryLevel | number 0–100 | 100 | Status-bar battery indicator. |
showDeviceFrame | boolean | false | Wrap in a phone frame (pins to phone dimensions). |
showDeviceStatus | boolean | true | Show the status bar. |
showHeader | boolean | true | YouTube only: show the YouTube app bar at the top. |
statusBarTime | string | "9:41" | Status-bar time. |
timeNotation | "12h" | "24h" | "24h" | Time format. |
Comment user
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Referenced by comments[].userId. |
name | string | yes | Display name. |
username | string | yes | Handle. |
avatar | string | no | Avatar URL or data URL. |
isCreator | boolean | no | Mark as the post creator (badge). |
Comment
comments is an array of Comment, each of which can nest replies:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Unique within the thread. |
userId | string | yes | Must match a users[], postAuthor, or currentUser id. |
text | string | yes | The comment body. |
likes | number | yes | Like count. |
timestamp | string (ISO 8601) | yes | When it was posted. |
username | string | no | Override username for this comment. |
avatar | string | no | Override avatar for this comment. |
replies | Comment[] | no | Nested replies (same shape, recursive). |
Email props
For mockupType: "emails", props describes an email thread:
| Field | Type | Default | Description |
|---|---|---|---|
platform | string | — | One of the email platforms; must match top-level. |
conversation | EmailConversation | — | The thread: subject, participants, and messages. |
darkMode | boolean | false | Render in dark mode. |
batteryLevel | number 0–100 | 100 | Status-bar battery indicator. |
showDeviceFrame | boolean | false | Wrap in a phone frame. |
showDeviceStatus | boolean | true | Show the status bar. |
statusBarTime | string | "9:41" | Status-bar time. |
timeNotation | "12h" | "24h" | "24h" | Time format. |
Email conversation
| Field | Type | Required | Description |
|---|---|---|---|
subject | string | yes | The thread subject line. |
participants | EmailParticipant[] | yes | Everyone in the thread. |
emails | Email[] | yes | The messages, in order. |
attachment | string | no | An attachment image — URL or data URL. |
Email participant
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Referenced by emails[].senderId. |
name | string | yes | Display name. |
email | string | yes | Email address. |
avatar | string | no | Avatar URL or data URL. |
isNameRedacted | boolean | yes | Blur/redact the name (for "leaked" style mockups). |
isEmailRedacted | boolean | yes | Blur/redact the email address. |
Email message
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Unique within the thread. |
senderId | string | yes | Must match a participants[].id. |
body | string | yes | The email body. |
date | string (ISO 8601) | yes | When the email was sent. |
GitHub chart props
For mockupType: "contribution-chart" (no platform, image only). Renders a GitHub-style contribution chart — the grid of green squares. The contribution count is derived automatically from the filled squares.
| Field | Type | Default | Description |
|---|---|---|---|
levels | number[] (0–4 each, 1–400) | — | One entry per day, in grid order; each value is the shade level (0 = empty → 4 = darkest green). |
year | number | 2026 | The year the chart represents. |
theme | "light" | "dark" | "light" | GitHub's light or dark palette. |
{
"mockupType": "contribution-chart",
"renderKind": "image",
"resolutionScale": "2x",
"rendererVersion": "mockup-remotion-v1",
"props": { "levels": [0, 1, 2, 3, 4, 2, 1], "year": 2026, "theme": "light" }
}
Stripe chart props
For mockupType: "dashboard-chart" (no platform, image only). Renders a Stripe-dashboard-style metric card — a headline number, a line, and (optionally) a dotted previous-period line with an auto-calculated percentage.
| Field | Type | Default | Description |
|---|---|---|---|
metric | "MRR" | "Net volume" | "Gross volume" | "New customers" | "Successful payments" | "MRR" | The metric. MRR reads as the last value; the rest total over the period. |
points | number[] (2–60) | — | The main line's values. |
comparePoints | number[] (2–60) | — | Optional previous-period line; adds the dotted line and the % change. |
currencyCode | string | "USD" | Currency for monetary metrics (e.g. USD, EUR, GBP). Ignored for count metrics. |
startDate | string (ISO date) | "2026-02-01" | Left axis date label. |
endDate | string (ISO date) | "2026-06-28" | Right axis date label. |
updatedSeconds | number | 4 | The "Updated N seconds ago" footer value. |
theme | "light" | "dark" | "light" | Light or dark card. |
{
"mockupType": "dashboard-chart",
"renderKind": "image",
"resolutionScale": "2x",
"rendererVersion": "mockup-remotion-v1",
"props": {
"metric": "MRR",
"points": [4200, 6300, 9800, 13400, 18200, 24800],
"comparePoints": [2800, 4100, 6200, 8300, 11400, 15800],
"currencyCode": "USD",
"theme": "light"
}
}
Supported platforms
Chat mockups (mockupType: "chats") — 23 chat apps. Use the slug (left column) as the value of platform and props.platform:
| Slug | App |
|---|---|
whatsapp | |
imessage | iMessage |
instagram | |
discord | Discord |
telegram | Telegram |
slack | Slack |
linkedin | |
microsoftTeams | Microsoft Teams |
messenger | Facebook Messenger |
snapchat | Snapchat |
x | X (Twitter) |
reddit | |
signal | Signal |
wechat | |
tinder | Tinder |
bumble | Bumble |
bluesky | Bluesky |
msn | MSN Messenger |
line | LINE |
tiktok | TikTok |
onlyfans | OnlyFans |
custom | Custom — bring your own colors via customTheme |
Both render kinds are supported for chats — set renderKind: "image" for a PNG or "video" for an MP4.
AI chat mockups (mockupType: "ai") — 5 platforms. Supports image and video:
| Slug | App |
|---|---|
chatgpt | ChatGPT |
claude | Claude |
gemini | Gemini |
grok | Grok |
perplexity | Perplexity |
Story mockups (mockupType: "stories") — 2 platforms. Supports image and video:
| Slug | App |
|---|---|
instagram | |
snapchat | Snapchat |
Post mockups (mockupType: "posts") — 8 platforms. Image only:
| Slug | App |
|---|---|
x | X (Twitter) |
instagram | |
facebook | |
linkedin | |
threads | Threads |
bluesky | Bluesky |
tiktok | TikTok |
pinterest |
Comment mockups (mockupType: "comments") — 8 platforms. Image only:
| Slug | App |
|---|---|
youtube | YouTube |
instagram | |
tiktok | TikTok |
x | X (Twitter) |
facebook | |
linkedin | |
reddit | |
threads | Threads |
Email mockups (mockupType: "emails") — 4 platforms. Image only:
| Slug | App |
|---|---|
gmail | Gmail |
apple-mail | Apple Mail |
outlook | Outlook |
leaked | Leaked-style |