BulkPublish — Media & Bulk Publishing Reference
upload_media parameters
url (string, optional) — public URL to download from
filePath (string, optional) — absolute local file path (e.g. /Users/me/photo.png)
filename (string, optional) — override filename, otherwise derived from url/path
Provide either url OR filePath, not both.
Supported formats
| Type | Formats | Max size |
|---|---|---|
| Image | JPEG, PNG, WebP, GIF | 100MB |
| Video | MP4, MOV, WebM | 100MB (up to 1GB via multipart — see below) |
Response
Returns: id (use this in mediaFileIds when creating posts), fileName, mimeType, sizeBytes, width, height, duration (video), originalUrl, thumbnailUrl, previewUrl.
Other media tools
| Tool | Use for | Key params |
|---|---|---|
list_media |
Browse uploaded files | search, page, limit |
get_media |
Single file details | mediaId |
delete_media |
Remove a file | mediaId |
Media requirements by platform
| Platform | Image | Video | Notes |
|---|---|---|---|
| Instagram Reels | — | MP4, 9:16 | 3 seconds–15 minutes |
| Instagram Stories | JPEG/PNG, 9:16 | MP4, 9:16 | 1080x1920 recommended; video 3–60 seconds |
| Instagram Carousel | JPEG/PNG | — | 2-10 images |
| TikTok | — | MP4 | Up to 3 minutes for every account; some accounts 5 or 10 |
| YouTube | — | MP4 | Requires title in platformSpecific |
| JPEG/PNG, 2:3 | MP4 | 1000x1500 recommended; video pins at least 4 seconds | |
| Facebook/X/LinkedIn | JPEG/PNG | MP4 | Most formats accepted |
Large files — multipart upload (REST API)
For videos over 100MB (up to 1GB), use the chunked multipart flow: MCP tools create_multipart_upload, complete_multipart_upload, abort_multipart_upload, or the REST API (Authorization: Bearer bp_your_key, base https://app.bulkpublish.com):
POST /api/media/multipart/create— body{contentType, sizeBytes}(exact size) →{r2Key, uploadId, partSize, partUrls, expiresIn}.partSizeis fixed at 10MB (10485760);partUrlsis one presigned PUT URL per part, in order; URLs expire in 3600s.PUTeach 10MB slice of the file to itspartUrland save theETagresponse header per part. A failed part can be retried alone — a network drop never restarts the whole file.POST /api/media/multipart/complete— body{r2Key, uploadId, parts: [{partNumber, etag}], fileName, mimeType, sizeBytes, width?, height?, duration?}→{file}(same media object as a normal upload; itsidgoes inmediaFileIds). Failed assembly auto-aborts the upload.
- To cancel mid-flight:
POST /api/media/multipart/abort— body{r2Key, uploadId}(frees stored parts) - 400 = disallowed type or too large; 403 with
error.code: "QUOTA_EXCEEDED"= storage quota exceeded
Bulk actions and approval
bulk_posts (delete | retry | reschedule) does not take requestApproval.
A bulk retry on posts whose role lacks post:publish fails with 403
APPROVAL_REQUIRED — those posts must be submitted for team approval instead
(create/update with requestApproval: true, then a teammate calls
approve_post). Posts with approvalStatus "pending" or "rejected" do
not publish, even after a reschedule, until they are approved.
A bulk reschedule counts against the same scheduling limits as creating a
post: moving drafts past the pending-scheduled cap, or more posts onto one day
than the per-day cap allows, returns 403 QUOTA_EXCEEDED and changes
nothing. It returns 400 when scheduledAt is missing or not an ISO 8601
date-time, or when none of the posts is a draft or scheduled. See
the schedule-post skill for the full approval flow.
Bulk pattern
For multiple files: call upload_media for each file, collect the returned IDs, then pass all IDs in mediaFileIds when creating the post.
