API Reference

Fake text screenshot

A picture of a chat that never happened. Same conversation you would send to the fake text video endpoint, drawn as a still png instead of played out and narrated.

POST/v1/fake-text-screenshots

Screenshot a conversation

Draws the chat and returns the png url. The picture is taken while the request is open, so it comes back in a few seconds rather than as a job to poll.
Body
charactersrequired
object[]
Who is chatting, at least two. Each one gets a side of the screen, see character fields.
messagesrequired
object[]
The chat itself, top to bottom, see message fields. Up to 1,000 of them, though a picture this tall is rarely what you want.
template
"iphone" | "iphone-dark" | "whatsapp" | "whatsapp-dark" | "instagram" | "instagram-dark" | "tinder" | "tinder-dark" | "cantina"
Which chat app the conversation is styled as.
default: iphone-dark
groupName
string
Title in the chat header. Shown once the conversation has more than two characters.
default: Group name
groupPhoto
string
Avatar shown in the chat header of a group conversation. Upload it with Files and pass back the file name it returns.
tinderMatch
string
The "you matched on" line above the chat. Tinder templates only.
character fields
namerequired
string
Shown in the chat header and, in group chats, above the messages. Messages refer to a character by this name.
id
string
What messages refer to this character by, when the name is awkward to repeat or two characters share one. Defaults to the name.
side
"left" | "right"
Right is the phone owner, whose messages sit on the right in the sent bubble colour. Everyone else reads as the person being texted.
default: left
avatar
string
Profile picture. Templates fall back to their placeholder avatar. Upload it with Files and pass back the file name it returns.
color
string
Name colour in group chats.
default: #1677ff
userId
string
Handle under the name. Instagram templates only.
message fields
fromrequired
string
Which character sent it, matching their id or name.
type
"text" | "image"
Text is a chat bubble, image attaches a picture. The hook and comment messages a video can carry have nowhere to go in a still picture and are rejected.
default: text
text
string
What the bubble says. Required on text messages, up to 400 characters.
image
string
Image or gif attached to the message. Required on image messages. Upload it with Files and pass back the file name it returns.
imageWidth
number
Pixel width of the file, as returned by the upload. Pass it with imageHeight or the bubble may be sized wrong.
imageHeight
number
Pixel height of the file.
Response fields
urlrequired
string
Where the png lives. No authentication needed, so it can be linked or downloaded straight away. Transparent outside the chat.
creditsrequired
number
What the picture cost.
expiresAtrequired
string
When the url stops resolving. Copy the png to your own storage if you need it for longer.
Request
curl -X POST "https://api.vsub.io/v1/fake-text-screenshots" \
  -H "Authorization: Bearer vp_a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90" \
  -H "Content-Type: application/json" \
  -d '{
    "template": "iphone-dark",
    "characters": [
      { "name": "Mia", "side": "left" },
      { "name": "Me", "side": "right" }
    ],
    "messages": [
      { "from": "Mia", "text": "did you see what he posted" },
      { "from": "Me", "text": "no?? send it" },
      { "from": "Mia", "text": "you are not ready for this" }
    ]
  }'
Response 200
{
  "url": "https://files.vsub.io/expire-30-vsub-free-fake-text-screenshot-641671c3-61e2-4415-91bf-93b9fce3cba8.png",
  "credits": 10,
  "expiresAt": "2026-09-06T03:13:36.954Z"
}

A screenshot costs 10 credits, charged once the png is stored, so a picture that failed to draw is free. The request fails with a 400 when the workspace has fewer than 10 credits left. The png stays available for 30 days. The tool in the app costs nothing, this price is for taking the picture from your own code.

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.

Body
{
  "template": "whatsapp",
  "groupName": "Bali trip",
  "groupPhoto": "expire-30-user-image-2b7f9c14-8a3e-4d21-9f07-1c5b6a8e2d40.png",
  "characters": [
    {
      "name": "Ana",
      "side": "left",
      "color": "#f759ab",
      "avatar": "expire-30-user-image-6c1a72f5-4b98-4e3a-8d16-9f2c0b7a5e31.png"
    },
    { "name": "Leo", "side": "left", "color": "#52c41a" },
    { "name": "Me", "side": "right" }
  ],
  "messages": [
    { "from": "Ana", "text": "I booked the flights, we land at 6am on the 4th" },
    { "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" }
  ]
}

Bubble colour, the unread badge and the rest of the chrome come from your workspace defaults, the same ones the app starts a fake text with, so a screenshot looks like what the tool in the app draws for you. To have the conversation typed out and narrated instead, send the same characters and messages to Fake Text.