From 979620e4d0fce838ddd512617375de08e6a063e6 Mon Sep 17 00:00:00 2001 From: Gilad Resisi Date: Mon, 19 Oct 2026 21:53:07 +0700 Subject: [PATCH 1/3] docs: opt-in adjust to platform limits on uploads and media status Co-Authored-By: Claude Opus 5.5 --- cli/media-upload.mdx | 11 ++++ docs.json | 1 + mcp/tools.mdx | 44 +++++++++++++ public-api/openapi.json | 87 ++++++++++++++++++++++++++ public-api/uploads/media-status.mdx | 34 ++++++++++ public-api/uploads/upload-file.mdx | 26 +++++++- public-api/uploads/upload-from-url.mdx | 2 + 7 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 public-api/uploads/media-status.mdx diff --git a/cli/media-upload.mdx b/cli/media-upload.mdx index aefaf0d5..c876454a 100644 --- a/cli/media-upload.mdx +++ b/cli/media-upload.mdx @@ -25,6 +25,17 @@ The command returns a JSON response with the uploaded file's URL: You must upload media files to Postiz before using them in posts. Many platforms (TikTok, Instagram, YouTube) require verified URLs and will reject external links. +## Adjusting Media to Platform Limits + +Platforms reject media that is too large, too small or in an encoding they don't accept. Add `--adjust` (off by default) to adjust the file after the upload: videos are scaled to 1080p and re-encoded to MP4, oversized images are scaled down. See [Upload File](/public-api/uploads/upload-file#adjusting-media-to-platform-limits) for the details. + +```bash +postiz upload video.mp4 --adjust +postiz media:status +``` + +The returned `path` is usable right away, and the adjusted file replaces the original at the same `path` when it's done. A post published before that uses the original. Poll `media:status` only while the status is `processing`. If the adjustment fails, the original file is kept and used for publishing, and the status is `ready` with a `warning`. + ## Upload and Post Workflow ```bash diff --git a/docs.json b/docs.json index 0886c699..3e7edfc9 100644 --- a/docs.json +++ b/docs.json @@ -367,6 +367,7 @@ "pages": [ "public-api/uploads/upload-file", "public-api/uploads/upload-from-url", + "public-api/uploads/media-status", "public-api/uploads/list-media" ] }, diff --git a/mcp/tools.mdx b/mcp/tools.mdx index 926027c0..f1884634 100644 --- a/mcp/tools.mdx +++ b/mcp/tools.mdx @@ -256,6 +256,50 @@ Use an item's `path` in the `attachments` array when scheduling a post. --- +## uploadFromUrlTool + +Upload a remote image or video into the media library from a public http(s) URL. Local or private files can't be fetched, upload those with the [CLI](/cli/media-upload) or the [public API](/public-api/uploads/upload-file). + +**Parameters:** + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `url` | string | Yes | Public http(s) URL of the image or video | +| `adjust` | boolean | No | Adjust the media to the platforms' limits after the upload (default false), see [Upload File](/public-api/uploads/upload-file#adjusting-media-to-platform-limits) for what it changes | + +**Returns:** + +| Field | Type | Description | +|-------|------|-------------| +| `id` | string | Media ID | +| `path` | string | URL of the uploaded file, usable as an attachment right away | +| `status` | string | `ready`, or `processing` while an upload with `adjust` is being adjusted | + +With `adjust`, the adjusted file replaces the original at the same `path` when it's done, and a post published before that uses the original. Use `mediaStatusTool` to know when it's in place. + +--- + +## mediaStatusTool + +Check whether a media uploaded with `adjust` set to true finished adjusting, using the `id` returned by `uploadFromUrlTool`, the public API or the CLI. Files uploaded through the upload widget (in clients that display MCP Apps) are checked with `uploadWidgetStatusTool` instead. + +**Parameters:** + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `id` | string | Yes | The media ID returned by the upload | + +**Returns:** + +| Field | Type | Description | +|-------|------|-------------| +| `id` | string | Media ID | +| `path` | string | URL of the file | +| `status` | string | `processing` while the adjustment runs, `ready` once the adjusted file is in place | +| `warning` | string | Present with `ready` when the adjustment failed: the original file was kept and is used for publishing | + +--- + ## generateImageTool Generate an AI image to use as a post attachment. diff --git a/public-api/openapi.json b/public-api/openapi.json index b5a094ec..1c81dfbe 100644 --- a/public-api/openapi.json +++ b/public-api/openapi.json @@ -1997,6 +1997,15 @@ "type": "string", "format": "binary", "description": "The file to upload" + }, + "adjust": { + "type": "string", + "default": "false", + "description": "Adjust the file to the platforms' limits after the upload: videos are scaled to a 1080 px short side (long side at most 1920 px) and re-encoded to H.264 MP4 with AAC audio, images larger than that are scaled down. Runs in the background, poll GET /media/{id}/status for the result. Defaults to false.", + "enum": [ + "true", + "false" + ] } }, "required": [ @@ -2039,6 +2048,11 @@ "type": "string", "format": "uri", "description": "URL of the file to upload" + }, + "adjust": { + "type": "boolean", + "default": false, + "description": "Adjust the file to the platforms' limits after the upload: videos are scaled to a 1080 px short side (long side at most 1920 px) and re-encoded to H.264 MP4 with AAC audio, images larger than that are scaled down. Runs in the background, poll GET /media/{id}/status for the result. Defaults to false." } }, "required": [ @@ -2065,6 +2079,71 @@ } } }, + "/media/{id}/status": { + "get": { + "tags": [ + "Uploads" + ], + "summary": "Get media status", + "description": "Check whether a file uploaded with adjust set to true finished adjusting. A failed adjustment returns status \"ready\" with a warning: the original file was kept and is used for publishing.", + "operationId": "getMediaStatus", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "The media id returned by the upload", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Media status", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "path": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "processing", + "ready", + "failed" + ] + }, + "warning": { + "type": "string", + "description": "Present when the adjustment failed and the original file was kept" + }, + "error": { + "type": "string", + "description": "Present with status \"failed\", only when the adjustment failed and the original file's format cannot be published as is" + } + } + }, + "example": { + "id": "e639003b-f727-4a1e-87bd-74a2c48ae41e", + "path": "https://uploads.postiz.com/video.mp4", + "status": "ready" + } + } + } + }, + "404": { + "description": "Media not found" + } + } + } + }, "/media": { "get": { "tags": [ @@ -2722,6 +2801,14 @@ "updatedAt": { "type": "string", "format": "date-time" + }, + "status": { + "type": "string", + "enum": [ + "ready", + "processing" + ], + "description": "\"processing\" while an upload with adjust set to true is being adjusted, otherwise \"ready\"" } }, "example": { diff --git a/public-api/uploads/media-status.mdx b/public-api/uploads/media-status.mdx new file mode 100644 index 00000000..cb1942ba --- /dev/null +++ b/public-api/uploads/media-status.mdx @@ -0,0 +1,34 @@ +--- +title: 'Media Status' +openapi: 'GET /media/{id}/status' +icon: 'spinner' +--- + +Check whether a file uploaded with `adjust` set to `true` (on [Upload File](/public-api/uploads/upload-file) or [Upload from URL](/public-api/uploads/upload-from-url)) finished adjusting to the platforms' limits. Uploads without `adjust` are `ready` as soon as the upload call returns and don't need this endpoint. + +## Example + +```bash +curl "https://api.postiz.com/public/v1/media/01HXYZ123ABCDEF/status" \ + -H "Authorization: your-api-key" +``` + +Response: + +```json +{ + "id": "01HXYZ123ABCDEF", + "path": "https://uploads.postiz.com/video.mp4", + "status": "ready" +} +``` + +## Statuses + +| Status | Meaning | +|---|---| +| `processing` | The adjustment is still running. The `path` is already usable, a post published now uses the original file. Call again in a few seconds. | +| `ready` | The adjusted file is in place at the same `path`. | +| `ready` with a `warning` | The adjustment failed. The original file was kept at the same `path` and is used for publishing. | + +An unknown `id`, or one from another organization, returns `404`. diff --git a/public-api/uploads/upload-file.mdx b/public-api/uploads/upload-file.mdx index e169f9c3..29af4c6d 100644 --- a/public-api/uploads/upload-file.mdx +++ b/public-api/uploads/upload-file.mdx @@ -36,10 +36,34 @@ Example response: ```json { "id": "01HXYZ123ABCDEF", - "path": "https://uploads.postiz.com/photo.jpg" + "path": "https://uploads.postiz.com/photo.jpg", + "status": "ready" } ``` +## Adjusting media to platform limits + +Platforms reject media that is too large, too small or in an encoding they don't accept. Send the optional `adjust` field as `true` to adjust the file after the upload. It defaults to `false`, which stores the file as uploaded. + +- Videos get their short side scaled to 1080 px, up or down, with the long side at most 1920 px. They are re-encoded to H.264 MP4 (yuv420p, at most 60 fps) with AAC audio (128 kbps, 48 kHz) and the metadata moved to the start of the file for streaming. +- Images are only scaled down, to a short side of at most 1080 px and a long side of at most 1920 px, and keep their format. +- GIF, AVIF, BMP and TIFF files are stored as uploaded. + +```bash +curl -X POST "https://api.postiz.com/public/v1/upload" \ + -H "Authorization: your-api-key" \ + -F "adjust=true" \ + -F "file=@video.mp4" +``` + +The adjustment runs in the background, so the response comes back with `"status": "processing"`. The `path` is usable right away: the adjusted file replaces the original at the same `path` when it's done, and a post published before that uses the original. If you need to know when the adjusted file is in place, poll [Media Status](/public-api/uploads/media-status) every few seconds until the status is no longer `processing`. Without `adjust` the upload is synchronous and there is nothing to poll. + +If the adjustment fails, the original file is kept and used for publishing, and Media Status returns `"status": "ready"` with a `warning`. + + +On self-hosted instances without the media processor configured, `adjust` has no effect and the file is stored as uploaded with `"status": "ready"`. + + ## Usage in a post ```json diff --git a/public-api/uploads/upload-from-url.mdx b/public-api/uploads/upload-from-url.mdx index 9216938a..7f45bdab 100644 --- a/public-api/uploads/upload-from-url.mdx +++ b/public-api/uploads/upload-from-url.mdx @@ -23,6 +23,8 @@ curl -X POST "https://api.postiz.com/public/v1/upload-from-url" \ Response shape matches [Upload File](/public-api/uploads/upload-file). +Add `"adjust": true` to the body to adjust the file to the platforms' limits after the upload. It works the same as on [Upload File](/public-api/uploads/upload-file#adjusting-media-to-platform-limits). + ## When to prefer multipart upload If your source URLs are slow or unreliable, the round-trip through Postiz can fail or take a long time. For best results: From 9014a0848c36e2d51b7b58bef28eec958be0dd4b Mon Sep 17 00:00:00 2001 From: Gilad Resisi Date: Tue, 20 Oct 2026 13:41:53 +0700 Subject: [PATCH 2/3] docs: wait for ready before publishing adjusted media A post published while an adjusted upload is still processing uses the original file, so the path is not usable right away with adjust. Co-Authored-By: Claude Opus 5.5 --- cli/media-upload.mdx | 2 +- mcp/tools.mdx | 4 ++-- public-api/uploads/media-status.mdx | 2 +- public-api/uploads/upload-file.mdx | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cli/media-upload.mdx b/cli/media-upload.mdx index c876454a..9859e86f 100644 --- a/cli/media-upload.mdx +++ b/cli/media-upload.mdx @@ -34,7 +34,7 @@ postiz upload video.mp4 --adjust postiz media:status ``` -The returned `path` is usable right away, and the adjusted file replaces the original at the same `path` when it's done. A post published before that uses the original. Poll `media:status` only while the status is `processing`. If the adjustment fails, the original file is kept and used for publishing, and the status is `ready` with a `warning`. +The status is `processing` until the adjusted file replaces the original at the same `path`, usually within seconds. Poll `media:status` and wait until it is `ready` before publishing a post with this `path`: a post published while it is `processing` uses the original, unadjusted file. If the adjustment fails, the original file is kept and used for publishing, and the status is `ready` with a `warning`. ## Upload and Post Workflow diff --git a/mcp/tools.mdx b/mcp/tools.mdx index f1884634..0c3a1b55 100644 --- a/mcp/tools.mdx +++ b/mcp/tools.mdx @@ -272,10 +272,10 @@ Upload a remote image or video into the media library from a public http(s) URL. | Field | Type | Description | |-------|------|-------------| | `id` | string | Media ID | -| `path` | string | URL of the uploaded file, usable as an attachment right away | +| `path` | string | URL of the uploaded file, to use as an attachment | | `status` | string | `ready`, or `processing` while an upload with `adjust` is being adjusted | -With `adjust`, the adjusted file replaces the original at the same `path` when it's done, and a post published before that uses the original. Use `mediaStatusTool` to know when it's in place. +With `adjust`, the status is `processing` until the adjusted file replaces the original at the same `path`, usually within seconds. Wait until `mediaStatusTool` returns `ready` before publishing a post with this `path`: a post published while it is `processing` uses the original, unadjusted file. Without `adjust` the `path` is ready immediately. --- diff --git a/public-api/uploads/media-status.mdx b/public-api/uploads/media-status.mdx index cb1942ba..cba00aca 100644 --- a/public-api/uploads/media-status.mdx +++ b/public-api/uploads/media-status.mdx @@ -27,7 +27,7 @@ Response: | Status | Meaning | |---|---| -| `processing` | The adjustment is still running. The `path` is already usable, a post published now uses the original file. Call again in a few seconds. | +| `processing` | The adjustment is still running. Don't publish a post with this `path` yet, it would use the original file. Call again in a few seconds. | | `ready` | The adjusted file is in place at the same `path`. | | `ready` with a `warning` | The adjustment failed. The original file was kept at the same `path` and is used for publishing. | diff --git a/public-api/uploads/upload-file.mdx b/public-api/uploads/upload-file.mdx index 29af4c6d..359a9639 100644 --- a/public-api/uploads/upload-file.mdx +++ b/public-api/uploads/upload-file.mdx @@ -56,7 +56,7 @@ curl -X POST "https://api.postiz.com/public/v1/upload" \ -F "file=@video.mp4" ``` -The adjustment runs in the background, so the response comes back with `"status": "processing"`. The `path` is usable right away: the adjusted file replaces the original at the same `path` when it's done, and a post published before that uses the original. If you need to know when the adjusted file is in place, poll [Media Status](/public-api/uploads/media-status) every few seconds until the status is no longer `processing`. Without `adjust` the upload is synchronous and there is nothing to poll. +The adjustment runs in the background, so the response comes back with `"status": "processing"`. The adjusted file replaces the original at the same `path`, usually within seconds. Poll [Media Status](/public-api/uploads/media-status) every few seconds and wait until the status is `ready` before publishing a post with this `path`: a post published while it is `processing` uses the original, unadjusted file. Without `adjust` the upload is synchronous and the `path` is ready immediately. If the adjustment fails, the original file is kept and used for publishing, and Media Status returns `"status": "ready"` with a `warning`. From af7c5a0398f5cd7a3989f1a35c0e334c421b8654 Mon Sep 17 00:00:00 2001 From: Gilad Resisi Date: Tue, 20 Oct 2026 13:59:03 +0700 Subject: [PATCH 3/3] docs: clarify ready status and document mediaStatusTool error Co-Authored-By: Claude Opus 5.5 --- mcp/tools.mdx | 3 ++- public-api/uploads/media-status.mdx | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mcp/tools.mdx b/mcp/tools.mdx index 0c3a1b55..9d88c64b 100644 --- a/mcp/tools.mdx +++ b/mcp/tools.mdx @@ -295,8 +295,9 @@ Check whether a media uploaded with `adjust` set to true finished adjusting, usi |-------|------|-------------| | `id` | string | Media ID | | `path` | string | URL of the file | -| `status` | string | `processing` while the adjustment runs, `ready` once the adjusted file is in place | +| `status` | string | `processing` while the adjustment runs, `ready` once the file is ready to publish: adjusted, or unchanged when it was already within the limits or its format isn't adjusted | | `warning` | string | Present with `ready` when the adjustment failed: the original file was kept and is used for publishing | +| `error` | string | Returned instead of the fields above when the lookup failed, e.g. an unknown `id` | --- diff --git a/public-api/uploads/media-status.mdx b/public-api/uploads/media-status.mdx index cba00aca..e37eac62 100644 --- a/public-api/uploads/media-status.mdx +++ b/public-api/uploads/media-status.mdx @@ -28,7 +28,7 @@ Response: | Status | Meaning | |---|---| | `processing` | The adjustment is still running. Don't publish a post with this `path` yet, it would use the original file. Call again in a few seconds. | -| `ready` | The adjusted file is in place at the same `path`. | +| `ready` | The file is ready to publish at the same `path`: adjusted, or unchanged when it was already within the limits or its format isn't adjusted. | | `ready` with a `warning` | The adjustment failed. The original file was kept at the same `path` and is used for publishing. | An unknown `id`, or one from another organization, returns `404`.