POST /api/upload
Host an image on Vercel Blob so the content carries an absolute public URL — the prerequisite for Medium import. Raw body, x-filename header, 4.5 MB max.
The web editor calls this when you drop an image. There’s no dedicated CLI command — the route exists so every image in a story is a fetchable public URL, which is what Medium import requires.
Accepts an image and hosts it on Vercel Blob, returning an absolute public URL. Medium’s bot fetches the story server-side and can’t read inline data: images, so every image src must be a public URL.
Endpoint
POST https://scripto.codika.io/api/upload Auth
Authorization: Bearer scripto_… (or a session).
Request
The raw file is the request body (not multipart). The original filename goes in an x-filename header.
| Constraint | Value |
|---|---|
| Content types | image/png, image/jpeg, image/gif, image/webp, image/avif, image/svg+xml |
| Max size | 4.5 MB (Vercel Functions reject larger bodies) |
Response (201)
{ "success": true, "data": { "url": "https://…vercel-storage.com/articles/<user>/<uuid>-hero.png" } } Errors
| HTTP | code | Cause |
|---|---|---|
| 400 | invalid-argument | Not an image type, empty file, or > 4.5 MB. |
| 401 | unauthenticated | Missing or invalid key. |
| 500 | internal | Upload failed. |
curl
curl -sS -X POST https://scripto.codika.io/api/upload \
-H "Authorization: Bearer $SCRIPTO_API_KEY" \
-H "Content-Type: image/png" \
-H "x-filename: hero.png" \
--data-binary @hero.png Next
- Import, don’t paste — why hosted images matter for Medium.