Fake Text
Send the conversation you want to see typed out and Vsub renders it as a chat on an iPhone, WhatsApp, Instagram, Tinder or Cantina screen, narrating each message in its character's voice over gameplay. Creation returns immediately, so poll the video or listen with webhooks.
/v1/fake-text-videosCreate a fake text video
conversationsrequiredrenderwebhookUrlcharactersrequiredmessagesrequiredtemplateiphone-darklanguageEnglishautoSplitfalsegroupNameGroup namegroupPhototinderMatchuseVoiceV2truenamerequiredidsideleftvoiceIdvoiceProvider11voiceStyleavatarcolor#1677ffuserIdfromtypetexttextemphasizefalseimageimageWidthimageHeightimageDurationhookTypecustomhookcommenthook.textSay somethinghook.displayTexthook.voiceIdpNInz6obpgDQGcFmaJgBhook.voiceProvider11hook.voiceStylehook.imagehook.layouthook.layout.paddingTop300hook.layout.paddingX100hook.layout.radius30hook.layout.useShadowtruehook.layout.shadowColorrgba(0, 0, 0, 0.1)hook.layout.shadowSize15hook.layout.rizzTotalMessages4hook.layout.rizzDuration2000voiceStyle.stability38voiceStyle.similarityBoost75voiceStyle.style0voiceStyle.speed100render.formatstandardrender.frameRate30curl -X POST "https://api.vsub.io/v1/fake-text-videos" \
-H "Authorization: Bearer vp_a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90" \
-H "Content-Type: application/json" \
-d '{
"conversations": [
{
"template": "iphone-dark",
"characters": [
{ "name": "Mom", "side": "left" },
{ "name": "Me", "side": "right" }
],
"messages": [
{ "from": "Mom", "text": "Where are you?" },
{ "from": "Me", "text": "Still at the office" },
{ "from": "Mom", "text": "It is 11pm", "emphasize": true }
]
}
],
"webhookUrl": "https://your-app.example.com/hooks/vsub-video"
}'{
"id": "9f0c1d5e-3a1b-4c2f-9d7e-8b1a2c3d4e5f",
"status": "processing",
"step": "create-vocal",
"render": false,
"createdAt": "2026-08-05T09:20:11.000Z",
"editorUrl": "https://vsub.io/workspace/editor/9f0c1d5e-3a1b-4c2f-9d7e-8b1a2c3d4e5f"
}Generation runs in the background. Follow the video with Video status or let a webhook tell you when it's done.
More examples
Each of these is the body of the same request, the url and headers don't change.
Group chat with an image
Three characters make it a group chat, so the header shows groupName and the photo, and each name is written in its own colour. The image message carries the key and size returned by Files, and autoSplit breaks Ana's long message into three that arrive one after another.
{
"conversations": [
{
"template": "whatsapp",
"groupName": "Bali trip",
"groupPhoto": "expire-30-user-image-2b7f9c14-8a3e-4d21-9f07-1c5b6a8e2d40.png",
"autoSplit": true,
"characters": [
{
"name": "Ana",
"side": "left",
"color": "#f759ab",
"avatar": "expire-30-user-image-6c1a72f5-4b98-4e3a-8d16-9f2c0b7a5e31.png"
},
{ "name": "Leo", "side": "left", "color": "#52c41a", "voiceId": "pNInz6obpgDQGcFmaJgB" },
{ "name": "Me", "side": "right" }
],
"messages": [
{
"from": "Ana",
"text": "I booked the flights. We land at 6am on the 4th. Do not plan anything for that morning."
},
{ "from": "Leo", "text": "Look at the place I found" },
{
"from": "Leo",
"type": "image",
"image": "expire-30-user-image-91d0e4a7-2f65-4c88-b3a9-7e1d5c0f8b42.png",
"imageWidth": 1080,
"imageHeight": 1350
},
{ "from": "Me", "text": "Book it", "emphasize": true }
]
}
]
}Opening on a hook, closing on a comment
The hook plays before the chat with its own voice, reading hook.text while the card shows the shorter displayText. The comment lands over the conversation at the end, also in its own voice. Neither takes a from. The characters here carry an id, which is handy when the on screen name is long or repeated.
{
"conversations": [
{
"template": "iphone-dark",
"characters": [
{ "id": "her", "name": "Sofia", "side": "left" },
{
"id": "me",
"name": "Me",
"side": "right",
"voiceId": "Er9R704Replxn1FtlRde",
"voiceStyle": { "stability": 60, "speed": 105 }
}
],
"messages": [
{
"type": "hook",
"hookType": "rizzApp",
"hook": {
"text": "She left me on read for three days, so I asked an app what to send",
"displayText": "What do I send after three days?",
"layout": { "rizzTotalMessages": 3, "rizzDuration": 1800 }
}
},
{ "from": "me", "text": "Still thinking about that taco place" },
{ "from": "her", "text": "You waited three days to say that" },
{
"type": "comment",
"text": "he really used an app for this",
"comment": { "voiceId": "aEO01A4wXwd1O8GPgGlF" }
}
]
}
]
}Two conversations in one video
The conversations play back to back, each with its own app and cast, which is how you cut from the match to the fallout. Tinder templates take tinderMatch for the line above the chat, and Instagram templates show a character's userId as their handle.
{
"conversations": [
{
"template": "tinder",
"tinderMatch": "You matched with Julia on 3 May",
"characters": [
{ "name": "Julia", "side": "left" },
{ "name": "Me", "side": "right" }
],
"messages": [
{ "from": "Julia", "text": "Hey, you look familiar" },
{ "from": "Me", "text": "We went to the same school" }
]
},
{
"template": "instagram-dark",
"characters": [
{ "name": "Julia", "userId": "@julia.k", "side": "left" },
{ "name": "Me", "userId": "@dan", "side": "right" }
],
"messages": [
{ "from": "Julia", "text": "My sister just sent me your yearbook photo" },
{ "from": "Me", "text": "Please delete it", "emphasize": true }
]
}
]
}The gameplay behind the chat, the bubble styling and the sound effects come from your workspace defaults, the same ones the app starts a fake text video with. Anything the request doesn't cover, such as swapping the background or muting a single message, is still yours to change in the editor before rendering.

comment.voiceIdpNInz6obpgDQGcFmaJgBcomment.voiceProvider11comment.voiceStyle