Skip to content

feat: add multipart media upload endpoint and split URL flow#15

Merged
paulocastellano merged 1 commit into
mainfrom
feature/api-media-multipart-upload
May 4, 2026
Merged

feat: add multipart media upload endpoint and split URL flow#15
paulocastellano merged 1 commit into
mainfrom
feature/api-media-multipart-upload

Conversation

@paulocastellano
Copy link
Copy Markdown
Contributor

Summary

  • Adds POST /api/posts/{post}/media for direct file (multipart) upload — closes the bytes-upload gap previously only the web app had.
  • Renames the existing URL-based attach endpoint to POST /api/posts/{post}/media/from-url (route name api.posts.attach-media-from-url, controller method attachMediaFromUrl) so the path matches HTTP semantics — POST <resource>/media is 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 (/upload vs /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 storeMedia

  1. StoreMediaRequest: mimetypes allow-list (image/jpeg, png, gif, webp, video/mp4, quicktime) + global max (video cap).
  2. Controller: MediaType::fromMime() → check intersection with $post->allowedMediaTypes() (e.g. TikTok-only post + image upload → 422).
  3. Controller: per-type maxSizeInBytes() cap.
  4. Reuses Workspace::addMedia (PNG/WEBP → JPEG normalization) + Post::appendMedia (lockForUpdate JSON merge).

MCP

No changes. AttachMediaFromUrlTool was 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 for attach-media-from-url).
  • Full Feature/Api suite: 89 pass.
  • Full Feature/Mcp suite: 75 pass.
  • Full suite (parallel): 1368 pass / 2 skipped.
  • Pint clean.
  • Wayfinder regenerated (storeMedia, attachMediaFromUrl).

Breaking change

Route name api.posts.attach-mediaapi.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.

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.
@paulocastellano paulocastellano merged commit d92ee8d into main May 4, 2026
2 checks passed
@paulocastellano paulocastellano deleted the feature/api-media-multipart-upload branch May 4, 2026 21:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant