feat: add multipart media upload endpoint and split URL flow#15
Merged
Conversation
Adds POST /api/posts/{post}/media for direct file (multipart) upload
and renames the existing URL-based flow to /api/posts/{post}/media/from-url
so the path matches HTTP semantics (POST <resource>/media expects a file
body, not JSON URLs).
The multipart action validates type against the post's enabled platforms
(image rejected on TikTok-only posts), enforces per-type size caps, and
reuses Workspace::addMedia + Post::appendMedia. URL-based attaching is
unchanged behaviorally — only the route name and controller method are
renamed for symmetry. The MCP AttachMediaFromUrlTool was already named
correctly and needs no changes; binary upload via MCP is a host-protocol
limitation that no MCP server (including Postiz) supports.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
POST /api/posts/{post}/mediafor direct file (multipart) upload — closes the bytes-upload gap previously only the web app had.POST /api/posts/{post}/media/from-url(route nameapi.posts.attach-media-from-url, controller methodattachMediaFromUrl) so the path matches HTTP semantics —POST <resource>/mediais expected to take a file body, not JSON URLs.Why
Until now, attaching media via REST/MCP was URL-only (
MediaAttacher::attachFromUrls). For SDK/curl callers that have local bytes (no public URL), there was no way in. ChatGPT's MCP integration can't pass binary either, but custom apps and direct-API users now have a proper multipart path.Mirrors Postiz's split (
/uploadvs/upload-from-url), with one difference of design choice: ours stays post-scoped (one round-trip = upload + attach) instead of workspace-scoped media library. Can revisit later if a media-library use case shows up.Validation flow on
storeMediaStoreMediaRequest:mimetypesallow-list (image/jpeg, png, gif, webp, video/mp4, quicktime) + globalmax(video cap).MediaType::fromMime()→ check intersection with$post->allowedMediaTypes()(e.g. TikTok-only post + image upload → 422).maxSizeInBytes()cap.Workspace::addMedia(PNG/WEBP → JPEG normalization) +Post::appendMedia(lockForUpdate JSON merge).MCP
No changes.
AttachMediaFromUrlToolwas already named correctly. Binary upload via MCP isn't supported by any MCP server (Postiz included) — it's a protocol limitation: tool inputs are JSON, no binary type. SDK/custom clients use the new REST endpoint.Test plan
tests/Feature/Api/PostMediaApiTest.php— 12 tests pass (5 new for multipart: success, unsupported MIME, type-platform mismatch, cross-workspace 404, missing field; 4 existing renamed forattach-media-from-url).storeMedia,attachMediaFromUrl).Breaking change
Route name
api.posts.attach-media→api.posts.attach-media-from-url. URL/api/posts/{post}/media(JSON urls[]) →/api/posts/{post}/media/from-url. The REST API is fresh (PR #14 merged yesterday), impact should be near zero.