Media Upload
Upload local files or mirror a public URL into the OpenQuok media library, then reference the returned id and path in `posts:create`.
Connect your agent today
Draft from chat, review in your calendar, and publish only what you approve.
Overview
The upload and upload-from-url commands wrap the Uploads APIs:
- upload — multipart upload of a local file.
- upload-from-url — instructs the backend to fetch a public http(s) URL and store it.
Both return the same JSON envelope so downstream code (especially posts:create -m) is identical regardless of the source.
Why uploads ?
Instagram, Threads, TikTok, YouTube and etc require the asset to live on a verified URL. External links — even https:// — are rejected at publish time. Upload first, then pass the returned data.id and data.filePath to posts:create.
Upload a local file
openquok upload ./image.png
openquok upload /tmp/clip.mp4 | Argument | Description |
|---|---|
| <filePath> (positional) | Local path to the media file (image, video, audio, PDF, …). |
Response shape
{
"success": true,
"data": {
"id": "1a2b3c4d-5e6f-7081-9192-a3b4c5d6e7f8",
"filePath": "uploads/2026/05/hero.png",
"originalName": "hero.png",
"publicUrl": "https://cdn.openquok.example/uploads/2026/05/hero.png"
},
"message": "Media uploaded successfully"
} data.publicUrl is only present when the workspace's storage provider exposes a public URL. The pair you need for posts:create is data.id + data.filePath. Pass that filePath as media[].path — there is no data.path on the upload response.
Upload from a public URL
openquok upload-from-url "https://cdn.example.com/banner.png"
openquok upload-from-url "https://cdn.example.com/clip.mp4" The backend fetches the URL server-side, derives the MIME type from the response Content-Type (or the URL extension when the header is generic), and stores the bytes in the same media bucket as openquok upload. The response shape is identical, so any script that consumes upload works unchanged against upload-from-url.
Only http(s)
The backend validates the URL up front and rejects any scheme other than http: / https:. Authentication, redirects, and request bodies are not supported — host the asset on a publicly reachable URL or use openquok upload for files behind auth.
Upload-and-post workflow
RESULT=$(openquok upload ./photo.jpg)
MEDIA_ID=$(echo "$RESULT" | jq -r '.data.id')
MEDIA_PATH=$(echo "$RESULT" | jq -r '.data.filePath')
openquok posts:create
-s "2026-01-15T10:00:00Z"
-t schedule
-c "Check out this photo!"
-i "<integration-id>"
-m "[{"id":"${MEDIA_ID}","path":"${MEDIA_PATH}"}]" Or, more compactly, build the media JSON in one jq step:
MEDIA=$(openquok upload ./photo.jpg | jq -c '[{id: .data.id, path: .data.filePath}]')
openquok posts:create
-s "2026-01-15T10:00:00Z"
-t schedule
-c "Check out this photo!"
-i "<integration-id>"
-m "$MEDIA" Supported file types
Large videos
openquok upload posts small files through POST /public/upload. On OpenQuok Cloud that inbound path is about 4.5 MB. For larger files the CLI automatically uses direct-to-storage multipart (create-multipart → PUT parts → complete-multipart). Prefer the CLI (or the Node SDK) over raw curl for TikTok / Reels / YouTube clips. Application video cap remains 1 GB.
Per-file size is capped by MAX_MEDIA_UPLOAD_BYTES on the backend (1 GB for video). The hosted simple-upload gateway is lower — see the callout above.