Upload Chat Image
POST/v1/chats/upload-image
Phase 95 SA1 — chat textarea image upload (PHASE95/PLAN.md contract).
Accepts a single image (PNG / JPEG / WebP / GIF, max 10 MB) from the
chat textarea drag-and-drop or paperclip path (SA2). Persists to object
storage under account/<account_id>/chat-images/<uuid>.<ext> and
returns a 1-hour presigned GET URL the frontend can attach to the next
user message via images: [{ url, objectPath }].
We do server-side PUT rather than the 2-step presigned-PUT flow used by
/v1/upload/<folder> for two reasons:
- Chat UX wants a single round-trip (drop → upload → attach) — the 2-step flow needs a second fetch from the browser to S3 which adds a round-trip and surfaces CORS pain.
- We validate mimetype + size on the server so the LLM provider (Anthropic / OpenAI) never sees malformed payloads. Presigned PUT skips that gate.
The returned URL is intentionally short-lived (3600s). For long-running
chats we re-presign via object_service.get_presigned_url(object_path)
on render — the object_path round-trip is the source of truth, not
the URL itself.
Request
Responses
- 200
- 404
- 422
Successful Response
Not found
Validation Error