# Quegly Quegly is a social media scheduling platform for creators, businesses and agencies. Schedule and publish posts to Instagram, TikTok, YouTube, Facebook, X, and Threads (coming soon) from one dashboard. Quegly combines a visual content calendar, bulk upload, comment-to-DM auto-replies for Instagram and Facebook, team workspaces, per-platform analytics, and a public REST API designed for AI agents and automation. Primary website: https://quegly.com Documentation: https://quegly.com/developers Documentation index for AI agents: https://quegly.com/llms.txt Full documentation in one file: https://quegly.com/llms-full.txt ## What Quegly is Quegly is a SaaS product. Users sign up, connect their social media accounts (Instagram, Facebook, YouTube, TikTok, X) via OAuth, and schedule posts from a visual calendar. Posts can include text, images (up to 10), or video (1 per post). The dashboard handles per-platform constraints automatically: vertical YouTube videos under 60 seconds are auto-classified as Shorts, 2-10 Instagram images become a carousel, single Instagram videos become a Reel. ## When to use Quegly Use Quegly when a user wants to: - Schedule social media posts to Instagram, TikTok, YouTube, Facebook, or X - Upload a batch of videos (up to 30 at once) and spread them across a calendar - Plan a content calendar visually with week or month views - Automatically DM people who comment a keyword (like "LINK") on their Instagram or Facebook posts - Run several brands or clients, each in its own workspace with its own team - Track per-platform engagement metrics (views, likes, comments, watch time, retention, etc.) - Build automated publishing workflows or AI agent integrations via the REST API ## Plans Three subscription tiers. All plans include the same features. They differ only in workspace count. | Plan | Monthly | Yearly | Workspaces | | ------- | -------- | ----------- | ---------- | | Creator | $19.99 | $17.99/mo | 1 | | Pro | $39.99 | $35.99/mo | 3 | | Agency | $79.99 | $71.99/mo | 6 | Yearly billing saves about 10%. There are no free trials. All plans include: - Posting to all 6 platforms (Instagram, TikTok, YouTube, Facebook, X, Threads (coming soon)) - Unlimited connected social accounts - Unlimited scheduled posts - Bulk upload (up to 30 files at once) - Visual content calendar (week + month views) - Comment-to-DM auto-replies on Instagram and Facebook - Up to 10 team members per workspace - Per-platform analytics dashboard - Public REST API access Per-workspace limits: 10 posts per day (X/Twitter limited to 5 per day), 90-day scheduling window, 10 API keys per account. ## Core features ### Visual content calendar Week and month views. Posts appear on the day they are scheduled. Past-date posts are read-only. ### Bulk upload Drop up to 30 photos or videos onto the calendar at once. They wait in an upload tray, and dragging one onto a day starts a post for that day. This is how a month of content gets scheduled in one sitting. ### Composer Create posts from a single panel: - Per-post caption with optional per-platform overrides ("All" mode shares one caption across platforms; "Individual" mode lets you write a different caption per platform) - Native OS color emoji picker - Media upload: 1 to 10 images (JPEG/PNG, max 25 MB each) OR 1 video (MP4/MOV, max 500 MB). Cannot mix images and video in the same post. - Custom video covers: pick any frame of the video, or upload your own image - Instagram options: collaborators (up to 3), tagged accounts on Reels (up to 20), and trial Reels (shown to non-followers first, then shared with followers by hand or automatically if they perform well) - Facebook Reel collaborators (other Pages, up to 10), YouTube title and privacy, TikTok privacy, interaction and disclosure settings, X media tags, Threads topic tags - Three publishing modes: schedule (future), post now (immediate), draft (no schedule) - Per-platform constraints validated upfront (YouTube needs a video; TikTok Photo Mode needs 2+ images; X is capped at 4 images; etc.) ### Comment-to-DM auto-replies (Instagram and Facebook) When someone comments on a post, Quegly can send them a private DM automatically: the "comment LINK and I'll send you the link" flow. - Set up per connected account in the dashboard, in the Instagram Reply and Facebook Reply tabs. The settings cover every post that account published through Quegly. Posts published elsewhere are not answered. - Triggers: an exact keyword (the whole comment is the word, like LINK), a keyword anywhere in the comment as a whole word, or every comment. Keywords are not case-sensitive. - The DM: write several versions and Quegly picks one at random for each person, so replies don't all read the same. - Optional public reply under the comment (for example "Check your DMs!"), with its own rotating versions. It can be turned off. - Meta's rules apply: one private reply per comment, sent within 7 days of the comment, and only to people (a Facebook Page that comments can't be messaged). - Configured in the dashboard only; the public API does not expose auto-reply settings. ### Workspaces and teams (multi-tenancy) Each workspace owns its own social accounts, posts, media, and integrations. Workspaces are slug-based: `https://quegly.com//...`. Plans include 1, 3, or 6 workspaces (Creator/Pro/Agency). Invite up to 10 team members per workspace by email; they work in the workspace without anyone sharing social media passwords. Archived workspaces have a 30-day lifecycle before deletion. ### Per-platform engagement analytics Per-post metrics for each platform a post was published to. Backed by a 1-hour read-through cache and a 30-day refresh window. Posts older than 30 days keep their last captured snapshot. Available metrics by platform: - **Instagram**: views, reach, likes, comments, saved, shares, total_interactions, watch_time_seconds (Reels), avg_view_duration_seconds (Reels) - **Facebook**: views, likes, reactions, comments, shares, post_clicks - **YouTube**: views, likes, comments, favorites, shares, watch_time_seconds, avg_view_duration_seconds, avg_view_percentage, subscribers_gained, subscribers_lost - **TikTok**: views, likes, comments, shares - **X**: views, impressions, likes, comments, retweets, quotes, bookmarks, url_link_clicks (30-day window only), user_profile_clicks (30-day window only) - **Threads**: views, likes, comments (replies), reposts, quotes, shares ### Public REST API (v1) Programmatic access to scheduling, uploads, accounts, workspaces, and analytics: - `GET /v1/workspaces`. List the workspaces the key can act on (discovery for all-scope keys) - `POST /v1/posts`. Create and schedule a post (single call fans out to multiple platforms via account_ids) - `GET /v1/posts`. List posts in a date range - `GET /v1/posts/{id}`. Get a single post - `PUT /v1/posts/{id}`. Update a scheduled post - `DELETE /v1/posts/{id}`. Delete a scheduled post - `POST /v1/posts/{id}/publish-now`. Publish immediately - `POST /v1/upload`. Upload media file (multipart; videos accept an optional `thumbnail` field) - `POST /v1/upload-from-url`. Upload media from a public URL - `POST /v1/media/{id}/thumbnail`. Set/replace a video's poster image (multipart `thumbnail`, JPEG/PNG <=5MB). Also refreshes the cover on posts still scheduled/incomplete (response includes `posts_updated`). Videos only. - `DELETE /v1/media/{id}/thumbnail`. Remove a video's poster image (idempotent) - `GET /v1/accounts`. List connected social accounts in the workspace - `GET /v1/analytics/post/{id}`. Get post analytics Authentication: Bearer token (`qgl_` prefix), passed via the `Authorization` header. Both bare (`qgl_xxx`) and `Bearer qgl_xxx` forms accepted. API key scopes: - **workspace**. Bound to one workspace at creation. Workspace is implicit on every request. - **all**. Authorizes any workspace owned by the user. Pass `X-Workspace-Id: ` header on every request to specify which workspace. Rate limits (per API key, per minute): - Creator: 60 req/min - Pro: 120 req/min - Agency: 300 req/min `Idempotency-Key` header on `POST /v1/posts` prevents duplicate creation on retries (max 255 chars). Replays in a different workspace return 409. API keys are generated at https://quegly.com/settings/api. Full API documentation at https://quegly.com/developers. ## Supported platforms Every platform also accepts a per-platform `caption` under `platform_settings.`, overriding the post's shared caption. | Platform | What gets posted | Configurable settings (`platform_settings.`) | | ------------ | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | Instagram | Feed, carousels (2-10 images), Reels | collaborators (usernames, up to 3), user_tags (usernames, up to 20, Reels only), trial_reel, trial_graduation_strategy (MANUAL or SS_PERFORMANCE) | | Facebook | Text, images, video; published to Page | collaborator_page_ids (numeric Page IDs, up to 10; single vertical video only, published as a Reel) | | YouTube | Videos; vertical < 60s = Shorts | title, youtube_privacy_status, collaborator_handles (saved as a reminder; YouTube's API can't add collaborators) | | TikTok | Video or Photo Mode (2-35 images) | privacy_level, draft_mode, allow_comment, allow_duet, allow_stitch, brand_organic, brand_content, commercial_content, auto_add_music | | X (Twitter) | Text, images (1-4), video (1) | tagged_user_ids (numeric user IDs, up to 10; posts with media only) | | Threads (coming soon) | Text, images, video, mixed carousels (1-10) | topic_tag | Per-platform deep dives: - https://quegly.com/developers/platforms/instagram - https://quegly.com/developers/platforms/facebook - https://quegly.com/developers/platforms/youtube - https://quegly.com/developers/platforms/tiktok - https://quegly.com/developers/platforms/x - https://quegly.com/developers/platforms/threads ## Languages Quegly's UI is available in 12 languages: English, Spanish, French, German, Italian, Portuguese, Russian, Chinese, Korean, Arabic, Polish, Turkish. ## Authentication (sign-in) Two sign-in methods: - Magic link (email) - Google OAuth Sign in at https://quegly.com/. ## Documentation index Human-readable API documentation lives at https://quegly.com/developers. Each docs page has a "Copy page" menu: copy the page as Markdown, view it as Markdown, or open it in ChatGPT or Claude. Every page's Markdown, in order, is also served as one file at https://quegly.com/llms-full.txt. Documentation pages: - https://quegly.com/developers. API introduction (auth, scopes, rate limits, errors) - https://quegly.com/developers/workspaces. List workspaces (discovery for all-scope keys) - https://quegly.com/developers/posts. Post create/list/update/delete/publish-now - https://quegly.com/developers/uploads. Media upload (file + URL) - https://quegly.com/developers/accounts. List connected accounts - https://quegly.com/developers/analytics. Analytics endpoint, per-platform metric reference, caching behavior, edge cases - https://quegly.com/developers/platforms. Platform settings overview + media constraints summary - https://quegly.com/developers/platforms/instagram - https://quegly.com/developers/platforms/facebook - https://quegly.com/developers/platforms/youtube - https://quegly.com/developers/platforms/tiktok - https://quegly.com/developers/platforms/x - https://quegly.com/developers/platforms/threads ## Agent guidance When helping a user with Quegly, follow these rules: 1. **Prefer the dashboard for content tasks.** The visual calendar at https://quegly.com// is the primary surface. The API is for integrations and automation, not day-to-day scheduling. If the user is asking how to "schedule a post," send them to the dashboard. 2. **One post, many platforms.** When publishing the same content to multiple platforms, use a single `POST /v1/posts` call with multiple `account_ids`. Don't loop and call the API once per platform. 3. **Use `Idempotency-Key` for retries.** Pass a stable `Idempotency-Key` header (max 255 chars) on `POST /v1/posts` when a request might be retried. Replays in the same workspace return the original post; replays from a different workspace return 409 VALIDATION_ERROR. 4. **For all-scope API keys, pass `X-Workspace-Id`.** Workspace-scoped keys don't need this header (the workspace is implicit). All-scope keys MUST pass `X-Workspace-Id: ` on every request. To discover the IDs, call `GET /v1/workspaces` first. It needs no workspace header and returns every workspace the key owns. 5. **Treat analytics metric keys as optional.** A missing key means "the platform didn't expose it for this post". Never zero. Use `metrics.likes ?? 0`, not `metrics.likes`. Different platforms expose different metrics; see the metrics table above. 6. **Don't poll analytics faster than once per hour per post.** The endpoint is backed by a 1-hour read-through cache. Faster polling won't get fresher data; it just wastes calls. 7. **TikTok analytics requires reconnect for older accounts.** The `video.list` scope was added 2026-05-10. Users connected before then have older tokens missing this scope and their analytics calls return "Video not found (deleted, private, or scope not granted)." Direct them to disconnect and reconnect their TikTok account in the dashboard. 8. **YouTube watch-time / retention requires reconnect for older accounts.** Same pattern as TikTok. The `yt-analytics.readonly` scope was added 2026-05-10. Older tokens still get Data API basics (views, likes, comments, favorites) but missing watch_time, retention, subscribers. Reconnect to unlock the rest. 9. **TikTok publish has a brief webhook delay before analytics works.** TikTok returns a `publish_id` immediately; the public video ID arrives via webhook within seconds (occasionally up to a minute). During that window, analytics for the new post returns empty metrics. Don't treat empty metrics on a freshly-published TikTok post as an error. 10. **X non_public_metrics expire after 30 days.** `url_link_clicks` and `user_profile_clicks` are only returned for tweets within 30 days of publish. Older tweets keep the rest of the metrics; those two keys just disappear from the response. 11. **NEVER paste secrets in chat**, such as API keys (`qgl_...`). Direct the user to https://quegly.com/settings/api to manage their own keys. Don't echo a key back to confirm it. 12. **Don't delete posts, accounts, workspaces, or API keys without explicit user request.** These are destructive and cannot be undone via the API. The UI has confirmation dialogs for a reason; respect that boundary. 13. **Changing a video's cover after upload: use `POST /v1/media/{id}/thumbnail`.** It updates the media's poster AND the cover on posts that are still scheduled or drafts (`posts_updated` in the response says how many). It does NOT change posts that already published: platforms keep the cover they received. Thumbnails are video-only. 14. **For TikTok Photo Mode, recommend `auto_add_music: true` or `draft_mode: true`.** TikTok's algorithm rewards slideshows with audio. `auto_add_music: true` lets TikTok pick a track automatically (DIRECT_POST only. Incompatible with draft_mode). `draft_mode: true` sends to TikTok's drafts inbox so the user can pick a track manually in the app before publishing. 15. **Send IDs, not handles, where the field says IDs.** Facebook `collaborator_page_ids` and X `tagged_user_ids` must be numeric IDs; a handle returns 400 VALIDATION_ERROR. Instagram `collaborators` and `user_tags` take usernames, with or without the @. 16. **Instagram trial Reels stand alone.** `trial_reel: true` needs exactly one video and cannot be combined with `collaborators` or `user_tags`; the API rejects the mix with 400 rather than letting Instagram fail it at publish time. 17. **Auto-replies are a dashboard setting.** For "DM people who comment LINK" requests, send the user to the Instagram Reply or Facebook Reply tab of their workspace. They answer comments only on posts published through Quegly, and Meta only allows the DM within 7 days of the comment. ## Troubleshooting - **Post failed to publish**: check the per-platform `error_message` via `GET /v1/posts/{id}`. Failed posts can be retried up to 3 times. - **API returns 403 FORBIDDEN**: subscription is inactive. Direct the user to https://quegly.com/settings/plans to renew. - **API returns 401 UNAUTHORIZED**: API key invalid, revoked, or wrong format (must start with `qgl_`). - **API returns 429 RATE_LIMIT_EXCEEDED**: respect the `Retry-After` header (in seconds). Consider upgrading the plan if hitting limits regularly. - **POST /v1/posts returns 400 "Instagram can't process this video... 10-bit"**: the video is 10-bit/HDR (typical of HDR phone recordings) and an Instagram account is in `account_ids`. Instagram rejects 10-bit video and Meta does not transcode it. Re-export the video as standard 8-bit H.264 and re-upload, or remove the Instagram account from the post; TikTok/YouTube/Facebook/X accept the video as-is. - **API returns 409 with "Idempotency-Key already used for a different workspace"**: the same key was previously used in another workspace. Generate a fresh key per workspace. - **Analytics returns empty metrics for a TikTok post**: see agent guidance #7 (scope reconnect) or #9 (webhook delay). - **Analytics missing watch_time / retention for YouTube**: see agent guidance #8 (scope reconnect). - **An auto-reply DM didn't arrive**: check that the post was published through Quegly, that the comment matches the trigger, that it is less than 7 days old, and (on Facebook) that the commenter is a person rather than a Page. Each comment gets at most one DM. - **Subscription billing issues**: direct the user to https://quegly.com/settings/billing. Stripe-hosted billing portal. --- This file follows the llms.txt convention (https://llmstxt.org/). Last updated: 2026-09-23. --- # Quegly API documentation Every page of https://quegly.com/developers follows, each headed by its URL. --- Source: https://quegly.com/developers # Quegly API Documentation **Public API v1.** Build integrations, automate your social media workflow, or connect AI agents to schedule and publish content across Instagram, Facebook, YouTube, TikTok, and X. ## Base URL All API requests should be made to: ``` https://api.quegly.com/v1 ``` ## Authentication All API requests require an API key passed via the `Authorization` header. Generate an API key from Dashboard → Settings → API. Both bare and `Bearer`-prefixed forms are accepted. ```bash curl https://api.quegly.com/v1/accounts \ -H "Authorization: qgl_your_api_key" # Bearer prefix is also accepted: curl https://api.quegly.com/v1/accounts \ -H "Authorization: Bearer qgl_your_api_key" ``` **Keep your API key secret.** Keys are SHA-256 hashed at rest, so a leaked key cannot be recovered. If you suspect a key has been exposed, revoke it from Settings → API and generate a fresh one. ## API Key Scopes Each API key has a scope that controls which workspaces it can act on. - **workspace**. Tied to one workspace at creation time. Every request acts on that workspace automatically. - **all**. Authorizes any workspace you own. Each request must specify which workspace via the `X-Workspace-Id` header (or `?workspace_id=` query param). ```bash # all-scope key targeting a specific workspace curl https://api.quegly.com/v1/accounts \ -H "Authorization: qgl_your_all_scope_key" \ -H "X-Workspace-Id: workspace-uuid" ``` Don't know your workspace IDs? Call `GET /v1/workspaces` to list them, then use the `id` you want as `X-Workspace-Id`. You can generate up to 10 keys per account, with multiple keys per scope. Useful for rotating keys without downtime, or scoping integrations (one key for Zapier, one for n8n, etc.). ## Rate Limits The API uses a token-bucket limiter. Each key has its own budget. Keys on the same account don't share counters. Limits scale with your plan: | Plan | Requests / minute | Effective rate | | --- | --- | --- | | Creator | 60 | 1 req/sec average, bursts up to 60 | | Pro | 120 | 2 req/sec average, bursts up to 120 | | Agency | 300 | 5 req/sec average, bursts up to 300 | Additional scheduling caps: 10 posts per day per workspace (X/Twitter is limited to 5 per day, as the X API is metered), and posts can be scheduled up to 90 days in advance. Rate-limit headers on every response: | Header | Description | | --- | --- | | `X-RateLimit-Limit` | Maximum requests per minute for your tier | | `X-RateLimit-Remaining` | Tokens left in your bucket after this request | | `X-RateLimit-Reset` | Seconds until the bucket is fully refilled | | `Retry-After` | Only on 429. Seconds to wait before retrying. | ## Supported Platforms Quegly supports posting to Instagram, Facebook, YouTube, TikTok, and X. Each platform has its own constraints and optional settings. See the per-platform Platform Settings pages. ## Terminology - **Workspace**. An organizational unit containing social accounts, posts, and media. The scope of an API key is either one workspace ("workspace") or any of your workspaces ("all"). - **Account**. A connected social media account. The dashboard calls these "connected accounts." - **Post**. A scheduled or published piece of content. A single post can target multiple accounts/platforms simultaneously. - **Platform**. One of the 5 supported social networks: instagram, facebook, youtube, tiktok, x. - **Media**. An uploaded image or video file. Must be uploaded before being attached to a post. ## Quick Start ### Step 1: Upload your media ```bash curl -X POST https://api.quegly.com/v1/upload \ -H "Authorization: qgl_your_api_key" \ -F "file=@/path/to/image.jpg" ``` ### Step 2: Create a scheduled post ```bash curl -X POST https://api.quegly.com/v1/posts \ -H "Authorization: qgl_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "type": "schedule", "scheduled_at": "2026-06-01T14:00:00.000Z", "caption": "Check out this amazing room transformation!", "media_ids": ["media-id-from-step-1"], "account_ids": ["instagram-account-id", "tiktok-account-id"], "platform_settings": { "tiktok": { "privacy_level": "PUBLIC_TO_EVERYONE", "allow_comment": true, "allow_duet": true, "allow_stitch": true } } }' ``` ## Error Handling The API uses standard HTTP status codes and returns errors as JSON. The `code` is stable and safe to pattern-match on; the `message` is human-readable and may evolve. ```json { "error": { "code": "VALIDATION_ERROR", "message": "TikTok requires a privacy_level setting", "field": "platform_settings.tiktok.privacy_level" } } ``` | Status | Code | Description | | --- | --- | --- | | 200 | , | Success | | 201 | , | Created | | 400 | VALIDATION_ERROR | Bad request. Invalid parameters or missing required fields | | 401 | UNAUTHORIZED | Invalid or missing API key | | 403 | FORBIDDEN | Subscription inactive, or key lacks the requested scope | | 404 | NOT_FOUND | Resource doesn't exist (or your key can't see it) | | 409 | VALIDATION_ERROR | Conflict. E.g. Idempotency-Key reused with a different workspace | | 429 | RATE_LIMIT_EXCEEDED | Too many requests. See Retry-After | | 500 | INTERNAL_ERROR | Bug on our side; safe to retry idempotent operations | ## Endpoints Overview ### Workspaces - `GET /v1/workspaces`. List the workspaces your key can act on ### Posts - `POST /v1/posts`. Create and schedule a post - `GET /v1/posts`. List posts by date range - `GET /v1/posts/{id}`. Get a single post - `PUT /v1/posts/{id}`. Update a scheduled post - `DELETE /v1/posts/{id}`. Delete a post - `POST /v1/posts/{id}/publish-now`. Publish immediately ### Uploads - `POST /v1/upload`. Upload a media file - `POST /v1/upload-from-url`. Upload from a URL - `POST /v1/media/{id}/thumbnail`. Set/replace a video's thumbnail - `DELETE /v1/media/{id}/thumbnail`. Remove a video's thumbnail ### Accounts - `GET /v1/accounts`. List connected accounts ### Analytics - `GET /v1/analytics/post/{id}`. Get post analytics --- Source: https://quegly.com/developers/workspaces # Workspaces List the workspaces your API key can act on. Use a workspace ID as the `X-Workspace-Id` header (or `?workspace_id=` query param) on every other endpoint when using an all-scope key. ## List Workspaces Returns the workspaces owned by the key's account. - An **all-scope** key returns every workspace you own. - A **workspace-scoped** key returns only its single bound workspace. This is the discovery endpoint: it's how an all-scope key learns the workspace IDs the other endpoints require. It does not need an `X-Workspace-Id` header itself. `GET /v1/workspaces` ### Headers This endpoint takes no workspace header. Authentication alone determines what's returned. ### Example Request ```bash curl https://api.quegly.com/v1/workspaces \ -H "Authorization: qgl_your_api_key" ``` ### Response ```json { "workspaces": [ { "id": "b3f1c2d4-5e6a-7b8c-9d0e-1f2a3b4c5d6e", "name": "Faith Hero", "slug": "faith-hero", "description": "Faith Hero app marketing", "is_archived": false, "created_at": "2026-06-01T12:00:00Z" }, { "id": "a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d", "name": "Personal", "slug": "personal", "description": null, "is_archived": false, "created_at": "2026-05-15T09:30:00Z" } ] } ``` ### Response Fields - `id` (string). Workspace UUID. Pass this as `X-Workspace-Id` on other endpoints. - `name` (string). Display name. - `slug` (string). URL slug used in the dashboard (`https://quegly.com//...`). - `description` (string | null). Optional description. - `is_archived` (boolean). When true, the workspace is read-only and rejects posting. It's still listed so its ID never silently disappears. - `created_at` (string). ISO 8601 creation timestamp. Results are ordered newest first. ## Creating workspaces Workspaces are created in the Quegly dashboard, and the count is capped by your plan (1 / 3 / 6 on Creator / Pro / Agency). The API does not create or delete workspaces. --- Source: https://quegly.com/developers/posts # Posts Create, schedule, list, update, and delete posts across your connected social media accounts. ## Create Post Create a new post and either schedule it for later, publish it immediately, or save it as a draft. A single request can target multiple platforms and accounts simultaneously. `POST /v1/posts` ### Request Body - `type` (string, required) , `schedule`, `now`, or `draft`. Determines when the post is published. - `caption` (string, required). Post caption/text. Max 2,000 characters. Platform-specific limits may apply. - `scheduled_at` (string, optional). ISO 8601 UTC datetime for scheduling. Required when type is `schedule`. - `media_ids` (string[], optional). Array of media file IDs from the Upload endpoint. - `account_ids` (string[], required). Array of connected account IDs to post to. - `platform_settings` (object, optional). Per-platform settings keyed by platform identifier. - `platform_captions` (object, optional). Per-platform caption overrides keyed by platform identifier. ### Headers - `Idempotency-Key` (string, optional). Up to 255 chars. Replaying the same key with the same workspace returns the original post instead of creating a duplicate. - `X-Workspace-Id` (string, optional). Required when using an all-scope API key. ### Idempotency-Key is scoped per (user, workspace) Replaying an `Idempotency-Key` that was already used in another workspace returns `409 VALIDATION_ERROR` with `"Idempotency-Key already used for a different workspace"`. This is intentional defense for users with multiple keys. Replays should hit the original workspace, not bleed into a different one. Generate a fresh key per workspace, or scope the key string with a workspace prefix. ### Media Rules (enforced across all platforms) - Maximum 10 images or 1 video per post (X limited to 4 images). - You cannot mix images and videos in the same post. - Images: JPEG or PNG, max 25 MB per file. - Videos: MP4 only, max 500 MB per file. - Platform-specific constraints are validated at post creation (e.g. YouTube requires exactly 1 video, TikTok Photo Mode requires 2+ images). - **Instagram + 10-bit (HDR) video is rejected at creation** with `400 VALIDATION_ERROR`. Instagram's ingestion cannot process 10-bit video (typical of HDR phone recordings) and Meta does not transcode it. Re-export the video as standard 8-bit H.264, or drop the Instagram account from `account_ids` (all other platforms accept the video as-is). Drafts are exempt until scheduled. - Maximum 10 posts per day per workspace (includes scheduled, posting, and published posts). **X (Twitter) is limited to 5 posts per day** because the X API is metered; exceeding it returns `400 VALIDATION_ERROR`. - Posts can be scheduled up to 90 days in advance. ### Example ```bash curl -X POST https://api.quegly.com/v1/posts \ -H "Authorization: qgl_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "type": "schedule", "scheduled_at": "2026-06-01T14:00:00.000Z", "caption": "Check out this amazing transformation! #design #homedecor", "media_ids": ["e639003b-f727-4a1e-87bd-74a2c48ae41e"], "account_ids": ["instagram-account-id", "tiktok-account-id"], "platform_settings": { "tiktok": { "privacy_level": "PUBLIC_TO_EVERYONE", "allow_comment": true, "allow_duet": true, "allow_stitch": true } } }' ``` ## List Posts Retrieve posts within a date range. Returns both scheduled and published posts. `GET /v1/posts` Query parameters: - `start_date` (string, required). Range start, ISO 8601 UTC. - `end_date` (string, required). Range end, ISO 8601 UTC. ## Get Post Retrieve a single post by ID, including its platform statuses, media, and any error messages. `GET /v1/posts/{id}` ## Update Post Update a scheduled post. Only posts with status `scheduled` or `incomplete` can be updated. Published posts cannot be modified. `PUT /v1/posts/{id}` All body fields are optional: `caption`, `scheduled_at`, `media_ids`, `account_ids`, `platform_settings`. ## Delete Post Delete a scheduled post. Posts whose scheduled time has already passed cannot be deleted via the API. `DELETE /v1/posts/{id}` ## Publish Now Immediately publish a scheduled post, bypassing its scheduled time. Idempotent: if the post is already posted/partial, the current state is returned. `POST /v1/posts/{id}/publish-now` Publishing is asynchronous. The response confirms the publish was triggered. Poll Get Post for the final per-platform status. ## Post Statuses - `incomplete`. Post is being created, missing required fields. - `scheduled`. Complete and queued for publishing at the scheduled time. - `posting`. Currently being published to platforms. - `posted`. Successfully published to all target platforms. - `partial`. Published to some platforms but failed on others. - `failed`. Failed to publish on all platforms. --- Source: https://quegly.com/developers/uploads # Uploads Upload media files (images and videos) to use in your posts. Media must be uploaded before creating a post. ## Supported Formats | Type | Formats | Max Size | | --- | --- | --- | | Images | image/jpeg, image/png | 25 MB | | Videos | video/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. **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 `POST /v1/upload` Upload a media file directly via multipart form data. Returns a media object with an `id` you can reference when creating posts. ### Request Body (multipart/form-data) - `file` (binary, required). The media file to upload (image or video). - `thumbnail` (binary, optional). A poster image (JPEG or PNG, max 10 MB) for a **video** upload. Used as the dashboard preview tile. Ignored for image uploads. See "Video thumbnails" below. ### Headers - `X-Workspace-Id` (string, optional). Required when using an all-scope API key. ### Example ```bash curl -X POST https://api.quegly.com/v1/upload \ -H "Authorization: qgl_your_api_key" \ -F "file=@/path/to/room-photo.jpg" ``` ```bash # Video with an explicit poster frame: curl -X POST https://api.quegly.com/v1/upload \ -H "Authorization: qgl_your_api_key" \ -F "file=@/path/to/video.mp4" \ -F "thumbnail=@/path/to/poster.jpg" ``` ### Response ```json { "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" } ``` ### Video thumbnails Browser uploads generate a poster frame automatically (the page grabs a frame with a canvas before uploading). A server can't run that browser-only trick, so for video uploaded through the API the poster comes from one of two places: 1. **You send one.** Pass a `thumbnail` image alongside the video. It's stored and returned as `thumbnail_url`. This is the reliable option and matches how the dashboard works. 2. **Automatic.** If the workspace has Cloudflare Media Transformations enabled, a poster is generated server-side from the video's first frame when you don't send one. No extra work for the caller. If neither applies, `thumbnail_url` is `null` and the dashboard shows a blank tile until the video is played once. This is cosmetic only. Publishing to platforms is unaffected. ## Upload from URL `POST /v1/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). ### Request Body (JSON) - `url` (string, required). Publicly accessible URL of the media file to download. - `filename` (string, optional). If not provided, extracted from the URL. ### Example ```bash 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" }' ``` 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 `POST /v1/media/{id}/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. Pending posts are updated too: any post that references this media and is still `scheduled` or `incomplete` gets the new cover. Already-published posts keep the cover they went out with. ### Request Body (multipart/form-data) - `thumbnail` (binary, required). JPEG or PNG, max 5 MB. ### Example ```bash curl -X POST https://api.quegly.com/v1/media/MEDIA_ID/thumbnail \ -H "Authorization: qgl_your_api_key" \ -F "thumbnail=@/path/to/poster.jpg" ``` ### Response ```json { "id": "e639003b-f727-4a1e-87bd-74a2c48ae41e", "thumbnail_url": "https://media.quegly.com/thumbnails/...jpg", "posts_updated": 2 } ``` - `posts_updated` (number). How many still-pending (scheduled/draft) posts had their cover refreshed. Constraints: videos only (images are their own preview); the media file must still exist in storage (not yet cleaned up after publishing); same per-key upload rate limit as the Upload endpoints. ### Remove a thumbnail `DELETE /v1/media/{id}/thumbnail` removes the poster (and clears it from still-pending posts). Idempotent: deleting a thumbnail that isn't there returns success. ## 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. | Stage | Media Status | | --- | --- | | Uploaded | File stored, ready to attach to posts | | Attached to post | Referenced by a post's media_ids | | Post published | File delivered to platforms, then cleaned up from storage | | Post failed | File retained for retry attempts | --- Source: https://quegly.com/developers/accounts # Accounts Retrieve your connected social media accounts. Use account IDs when creating posts to specify which platforms to publish to. ## List Accounts Returns all active connected social media accounts for the workspace. Inactive (revoked / disconnected) accounts are filtered out. `GET /v1/accounts` ### Headers - `X-Workspace-Id` (string, optional). Required when using an all-scope API key. The workspace whose accounts to list. ### Example Request ```bash curl https://api.quegly.com/v1/accounts \ -H "Authorization: qgl_your_api_key" ``` ### Response ```json { "accounts": [ { "id": "acc-instagram-123", "platform": "instagram", "account_username": "mydesigncarousel", "display_name": "My Design Carousels", "profile_picture_url": "https://scontent.cdninstagram.com/avatar.jpg", "is_active": true }, { "id": "acc-tiktok-456", "platform": "tiktok", "account_username": "mydesigncarousel", "display_name": "My Design Carousels", "profile_picture_url": "https://p16-sign.tiktokcdn.com/avatar.jpg", "is_active": true } ] } ``` ### Response Fields - `id` (string). Unique account ID. Use this in `account_ids` when creating posts. - `platform` (string). One of: `instagram`, `facebook`, `youtube`, `tiktok`, `x`, `threads`. - `account_username` (string). Username/handle on the platform. - `display_name` (string). Display name on the platform. - `profile_picture_url` (string). Profile picture URL. - `is_active` (boolean). Always true on returned rows (inactive accounts are filtered out). ## Connecting accounts Social media accounts must be connected through the Quegly dashboard via OAuth. The API does not support connecting new accounts. This requires browser-based authentication with each platform. Once connected, you can use the account IDs returned here in all API calls. --- Source: https://quegly.com/developers/analytics # Analytics Retrieve per-platform engagement metrics for your published posts. Backed by an age-tiered read-through cache (hourly for day-1 posts, every 12h on day 2, daily after, hard 30-day window); live across Instagram, Facebook, YouTube, TikTok, and X. ## Post Analytics Get per-platform analytics for a specific post. Only available for posts with status `posted` or `partial`. `GET /v1/analytics/post/{id}` ### Path Parameters - `id` (string, required). The post ID. ### Example Request ```bash curl https://api.quegly.com/v1/analytics/post/post-abc123 \ -H "Authorization: qgl_your_api_key" ``` ### Response ```json { "post_id": "post-abc123", "platforms": [ { "platform": "instagram", "account_id": "acc-instagram-123", "post_url": "https://www.instagram.com/p/abc123", "metrics": { "views": 15420, "reach": 11290, "likes": 892, "comments": 47, "shares": 123, "saved": 234, "total_interactions": 1296 }, "fetched_at": "2026-06-02T10:00:00.000Z" }, { "platform": "x", "account_id": "acc-x-345", "post_url": "https://x.com/user/status/123456", "metrics": { "views": 38400, "impressions": 38400, "likes": 412, "comments": 18, "retweets": 67, "quotes": 9, "bookmarks": 51, "url_link_clicks": 124, "user_profile_clicks": 22 }, "fetched_at": "2026-06-02T10:00:00.000Z" } ] } ``` The `metrics` object is platform-specific. Keys vary by platform (TikTok exposes 4 keys, YouTube up to 10). Missing keys mean "the platform didn't expose that metric for this post," never zero. ## Workspace Analytics (bulk) Every published post in a date window with its per-platform metrics, in one call. Serves cached snapshots only; never hits platform APIs. Pair with the refresh endpoint below when freshness matters. `GET /v1/analytics` ### Query Parameters - `start_date` (ISO date, optional). Defaults to 30 days ago. - `end_date` (ISO date, optional). Defaults to now. ### Example Request ```bash curl "https://api.quegly.com/v1/analytics?start_date=2026-06-01&end_date=2026-06-30" \ -H "Authorization: qgl_your_api_key" ``` ### Response ```json { "workspace_id": "ws-123", "start_date": "2026-06-01T00:00:00.000Z", "end_date": "2026-06-30T23:59:59.000Z", "count": 1, "posts": [ { "id": "post-abc123", "caption": "3 Ways to Prep Your Skin Before a Big Event", "status": "posted", "scheduled_at": "2026-06-28T13:00:00.000Z", "platforms": [ { "platform": "instagram", "account_username": "myhandle", "post_url": "https://www.instagram.com/p/abc123", "metrics": { "views": 15420, "likes": 892, "comments": 47 }, "captured_at": "2026-06-29T10:00:00.000Z" } ] } ] } ``` `metrics` is `{}` and `captured_at` is `null` when nothing has been captured yet for that post+platform (distinct from a captured 0). The window may reach back past 30 days; posts older than the refresh window return their last (frozen) snapshot. ## Refresh Analytics Trigger an on-demand refresh sweep for the workspace. The scripted flow is: refresh, wait a few seconds, then `GET /v1/analytics`. `POST /v1/analytics/refresh` ### Example Request ```bash curl -X POST https://api.quegly.com/v1/analytics/refresh \ -H "Authorization: qgl_your_api_key" ``` ### Response ```json { "workspace_id": "ws-123", "attempted": 42, "refreshed": 40, "skipped": 108, "failed": 2 } ``` - `attempted`. Stale rows fetched this sweep. - `refreshed`. Fetched and stored successfully. - `skipped`. Still fresh (inside the 1-hour on-demand TTL), not fetched. - `failed`. Platform errors; picked up again on a later sweep. Repeat calls within an hour re-fetch nothing (everything reports as skipped), and posts older than 30 days are never re-fetched by any path. ## Available Metrics by Platform ### Instagram From the post-March-2025 metric set on the Graph API media insights endpoint. `views` replaced the deprecated `impressions`. - `views`. Total views (Reels) or impressions (Feed/Carousel) post-March 2025. - `reach`. Unique accounts that saw the post. - `likes`. Like count. - `comments`. Comment count. - `saved`. Times the post was saved. - `shares`. Times the post was shared (DM, story re-share). - `total_interactions`. Aggregate of likes + comments + saves + shares (Meta-computed). - `watch_time_seconds`. Reels only. Total seconds watched across all viewers. - `avg_view_duration_seconds`. Reels only. Average seconds watched per view. ### Facebook Page Posts use the post-2026 `post_views` / `post_clicks` insights (the deprecated `post_impressions` family is sunset June 2026). Video Page Posts route through the Video node and expose a narrower set. - `views` , `post_views` for Page Posts; lifetime view count for Video nodes. - `likes`. Reaction count (mirrors `reactions`). - `reactions`. Page Posts only. Total reactions count. - `comments`. Comment count. - `shares`. Page Posts only. Share count. - `post_clicks`. Page Posts only. Link/photo/video clicks. ### YouTube Two endpoints combined: Data API (basic stats, always granted) plus Analytics API (watch time + retention + subscriber attribution, requires `yt-analytics.readonly` scope. See Edge Cases). - `views`, `likes`, `comments`, `favorites`. Data API. - `shares`, `watch_time_seconds`, `avg_view_duration_seconds`, `avg_view_percentage`, `subscribers_gained`, `subscribers_lost`. Analytics API only. ### TikTok From the v2 video query endpoint. Requires the `video.list` scope (approved May 2026. See Edge Cases for older tokens). - `views`, `likes`, `comments`, `shares`. ### X (Twitter) `public_metrics` are always available; `non_public_metrics` (link clicks, profile clicks) are only returned within 30 days of the tweet's publish time. - `views`. Impression count. - `impressions`. Same value as `views`. - `likes`, `comments`, `retweets`, `quotes`, `bookmarks`. - `url_link_clicks`, `user_profile_clicks`. Non_public_metrics, 30-day window only. ### Threads From the media insights endpoint. Threads exposes no reach, saves, or watch-time metric. - `views`, `likes`, `shares`. - `comments`. Threads calls these replies; mapped to `comments` for cross-platform parity. - `reposts`, `quotes`. Threads' two amplification counts. ## Caching & Refresh Analytics are served from a database cache, refreshed on a read-through pattern when the dashboard's Analytics page is opened or when you call `POST /v1/analytics/refresh`. Hitting the read endpoints repeatedly is cheap and won't cost extra platform-side reads. - **Cache TTL** , age-tiered. Posts under 24h old refresh at most hourly, day-2 posts every 12 hours, day-3+ posts daily. `POST /v1/analytics/refresh` uses a flat 1-hour TTL for every post in the window instead. - **Refresh window** , 30 days, hard. Posts older than 30 days keep their last captured snapshot forever; no path re-fetches them, dashboard or API. - **Staleness signal** , `fetched_at` / `captured_at` on each platform entry tells you when the snapshot was last refreshed. - **Concurrency**. Up to 8 platform fetches in flight per refresh sweep, with a 4-second per-fetch timeout. For scripted pulls: `POST /v1/analytics/refresh`, wait a few seconds, then `GET /v1/analytics`. ## Edge Cases Four real cases worth knowing about before you call this endpoint in production. Each one shows up as "empty metrics" or "missing fields" and is otherwise hard to debug from the response alone. ### TikTok: brief delay between publish and analytics availability When TikTok accepts a publish, we get back a `publish_id`. The actual public video ID arrives later via TikTok's `post.publish.publicly_available` webhook. Until that webhook fires (typically seconds, occasionally up to a minute under load), analytics for the post will return an empty metrics object. If you're polling immediately after a Publish Now call, expect the first sweep or two to be empty for TikTok. ### TikTok: `video.list` scope (added May 2026) TikTok analytics requires the `video.list` scope, which Quegly added on 2026-05-10. Users who connected their TikTok account before that date have older tokens missing this scope. Their analytics calls return "Video not found (deleted, private, or scope not granted)." Fix: have the user disconnect and reconnect their TikTok account in the dashboard. ### X: `url_link_clicks` / `user_profile_clicks` only within 30 days X gates the `non_public_metrics` field set (link clicks, profile clicks) to a 30-day window after publish. For tweets older than 30 days, those two keys disappear from the response. The rest of the metrics keep working. We age-check `posted_at` before requesting the field set, so older tweets won't error; they just return without the click attribution data. ### YouTube: watch-time / retention / subscriber metrics require a re-connect The YouTube fetcher pulls basic stats (views, likes, comments, favorites) from the Data API. Always granted. Watch-time, retention percentage, and subscriber attribution come from the YouTube Analytics API, which needs the `yt-analytics.readonly` scope. Quegly added that scope on 2026-05-10; older tokens fall back to Data-API-only metrics. Fix: same as TikTok. Disconnect and reconnect to grant the new scope. **Defensive coding tip:** when reading the `metrics` object, always treat keys as optional. Use `metrics.likes ?? 0` rather than assuming the key exists. --- Source: https://quegly.com/developers/platforms # Platform Settings Each platform has specific media requirements and optional settings that can be configured via the `platform_settings` field when creating a post. ## Media Rules Summary | Platform | Images | Video | Text-Only | Mix Media | | --- | --- | --- | --- | --- | | Instagram | 1-10 | 1 (→ Reels) | No | No | | Facebook | 1-10 | 1 | Yes | No | | YouTube | 0 (thumbnail only) | 1 (required) | No | No | | TikTok | 2-35 (Photo Mode) | 1 | No | No | | X (Twitter) | 1-4 | 1 | Yes | No | | Threads | 1-10 | 1-10 | Yes | Yes | Images and videos cannot be mixed in the same post on any platform. ## Platform Details ### Instagram Media: 1-10 images or 1 video. Videos auto-post as Reels. 2+ images create a carousel. Media required for all posts. Optional collaborators, tags and trial Reels. ### Facebook Media: 1-10 images or 1 video. Supports text-only posts. Multi-image posts supported. Optional collaborator Pages on Reels. ### YouTube Media: 1 video (required). Video-only platform. Vertical videos under 60s become Shorts. Optional title and privacy settings. ### TikTok Media: 1 video or 2-35 images. Photo Mode requires 2+ images. Privacy level is required. Most configurable platform. ### Threads Media: 1-10 images and/or videos (mixed carousels allowed). Supports text-only posts. 500 character hard limit. Optional `topic_tag` setting. ### X (Twitter) Media: 1-4 images or 1 video. Supports text-only posts. 280 character advisory (not enforced). Optional tags on photos and video. --- Source: https://quegly.com/developers/platforms/instagram # Instagram Instagram supports feed posts, carousels (2+ images), and Reels (video). All videos are automatically posted as Reels. Media is required for all Instagram posts. ## Media Constraints | Constraint | Images | Videos | | --- | --- | --- | | Formats | JPEG, PNG | MP4 (H.264 + AAC) | | Max file size | 8 MB | 4 GB | | Max count per post | 10 | 1 | | Max duration | , | 15 minutes | | Aspect ratio | 4:5 to 16:9 | 4:5 to 16:9 | | Text-only posts | Not supported | Not supported | | Mix images + video | Not allowed | Not allowed | ## Posting Behavior **Single Image.** Posted as a standard feed photo post. **2-10 Images.** Automatically posted as a carousel. Images are displayed in the order provided in the `media_ids` array. **Single Video.** Automatically posted as a Reel. Instagram's feed video format is deprecated. All videos are Reels. ## Platform Settings All optional, under `platform_settings.instagram`. Leave the object out for a plain post. Usernames can be sent with or without the @. | Field | Type | Description | | --- | --- | --- | | `collaborators` | string[] | Up to 3 Instagram usernames to invite as collaborators. Once they accept, the post shows on their profile too. Feed posts, carousels and Reels. Not allowed on trial Reels. | | `user_tags` | string[] | Up to 20 public accounts to tag. Reels only (exactly one video). Not allowed on trial Reels. | | `trial_reel` | boolean | Publish the video as a trial Reel, shown to people who don't follow you first. Exactly one video; no collaborators or tags. Defaults to false. | | `trial_graduation_strategy` | string | `MANUAL` (default): you choose in Instagram whether to share it with your followers. `SS_PERFORMANCE`: Instagram shares it with your followers on its own if it does well. | A Reel with a collaborator: ```json { "type": "schedule", "scheduled_at": "2026-10-01T14:00:00.000Z", "caption": "Before and after, one weekend. #interiordesign", "media_ids": ["video-id-1"], "account_ids": ["instagram-account-id"], "platform_settings": { "instagram": { "collaborators": ["@studio.north"] } } } ``` A trial Reel that graduates on its own: ```json { "type": "schedule", "scheduled_at": "2026-10-01T14:00:00.000Z", "caption": "Testing a new hook.", "media_ids": ["video-id-1"], "account_ids": ["instagram-account-id"], "platform_settings": { "instagram": { "trial_reel": true, "trial_graduation_strategy": "SS_PERFORMANCE" } } } ``` ## Caption Rules - Max length: 2,000 characters. - Hashtags: include in the caption text. Instagram supports up to 30 hashtags. - Mentions: use @username format in the caption text. --- Source: https://quegly.com/developers/platforms/facebook # Facebook Facebook supports text-only posts, image posts, multi-image posts, and video posts. Posts are published to your connected Facebook Page. ## Media Constraints | Constraint | Images | Videos | | --- | --- | --- | | Formats | JPEG, PNG | MP4 (H.264 + AAC) | | Max file size | 25 MB | 4 GB | | Max count per post | 10 | 1 | | Max duration | , | 4 hours | | Text-only posts | Supported | Supported | | Mix images + video | Not allowed | Not allowed | ## Platform Settings One optional setting, under `platform_settings.facebook`. Leave the object out for a plain post. | Field | Type | Description | | --- | --- | --- | | `collaborator_page_ids` | string[] | Up to 10 numeric Facebook Page IDs to invite as collaborators. Used only when the post is a single vertical (9:16) video, which Quegly then publishes as a Reel (Facebook Reels run 3 to 90 seconds); ignored on other posts. Send IDs, not Page names or handles. | ```json { "type": "schedule", "scheduled_at": "2026-06-01T14:00:00.000Z", "caption": "Exciting news! Check out our latest room designs.", "account_ids": ["facebook-account-id"] } ``` ```json { "type": "now", "caption": "Before and after transformation #homedecor", "media_ids": ["image-id-1", "image-id-2"], "account_ids": ["facebook-account-id"] } ``` A Reel with a collaborator Page: ```json { "type": "schedule", "scheduled_at": "2026-10-01T14:00:00.000Z", "caption": "Our first collab with the team across the street.", "media_ids": ["vertical-video-id"], "account_ids": ["facebook-account-id"], "platform_settings": { "facebook": { "collaborator_page_ids": ["104785352000000"] } } } ``` ## Caption Rules - Max length: 2,000 characters. - Required: No. Text-only posts use the caption as the post body, but media posts can omit it. --- Source: https://quegly.com/developers/platforms/youtube # YouTube YouTube is a video-only platform. Every post requires exactly one video. Vertical videos under 60 seconds are automatically classified as YouTube Shorts. ## Media Constraints | Constraint | Value | | --- | --- | | Video format | MP4 (H.264 + AAC) | | Max file size | 256 GB | | Max duration | 12 hours | | Required media | Exactly 1 video | | Images | Not supported (thumbnail only) | | Text-only | Not supported | | Shorts | Vertical video under 60 seconds → auto-classified as Shorts | | Thumbnail format | JPEG or PNG, max 2 MB | ## Platform Settings YouTube requires additional settings in the `platform_settings.youtube` object. - `title` (string, optional). Video title, max 100 characters. If omitted, the first 100 characters of the caption are used. - `youtube_privacy_status` (string, optional) , `public` (default), `private`, or `unlisted`. Controls who can see the video. - `collaborator_handles` (string[], optional). Up to 10 YouTube channel handles you plan to add as collaborators, with or without the @. Saved with the post but not sent to YouTube: YouTube's API can't add collaborators. After the video publishes, the dashboard links you to YouTube Studio to invite them there. **Title sanitization:** The characters `<` and `>` are automatically replaced with `←` and `→` to comply with YouTube's API requirements. If no custom title is provided, the caption is truncated to 100 characters and used as the title. ## Examples ```json { "type": "schedule", "scheduled_at": "2026-06-01T14:00:00.000Z", "caption": "Watch this incredible room makeover in under 60 seconds! #shorts #homedecor #interiordesign", "media_ids": ["video-id"], "account_ids": ["youtube-account-id"], "platform_settings": { "youtube": { "title": "Room Makeover in 60 Seconds", "youtube_privacy_status": "public" } } } ``` ```json { "type": "now", "caption": "Full room transformation timelapse", "media_ids": ["video-id"], "account_ids": ["youtube-account-id"], "platform_settings": { "youtube": { "title": "Full Room Transformation Timelapse", "youtube_privacy_status": "unlisted" } } } ``` ## Caption Rules - Max length: 2,000 characters (used as video description). - Title: max 100 characters. Auto-generated from caption if not provided. --- Source: https://quegly.com/developers/platforms/tiktok # TikTok TikTok supports video posts and Photo Mode slideshows. It is the most configurable platform with required privacy settings and optional content disclosure toggles. ## Media Constraints | Constraint | Videos | Images (Photo Mode) | | --- | --- | --- | | Formats | MP4 (H.264) | JPEG, PNG | | Max file size | 500 MB | 5 MB per image | | Count per post | Exactly 1 | 2 to 35 images | | Max duration | 10 minutes | , | | Text-only | Not supported | Not supported | | Mix images + video | Not allowed | Not allowed | **Photo Mode requires at least 2 images.** A single image is not supported on TikTok. If you need to post a single image, consider using it as a video still or posting to another platform. ## Platform Settings TikTok requires a `platform_settings.tiktok` object with at minimum a `privacy_level` or `draft_mode`. ### Required - `privacy_level` (string). Who can see the post. One of: `PUBLIC_TO_EVERYONE`, `MUTUAL_FOLLOW_FRIENDS`, `FOLLOWER_OF_CREATOR`, `SELF_ONLY`. Not required when `draft_mode` is true (defaults to `SELF_ONLY`). ### Draft Mode - `draft_mode` (boolean, optional). Send to TikTok drafts inbox instead of posting directly. Allows adding trending sounds in the TikTok app before publishing. When true, `privacy_level` defaults to `SELF_ONLY` if not set. ### Interaction Settings - `allow_comment` (boolean, optional). Defaults to true. - `allow_duet` (boolean, optional). Video posts only. Defaults to true. - `allow_stitch` (boolean, optional). Video posts only. Defaults to true. ### Content Disclosure - `commercial_content` (boolean, optional). Enable commercial content disclosure. Defaults to false. - `brand_organic` (boolean, optional). Self-promotion flag ("Your Brand"). Cannot be combined with `brand_content`. - `brand_content` (boolean, optional). Paid partnership flag ("Branded Content"). Cannot be combined with `brand_organic` or `privacy_level: SELF_ONLY`. ### Music (Photo Mode only) - `auto_add_music` (boolean, optional). Tells TikTok to auto-add a recommended track to the slideshow. Photo Mode posts only. Ignored on videos. Cannot be used with `draft_mode` (the drafts inbox doesn't accept this flag; it's a DIRECT_POST-only field per TikTok's Content Posting API spec). Defaults to false. **When to enable auto_add_music.** TikTok's algorithm rewards Photo Mode slideshows with audio tracks over silent ones. Setting `auto_add_music: true` lets TikTok pick a fitting track at publish time and is the no-friction option for automated workflows. If you want manual control over the track instead, use `draft_mode: true` and pick one in the TikTok app before publishing. ## Business Rules **Privacy level is required (unless draft mode).** Every TikTok post must specify a `privacy_level`, unless `draft_mode` is true. When draft_mode is enabled, privacy_level defaults to SELF_ONLY. **draft_mode sends to TikTok inbox.** When draft_mode is true (or privacy_level is "SELF_ONLY"), the post is uploaded to your TikTok drafts inbox. This is useful for adding trending sounds and making final edits in the TikTok app before publishing. **Content disclosure constraints.** If commercial_content is true, at least one of brand_organic or brand_content must be true. brand_organic and brand_content cannot both be true. brand_content cannot be combined with privacy_level SELF_ONLY. **Duet and Stitch are video-only.** The allow_duet and allow_stitch settings only apply to video posts. They are ignored for Photo Mode slideshows. ## Examples ```json { "type": "schedule", "scheduled_at": "2026-06-01T14:00:00.000Z", "caption": "My landlord said I can't change anything so I showed her this #fyp #roomtransformation", "media_ids": ["video-id"], "account_ids": ["tiktok-account-id"], "platform_settings": { "tiktok": { "privacy_level": "PUBLIC_TO_EVERYONE", "allow_comment": true, "allow_duet": true, "allow_stitch": true } } } ``` ```json { "type": "now", "caption": "6 ways to redesign your kitchen without renovation #interiordesign #beforeandafter", "media_ids": ["slide-1-id", "slide-2-id", "slide-3-id", "slide-4-id", "slide-5-id", "slide-6-id"], "account_ids": ["tiktok-account-id"], "platform_settings": { "tiktok": { "draft_mode": true, "allow_comment": true } } } ``` **Tip for AI agents:** TikTok's algorithm heavily favors posts with trending sounds. For slideshows: either set `auto_add_music: true` (TikTok picks the track), or use `draft_mode: true` and pick a track manually in the TikTok app. ## Caption Rules - Max length: 2,000 characters. - Hashtags: include in caption text. TikTok currently limits to 5 hashtags. --- Source: https://quegly.com/developers/platforms/x # X (Twitter) X supports text-only tweets, tweets with images, and tweets with video. No additional platform settings are required. ## Media Constraints | Constraint | Images | Videos | | --- | --- | --- | | Formats | JPEG, PNG | MP4 (H.264 + AAC) | | Max file size | 5 MB | 512 MB | | Max count per post | 4 | 1 | | Max duration | , | 2 min 20 sec (140 seconds) | | Text-only | Supported | Supported | | Mix images + video | Not allowed | Not allowed | ## Platform Settings One optional setting, under `platform_settings.x`. Leave the object out for a plain post. | Field | Type | Description | | --- | --- | --- | | `tagged_user_ids` | string[] | Up to 10 numeric X user IDs to tag in the post's photos or video. Only used when the post has media; ignored on text-only posts. Send IDs, not @handles. | ## Examples ```json { "type": "now", "caption": "Just launched a new AI room redesign feature. Try it out and let me know what you think!", "account_ids": ["x-account-id"] } ``` ```json { "type": "schedule", "scheduled_at": "2026-06-01T14:00:00.000Z", "caption": "Before and after room transformation using AI. The results are incredible.", "media_ids": ["image-id-1", "image-id-2"], "account_ids": ["x-account-id"] } ``` ```json { "type": "schedule", "scheduled_at": "2026-06-01T18:00:00.000Z", "caption": "Watch this 60 second room transformation", "media_ids": ["video-id"], "account_ids": ["x-account-id"] } ``` ## Caption Rules - Max length: 2,000 characters. - 280-character advisory: captions over 280 characters trigger a warning but are not blocked. X Premium users can post longer tweets. If you're targeting free-tier X users, keep captions under 280 characters to ensure the full text is visible. The API accepts up to 2,000 characters but X may truncate long tweets for users without Premium. --- Source: https://quegly.com/developers/platforms/threads # Threads Threads supports text-only posts, a single image or video, and carousels of 2-10 items that can mix images and videos. One optional setting attaches a topic tag. ## Media Constraints | Constraint | Images | Videos | | --- | --- | --- | | Formats | JPEG, PNG | MP4 (H.264 or HEVC + AAC) | | Max file size | 8 MB | 1 GB | | Max count per post | 10 | 10 | | Max duration | , | 5 minutes | | Max resolution | 1440px wide | 1920x1080 | | Text-only | Supported | Supported | | Mix images + video | Allowed | Allowed | ## Platform Settings Optional, under `platform_settings.threads`. | Field | Type | Values | | --- | --- | --- | | `topic_tag` | string | 1-50 characters, no periods, ampersands or spaces. A leading `#` is stripped. | ## Examples ```json { "type": "now", "caption": "Shipping the Threads integration today. Text posts, images, video and carousels from one calendar.", "account_ids": ["threads-account-id"] } ``` ```json { "type": "schedule", "scheduled_at": "2026-10-01T14:00:00.000Z", "caption": "Three room makeovers, one afternoon.", "media_ids": ["image-id-1", "image-id-2", "video-id-1"], "account_ids": ["threads-account-id"], "platform_settings": { "threads": { "topic_tag": "interiordesign" } } } ``` ## Caption Rules - Max length: 500 characters. This is a hard limit on Threads' side; longer captions are rejected before the post is saved. - Threads counts emoji as multi-byte, so a caption near 500 characters with many emoji can still be refused by Threads. Keep emoji-heavy posts a little shorter. - Up to 5 unique URLs per post.