Media API
The media library: upload images, PDFs and zips, keep alt text current, and delete what nothing should reference any more.
All endpoints need a bearer token (see Overview & auth).
Endpoints
| Method & path | What it does |
|---|---|
GET /api/v1/media | The library, newest first. Filters: q (file name and alt text), kind (image, pdf or zip), limit (up to 200; default 200), offset (skip that many, for paging through a library bigger than one response). |
POST /api/v1/media | Upload a file as multipart form data: the file under file, optional alt_text alongside. Refused with 422 when no storage backend is configured, the type isn't an image, PDF or zip, or the file is over its ceiling (10 MB for images, 25 MB for files). |
GET /api/v1/media/:id | One item: hosted URL, content type, kind, size, alt text. |
PATCH /api/v1/media/:id | Update alt_text — what an image carries when inserted into email content. |
DELETE /api/v1/media/:id | Deletes the stored file and the row. Already-sent emails referencing the URL keep the reference and lose the file behind it — delete only what nothing should point at any more. |
GET /api/v1/media/storage | Where media serves from: backend, uploads_enabled, public_base_url and configured. Credentials never appear here — storage keys are entered in Settings and stay in the instance. |
POST /api/v1/media/storage/check | Round-trips a probe file to prove media actually loads: uploads it, fetches it back over the public host, deletes it. 200 with ok: true on success, 422 with a message naming the step that broke otherwise. |
Checking media hosting
A media URL that 404s is frozen into every email referencing it, and already-sent mail can't be repointed — so it's worth proving the host serves before a send rather than after one.
curl -X POST https://your-instance.example.com/api/v1/media/storage/check \
-H "Authorization: Bearer $MIMEO_API_TOKEN"
{
"ok": true,
"message": "files.yourdomain.com served a test file — media hosting is working.",
"url": "https://files.yourdomain.com/mimeo-host-check/… .txt",
"storage": {
"backend": "r2",
"uploads_enabled": true,
"public_base_url": "https://files.yourdomain.com",
"configured": true
}
}
On failure the message distinguishes the causes that look
alike from the outside: a host that doesn't resolve yet, a certificate
still issuing, public access switched off, or a domain connected to the
wrong bucket.
Uploading
curl -X POST https://your-instance.example.com/api/v1/media \
-H "Authorization: Bearer $MIMEO_TOKEN" \
-F "[email protected]" \
-F "alt_text=The dashboard, mid-campaign"
The response is the stored item:
{
"media": {
"id": 12,
"filename": "hero.png",
"url": "https://media.example.com/3f9a.../hero.png",
"content_type": "image/png",
"kind": "image",
"byte_size": 48213,
"alt_text": "The dashboard, mid-campaign",
"created_at": "2026-08-02T12:00:00Z"
}
}
Referencing media in email content
Email bodies are markdown; media inserts by URL. An image goes in as an inline image carrying its alt text, and a PDF or zip as a link:

[press-kit.zip](https://media.example.com/81c2.../press-kit.zip)
Errors
| Status | When |
|---|---|
422 | No storage configured, no file part, an unsupported type, an over-ceiling file, or a failed alt-text save. The error names the fix. |
404 | No media item with that id. |