Media
Uploading images, videos and documents, and resolving media paths back to URLs.
Uploading
Three routes, one file per call, field name file, multipart/form-data:
| Route | Accepts | Max |
|---|---|---|
POST /api/v1/posts/media | JPG, PNG, WebP | 10 MB |
POST /api/v1/posts/videos | MP4, WebM, MOV | 50 MB |
POST /api/v1/posts/documents | PDF, Word, Excel, PowerPoint, CSV, TXT | 20 MB |
POST /api/v1/users/me/avatar | JPG, PNG, WebP | 2 MB |
posts/media returns { "url": "…" }. The other two return the whole object —
{ url, name, mimeType, sizeBytes } — which you pass straight back into the post
body. The avatar route returns the updated profile, so there is nothing to
re-fetch.
Upload first, then create the post with the URLs you were given. Uploads are buffered in memory server-side, so on a phone: run them on a foreground task, show progress, and expect a dropped connection to mean starting that file over. Downscale camera photos client-side before sending — a modern phone camera routinely exceeds 10 MB.
Reading media back
Every media field the API returns is a path, not an absolute URL:
/api/v1/files/posts/9f2c1a3e-….jpg
/uploads/avatars/1b7d….png ← older rows, written before object storageTwo rules:
- Resolve it against the API base URL.
"$BASE_URL$path". A path already starting withhttpis absolute — leave it alone. - Send the session with the request. These files are behind the same guard
as everything else. An image loader that does not send
Authorizationgets a 401 and renders nothing.
Coil (Android):
AsyncImage(
model = ImageRequest.Builder(context)
.data(resolveMedia(post.author.image))
.addHeader("Authorization", "Bearer $token")
.build(),
contentDescription = null,
)Kingfisher (iOS):
let modifier = AnyModifier { request in
var r = request
r.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
return r
}
imageView.kf.setImage(with: url, options: [.requestModifier(modifier)])Responses are immutable and safe to cache indefinitely: the key is a fresh uuid per upload and the bytes behind it never change.