Uploads

Upload media files (images and videos) to use in your posts. Media must be uploaded before creating a post.

Supported Formats

TypeFormatsMax Size
Imagesimage/jpeg, image/png25 MB
Videosvideo/mp4, video/quicktime (MOV)500 MB

Each platform has additional size and format constraints. For example, Instagram images max at 8 MB and TikTok images max at 5 MB. These are validated when you create a post, not at upload time. See the Platform Settings pages for full details.

Security: Uploaded files are validated by sniffing the actual bytes (not the client-supplied Content-Type). Polyglot files / MIME-spoofed payloads are rejected. The detected MIME type is what gets stored. Never the client's claim.

Upload File

Upload a media file directly via multipart form data. Returns a media object with an id you can reference when creating posts.

POST/v1/uploadUpload a media file

Request Body (multipart/form-data)

ParameterTypeDescription
filebinaryThe media file to upload (image or video)
thumbnailbinaryOptional poster image (JPEG/PNG, max 10 MB) for a video. Used as the dashboard preview tile. Ignored for images.

Headers

ParameterTypeDescription
X-Workspace-IdstringRequired when using an all-scope API key. The workspace this media belongs to.
Example: Upload an image
curl -X POST https://api.quegly.com/v1/upload \
  -H "Authorization: qgl_your_api_key" \
  -F "file=@/path/to/room-photo.jpg"
Example: Upload a video
curl -X POST https://api.quegly.com/v1/upload \
  -H "Authorization: qgl_your_api_key" \
  -F "file=@/path/to/video.mp4"

Response

201 Created. MediaFile object
{
  "id": "e639003b-f727-4a1e-87bd-74a2c48ae41e",
  "filename": "room-photo.jpg",
  "url": "https://media.quegly.com/workspace-123/room-photo.jpg",
  "media_type": "image",
  "file_size": 2048576,
  "thumbnail_url": null,
  "width": null,
  "height": null,
  "created_at": "2026-05-15T12:00:00.000Z"
}

Response Fields

ParameterTypeDescription
idstringUnique media file ID. Use this in the media_ids array when creating posts.
filenamestringOriginal filename
urlstringDirect URL to the uploaded file
media_typestring"image" or "video"
file_sizenumberFile size in bytes
thumbnail_urlstring | nullVideo poster image URL (from an uploaded thumbnail or auto-generation). null for images and for videos with no poster.
widthnumberWidth in pixels (may be null at upload time)
heightnumberHeight in pixels (may be null at upload time)
created_atstringISO 8601 timestamp

Video thumbnails: the dashboard generates a poster frame in the browser before upload, which a server can't do. So for video uploaded via the API, either send a thumbnail image with the request (reliable, matches the dashboard), or, if the workspace has Cloudflare Media Transformations enabled, a poster is generated automatically from the first frame. Otherwise thumbnail_url is null and the tile is blank until played. Cosmetic only. Publishing is unaffected.

Upload from URL

Upload a media file by providing a publicly accessible URL. Quegly downloads the file server-side via an SSRF-safe fetcher (private IPs / loopback / non-http schemes are rejected) and stores it. Useful for AI agents that produce URLs but not bytes (e.g. OpenAI image generation).

POST/v1/upload-from-urlUpload a file from a URL

Request Body (JSON)

ParameterTypeDescription
urlstringPublicly accessible URL of the media file to download
filenamestringOptional filename. If not provided, extracted from the URL.
Example: Upload an AI-generated image from URL
curl -X POST https://api.quegly.com/v1/upload-from-url \
  -H "Authorization: qgl_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://oaidalleapiprodscus.blob.core.windows.net/generated-image.png",
    "filename": "ai-room-design.png"
  }'

Response

Returns the same MediaFile object as the Upload File endpoint.

The URL must be publicly accessible (no authentication required). Pre-signed URLs from S3 / R2 / OpenAI work well. The fetcher rejects non-http(s) schemes, embedded credentials, and private/loopback IPs to prevent SSRF abuse.

Update Video Thumbnail

Set or replace the poster image of an already-uploaded video. {id} is the media ID returned by the Upload endpoints. The thumbnail becomes the cover used on Instagram and YouTube (TikTok picks its own), and the preview tile in the dashboard. Any post referencing this media that is still scheduled or incomplete gets the new cover too; already-published posts keep the cover they went out with.

POST/v1/media/{id}/thumbnailSet or replace a video's thumbnail

Request Body (multipart/form-data)

ParameterTypeDescription
thumbnailbinaryJPEG or PNG poster image, max 5 MB

Or a link (application/json)

ParameterTypeDescription
urlstringA public link to a JPEG or PNG, max 5 MB. Downloaded the same SSRF-safe way as Upload from URL; the bytes decide its type. This is how AI agents and the MCP server set a cover.
Example: Replace a video's cover
curl -X POST https://api.quegly.com/v1/media/MEDIA_ID/thumbnail \
  -H "Authorization: qgl_your_api_key" \
  -F "thumbnail=@/path/to/poster.jpg"
Example: Set a cover from a link
curl -X POST https://api.quegly.com/v1/media/MEDIA_ID/thumbnail \
  -H "Authorization: qgl_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://example.com/poster.jpg" }'

Response

200 OK
{
  "id": "e639003b-f727-4a1e-87bd-74a2c48ae41e",
  "thumbnail_url": "https://media.quegly.com/thumbnails/...jpg",
  "posts_updated": 2
}

Response Fields

ParameterTypeDescription
idstringThe media file ID
thumbnail_urlstringPublic URL of the new thumbnail
posts_updatednumberHow many still-pending (scheduled/draft) posts had their cover refreshed
DELETE/v1/media/{id}/thumbnailRemove a video's thumbnail

Removes the poster and clears it from still-pending posts. Idempotent: deleting a thumbnail that isn't there returns success. Constraints for both endpoints: videos only (images are their own preview), the media file must still exist in storage, and the per-key upload rate limit applies to the POST.

Media Lifecycle

Uploaded media files are stored in object storage until the post is published. After successful publishing, files are cleaned up to keep storage costs predictable. The media metadata and IDs remain in the system for analytics and history.

StageMedia Status
UploadedFile stored, ready to attach to posts
Attached to postReferenced by a post's media_ids
Post publishedFile delivered to platforms, then cleaned up from storage
Post failedFile retained for retry attempts