Render the scene. Ship the file.
Turn TheFake scene data into screenshots and social-ready videos from your own scripts, MCP tools, queues, or publishing pipeline.
$15/month. No trial. Access activates after payment.
curl -X POST https://www.thefake.design/api/v1/video-renders \
-H "x-api-key: $THEFAKE_API_KEY" \
-H "Idempotency-Key: publish-scene-001" \
-H "Content-Type: application/json" \
-d '{
"template": "chat-vertical",
"durationSeconds": 5,
"fps": 30,
"scale": 1,
"format": "mp4",
"scene": {
"platform": "whatsapp",
"messages": [
{"id": "question", "type": "text", "text": "publish it?", "direction": "incoming", "status": "read"},
{"id": "answer", "type": "text", "text": "already queued.", "direction": "outgoing", "status": "read"}
]
}
}'{
"success": true,
"data": {
"id": "render_01J...",
"status": "queued",
"creditsUsed": 1,
"statusUrl": "/api/v1/video-renders/render_01J...",
"downloadUrl": null
}
}200 credits
Included every month
PNG + JPEG
Synchronous screenshots
MP4 + WebM
Private video jobs
30 templates
Chat, post, story, email
Quickstart
From payment to a saved image.
Subscribe to API Starter, create a scoped key, then send one JSON request. Screenshots return the file immediately; video creates return a private job.
- 01
Subscribe
Start API Starter for $15/month. Access activates after Polar confirms payment.
- 02
Create a key
Name the integration, choose screenshot or video scopes, and copy the secret once.
- 03
Render
Send the key in x-api-key, add an idempotency key, and save or poll the result.
curl -X POST https://www.thefake.design/api/v1/screenshots \
-H "x-api-key: $THEFAKE_API_KEY" \
-H "Idempotency-Key: tender-summary-001" \
-H "Content-Type: application/json" \
-o tender-summary.png \
-d '{
"template": "chat-square",
"frameIndex": 90,
"format": "png",
"scale": 2,
"filename": "tender-summary.png",
"scene": {
"platform": "imessage",
"messages": [
{
"id": "question",
"type": "text",
"text": "What did the department spend?",
"direction": "incoming",
"status": "read"
},
{
"id": "answer",
"type": "text",
"text": "$4.2m across 18 awarded tenders.",
"direction": "outgoing",
"status": "read"
}
]
}
}'const renderRequest = {
template: "chat-square",
format: "png",
scale: 2,
scene: {
platform: "imessage",
messages: [
{
id: "finding",
type: "text",
text: "$4.2m across 18 awarded tenders.",
direction: "outgoing",
status: "read"
}
]
}
};
const response = await fetch(
"https://www.thefake.design/api/v1/screenshots",
{
method: "POST",
headers: {
"x-api-key": process.env.THEFAKE_API_KEY,
"Idempotency-Key": "tender-summary-001",
"Content-Type": "application/json"
},
body: JSON.stringify(renderRequest)
}
);
if (!response.ok) {
throw new Error(await response.text());
}
const image = Buffer.from(await response.arrayBuffer());Authentication
Use x-api-key for server integrations. A bearer value beginning with tf_ is also accepted. Never expose a key in browser code or a public repository.
Scopes and rotation
Keys can carry screenshots, videos, or both. Create a replacement before revoking an old key. Revocation takes effect on the next request.
MCP review boundary
Expose render creation as a server-side MCP tool, then return the file or job to the chat for review. Keep the final social publish action separate so a person approves the output.
Scene data
Send only the scene fields you want to change.
The scene object is merged with each template's working defaults. Start with the content, then add headers, settings, participants, media, or platform-specific details.
{
"platform": "whatsapp",
"messages": [
{
"id": 1,
"type": "text",
"text": "Can you summarize the result?",
"direction": "incoming",
"status": "read"
},
{
"id": 2,
"type": "photo",
"mediaUrl": "https://cdn.example.com/chart.png",
"text": "Here is the spending breakdown.",
"direction": "outgoing",
"status": "read"
}
],
"isGroupChat": false,
"settings": {
"darkMode": false,
"showStatusBar": true
}
}Content families
| Family | Templates | Required scene fields | Optional scene fields |
|---|---|---|---|
Chat | chat-* | platform, messages | header, settings, participants, isGroupChat, wallpaper, showDeviceFrame |
Post | post-* | post | settings, showDeviceFrame |
Comments | comments-* | post | settings, commentPlatform, showDeviceFrame |
Story | story-*, tiktok-story-* | story | storySlides, settings, showDeviceFrame |
Email | email-thread | platform, settings, showDeviceFrame | |
X features | x-feature-* | mode | block, suspension, replyChain, profile, showDeviceFrame |
Chat message fields
Every message needs an ID, type, direction, and delivery status.
Image fields must use a direct media URL, not a webpage URL.
| Field | Type | Meaning |
|---|---|---|
id | string | number | Unique message identifier within the request. |
type | string | text, photo, video, audio, view_once, typing_pause, call_event, deleted, or system_event. |
direction | string | outgoing for the account owner, incoming for another participant. |
status | string | none, sent, delivered, or read. |
text | string | Required for text messages and optional as a media caption. |
mediaUrl | string | Direct media URL for photo or supported media messages. |
durationSeconds | number | Duration for video, audio, and typing-pause messages. |
sentAt | string | Optional local ISO-style date and time displayed on the message. |
senderId | string | Participant ID for received messages in group chats. |
Scene recipes
Use these as minimal starting shapes for the other content families.
Post and comments post-*, comments-*
{
"post": {
"id": 1,
"postType": "linkedin_post",
"author": {
"name": "Avery Morgan",
"handle": "averymorgan",
"isVerified": true
},
"text": "Five findings from this week's tender data.",
"timestamp": "2m",
"metrics": {
"likes": 42,
"reposts": 5,
"comments": 3
},
"comments": []
},
"settings": {
"showStatusBar": true,
"showNotch": false,
"showComments": true
}
}Story story-*, tiktok-story-*
{
"story": {
"backgroundMedia": "",
"author": {
"username": "averymorgan",
"isVerified": true
},
"timeAgo": "2h",
"gradientIndex": 2,
"textOverlays": [
{
"id": "finding-1",
"text": "$4.2m across 18 tenders",
"xPercent": 50,
"yPercent": 48,
"style": "strong",
"fontSize": 28,
"align": "center"
}
]
},
"settings": {
"showStatusBar": false
}
}Email email-thread
{
"platform": "gmail",
"email": {
"subject": "Re: Tender analysis",
"attachmentName": "findings.pdf",
"folderLabel": "Inbox",
"isStarred": false,
"participants": [
{"id": "analyst", "name": "Avery", "email": "avery@example.com"},
{"id": "editor", "name": "Jordan", "email": "jordan@example.com"},
{"id": "lead", "name": "Sam", "email": "sam@example.com"}
],
"messages": [
{
"id": "email-1",
"senderId": "analyst",
"toIds": ["editor"],
"ccIds": ["lead"],
"sentAt": "2026-08-04T10:15",
"body": "The spending summary is ready for review."
}
]
}
}Endpoint reference
A small surface with predictable responses.
All authenticated endpoints are owner-scoped. A key can only poll, download, or cancel jobs created by the same account.
/api/v1/templatesPublicList templates and supported output types.
/api/v1/screenshotsscreenshotsRender and stream a PNG or JPEG.
/api/v1/video-rendersvideosCreate an asynchronous MP4 or WebM job.
/api/v1/video-renders/{renderId}videosRefresh and return a private job.
/api/v1/video-renders/{renderId}/downloadvideosStream a completed video.
/api/v1/video-renders/{renderId}videosCancel and remove a job.
Returns a PNG or JPEG binary with 200 OK. Save the body directly instead of parsing JSON.
| Field | Type | Required | Description |
|---|---|---|---|
template | string | Yes | A template ID returned by GET /api/v1/templates. |
scene | object | Yes | Content and presentation fields merged with the template defaults. |
frameIndex | integer | No | Frame to capture. Defaults to the final frame. |
format | png | jpeg | No | Output format. Defaults to png. |
scale | number | No | Render scale from 1 to 4. Defaults to 2. |
filename | string | No | Download filename, up to 120 characters. |
Returns a JSON job with 202 Accepted. Poll its status URL until a download URL appears.
| Field | Type | Required | Description |
|---|---|---|---|
template | string | Yes | A video-capable template ID. |
scene | object | Yes | Content and presentation fields merged with the template defaults. |
durationSeconds | number | Yes | Video duration in seconds, from more than 0 up to 600. |
fps | integer | No | Frame rate from 1 to 60. Defaults to 30. |
scale | number | No | Render scale from 1 to 4. Defaults to 1. |
format | mp4 | webm | No | Output format. Defaults to mp4. |
filename | string | No | Download filename, up to 120 characters. |
curl -X POST https://www.thefake.design/api/v1/video-renders \
-H "x-api-key: $THEFAKE_API_KEY" \
-H "Idempotency-Key: tender-video-001" \
-H "Content-Type: application/json" \
-d '{
"template": "chat-vertical",
"durationSeconds": 5,
"fps": 30,
"scale": 1,
"format": "mp4",
"scene": {
"platform": "whatsapp",
"messages": [
{
"id": 1,
"type": "text",
"text": "Ready to publish?",
"direction": "incoming",
"status": "read"
}
]
}
}'{
"success": true,
"requestId": "req_01J...",
"data": {
"id": "render_01J...",
"status": "queued",
"template": "chat-vertical",
"format": "mp4",
"fps": 30,
"scale": 1,
"durationSeconds": 5,
"creditsUsed": 1,
"progressPercent": 0,
"statusUrl": "/api/v1/video-renders/render_01J...",
"downloadUrl": null
}
}# Poll until status is completed or failed
curl https://www.thefake.design/api/v1/video-renders/render_01J... \
-H "x-api-key: $THEFAKE_API_KEY"
# Download a completed job
curl https://www.thefake.design/api/v1/video-renders/render_01J.../download \
-H "x-api-key: $THEFAKE_API_KEY" \
-o tender-summary.mp4
# Cancel and remove a job
curl -X DELETE https://www.thefake.design/api/v1/video-renders/render_01J... \
-H "x-api-key: $THEFAKE_API_KEY"queuedAccepted and waiting for renderer capacity.
renderingFrames are being composed and encoded.
completeddownloadUrl is ready for the same API key.
failedNo output is available and reserved credits are refunded.
Template catalog
Thirty templates, one discovery endpoint.
Call GET /api/v1/templates at runtime to discover the current catalog. Each result declares whether it supports screenshots, videos, or both.
Chat
6 templates- mobile · screenshots + videos
chat-mobileMobile chat thread export for short-form screenshots and animated message stories.
- desktop · screenshots + videos
chat-desktopDesktop chat layout for browser-style or workstation-style conversation mockups.
- mobile · screenshots + videos
chat-verticalVertical chat composition optimized for short-form video platforms.
- mobile · screenshots + videos
chat-portraitPortrait chat composition sized for feed-style social posts.
- mobile · screenshots + videos
chat-squareSquare chat composition for 1:1 social placements.
- desktop · screenshots + videos
chat-landscapeWide chat composition for YouTube, presentations, and embeds.
- mobile · screenshots
email-threadMobile email thread composition for Gmail, Apple Mail, Outlook, and redacted screenshots.
Story
13 templates- mobile · screenshots + videos
story-mobileMobile full-screen story composition with overlays and viewer context.
- desktop · screenshots + videos
story-desktopDesktop story composition for previewing story visuals in a wider interface.
- mobile · screenshots + videos
story-verticalVertical story composition optimized for short-form story sharing.
- mobile · screenshots + videos
story-portraitPortrait story composition sized for feed-style social posts.
- mobile · screenshots + videos
story-squareSquare story composition for 1:1 social placements.
- desktop · screenshots + videos
story-landscapeWide story composition for YouTube, presentations, and embeds.
- mobile · screenshots + videos
tiktok-story-mobileTikTok-style mobile story composition for creator-first vertical content.
- desktop · screenshots + videos
tiktok-story-desktopDesktop TikTok story composition for wider preview and review workflows.
- mobile · screenshots + videos
tiktok-story-verticalVertical TikTok story composition optimized for short-form sharing.
- mobile · screenshots + videos
tiktok-story-portraitPortrait TikTok story composition sized for feed-style social posts.
- mobile · screenshots + videos
tiktok-story-squareSquare TikTok story composition for 1:1 social placements.
- desktop · screenshots + videos
tiktok-story-landscapeWide TikTok story composition for landscape placements and embeds.
- mobile · screenshots + videos
tiktok-replyStandalone TikTok reply-to-comment sticker composition for creator hooks and mockups.
X features
2 templates- mobile · screenshots + videos
x-feature-mobileMobile X-style post and feature composition for feed or thread exports.
- desktop · screenshots + videos
x-feature-desktopDesktop X-style composition for wider social feed previews.
Post
5 templates- mobile · screenshots + videos
post-mobileStandard social post composition for feed-based screenshot and video exports.
- mobile · screenshots + videos
post-squareSquare post composition optimized for 1:1 social content previews.
- mobile · screenshots + videos
post-portraitPortrait post composition for taller social placements and story-like crops.
- mobile · screenshots + videos
post-verticalStory-style post composition for immersive vertical placements.
- desktop · screenshots + videos
post-landscapeWide post composition for landscape placements and embedded previews.
Comments
3 templates- mobile · screenshots + videos
comments-mobileComments thread composition for reply chains, reactions, and community views.
- mobile · screenshots + videos
comments-verticalVertical comments thread composition optimized for short-form story placements.
- desktop · screenshots + videos
comments-landscapeWide comments thread composition for desktop reviews and embedded use cases.
Credits and limits
Know the cost before the render starts.
API Starter includes 200 monthly credits. Monthly credits are consumed first, then purchased credits. A rejected create or failed render returns its reservation.
| Output | Settings | Cost |
|---|---|---|
Screenshot | Scale 1 or 2 | 1 credit |
Screenshot | Scale 3 | 2 credits |
Screenshot | Scale 4 | 4 credits |
Video | 5 seconds, 30 FPS, scale 1 | 1 credit |
Video | Higher FPS or scale | Rounded up from duration × FPS × scale² |
Video formula: ceil(seconds ÷ 5 × FPS ÷ 30 × scale²). Purchased packs add 200 credits for $10 and remain valid for 12 months.
| Operation | Limit |
|---|---|
Screenshot renders | 20 per minute |
Video creates | 5 per minute |
Video status and cancellation | 60 per minute |
Video downloads | 20 per minute |
Read the rate-limit headers on every response. When blocked, wait for Retry-After instead of using a fixed delay.
Response headers
| Header | Meaning |
|---|---|
X-Request-Id | Trace identifier to include in support requests. |
X-RateLimit-Limit | Maximum requests in the current window. |
X-RateLimit-Remaining | Requests remaining in the current window. |
X-RateLimit-Reset | Window reset time as Unix milliseconds. |
X-TheFake-Credits-Used | Credits reserved by this create request. |
X-TheFake-Credits-Remaining | Total monthly and extra credits remaining. |
X-TheFake-Credits-Reset | Monthly credit reset time as Unix milliseconds. |
X-TheFake-Template | Readable template ID used for a screenshot render. |
X-TheFake-Frame-Index | Frame index captured for a screenshot render. |
Idempotent-Replayed | true when a completed response was replayed. |
Retry-After | Seconds to wait after a 409, 429, or temporary renderer error. |
Errors and retries
Branch on the code. Log the request ID.
JSON errors always include a stable code and a support-safe request ID. Preserve both in logs, then retry only the states described below.
{
"success": false,
"requestId": "req_01J...",
"error": {
"message": "This render needs 4 credits, but only 2 remain.",
"code": "insufficient_credits"
}
}| HTTP | Code | Meaning |
|---|---|---|
400 | invalid_body / invalid_request | Malformed JSON or an invalid render field. |
400 | invalid_idempotency_key | The key is outside the supported length or character set. |
401 | authentication_required / invalid_api_key | Credentials are missing, invalid, or revoked. |
402 | subscription_required | The account does not have an active Render API subscription. |
402 | insufficient_credits | The account does not have enough credits for the render. |
409 | idempotency_in_progress | The same create request is still running. |
409 | render_not_ready | The video exists but is not ready to download. |
410 | idempotency_response_expired | The original response is no longer replayable. |
413 | payload_too_large | The JSON request body exceeds 5 MB. |
422 | idempotency_key_mismatch | The same key was reused with different JSON. |
429 | rate_limited | The account exceeded an endpoint limit. |
503 | renderer_busy / renderer_unavailable | Capacity is temporarily unavailable. |
504 | renderer_timeout | The renderer did not finish within its timeout. |
Idempotency keys
Use 8 to 255 characters from letters, numbers, underscore, hyphen, period, slash, or colon. Keep one key per logical create.
Retry policy
Retry 409 in-progress, 429, 503, and 504 responses using Retry-After when present. Reuse the same idempotency key.
Replay window
Completed create responses are replayable for 24 hours when the body is cacheable. A replay never creates another credit reservation.
Access and keys
Pay, create a key, start rendering.
API Starter includes 200 monthly render credits for $15/mo. Every paying customer receives immediate access, with no application or approval step.
API Starter
Render when the story is ready.
One paid plan for human-reviewed workflows, small publishing queues, and the first automation that saves you from another copy and paste.
- 200 render credits every month
- Screenshots and asynchronous video
- Scoped keys you can revoke anytime
Monthly, cancel anytime
$15/mo
A standard screenshot uses 1 credit. Standard 30 FPS video uses 1 credit per 5 seconds. Higher scale and frame rates use more.
No free tier. No trial. Pro access is not included.
Before you automate publishing
Create responsibly. Review platform rules.
TheFake creates fictional mockups. Do not use exports to impersonate people, fabricate harmful evidence, or mislead audiences.