# PostQuickAI API REST API for PostQuickAI — generate content, schedule posts, manage social accounts, and run analytics across 8+ platforms. Bearer token auth (pq_live_*). Used directly or via the @postquickai/mcp MCP server for agent integration. Version: 1.0.0 Base URL: https://www.postquick.ai/api ## Authentication All endpoints require `Authorization: Bearer pq_live_...` header. Obtain an API key from https://www.postquick.ai/dashboard/api (requires API add-on). ## Endpoints ### GET /v1/accounts **operationId**: `listAccounts` **summary**: List connected social accounts Returns every social account (Twitter/X, Threads, Bluesky, LinkedIn, Facebook, Instagram, YouTube, TikTok) connected across all the user's content groups. **tags**: Accounts ### DELETE /v1/accounts/{accountId} **operationId**: `disconnectAccount` **summary**: Disconnect a social account Permanently disconnect a social account. Deletes stored OAuth tokens. Re-connecting requires the dashboard OAuth flow. **tags**: Accounts ### GET /v1/accounts/{accountId}/followers **operationId**: `getAccountFollowers` **summary**: Follower history for a connected account Returns the daily follower-count history for a connected social account, plus the most recent snapshot. History is populated by a daily cron. Useful for tracking growth over time without scraping public profile pages. **tags**: Accounts, Analytics ### GET /v1/analytics **operationId**: `getApiAnalytics` **summary**: API analytics Operational analytics for your own API usage: request volume, error rates, average response times, breakdowns by endpoint / status code / key, recent errors, and rate-limit meters. Read-only and scoped to the authenticated account. Accepts a pq_live_ API key or a dashboard session. **tags**: Account ### POST /v1/captions/carousel **operationId**: `generateCarouselCaption` **summary**: Generate a carousel caption Generate a caption specifically tailored for a multi-slide carousel post. **tags**: AI Content ### POST /v1/captions/generate **operationId**: `generateCaption` **summary**: Generate a caption Generate a social media caption with AI, optionally grounded in a content group's brand profile. Counts as 1 AI text generation. **tags**: AI Content ### POST /v1/captions/video **operationId**: `generateVideoCaption` **summary**: Generate a video caption Generate an engaging caption for a video post (hooks, CTAs, optimized for TikTok/Reels/Shorts). **tags**: AI Content ### GET /v1/content-groups **operationId**: `listContentGroups` **summary**: List content groups Returns every content group (a.k.a. "app" — one per brand/project) owned by the authenticated user. **tags**: Content Groups ### POST /v1/content-groups **operationId**: `createContentGroup` **summary**: Create a content group Creates a new content group. Content groups act as containers for posts, brand instructions, and connected social accounts. Subject to the content-group limit on your plan. **tags**: Content Groups ### GET /v1/content-groups/{groupId} **operationId**: `getContentGroup` **summary**: Retrieve a content group Returns a single content group with its associated platforms, social accounts, and brand instructions. **tags**: Content Groups ### DELETE /v1/content-groups/{groupId} **operationId**: `deleteContentGroup` **summary**: Delete a content group Permanently deletes a content group and all its associated posts. Social account connections are preserved. **tags**: Content Groups ### GET /v1/content-groups/{groupId}/analytics **operationId**: `getGroupAnalytics` **summary**: Group analytics Aggregate social performance analytics for all posts in a content group. Breaks down by platform, content type, and includes top posts + daily trend. **tags**: Content Groups, Analytics ### POST /v1/content-groups/{groupId}/analyze **operationId**: `analyzeNiche` **summary**: Analyze niche & propose instruction edits Run the self-improving loop for a content group: search popular content in its niche, then draft instruction-edit proposals (or auto-apply them if mode/auto_improve is on). Returns a summary + a jobId to poll. Proposals appear at GET /v1/content-groups/{groupId}/instruction-proposals. **tags**: Content Groups ### GET /v1/content-groups/{groupId}/analyze **operationId**: `listNicheAnalysisRuns` **summary**: List niche-analysis runs List recent self-improvement runs for a content group (newest first) — including daily auto-improve cron runs. Each run shows its mode, status, and how many edits were proposed/applied, so you can monitor what the automation has done. **tags**: Content Groups ### GET /v1/content-groups/{groupId}/analyze/{jobId} **operationId**: `getNicheAnalysisJob` **summary**: Poll a niche-analysis job Get an analysis job's status, progress, and result. Terminal states: complete, error. **tags**: Content Groups ### GET /v1/content-groups/{groupId}/instruction-changes **operationId**: `listInstructionChanges` **summary**: List instruction change history The audit trail: every applied (or reverted) instruction change for a content group, newest first, with before/after, reason, and source (agent/user). **tags**: Content Groups ### GET /v1/content-groups/{groupId}/instruction-proposals **operationId**: `listInstructionProposals` **summary**: List instruction-edit proposals List the self-improving loop's proposed instruction edits for a content group. Filter by status to show, e.g., only the pending queue (status=proposed). **tags**: Content Groups ### GET /v1/content-groups/{groupId}/instructions **operationId**: `getInstructions` **summary**: Get brand instructions Retrieves the brand profile + generation settings for a content group (brand_name, tone, target audience, topics, auto-generation flags, YOLO mode, etc.). **tags**: Content Groups, Instructions ### PUT /v1/content-groups/{groupId}/instructions **operationId**: `updateInstructions` **summary**: Update brand instructions Create or update brand profile fields for a content group. Upsert — any subset of fields can be passed. **tags**: Content Groups, Instructions ### GET /v1/content-groups/{groupId}/trending **operationId**: `searchTrendingContent` **summary**: Search popular niche content Look up the most popular content in this content group's niche across social platforms. The niche is derived from the group's brand instructions (topics + target audience). Each platform returns up to `limit` posts; platforms without an available API (or pending app review) appear under `unavailable` with a reason. **tags**: Content Groups ### POST /v1/content/adjust-tone **operationId**: `adjustTone` **summary**: Adjust tone Rewrite existing copy in a different tone while preserving meaning. **tags**: AI Content ### POST /v1/content/custom-edit **operationId**: `customEdit` **summary**: Custom edit Apply a free-form natural-language edit to existing copy. **tags**: AI Content ### POST /v1/content/make-concise **operationId**: `makeConcise` **summary**: Make concise Tighten copy while preserving meaning. Useful for Twitter/X 280-char limit. **tags**: AI Content ### POST /v1/content/proofread **operationId**: `proofread` **summary**: Proofread Grammar and spelling fixes while preserving voice and style. **tags**: AI Content ### POST /v1/hashtags/generate **operationId**: `generateHashtags` **summary**: Generate hashtags AI-generated hashtags optimized for the target platform. Platform-specific defaults: Instagram=30, Twitter=1-2, LinkedIn=3-5. **tags**: AI Content ### POST /v1/images/generate **operationId**: `generateImage` **summary**: Generate an image Generate an AI image via Gemini Flash (default), GPT Image 2, or Nano Banana Pro. Image is uploaded to Supabase Storage; response includes a public URL. **tags**: Images ### POST /v1/images/upload **operationId**: `uploadImage` **summary**: Upload an image Uploads an image to PostQuickAI storage and returns a public URL hosted on a domain whitelisted by our TikTok developer app. Use this to host externally-generated carousel slides (or any image) on a URL that TikTok will accept when publishing via /v1/posts/create. Accepts three input shapes: - multipart/form-data with a `file` field — direct binary upload (best for browsers / curl). - application/json with a `data` field — base64-encoded raw bytes (best for MCP clients / Claude / ChatGPT that have a file inline but cannot send multipart). Optionally include `contentType` and `fileName`. - application/json with a `sourceUrl` field — server fetches and re-hosts a public URL (best for re-hosting from your own CDN). Limits: image/jpeg, image/png, image/webp, image/gif. Max 10MB. Counts against your storage quota. Typical MCP flow: call `uploadImage` with base64 `data` → take the returned `imageUrl` → pass it as `imageUrl` to `createPost` (or as one entry in `imageUrls` for a carousel). **tags**: Images ### POST /v1/instruction-changes/{changeId}/revert **operationId**: `revertInstructionChange` **summary**: Revert an instruction change Undo an applied instruction change by restoring the previous value. The reversal is itself logged as a new change (append-only history), so it too can be undone. **tags**: Content Groups ### POST /v1/instruction-proposals/{proposalId}/approve **operationId**: `approveInstructionProposal` **summary**: Approve an instruction proposal Apply a proposed instruction edit: write the new value, log it to the audit trail, and mark the proposal approved. Returns the applied change. **tags**: Content Groups ### POST /v1/instruction-proposals/{proposalId}/reject **operationId**: `rejectInstructionProposal` **summary**: Reject an instruction proposal Dismiss a proposed instruction edit without applying it. No change is written. **tags**: Content Groups ### GET /v1/me **operationId**: `getMe` **summary**: Authenticated user info Returns the authenticated user's email, user ID, subscription plan, and API key info. **tags**: Account ### GET /v1/posts **operationId**: `listPosts` **summary**: List posts List posts filtered by content group and/or status. Use this to enumerate posts before acting on a specific one. **tags**: Posts ### POST /v1/posts/create **operationId**: `createPost` **summary**: Create a post Manually create a post with your own content. Supports text, image, and carousel post types. Media URLs must be publicly accessible. For video / Reels (TikTok, YouTube, Instagram Reels, Facebook Reels, X, Threads, LinkedIn), use POST /v1/videos instead — postType="video" is not accepted here. Attaching a raw file you have inline (e.g. a file the user uploaded to Claude/ChatGPT): first call `uploadImage` with the base64 `data` to get a public `imageUrl`, then pass that here. Posting an existing image already on the web works too — call `uploadImage` with `sourceUrl` first so the URL ends up on a TikTok-whitelisted domain. **tags**: Posts ### POST /v1/posts/generate **operationId**: `generatePost` **summary**: Generate a post Uses the content group's brand profile (tone, audience, topics) to generate a new post via AI. Counts as 1 AI text generation. **tags**: Posts ### GET /v1/posts/{postId} **operationId**: `getPost` **summary**: Retrieve a post Fetch a single post by ID. **tags**: Posts ### PUT /v1/posts/{postId} **operationId**: `updatePost` **summary**: Update a post Update content, platforms, media, scheduling, or thread parts on an existing post. **tags**: Posts ### PATCH /v1/posts/{postId} **operationId**: `patchPost` **summary**: Patch a post Partial update — only provided fields change. Refuses with 409 if the post has already been published (the platforms would not reflect the change). **tags**: Posts ### DELETE /v1/posts/{postId} **operationId**: `deletePost` **summary**: Delete a post Permanently deletes a post. Cannot be undone. **tags**: Posts ### GET /v1/posts/{postId}/analytics **operationId**: `getPostAnalytics` **summary**: Post analytics Per-platform social performance metrics (views, likes, comments, shares, saves) for a post, plus 30-day history. **tags**: Posts, Analytics ### PUT /v1/posts/{postId}/images **operationId**: `updatePostImages` **summary**: Update post images Attach, replace, or remove images on a post. Attaching a raw file you have inline: first call `uploadImage` with the base64 `data` to get a public `imageUrl`, then call this endpoint with action `set_single_image` (or `set_multiple_images` for a carousel). **tags**: Posts ### POST /v1/posts/{postId}/publish **operationId**: `publishPost` **summary**: Publish a post Immediately publish a post to the specified platforms. Returns success/failure per platform. **tags**: Posts ### POST /v1/posts/{postId}/regenerate **operationId**: `regeneratePost` **summary**: Regenerate a post Rewrite an existing post with AI based on natural-language feedback. Optionally regenerate the image. **tags**: Posts ### POST /v1/posts/{postId}/reset-platforms **operationId**: `resetPostPlatforms` **summary**: Reset posted platforms Clear posted_platforms and error_message so the post can be republished cleanly. Useful after fixing a failed publish. **tags**: Posts ### POST /v1/posts/{postId}/schedule **operationId**: `schedulePost` **summary**: Schedule a post Schedule a post for future publishing. Cron picks it up and publishes automatically. **tags**: Posts ### GET /v1/stories **operationId**: `listStories` **summary**: List stories List stories for a content group. Filter by status if you only need a subset (e.g. status=scheduled). **tags**: Stories ### POST /v1/stories **operationId**: `createStory` **summary**: Create a Story Create a Story draft from a publicly accessible media URL. Charges against the image or video generation quota (one upload = one charge). Use POST /v1/stories/{storyId}/publish or /schedule to actually post it. **tags**: Stories ### POST /v1/stories/from-post/{postId} **operationId**: `convertToStory` **summary**: Convert a post or video into a Story Create a Story draft that reuses media from an existing post (or video post). The source media is referenced, not re-uploaded, and usage is NOT charged again — the underlying file was already counted against the user's quota when the source was created. Use the source query parameter to choose between generated_posts (default) and video_posts. **tags**: Stories ### GET /v1/stories/{storyId} **operationId**: `getStory` **summary**: Retrieve a story Fetch a single Story by ID. **tags**: Stories ### DELETE /v1/stories/{storyId} **operationId**: `deleteStory` **summary**: Delete a story Delete a Story. The underlying media is not deleted — managed externally by the caller. **tags**: Stories ### POST /v1/stories/{storyId}/publish **operationId**: `publishStory` **summary**: Publish a story Dispatch a Story for immediate publishing to Instagram, Facebook, and/or TikTok. Returns 202 — the publish job runs in the background. Poll GET /v1/stories/{storyId} for final status. **tags**: Stories ### POST /v1/stories/{storyId}/schedule **operationId**: `scheduleStory` **summary**: Schedule a story Schedule a Story for future publishing. The /api/cron/publish-scheduled handler picks it up at or after scheduledFor. **tags**: Stories ### GET /v1/usage **operationId**: `getUsage` **summary**: Usage & limits Returns current monthly usage vs. plan limits for text generation, image generation, video credits, and content groups. **tags**: Account ### GET /v1/videos **operationId**: `listVideos` **summary**: List videos List video posts (Reels) for a content group. Filter by status if you only need a subset (e.g. status=scheduled). **tags**: Videos ### POST /v1/videos **operationId**: `createVideo` **summary**: Create a video (Reel) from a URL Create a video post (Reel) draft from a publicly accessible video URL — the canonical way to post your OWN uploaded video to any platform (TikTok, YouTube, Instagram Reels, Facebook Reels, X, Threads, LinkedIn). Charges one video generation against your monthly quota. Then call POST /v1/videos/{videoId}/schedule or /publish. **tags**: Videos ### POST /v1/videos/generate **operationId**: `generateVideo` **summary**: Generate a video Start an async video generation job. Poll with getVideoStatus. Returns a video post record with status="generating". **tags**: Videos ### POST /v1/videos/upload **operationId**: `uploadVideo` **summary**: Upload a video Get a video file into PostQuickAI hosted storage. The returned `videoUrl` is on a domain whitelisted by our TikTok developer app, so it can be passed straight to /v1/posts/create as `videoUrl` for TikTok / YouTube / Instagram Reels publishing without URL ownership errors. Two modes: A) Inline base64 (MCP / LLM friendly, ≤ 25MB decoded): POST `{ data: base64String, contentType?, fileName? }` → get back `{ videoUrl, contentType, size }` in one call. No follow-up PUT needed. B) Signed URL (required for videos > 25MB, up to 500MB): 1. POST `{ contentType, size }` → get back `{ uploadUrl, videoUrl, headers }`. 2. PUT the raw video bytes to `uploadUrl` using the returned `headers`. Limits: video/mp4, video/webm, video/quicktime. Counts against your storage quota at request time. Typical MCP flow: call `uploadVideo` with inline base64 `data` → take the returned `videoUrl` → pass it as `videoUrl` to `createPost`. **tags**: Videos ### GET /v1/videos/{videoId} **operationId**: `getVideo` **summary**: Retrieve a video Fetch a single video post by ID. **tags**: Videos ### PUT /v1/videos/{videoId} **operationId**: `updateVideo` **summary**: Update a video Update title, description, platforms, or scheduling for a video post. **tags**: Videos ### DELETE /v1/videos/{videoId} **operationId**: `deleteVideo` **summary**: Delete a video Permanently deletes a video post. **tags**: Videos ### POST /v1/videos/{videoId}/publish **operationId**: `publishVideo` **summary**: Publish a video Immediately publish a video to TikTok, YouTube, Instagram Reels, or Twitter/X. **tags**: Videos ### POST /v1/videos/{videoId}/reset-platforms **operationId**: `resetVideoPlatforms` **summary**: Reset video posted platforms Clear posted_platforms/error_message on a video so it can be republished. **tags**: Videos ### POST /v1/videos/{videoId}/schedule **operationId**: `scheduleVideo` **summary**: Schedule a video Schedule a video post for future publishing. **tags**: Videos ### GET /v1/videos/{videoId}/status **operationId**: `getVideoStatus` **summary**: Check video status Poll the generation status of a video. Returns status (pending/generating/draft/failed), progress, and the final video URL when ready. **tags**: Videos ### GET /v1/webhooks **operationId**: `listWebhookEndpoints` **summary**: List webhook endpoints List your registered webhook endpoints. Optionally filter by `app_id`. The plaintext signing secret is never returned — only `secret_preview` for identification. **tags**: Webhooks ### POST /v1/webhooks **operationId**: `createWebhookEndpoint` **summary**: Create a webhook endpoint Register a URL to receive publish-event webhooks. Returns the plaintext signing secret EXACTLY ONCE — store it immediately. Use it to verify the X-PostQuickAI-Signature header on incoming deliveries. Lost secrets can be replaced via /rotate-secret but not retrieved. **tags**: Webhooks ### POST /v1/webhooks/deliveries/{id}/redeliver **operationId**: `redeliverWebhook` **summary**: Queue a fresh delivery from an existing one Create a new delivery attempt that reuses the original payload. The new delivery gets its own UUID — from the receiver's dedup perspective it is a distinct event. Use when the original delivery was lost and you want a fresh attempt that idempotent receivers will process. **tags**: Webhooks ### GET /v1/webhooks/{id} **operationId**: `getWebhookEndpoint` **summary**: Get a webhook endpoint Fetch a single endpoint. The plaintext secret is never returned. **tags**: Webhooks ### PATCH /v1/webhooks/{id} **operationId**: `updateWebhookEndpoint` **summary**: Update a webhook endpoint Toggle active state, change the URL, or change the subscribed events list. Re-enabling (active=true) resets the consecutive_failures counter so the endpoint gets a fresh window before auto-disable. **tags**: Webhooks ### DELETE /v1/webhooks/{id} **operationId**: `deleteWebhookEndpoint` **summary**: Delete a webhook endpoint Hard delete. Cascades to delete all delivery history for the endpoint. **tags**: Webhooks ### GET /v1/webhooks/{id}/deliveries **operationId**: `listWebhookDeliveries` **summary**: List delivery attempts for an endpoint Inspect delivery history for an endpoint. Filter by `status` (pending, delivering, succeeded, failed_retrying, failed) and/or `subject_id` (the post/video/story this event was about). Last 30 days are retained. **tags**: Webhooks ### POST /v1/webhooks/{id}/rotate-secret **operationId**: `rotateWebhookSecret` **summary**: Rotate a webhook signing secret Generate a new signing secret for an endpoint. Returns plaintext EXACTLY ONCE. The old secret is invalidated immediately — in-flight deliveries signed with it will fail signature verification on the receiver. For zero-downtime rotation, register a second endpoint with a new secret, migrate traffic, then delete the original. **tags**: Webhooks ### POST /v1/webhooks/{id}/test **operationId**: `testWebhookEndpoint` **summary**: Send a test event to an endpoint Queue a synthetic `post.posted` event with `data.test=true` for immediate dispatch. The dispatch cron picks up pending deliveries every minute, so the receiver should observe the test within ~60 seconds. Useful for sanity-checking a newly-registered endpoint without waiting for real publish activity. **tags**: Webhooks --- For the full machine-readable spec, see /openapi.json. For agent integrations, see /ai-agents.