# Let your users send pictures — vision in roleplay chat

> Image input is the highest-retention feature per credit in character products. The UX patterns that work, the implementation in one request, and the moderation duties that stay on your side.

Published 2026-08-14 · eroq.ai — canonical: https://eroq.ai/blog/let-users-send-pictures-vision-roleplay


Text roleplay has a one-way intimacy problem: the character describes her world, the user can only describe his back. Vision input closes the loop — he sends a photo of his desk, his dog, his dinner, and she *reacts to his actual day*. In production character apps, that reaction moment is one of the strongest retention events per credit spent.

## The feature, mechanically

[Chat completions](/docs/chat) accept image parts on user turns: `content` becomes an array mixing text and `image_url` entries (https URL or data URI, up to 2 images per request). Each attached image adds **2 credits** on top of the completion — a photo-reaction turn on RP mini costs 3 credits total, about three cents.

```json
{
  "model": "eroq-rp-mini",
  "context": "Mira: sardonic starship mechanic. Relationship: three weeks in.",
  "messages": [{
    "role": "user",
    "content": [
      { "type": "text", "text": "look what i built today" },
      { "type": "image_url", "image_url": { "url": "data:image/jpeg;base64,…" } }
    ]
  }]
}
```

The engine looks at the image and the character responds **in character** — not with an image caption. That distinction is the product: "That's a beautiful golden retriever" is a vision demo; "*wipes grease off her hands* okay, the dog is cuter than you. What's his name?" is a relationship.

## UX patterns that earn their credits

- **The reaction moment.** A camera button in the chat composer, full stop. Users discover it themselves; the first "she noticed the details" reply is the hook.
- **Prompted shares.** Have the character *ask* — "show me where you're sitting right now" — at natural beats. Prompted photos convert 3–4× better than a passive button, and they pace your vision spend.
- **Memory callbacks.** Fold what she saw into your rolling summary ("his desk faces a window; the dog is Biscuit"). A callback two days later — "how's Biscuit?" — is the cheapest wow in the category, and it costs zero extra credits because it's just [context](/docs/chat).
- **Cap it visibly.** Two images per request is the API ceiling; a per-day allowance in your free tier keeps the unit economics boring. Vision is cheap per event, not free at scale — budget it like every other [flat price](/pricing).

## The responsibilities that stay yours

User-submitted images are user-generated content, and the duties that come with UGC don't transfer to your model provider:

- **Scan uploads on your side** (CSAM detection against industry hash lists at minimum) *before* the API call. eroq's [acceptable-use policy](/legal/aup) bans minors and non-consensual real-person content absolutely — requests outside it return `content_blocked` and are never charged — but detection tooling on the upload path is your legal surface, not a nice-to-have.
- **Age-gate the feature** with the rest of your product. Photo exchange belongs behind the same adults-only wall as the roleplay itself.
- **Store nothing you don't need.** Pass data URIs through and keep only what the product requires (the summary line, not the photo). If the user *unlocks her sending photos back*, that's [image generation](/docs/images) — and those you can host durably with [`store: true`](/storage).

## Ship it in an afternoon

Vision input is the rare feature that's one composer button, one array change in an existing call, and no new infrastructure. A [key](/signup) and the 50 free credits cover the whole test: send the API a photo of your own desk and watch the character notice the coffee cups. That reaction is the feature — the rest is product discipline.
