API Reference

The PostQuickAI API is organized around REST. It accepts JSON-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs.

Use the API to generate AI content, create and manage posts, publish to social platforms, schedule posts, generate images and videos — everything available in the dashboard, fully programmable.

The API is designed for developers building integrations, automations, and AI agents that manage social media workflows at scale.

Base URL

https://www.postquick.ai/api

Client Libraries

Use any HTTP client. The API returns standard JSON — no SDK required. Works with cURL, Python requests, JavaScript fetch, and any AI agent framework.

Authentication

The PostQuickAI API uses API keys to authenticate requests. Include your key in the Authorization header as a Bearer token.

API keys carry full access to your account. Keep them secure — don't share them in client-side code, public repositories, or logs.

All requests must be made over HTTPS. Requests without authentication return 401.

Create and manage keys in your API Dashboard.

Authenticated Request
curl https://www.postquick.ai/api/v1/content-groups \
  -H "Authorization: Bearer pq_live_your_key_here"

Base URL

All API endpoints are relative to the base URL. All requests use the /api/v1 prefix for the current API version.

Important: Always use www.postquick.ai — requests to the bare domain are redirected, which strips the Authorization header.

https://www.postquick.ai/api/v1

Response Format

All responses return a consistent JSON structure. Successful responses contain a success boolean and a data object.

Error responses contain an error object with a machine-readable code and human-readable message.

Success
{
  "success": true,
  "data": {
    "post": {
      "id": "abc123",
      "content": "Just shipped a new feature...",
      "status": "pending",
      "post_type": "text"
    }
  }
}
Error
{
  "success": false,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Try again in 45 seconds.",
    "details": { "retryAfter": 45 }
  }
}

Errors

PostQuickAI uses conventional HTTP response codes. Codes in the 2xx range indicate success. 4xx codes indicate client errors (bad request, auth failure, limit exceeded). 5xx codes indicate server errors (rare).

When a request fails, check the error.code field for the specific error type and implement retry logic where appropriate (e.g., exponential backoff for rate limits).

CodeDescription
200OK — Request succeeded.
201Created — Resource was created.
202Accepted — Async operation started (video generation, publishing).
400Bad Request — Missing or invalid parameters.
401Unauthorized — Invalid or missing API key.
403Forbidden — Subscription inactive, API not enabled, or limit exceeded.
404Not Found — Resource doesn't exist.
409Conflict — Resource is in a conflicting state (e.g., already processing).
429Too Many Requests — Rate limit exceeded. Check Retry-After header.
500Server Error — Something went wrong on our end. Retry with exponential backoff.

Error Codes

The error.code field contains a machine-readable error identifier. Use this for programmatic error handling.

MISSING_AUTHNo Authorization header provided. Add Bearer token to all requests.
INVALID_KEY_FORMATKey doesn't match expected format (pq_live_...). Check for typos.
INVALID_KEYAPI key is invalid or has been revoked. Create a new key in the dashboard.
KEY_EXPIREDAPI key has passed its expiration date. Keys are valid indefinitely unless revoked.
NO_SUBSCRIPTIONNo active subscription found. Subscribe at postquick.ai/pricing.
SUBSCRIPTION_INACTIVESubscription is cancelled or expired. Renew to continue using the API.
API_NOT_ENABLEDAPI add-on has not been purchased. Enable in dashboard settings.
RATE_LIMIT_EXCEEDEDPer-minute or daily rate limit hit. Wait for retryAfter seconds.
LIMIT_EXCEEDEDPlan generation limit exceeded (images, text, videos). Upgrade or wait for reset.
NOT_FOUNDThe requested resource was not found or you don't have access to it.
INTERNAL_ERRORUnexpected server error. Retry the request. Contact support if it persists.
Error Response
{
  "success": false,
  "error": {
    "code": "INVALID_KEY",
    "message": "Invalid or revoked API key."
  }
}

Error Recovery Pattern

For rate limits (429), implement exponential backoff: start with a 1s delay, double on each retry (1s, 2s, 4s, 8s...), max 5 retries. Use the Retry-After header value if provided.

Rate Limits

Rate limits are applied per API key using a sliding window algorithm. Every response includes rate limit headers so you can track your usage in real-time.

Important: Your plan's content generation limits (images, text, videos) are shared between the dashboard and API. Rate limits control request throughput; generation limits control content volume.

When you hit a rate limit, the API returns 429 with a Retry-After header indicating seconds to wait. Implement exponential backoff for production apps.

PlanPer MinutePer Day
Basic ($8/mo)30 requests5,000 requests
Pro ($20/mo)120 requests50,000 requests

Response Headers

X-RateLimit-Limit-MinuteMaximum requests per minute for your plan (30 for Basic, 120 for Pro).
X-RateLimit-Limit-DayMaximum requests per day for your plan (5,000 for Basic, 50,000 for Pro).
Retry-AfterSeconds to wait before retrying (only sent with 429 responses). Use this value for your backoff timer.
429 Response
{
  "success": false,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Try again in 45 seconds.",
    "details": { "retryAfter": 45 }
  }
}

Rate Limit Headers Example

X-RateLimit-Limit-Minute: 120
X-RateLimit-Limit-Day: 50000

Object Schemas

The API works with three core object types: Post (text/image/carousel posts), Video Post (AI-generated videos), and Content Group (brands/accounts). Below are the complete schemas with every field documented.

The Post Object

id
string
Unique identifier for the post (UUID).
content
string
The post caption/text. May include hashtags and emojis.
status
enum
One of: "draft", "pending", "posted", "scheduled", "failed", "processing", "published".
post_type
enum
One of: "text", "image", "carousel", "video".
app_id
string
The content group (brand) this post belongs to (UUID).
platforms
string[]
Target platforms for publishing. See Supported Platforms.
posted_platforms
string[]
Platforms this post has been successfully published to.
image_url
string | null
Public URL of a single image (for post_type: "image").
image_urls
string[] | null
Array of image URLs (for post_type: "carousel"). 2-10 images.
video_url
string | null
Public URL of a video (for post_type: "video").
is_manual
boolean
True if created via API or manual upload, false if AI-generated via /posts/generate.
scheduled_for
string | null
ISO 8601 timestamp for scheduled publishing. Null if not scheduled.
error_message
string | null
Human-readable error description when status is "failed".
created_at
string
ISO 8601 timestamp when the post was created.
updated_at
string | null
ISO 8601 timestamp when the post was last updated.
posted_at
string | null
ISO 8601 timestamp when the post was actually published to platforms.
photo_cover_index
number | null
Index of the cover image for TikTok carousel posts (0-based). Only relevant for carousel posts published to TikTok.
platform_post_ids
object | null
Platform-specific post IDs for analytics. Keyed by platform name (e.g. twitter_x, instagram, tiktok). Populated after publish.
linkedin_target
object | null
LinkedIn publish target: { type: "personal" | "organization", organizationId?: string }. Required when publishing to LinkedIn.
facebook_target
object | null
Facebook page target: { pageId: string, pageName?: string }. Required when publishing to Facebook.
thread_parts
object[] | null
Array of thread parts for multi-post threads (Twitter/X): [{ text: string, image_urls?: string[], video_url?: string, post_type: string }].

The Video Post Object

id
string
Unique identifier for the video post (UUID).
app_id
string
The content group (brand) this video belongs to (UUID).
user_id
string
User ID who created this video (UUID).
title
string
Display title for the video (shown in dashboard, not published).
description
string
The generation prompt used to create the video.
status
enum
One of: "pending" (queued), "generating" (in progress, 2-10 min), "completed" (ready), "failed", "scheduled", "processing" (publishing), "posted".
video_url
string | null
Public URL of the raw generated video. Available when status is "completed".
optimized_video_url
string | null
Public URL of the preprocessed video (transcoded for platform compatibility). Used for publishing. Falls back to video_url if preprocessing was skipped.
duration
number
Video duration in seconds (4, 6, 8, or 12 depending on model).
platforms
string[] | null
Target platforms for publishing.
posted_platforms
string[] | null
Platforms this video has been successfully published to.
scheduled_for
string | null
ISO 8601 timestamp for scheduled publishing.
error_message
string | null
Human-readable error description when status is "failed".
created_at
string
ISO 8601 timestamp when the video generation was started.
updated_at
string
ISO 8601 timestamp when the video was last updated.

The Content Group Object

id
string
Unique identifier for the content group (UUID).
user_id
string
User ID who owns this content group (UUID).
name
string
Display name for the content group (e.g., "My Brand", "Client A").
description
string | null
Optional description of the brand/account.
created_at
string
ISO 8601 timestamp when the content group was created.
app_platforms
object[]
Array of platform objects: [{ platform: "instagram" }, { platform: "twitter" }]. Indicates which platforms this group targets.
social_accounts
object[]
Array of connected social accounts: [{ id: string, platform: string, account_name: string }]. Only accounts connected via OAuth.
content_instructions
object | null
Brand profile used for AI generation: { brand_name, tone, target_audience, unique_angle, instructions, image_model, video_model, ... }. Shapes AI output for this group.

Supported Platforms

PostQuickAI supports publishing to 7 social platforms. Each platform has specific requirements and constraints. Use these platform names in the platforms array when creating, publishing, or scheduling content.

Instagram

instagram
Supported: Image, Carousel (2-10 images), Video (Reels)
Requirements: Requires business or creator account. Video max 90s. Images must be 1:1 or 4:5 aspect ratio.
Notes: Stories not supported via API. Carousel captions shared across all images.

Twitter / X

twitter
Supported: Text, Image, Video
Requirements: 280 character limit for text. Videos max 2min 20s (Basic) or 10min (Pro). Images max 4 per post.
Notes: Use "twitter" or "twitter_x" in API calls (both work). Threads supported via thread_parts array.

LinkedIn

linkedin
Supported: Text, Image, Video
Requirements: Requires linkedinTarget parameter specifying personal profile or organization page. Videos max 10min.
Notes: Organization posting requires admin permissions on the page. Text limit: 3,000 characters.

Facebook

facebook
Supported: Text, Image, Video
Requirements: Requires facebookTarget parameter specifying page ID. Must have page publishing permissions.
Notes: Posts to pages only (not personal profiles). Videos max 240min.

TikTok

tiktok
Supported: Image Carousel (2-35 images), Video
Requirements: Image carousel requires minimum 2 images. Text-only posts not supported. Videos 3s-10min.
Notes: Use photo_cover_index to set carousel cover image (0-based index). Videos auto-publish to TikTok feed.

Threads

threads
Supported: Text, Image, Carousel, Video
Requirements: Meta platform. Uses Instagram credentials. 500 character limit.
Notes: Carousel max 10 images. Videos max 5min. Supports replies (not via API yet).

Bluesky

bluesky
Supported: Text, Image, Video
Requirements: AT Protocol. Requires Bluesky account. 300 character limit. Max 4 images.
Notes: Videos max 1min, max 50MB. Handles and mentions use @ prefix.

Video Models

PostQuickAI supports multiple AI video generation models. Each model has different quality, speed, and credit costs. Specify the model in the model parameter when generating videos.

Video generation is asynchronous — the API returns 202 Accepted immediately, then processes the video in the background (2-10 minutes). Poll the /videos/:id/status endpoint to check progress.

Model IDNameCreditsDurationsProvider
veo-3.1-fast-generate-previewGoogle Veo 3.1 Fast14s, 6s, 8s
Google
Fast generation (~2-4 min). Default model.
veo-3.1-generate-previewGoogle Veo 3.134s, 6s, 8s
Google
Higher quality, slower (~6-10 min).
sora-2OpenAI Sora 214s, 8s, 12s
OpenAI
Realistic, cinematic quality.
sora-2-proOpenAI Sora 2 Pro34s, 8s, 12s
OpenAI
Best quality, longest durations.

Aspect Ratios

  • 9:16 — Portrait (TikTok, Reels, Shorts). Default.
  • 16:9 — Landscape (YouTube, LinkedIn).
  • 1:1 — Square (Instagram feed).

Image Models

PostQuickAI supports multiple AI image generation models. Each model has a different visual style and quality level. Specify the model in the model parameter when generating images.

All image generation consumes 1 image credit, regardless of model. Images are uploaded to cloud storage and returned as public URLs.

Model IDDescription
gemini-flashGoogle Gemini — fast generation, good quality, versatile. Default model.
gpt-image-1.5OpenAI GPT Image — high detail, accurate prompt following, excellent for complex scenes.
nano-banana-proNano Banana Pro — premium photorealistic quality, stylized or realistic. Great for product shots, portraits, and creative content.

Workflows

Below are complete end-to-end workflows showing how to combine API endpoints for common use cases. These examples show the full request/response cycle.

Workflow 1: AI Content Pipeline

Generate brand-aligned content, review it, optionally edit, then publish to platforms.

1. Create content group
POST /v1/content-groups with name, description, and platforms.
Brand instructions are configured separately in the dashboard and then used automatically by AI generation endpoints.
2. AI-generate post matching your brand voice
POST /v1/posts/generate with contentGroupId. Optionally set generateImage: true.
← Returns complete post object with AI-generated content, image URL (if requested), status "pending".
3. Review the generated content
GET /v1/posts/:id to fetch the full post.
4. (Optional) Edit if needed
PUT /v1/posts/:id to update content, platforms, etc.
Or use POST /v1/content/adjust-tone, /proofread, /make-concise to refine via AI.
5. Publish to platforms
POST /v1/posts/:id/publish with platforms array.
← Returns publishedTo array and any platform-specific errors.

Workflow 2: Video Generation Pipeline

Generate an AI video, wait for it to complete, then publish to TikTok and Instagram Reels.

1. Start video generation
POST /v1/videos/generate with prompt, contentGroupId, model, aspectRatio, duration.
← Returns 202 Accepted with video post object (status: "pending" or "generating"). Video generation starts in background (2-10 minutes).
2. Poll status until completed
GET /v1/videos/:id/status every 10-30 seconds.
← When status is "completed", video_url and optimized_video_url are populated.
If status is "failed", error_message explains what went wrong (quota exceeded, invalid prompt, etc). Credits are auto-refunded on failure.
3. Get the full video object
GET /v1/videos/:id to fetch complete video post with URLs, duration, metadata.
4. Publish to platforms
POST /v1/videos/:id/publish with platforms: ["instagram", "tiktok"].
← Returns 202 Accepted. Publishing happens asynchronously via Cloud Run (1-3 minutes). Check video status again to see posted_platforms populate.

Workflow 3: Scheduled Content Calendar

Batch-create content for the week, schedule posts for specific times, and let the cron system auto-publish.

1. Generate or create posts throughout the week
→ Use POST /v1/posts/generate or POST /v1/posts/create multiple times to build your content queue.
2. Schedule each post for future publishing
POST /v1/posts/:id/schedule with scheduledFor (ISO 8601 timestamp, must be in future) + platforms array.
← Post status changes to "scheduled".
3. The cron system auto-publishes at scheduled time
PostQuickAI's cron job runs every 15 minutes, checking for posts with scheduledFor <= now. Automatically publishes and updates status to "posted".
4. Monitor scheduled queue
GET /v1/posts?contentGroupId=...&status=scheduled to see upcoming posts.
GET /v1/posts?contentGroupId=...&status=posted to see published posts.

Async Operations

Several API operations are asynchronous because they involve long-running processes (video generation, video publishing, platform API calls). The API returns 202 Accepted immediately, then processes the job in the background.

Why async? Video generation takes 2-10 minutes (AI model processing). Video publishing requires transcoding, platform uploads, and OAuth calls — 1-3 minutes. Without async, you'd hit request timeouts.

How to handle async operations:

Video Generation (POST /v1/videos/generate)

  1. Call POST /v1/videos/generate → receives 202 with video post object (status: "pending").
  2. Poll GET /v1/videos/:id/status every 10-30 seconds.
  3. When status is "completed", video_url is ready.
  4. If status is "failed", check error_message. Credits are auto-refunded.
Typical generation time: Veo Fast (2-4 min), Veo Standard (6-10 min), Sora (3-6 min).

Video Publishing (POST /v1/videos/:id/publish)

  1. Call POST /v1/videos/:id/publish → receives 202 (job queued).
  2. Cloud Run worker picks up the job, transcodes video (if needed), uploads to platforms.
  3. Poll GET /v1/videos/:id to check posted_platforms array.
  4. When posted_platforms contains your target platforms, publishing is complete.
Typical publish time: 1-3 minutes (transcoding + platform uploads).

Post Publishing

POST /v1/posts/:id/publish publishes immediately to the specified platforms and returns the result of that publish attempt, including successful platforms and any platform-specific errors.

List content groups

GET/v1/content-groups

Returns all content groups (brands/accounts) for the authenticated user, including connected platforms, social accounts, and content instructions.

Use this endpoint to discover available content groups before creating posts. The returned IDs are used in contentGroupId parameters throughout the API.

curl https://www.postquick.ai/api/v1/content-groups \
  -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "success": true,
  "data": {
    "contentGroups": [
      {
        "id": "uuid-abc-123",
        "name": "My Brand",
        "description": "Tech startup social media",
        "created_at": "2026-03-01T10:00:00Z",
        "app_platforms": [
          { "platform": "instagram" },
          { "platform": "twitter" }
        ],
        "social_accounts": [
          {
            "id": "sa-1",
            "platform": "instagram",
            "account_name": "@mybrand"
          }
        ],
        "content_instructions": {
          "brand_name": "My Brand",
          "tone": "professional",
          "target_audience": "Tech founders",
          "unique_angle": "Developer tools"
        }
      }
    ]
  }
}

Create a content group

POST/v1/content-groups

Creates a new content group (brand/account). Content groups organize your posts and define brand voice for AI generation. Subject to your plan's content group limit (5 for Basic, unlimited for Pro).

Social accounts must be connected separately via OAuth in the dashboard. The API only creates the content group structure.

Parameters

namestringrequired

Display name for the content group (e.g., "My Brand", "Client A").

descriptionstring

Optional description of the brand/account.

platformsstring[]

Array of platform names this group targets. See Supported Platforms.

curl -X POST https://www.postquick.ai/api/v1/content-groups \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My Brand",
    "description": "Tech startup social media",
    "platforms": ["instagram", "twitter", "linkedin"]
  }'
Response
{
  "success": true,
  "data": {
    "contentGroup": {
      "id": "uuid-new-456",
      "name": "My Brand",
      "description": "Tech startup social media",
      "created_at": "2026-03-25T14:30:00Z"
    }
  }
}

Retrieve a content group

GET/v1/content-groups/:id

Retrieves a single content group by ID, including platform connections, connected social accounts, and full content instructions. Returns 404 if the content group doesn't exist or you don't have access to it.

curl https://www.postquick.ai/api/v1/content-groups/uuid-abc-123 \
  -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "success": true,
  "data": {
    "contentGroup": {
      "id": "uuid-abc-123",
      "name": "My Brand",
      "description": "Tech startup social media",
      "created_at": "2026-03-01T10:00:00Z",
      "app_platforms": [
        { "platform": "instagram" },
        { "platform": "twitter" }
      ],
      "social_accounts": [
        { "id": "sa-1", "platform": "instagram", "account_name": "@mybrand" }
      ],
      "content_instructions": {
        "brand_name": "My Brand",
        "tone": "professional",
        "target_audience": "Tech founders",
        "unique_angle": "Developer tools",
        "instructions": "Focus on product updates and thought leadership",
        "image_model": "gemini-flash",
        "video_model": "veo-3.1-fast-generate-preview"
      }
    }
  }
}

Delete a content group

DELETE/v1/content-groups/:id

Permanently deletes a content group and all associated posts (via CASCADE). This cannot be undone. Social account connections are preserved (they can be reused in other content groups).

Returns 404 if the content group doesn't exist or you don't have permission to delete it.

curl -X DELETE https://www.postquick.ai/api/v1/content-groups/uuid-abc-123 \
  -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "success": true,
  "data": {
    "message": "Content group deleted successfully"
  }
}

Get brand instructions

GET/v1/content-groups/:id/instructions

Retrieves the brand profile attached to a content group: brand name, target audience, tone, topics, auto-generation settings, YOLO mode config, and more. These instructions are used to ground every AI-generated post, caption, and image.

Returns instructions: null if no brand profile has been set for this group.

curl https://www.postquick.ai/api/v1/content-groups/uuid-abc-123/instructions \
  -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "success": true,
  "data": {
    "instructions": {
      "app_id": "uuid-abc-123",
      "brand_name": "Acme Fitness",
      "target_audience": "Busy professionals aged 25-40",
      "tone": "Motivating, direct, no-nonsense",
      "topics": "Home workouts, nutrition tips, mindset",
      "instructions": "Always include a clear CTA...",
      "include_image": true,
      "image_model": "nano-banana-pro",
      "auto_generate": false,
      "yolo_mode": false,
      "yolo_platforms": [],
      "frequency": "daily",
      ...
    }
  }
}

Update brand instructions

PUT/v1/content-groups/:id/instructions

Create or update the brand profile attached to a content group. This is an upsert — pass only the fields you want to set. All future AI generation for this group will be grounded in these instructions.

The brand profile drives caption quality significantly. Setting brand_name, target_audience, tone, and topics typically yields the biggest jump in output quality.

Parameters

brand_namestring

The brand or business name.

target_audiencestring

Who the brand speaks to (e.g. "busy parents, 30-50").

tonestring

Voice/tone guidance (e.g. "friendly and confident").

topicsstring

Topics the brand covers.

instructionsstring

Free-form guidance injected into every generation.

image_instructionsstring

Style guidance for image generation.

include_imageboolean

Whether auto-generated posts include images.

image_modelstring

"gemini-flash" | "gpt-image-1.5" | "nano-banana-pro".

auto_generateboolean

Enable cron-based auto post generation.

yolo_modeboolean

Auto-publish generated content to selected platforms.

yolo_platformsstring[]

Platforms to auto-publish to when yolo_mode is true.

generate_carouselsboolean

Generate carousel posts during auto-gen.

generate_videosboolean

Generate video posts during auto-gen.

website_urlstring

Brand website, used for tone/context scraping.

languagestring

Output language (e.g. "en", "es").

curl -X PUT https://www.postquick.ai/api/v1/content-groups/uuid-abc-123/instructions \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "brand_name": "Acme Fitness",
    "target_audience": "Busy professionals, 25-40",
    "tone": "Motivating, direct, no-nonsense",
    "topics": "Home workouts, nutrition, mindset",
    "instructions": "Always end with a clear CTA. Avoid fitness jargon.",
    "include_image": true,
    "image_model": "nano-banana-pro"
  }'
Response
{
  "success": true,
  "data": {
    "instructions": {
      "app_id": "uuid-abc-123",
      "brand_name": "Acme Fitness",
      "tone": "Motivating, direct, no-nonsense",
      ...
      "updated_at": "2026-04-17T09:31:02Z"
    }
  }
}

Group analytics

GET/v1/content-groups/:id/analytics

Returns aggregate social performance analytics for all posts in a content group: totals (views, likes, comments, shares, saves), per-platform breakdown, per-content-type breakdown, top 10 posts by views, and a daily trend.

Metrics are refreshed by the background analytics cron every 4 hours. lastFetched in each platform row tells you when that value was captured.

Parameters

periodstring

Time window: "7d", "30d" (default), or "90d".

curl "https://www.postquick.ai/api/v1/content-groups/uuid-abc-123/analytics?period=30d" \
  -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "success": true,
  "data": {
    "groupId": "uuid-abc-123",
    "groupName": "Acme Fitness",
    "period": "30d",
    "totals": {
      "views": 145230,
      "likes": 8912,
      "comments": 423,
      "shares": 1104,
      "saves": 678,
      "engagementRate": 0.0720
    },
    "platformBreakdown": [
      { "platform": "instagram", "totalViews": 89210, "totalLikes": 5612, "postCount": 18, "avgEngagementRate": 0.083 },
      { "platform": "twitter_x", "totalViews": 56020, "totalLikes": 3300, "postCount": 22, "avgEngagementRate": 0.061 }
    ],
    "contentTypeBreakdown": [
      { "postType": "carousel", "postCount": 12, "totalViews": 72100, "avgEngagementRate": 0.092 },
      { "postType": "video", "postCount": 5, "totalViews": 41230, "avgEngagementRate": 0.071 }
    ],
    "topPosts": [
      { "postId": "post-1", "postType": "carousel", "totalViews": 15420, "engagementRate": 0.11, "platforms": ["instagram"] }
    ],
    "dailyTrend": [
      { "date": "2026-03-20", "views": 4821, "likes": 312, "comments": 14, "shares": 42 }
    ],
    "totalPostsWithAnalytics": 40
  }
}

Generate a post

POST/v1/posts/generate

Uses AI to generate a complete social media post based on your content group's brand instructions, tone, target audience, and content strategy. The AI analyzes your brand profile and creates on-brand content automatically.

Optionally generates an accompanying image (consumes 1 image credit). The post is created with status "pending" and can be edited before publishing.

Consumes: 1 text generation credit (+ 1 image credit if generateImage: true).

Parameters

contentGroupIdstringrequired

The content group to generate for. The group's brand profile, tone, and instructions shape the AI output.

generateImageboolean

Whether to also generate an AI image for the post. Defaults to false. Consumes an additional image generation credit.

curl -X POST https://www.postquick.ai/api/v1/posts/generate \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "contentGroupId": "uuid-abc-123",
    "generateImage": true
  }'
Response
{
  "success": true,
  "data": {
    "post": {
      "id": "post-xyz-789",
      "app_id": "uuid-abc-123",
      "content": "Just shipped our new AI dashboard ✨\n\nThree months of late nights, 47 cups of coffee, and one very patient designer later — it's live.\n\nThe best tools don't just work. They disappear.\n\n#buildinpublic #saas #ai",
      "status": "pending",
      "post_type": "image",
      "image_url": "https://storage.postquick.ai/post-images/user-123/gemini-flash-abc.png",
      "image_urls": null,
      "video_url": null,
      "platforms": ["instagram", "twitter"],
      "posted_platforms": [],
      "is_manual": false,
      "scheduled_for": null,
      "error_message": null,
      "created_at": "2026-03-25T14:30:00Z",
      "updated_at": null,
      "posted_at": null
    }
  }
}

Create a post

POST/v1/posts/create

Manually create a post with your own content. Supports text, single image, carousel (2-10 images), and video post types. Does not consume generation credits.

Media URLs must be publicly accessible. The API does not upload files — host your media on your own CDN or use the /images/generate endpoint to create AI images.

Parameters

contentGroupIdstringrequired

The content group this post belongs to.

contentstringrequired

The post text/caption. Can include hashtags and emojis.

postTypestringrequired

One of: "text", "image", "carousel", "video". Determines which media fields are required.

platformsstring[]

Target platforms for publishing. Defaults to the content group's configured platforms.

imageUrlstring

Public URL of the image (required for postType: "image").

imageUrlsstring[]

Array of 2-10 public image URLs (required for postType: "carousel").

videoUrlstring

Public URL of the video (required for postType: "video").

isDraftboolean

Save as draft (status: "draft") instead of pending. Default: false.

scheduledForstring

ISO 8601 timestamp for scheduled publishing. Must be in the future.

linkedinTargetobject

LinkedIn target: { type: "personal" | "organization", organizationId?: string }. Required when publishing to LinkedIn.

facebookTargetobject

Facebook page target: { pageId: string, pageName?: string }. Required when publishing to Facebook.

threadPartsobject[]

Array of thread parts for reply-based threads. Supported on Twitter/X, Threads, and Bluesky — each part is posted as a reply to the previous. Format: [{ text, image_urls?, video_url?, post_type }]. The root content field should match the first part. Minimum 2 parts.

curl -X POST https://www.postquick.ai/api/v1/posts/create \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "contentGroupId": "uuid-abc-123",
    "content": "Excited to announce our Series A! 🚀\n\n$10M led by @ventureCapital to scale our platform.\n\nThank you to everyone who believed in us.\n\n#startup #funding",
    "postType": "image",
    "platforms": ["instagram", "twitter", "linkedin"],
    "imageUrl": "https://example.com/announcement.jpg"
  }'
Response
{
  "success": true,
  "data": {
    "post": {
      "id": "post-manual-456",
      "app_id": "uuid-abc-123",
      "content": "Excited to announce our Series A! 🚀...",
      "status": "pending",
      "post_type": "image",
      "image_url": "https://example.com/announcement.jpg",
      "platforms": ["instagram", "twitter", "linkedin"],
      "posted_platforms": [],
      "is_manual": true,
      "created_at": "2026-03-25T14:45:00Z"
    }
  }
}

Creating a reply thread

Pass threadParts to create a multi-part thread. Each part is posted as a reply to the previous one on twitter_x, threads, and bluesky. Other platforms will only post the first part.

{
  "contentGroupId": "uuid-abc-123",
  "content": "The 3 biggest mistakes new founders make (a thread) 🧵",
  "postType": "text",
  "platforms": ["twitter_x", "threads", "bluesky"],
  "threadParts": [
    { "text": "The 3 biggest mistakes new founders make (a thread) 🧵", "post_type": "text" },
    { "text": "1/ Hiring too fast. Team size is a lagging indicator of success, not a leading one.", "post_type": "text" },
    { "text": "2/ Building in secret. Customers can't validate what they can't see.", "post_type": "text" },
    { "text": "3/ Ignoring retention. Growth without retention is a leaky bucket.", "post_type": "text" }
  ]
}

List posts

GET/v1/posts?contentGroupId=...&status=...

Returns all posts for a content group, optionally filtered by status. Results are sorted by created_at descending (newest first). Use this to build content calendars, dashboards, or monitoring tools.

Status filtering is useful for building queues: pending for drafts awaiting publish, scheduled for upcoming posts, posted for published content.

Query Parameters

contentGroupIdstringrequired

Filter by content group. Returns 400 if missing.

statusstring

Filter by status: "pending", "draft", "posted", "scheduled", "failed", "processing", "published".

curl "https://www.postquick.ai/api/v1/posts?contentGroupId=uuid-abc-123&status=pending" \
  -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "success": true,
  "data": {
    "posts": [
      {
        "id": "post-1",
        "content": "Post content here...",
        "status": "pending",
        "post_type": "image",
        "image_url": "https://...",
        "platforms": ["instagram"],
        "created_at": "2026-03-25T14:30:00Z"
      },
      {
        "id": "post-2",
        "content": "Another post...",
        "status": "pending",
        "post_type": "text",
        "platforms": ["twitter"],
        "created_at": "2026-03-25T12:00:00Z"
      }
    ]
  }
}

Retrieve a post

GET/v1/posts/:id

Retrieves a single post by ID with the complete object schema. Returns 404 if the post doesn't exist or you don't have access to it.

Use this to check publish status, fetch the latest version before editing, or retrieve media URLs.

curl https://www.postquick.ai/api/v1/posts/post-xyz-789 \
  -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "success": true,
  "data": {
    "post": {
      "id": "post-xyz-789",
      "app_id": "uuid-abc-123",
      "content": "Just shipped our new AI dashboard ✨...",
      "status": "posted",
      "post_type": "image",
      "image_url": "https://storage.postquick.ai/...",
      "platforms": ["instagram", "twitter"],
      "posted_platforms": ["instagram", "twitter"],
      "created_at": "2026-03-25T14:30:00Z",
      "posted_at": "2026-03-25T15:00:00Z"
    }
  }
}

Update a post

PUT/v1/posts/:id

Update a post's content, platforms, media URLs, or scheduling. Only provided fields are updated (partial update). Cannot update posts that have already been published (status "posted" or "published").

Returns 404 if the post doesn't exist, 409 if the post is already published or processing.

Parameters

contentstring

Updated post text/caption.

platformsstring[]

Updated target platforms.

imageUrlstring

Updated image URL (for image posts).

imageUrlsstring[]

Updated image URLs (for carousel posts).

scheduledForstring

Updated scheduled time (ISO 8601).

threadPartsobject[]

Replace the reply-thread structure. Pass an empty array to convert back to a single post. Format: [{ text, image_urls?, video_url?, post_type }].

curl -X PUT https://www.postquick.ai/api/v1/posts/post-xyz-789 \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Updated caption with new CTA ✨\n\nClick link in bio!",
    "platforms": ["instagram", "twitter", "threads"]
  }'
Response
{
  "success": true,
  "data": {
    "post": {
      "id": "post-xyz-789",
      "content": "Updated caption with new CTA ✨\n\nClick link in bio!",
      "platforms": ["instagram", "twitter", "threads"],
      "updated_at": "2026-03-25T15:30:00Z",
      ...
    }
  }
}

Delete a post

DELETE/v1/posts/:id

Permanently deletes a post. This cannot be undone. Deleting a post does not un-publish it from platforms — it only removes it from your PostQuickAI account.

Returns 404 if the post doesn't exist or you don't have permission to delete it.

curl -X DELETE https://www.postquick.ai/api/v1/posts/post-xyz-789 \
  -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "success": true,
  "data": {
    "message": "Post deleted successfully"
  }
}

Publish a post

POST/v1/posts/:id/publish

Publishes a post to the specified platforms immediately. Requires connected social accounts on the content group and returns the publish result, including successful platforms and any platform-specific errors.

Returns 403 if you don't have connected accounts for the target platforms.

Platform-specific requirements:

  • LinkedIn: requires linkedinTarget
  • Facebook: requires facebookTarget
  • TikTok: image posts require min 2 images, text-only not supported
  • Instagram: requires business/creator account

Parameters

platformsstring[]required

Platforms to publish to. Must have connected accounts for each.

linkedinTargetobject

LinkedIn target: { type: "personal" | "organization", organizationId?: string }.

facebookTargetobject

Facebook page target: { pageId: string, pageName?: string }.

curl -X POST https://www.postquick.ai/api/v1/posts/post-xyz-789/publish \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "platforms": ["instagram", "twitter"]
  }'
Response
{
  "success": true,
  "data": {
    "post": {
      "id": "post-xyz-789",
      "status": "posted",
      "posted_platforms": ["instagram", "twitter"],
      "posted_at": "2026-03-25T15:00:00Z",
      ...
    },
    "publishedTo": ["instagram", "twitter"],
    "errors": []
  }
}

Partial Failure Handling

If publishing fails on some platforms but succeeds on others, the post status remains "posted", posted_platforms contains successful platforms, and errors array contains failure details.

Schedule a post

POST/v1/posts/:id/schedule

Schedules a post for future publishing. The cron system automatically publishes it at the specified time (runs every 15 minutes). Post status changes to "scheduled".

The scheduled time must be at least 5 minutes in the future. Returns 400 if scheduledFor is in the past or too soon.

To cancel a scheduled post, update its status to "draft" via PUT /v1/posts/:id or delete it.

Parameters

contentGroupIdstringrequired

The content group the post belongs to.

scheduledForstringrequired

ISO 8601 timestamp. Must be at least 5 minutes in the future.

platformsstring[]

Override the post's target platforms. If omitted, uses post.platforms.

curl -X POST https://www.postquick.ai/api/v1/posts/post-xyz-789/schedule \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "contentGroupId": "uuid-abc-123",
    "scheduledFor": "2026-04-01T10:00:00Z",
    "platforms": ["instagram", "twitter"]
  }'
Response
{
  "success": true,
  "data": {
    "post": {
      "id": "post-xyz-789",
      "status": "scheduled",
      "scheduled_for": "2026-04-01T10:00:00Z",
      "platforms": ["instagram", "twitter"],
      ...
    }
  }
}

Regenerate a post

POST/v1/posts/:id/regenerate

Rewrites an existing post's content using AI based on natural-language feedback. Optionally also regenerates the attached image.

Counts as 1 AI text request. If generateImage: true, also counts as 1 image generation against your monthly image limit.

Parameters

instructionsstringrequired

Feedback guiding the rewrite (e.g. "make it shorter and less salesy").

generateImageboolean

If true, also regenerate the image. Default: false.

imageModelstring

"gemini-flash" | "gpt-image-1.5" | "nano-banana-pro". Default: "gemini-flash".

curl -X POST https://www.postquick.ai/api/v1/posts/post-xyz-789/regenerate \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "instructions": "Make it shorter, more punchy, and add a clear CTA.",
    "generateImage": false
  }'
Response
{
  "success": true,
  "data": {
    "post": {
      "id": "post-xyz-789",
      "content": "(rewritten text)",
      "image_url": "...",
      "updated_at": "2026-04-17T09:42:00Z",
      ...
    }
  }
}

Update post images

PUT/v1/posts/:id/images

Attach, replace, or remove images on a post. Useful for swapping in a custom image after generation or preparing a post for re-publish.

Parameters

actionstringrequired

"set_single_image", "set_multiple_images", "remove_all_images", or "remove_single_image".

imageUrlstring

Required when action is "set_single_image". Must be a publicly accessible URL.

imageUrlsstring[]

Required when action is "set_multiple_images". Carousel slides, in order.

curl -X PUT https://www.postquick.ai/api/v1/posts/post-xyz-789/images \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "set_multiple_images",
    "imageUrls": [
      "https://cdn.example.com/slide1.jpg",
      "https://cdn.example.com/slide2.jpg"
    ]
  }'
Response
{
  "success": true,
  "data": {
    "post": {
      "id": "post-xyz-789",
      "image_url": null,
      "image_urls": ["https://cdn.example.com/slide1.jpg", "https://cdn.example.com/slide2.jpg"],
      ...
    }
  }
}

Reset posted platforms

POST/v1/posts/:id/reset-platforms

Clears the posted_platforms array and error_message on a post. Use after fixing a failed publish so POST /v1/posts/:id/publish will retry every platform cleanly.

curl -X POST https://www.postquick.ai/api/v1/posts/post-xyz-789/reset-platforms \
  -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "success": true,
  "data": {
    "post": {
      "id": "post-xyz-789",
      "posted_platforms": [],
      "error_message": null,
      ...
    }
  }
}

Post analytics

GET/v1/posts/:id/analytics

Returns per-platform social performance metrics (views, likes, comments, shares, saves) for a single post, plus a 30-day history. Metrics are refreshed every 4 hours by the background analytics cron.

For video posts, pass ?type=video.

Parameters

typestring

"post" (default) or "video". Determines which table the ID refers to.

curl https://www.postquick.ai/api/v1/posts/post-xyz-789/analytics \
  -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "success": true,
  "data": {
    "postId": "post-xyz-789",
    "postType": "post",
    "totals": {
      "views": 15420,
      "likes": 892,
      "comments": 41,
      "shares": 104,
      "saves": 23,
      "engagementRate": 0.067
    },
    "platforms": [
      { "platform": "instagram", "views": 12100, "likes": 780, "comments": 35, "shares": 82, "fetched_at": "2026-04-17T08:00:00Z" },
      { "platform": "twitter_x", "views": 3320, "likes": 112, "comments": 6, "shares": 22, "fetched_at": "2026-04-17T08:00:00Z" }
    ],
    "history": [
      { "snapshot_date": "2026-04-15", "views": 8210, "likes": 512, "comments": 22 }
    ],
    "lastFetched": "2026-04-17T08:00:00Z"
  }
}

Generate a caption

POST/v1/captions/generate

Generates a social media caption using AI, grounded in your content group's brand profile (tone, target audience, unique angle). Uses GPT-4.1 or Claude 3.7 based on your plan. Subject to monthly AI text generation limits (400/month for Basic, 2,000/month for Pro).

Returns 403 if you've exceeded your monthly AI text usage limit. This limit is shared across dashboard and API usage.

If you provide a content group ID, the AI personalizes the caption using the group's content instructions. Without a content group, the AI generates generic captions.

Parameters

topicstringrequired

The topic or theme for the caption (e.g., "Product launch announcement", "Weekend motivation").

contentGroupIdstring

Content group ID to ground the caption in brand voice. Highly recommended for brand-consistent content.

platformstring

Target platform (instagram, twitter, linkedin, etc.). Optimizes caption length and style for that platform.

lengthstring

Desired length: "short" (1-2 sentences), "medium" (2-4 sentences), "long" (5+ sentences). Default: "medium".

curl -X POST https://www.postquick.ai/api/v1/captions/generate \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "topic": "New AI feature launch",
    "contentGroupId": "uuid-abc-123",
    "platform": "instagram",
    "length": "medium"
  }'
Response
{
  "success": true,
  "data": {
    "caption": "🚀 We just launched our most powerful AI feature yet — automated content scheduling that learns YOUR brand voice.\n\nNo more generic posts. No more copy-paste templates. Just authentic content that sounds like you.\n\nTry it free for 14 days. Link in bio. 👆\n\n#AIMarketing #ContentCreation #SocialMediaAutomation"
  }
}

Usage Limits

Each caption generation counts as 1 AI text request against your monthly limit. Check your remaining usage with GET /v1/usage. Exceeding the limit returns 403.

Generate video caption

POST/v1/captions/video

Generates a caption optimized for video posts (Reels, TikToks, YouTube Shorts, LinkedIn videos). The AI uses video-specific hooks, calls-to-action, and engagement patterns.

For AI-generated videos, you can pass the video description/prompt to help the AI create a contextual caption. For user-uploaded videos, describe the video content in the topic field.

Parameters

topicstringrequired

Video topic or the original video generation prompt.

contentGroupIdstring

Content group ID for brand voice.

platformstring

Target platform (instagram, tiktok, youtube, linkedin). Default: "instagram".

durationnumber

Video duration in seconds. Helps AI reference "watch till the end" for longer videos.

curl -X POST https://www.postquick.ai/api/v1/captions/video \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "topic": "Behind the scenes of our product design process",
    "contentGroupId": "uuid-abc-123",
    "platform": "instagram",
    "duration": 30
  }'
Response
{
  "success": true,
  "data": {
    "caption": "POV: You're watching our actual design process 🎨\n\n30 seconds from idea → prototype → final product.\n\nThis is how we ship fast without sacrificing quality.\n\nDrop a 🔥 if you want the full breakdown.\n\n#ProductDesign #BehindTheScenes #StartupLife"
  }
}

Adjust tone

POST/v1/content/adjust-tone

Rewrites existing content in a different tone while preserving the core message. Supports 10+ tones: professional, casual, friendly, enthusiastic, formal, humorous, inspirational, educational, storytelling, urgent.

Grounded in your content group's brand profile if provided. Counts as 1 AI text request against your monthly limit.

Use this to quickly A/B test different tones for the same post, or adapt content for different platforms (e.g., professional for LinkedIn, casual for Instagram).

Parameters

contentstringrequired

The original text to rewrite.

targetTonestringrequired

Desired tone: "professional", "casual", "friendly", "enthusiastic", "formal", "humorous", "inspirational", "educational", "storytelling", "urgent".

contentGroupIdstring

Content group ID to ground the rewrite in brand voice. Ensures the new tone still sounds like your brand.

curl -X POST https://www.postquick.ai/api/v1/content/adjust-tone \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "We launched a new feature. Check it out.",
    "targetTone": "enthusiastic",
    "contentGroupId": "uuid-abc-123"
  }'
Response
{
  "success": true,
  "data": {
    "adjustedContent": "🎉 We just dropped our most exciting feature yet! This is HUGE — you're gonna love it. Go check it out right now! 🚀",
    "originalTone": "neutral",
    "newTone": "enthusiastic"
  }
}

Tone Reference

  • Professional: Corporate, polished, authoritative
  • Casual: Relaxed, conversational, approachable
  • Friendly: Warm, welcoming, personal
  • Enthusiastic: Energetic, excited, positive
  • Formal: Official, respectful, traditional
  • Humorous: Funny, witty, entertaining
  • Inspirational: Motivating, uplifting, empowering
  • Educational: Informative, clear, teaching-focused
  • Storytelling: Narrative, engaging, descriptive
  • Urgent: Time-sensitive, action-oriented, pressing

Proofread

POST/v1/content/proofread

Proofreads content for grammar, spelling, punctuation, and clarity issues. Returns the corrected text plus a detailed list of changes with explanations.

Preserves tone and style — only fixes errors, doesn't rewrite. Counts as 1 AI text request.

Useful for quality control before publishing, especially for user-generated content or quick drafts.

Parameters

contentstringrequired

The text to proofread.

contentGroupIdstring

Content group ID. Optional but helps AI understand brand-specific terminology.

curl -X POST https://www.postquick.ai/api/v1/content/proofread \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Were launching are new feature tommorow. Its going to be amazing, you should definitly check it out!"
  }'
Response
{
  "success": true,
  "data": {
    "correctedContent": "We're launching our new feature tomorrow. It's going to be amazing, you should definitely check it out!",
    "corrections": [
      {
        "type": "spelling",
        "original": "Were",
        "corrected": "We're",
        "explanation": "Missing apostrophe in contraction"
      },
      {
        "type": "grammar",
        "original": "are",
        "corrected": "our",
        "explanation": "Wrong word - 'our' is possessive, 'are' is verb"
      },
      {
        "type": "spelling",
        "original": "tommorow",
        "corrected": "tomorrow",
        "explanation": "Misspelled word"
      },
      {
        "type": "spelling",
        "original": "definitly",
        "corrected": "definitely",
        "explanation": "Common misspelling"
      }
    ],
    "hasErrors": true
  }
}

Make concise

POST/v1/content/make-concise

Shortens content while preserving the core message and key details. Removes filler words, redundancies, and unnecessary clauses. Useful for fitting content within platform character limits (Twitter 280 chars) or improving readability.

You can specify a target character or word count. The AI will aim for that length while keeping the essential meaning.

Counts as 1 AI text request against your monthly limit.

Parameters

contentstringrequired

The text to shorten.

contentGroupIdstring

Content group ID for brand voice preservation.

targetLengthnumber

Target character count (e.g., 280 for Twitter). AI will aim for this length.

preserveToneboolean

If true, maintains original tone. If false, optimizes for brevity even if tone shifts slightly. Default: true.

curl -X POST https://www.postquick.ai/api/v1/content/make-concise \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "I wanted to take a moment to share with you all that we have just launched our brand new feature that we have been working on for several months now. It is something that I think you are all really going to love and appreciate, and I would highly encourage everyone to go ahead and check it out when you get a chance.",
    "targetLength": 280
  }'
Response
{
  "success": true,
  "data": {
    "conciseContent": "Just launched our new feature after months of work. We think you'll love it — check it out!",
    "originalLength": 285,
    "newLength": 94,
    "reduction": "67%"
  }
}

Custom edit

POST/v1/content/custom-edit

Applies a custom editing instruction to content. Pass free-form natural language instructions like "add more emojis", "remove the sales pitch", "make it sound more technical", "add a call-to-action at the end".

This is the most flexible content editing endpoint — use it when the other specialized endpoints (tone, proofread, concise) don't match your exact need.

Grounded in content group brand profile if provided. Counts as 1 AI text request.

Parameters

contentstringrequired

The original text to edit.

instructionstringrequired

Natural language editing instruction (e.g., "add more emojis and make it fun", "remove technical jargon").

contentGroupIdstring

Content group ID for brand voice grounding.

curl -X POST https://www.postquick.ai/api/v1/content/custom-edit \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "We launched a new feature. It helps you schedule posts.",
    "instruction": "Add emojis and a strong call-to-action at the end",
    "contentGroupId": "uuid-abc-123"
  }'
Response
{
  "success": true,
  "data": {
    "editedContent": "🚀 We just launched a game-changing new feature! It helps you schedule posts effortlessly.\n\nTry it now and never miss a posting window again! 👉",
    "instruction": "Add emojis and a strong call-to-action at the end"
  }
}

Example Instructions

  • "Make it shorter and punchier"
  • "Add 3 relevant emojis"
  • "Remove the first sentence"
  • "Add a question at the end to boost engagement"
  • "Replace technical terms with simple language"
  • "Add line breaks for better readability"
  • "Make it sound more confident and assertive"

Generate hashtags

POST/v1/hashtags/generate

Generates relevant hashtags for a post based on its content and target platform. Returns a mix of popular, niche, and branded hashtags optimized for discoverability.

Hashtag counts vary by platform: Instagram allows 30, Twitter best practice is 1-2, LinkedIn 3-5, TikTok 3-5. The AI adjusts recommendations based on the target platform.

Counts as 1 AI text request against your monthly limit.

Parameters

contentstringrequired

The post content to generate hashtags for.

platformstring

Target platform. Default: "instagram".

countnumber

Number of hashtags to generate. Default: platform-specific optimal count.

contentGroupIdstring

Content group ID. Helps include brand-specific hashtags if defined in content instructions.

curl -X POST https://www.postquick.ai/api/v1/hashtags/generate \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Just finished an amazing workout session. Feeling energized and ready to take on the day!",
    "platform": "instagram",
    "count": 10
  }'
Response
{
  "success": true,
  "data": {
    "hashtags": [
      "#Fitness",
      "#WorkoutMotivation",
      "#MorningWorkout",
      "#FitnessJourney",
      "#HealthyLifestyle",
      "#FitFam",
      "#GymLife",
      "#WorkoutComplete",
      "#FitnessGoals",
      "#ActiveLifestyle"
    ],
    "platform": "instagram",
    "count": 10
  }
}

Generate an image

POST/v1/images/generate

Generates an AI image using one of 3 models: Gemini Flash (default, fast, good quality), GPT Image 1.5 (high quality), or Nano Banana Pro (premium photorealistic/stylized).

Subject to monthly image generation limits: 100/month for Basic, 500/month for Pro. This limit is shared across dashboard and API usage. Returns 403 if limit exceeded.

Generated images are automatically stored in your PostQuickAI account and accessible via the dashboard Files page. The response includes a direct URL to the image (hosted on Supabase Storage).

Recommended aspect ratios by platform:

  • Instagram feed: 1:1 (square) or 4:5 (portrait)
  • Instagram Stories/Reels: 9:16 (vertical)
  • Twitter: 16:9 (landscape) or 1:1
  • LinkedIn: 1.91:1 or 1:1
  • TikTok: 9:16 (vertical)

Parameters

promptstringrequired

Detailed image generation prompt. Be specific: describe subject, style, lighting, composition, mood.

modelstring

Image model: "gemini-flash" (default), "gpt-image-1.5", "nano-banana-pro". See Image Models reference.

aspectRatiostring

Aspect ratio: "1:1", "4:5", "9:16", "16:9", "3:4", "4:3". Default: "1:1".

contentGroupIdstring

Content group ID. If provided, the prompt is grounded in the group's brand profile for consistent visual style.

curl -X POST https://www.postquick.ai/api/v1/images/generate \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "A modern minimalist office workspace with a laptop, coffee cup, and plants. Natural lighting, warm tones, clean aesthetic. Professional but cozy.",
    "model": "gemini-flash",
    "aspectRatio": "4:5",
    "contentGroupId": "uuid-abc-123"
  }'
Response
{
  "success": true,
  "data": {
    "imageUrl": "https://your-project.supabase.co/storage/v1/object/public/post-images/user-uuid/1711234567890-image.png",
    "model": "gemini-flash",
    "aspectRatio": "4:5",
    "width": 1080,
    "height": 1350,
    "prompt": "A modern minimalist office workspace with a laptop, coffee cup, and plants. Natural lighting, warm tones, clean aesthetic. Professional but cozy."
  }
}

Model Comparison

  • Gemini Flash: Best for most use cases. Fast (3-8s), good quality, reliable. Default choice.
  • GPT Image 1.5: Higher quality, better at complex prompts and text rendering. Slightly slower (8-15s).
  • Nano Banana Pro: Premium photorealistic or stylized. Best for product photos, portraits, creative content (5-10s).

Generate a video

POST/v1/videos/generate

Generates an AI video using Google Veo or OpenAI Sora models. This is an async operation: the endpoint returns 202 Accepted immediately with a video ID, then the video generates in the background (2-10 minutes depending on model and duration).

Workflow: POST to generate → poll GET /v1/videos/:id/status every 10-30 seconds until status is "completed" → retrieve video with GET /v1/videos/:id.

Video generation costs video credits (not monthly usage limits). Veo Fast and Sora 2 cost 1 credit each. Veo 3.1 and Sora 2 Pro cost 3 credits each. Users get 100 credits/month (Basic) or 500 credits/month (Pro). Check remaining credits with GET /v1/usage.

Returns 403 if you don't have enough video credits. Returns 400 if prompt is invalid or parameters are out of range.

Parameters

promptstringrequired

Detailed video generation prompt. Describe the scene, action, camera movement, style. Max 500 characters.

modelstring

Video model: "veo-3.1-fast-generate-preview" (1 credit, default), "veo-3.1-generate-preview" (3 credits), "sora-2" (1 credit), "sora-2-pro" (3 credits). See Video Models reference.

durationnumber

Video duration in seconds. Veo: 4, 6, or 8. Sora: 4, 8, or 12. Default: 6.

aspectRatiostring

Aspect ratio: "9:16" (portrait, TikTok/Reels) or "16:9" (landscape, YouTube). Default: "9:16".

contentGroupIdstring

Content group ID. Grounds the video style in your brand profile.

curl -X POST https://www.postquick.ai/api/v1/videos/generate \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "A close-up of coffee being poured into a white ceramic mug on a wooden table. Morning sunlight streaming through a window. Slow motion, cinematic, warm tones.",
    "model": "veo-3.1-fast-generate-preview",
    "duration": 6,
    "aspectRatio": "9:16",
    "contentGroupId": "uuid-abc-123"
  }'
Response
{
  "success": true,
  "data": {
    "video": {
      "id": "video-uuid-xyz-789",
      "title": "Coffee pouring cinematic",
      "description": "A close-up of coffee being poured into a white ceramic mug on a wooden table. Morning sunlight streaming through a window. Slow motion, cinematic, warm tones.",
      "status": "generating",
      "model": "veo-3.1-fast-generate-preview",
      "duration": 6,
      "aspectRatio": "9:16",
      "creditsUsed": 1,
      "created_at": "2026-03-25T16:00:00Z",
      "video_url": null
    },
    "estimatedCompletionTime": "2-5 minutes"
  }
}

Polling Best Practices

Poll GET /v1/videos/:id/status every 15-30 seconds. Don't poll more frequently — video generation takes 2-10 minutes regardless.

Faster models (Veo Fast, Sora 2): ~2-4 min. Slower models (Veo 3.1, Sora Pro): ~5-10 min. If status is "failed", credits are auto-refunded.

Retrieve a video

GET/v1/videos/:id

Retrieves full details for a video by ID, including video URL (when completed), status, metadata, and publishing history.

Returns 404 if the video doesn't exist or you don't have access to it.

The video_url field is null until status is "completed". Use GET /v1/videos/:id/status for lightweight polling.

curl https://www.postquick.ai/api/v1/videos/video-uuid-xyz-789 \
  -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "success": true,
  "data": {
    "video": {
      "id": "video-uuid-xyz-789",
      "app_id": "uuid-abc-123",
      "user_id": "user-uuid-123",
      "title": "Coffee pouring cinematic",
      "description": "A close-up of coffee being poured into a white ceramic mug...",
      "status": "completed",
      "video_url": "https://your-project.supabase.co/storage/v1/object/public/videos/user-uuid/video-xyz.mp4",
      "optimized_video_url": "https://your-project.supabase.co/storage/v1/object/public/videos/user-uuid/video-xyz-optimized.mp4",
      "duration": 6,
      "platforms": ["instagram", "tiktok"],
      "posted_platforms": [],
      "scheduled_for": null,
      "error_message": null,
      "created_at": "2026-03-25T16:00:00Z",
      "updated_at": "2026-03-25T16:04:32Z"
    }
  }
}

Check video status

GET/v1/videos/:id/status

Lightweight endpoint for polling video generation progress. Returns only status, video_url, and error_message (if any).

Use this instead of GET /v1/videos/:id when polling for completion to reduce response size and latency.

Status values:

  • "generating" — video is being created (poll every 15-30s)
  • "completed" — video ready, video_url available
  • "failed" — generation failed, credits refunded, see error_message
  • "processing" — video is being published (after calling publish endpoint)
  • "posted" — successfully published to platforms
curl https://www.postquick.ai/api/v1/videos/video-uuid-xyz-789/status \
  -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "success": true,
  "data": {
    "status": "completed",
    "video_url": "https://your-project.supabase.co/storage/v1/object/public/videos/user-uuid/video-xyz.mp4",
    "error_message": null
  }
}

Delete a video

DELETE/v1/videos/:id

Deletes a video and its associated files from storage. Video credits are NOT refunded when deleting completed videos (only refunded automatically if generation fails).

You can delete videos in any status: generating, completed, failed, posted. If the video is currently generating, the generation process is cancelled.

Returns 404 if the video doesn't exist or you don't have access to it.

curl -X DELETE https://www.postquick.ai/api/v1/videos/video-uuid-xyz-789 \
  -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "success": true,
  "data": {
    "message": "Video deleted successfully"
  }
}

Publish a video

POST/v1/videos/:id/publish

This is an async operation. Returns 202 Accepted immediately and dispatches the video to our Cloud Run publishing service. The actual publish happens in the background (5-60 seconds depending on video preprocessing needs).

Video must be in "completed" status. Returns 400 if video is still generating or already published. Returns 409 if video is currently processing.

Check publish progress by polling GET /v1/videos/:id/status — status will change from "completed""processing""posted".

Requires connected social accounts on the content group. Returns 403 if you don't have accounts connected for the target platforms.

Parameters

contentGroupIdstringrequired

The content group the video belongs to. Used to fetch connected social accounts.

platformsstring[]required

Platforms to publish to. Must have connected accounts for each.

captionstring

Video caption/description. If omitted, uses the video's original generation prompt as the caption.

linkedinTargetobject

LinkedIn target: { type: "personal" | "organization", organizationId?: string }.

facebookTargetobject

Facebook page target: { pageId: string, pageName?: string }.

curl -X POST https://www.postquick.ai/api/v1/videos/video-uuid-xyz-789/publish \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "contentGroupId": "uuid-abc-123",
    "platforms": ["instagram", "tiktok"],
    "caption": "Morning coffee vibes ☕️✨ #CoffeeLovers #MorningRoutine"
  }'
Response
{
  "success": true,
  "data": {
    "message": "Video publishing initiated. Check status at GET /v1/videos/:id/status",
    "video": {
      "id": "video-uuid-xyz-789",
      "status": "processing",
      ...
    }
  }
}

Schedule a video

POST/v1/videos/:id/schedule

Schedules a video for future publishing. The cron system automatically publishes it at the specified time (runs every 15 minutes). Video status changes to "scheduled".

Video must be in "completed" status. The scheduled time must be at least 5 minutes in the future. Returns 400 if scheduledFor is in the past or video is not completed.

To cancel a scheduled video, update it back to "completed" status or delete it.

Parameters

scheduledForstringrequired

ISO 8601 timestamp. Must be at least 5 minutes in the future.

platformsstring[]required

Platforms to publish to when the scheduled time arrives.

captionstring

Video caption to use when publishing.

curl -X POST https://www.postquick.ai/api/v1/videos/video-uuid-xyz-789/schedule \
  -H "Authorization: Bearer pq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "scheduledFor": "2026-04-01T14:00:00Z",
    "platforms": ["instagram", "tiktok"],
    "caption": "Happy Monday! ☕️"
  }'
Response
{
  "success": true,
  "data": {
    "video": {
      "id": "video-uuid-xyz-789",
      "status": "scheduled",
      "scheduled_for": "2026-04-01T14:00:00Z",
      "platforms": ["instagram", "tiktok"],
      ...
    }
  }
}

Reset video posted platforms

POST/v1/videos/:id/reset-platforms

Clears posted_platforms, error_message, and per-platform error state on a video so it can be republished cleanly.

curl -X POST https://www.postquick.ai/api/v1/videos/video-abc-456/reset-platforms \
  -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "success": true,
  "data": {
    "video": {
      "id": "video-abc-456",
      "posted_platforms": [],
      "error_message": null,
      ...
    }
  }
}

List connected accounts

GET/v1/accounts

Returns all social media accounts connected to your PostQuickAI user account, grouped by platform. Includes account metadata like username, profile picture, account type (personal/business), and connection status.

Social accounts must be connected via OAuth in the dashboard — the API cannot connect new accounts, only read existing connections.

Use this endpoint to verify which platforms you can publish to before calling publish/schedule endpoints.

curl https://www.postquick.ai/api/v1/accounts \
  -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "success": true,
  "data": {
    "accounts": [
      {
        "id": "acc-uuid-123",
        "platform": "instagram",
        "account_name": "@mybrand",
        "account_type": "business",
        "profile_picture_url": "https://...",
        "is_active": true,
        "connected_at": "2026-01-15T10:30:00Z"
      },
      {
        "id": "acc-uuid-456",
        "platform": "twitter",
        "account_name": "@mybrand",
        "account_type": "personal",
        "is_active": true,
        "connected_at": "2026-01-20T14:00:00Z"
      },
      {
        "id": "acc-uuid-789",
        "platform": "linkedin",
        "account_name": "John Doe",
        "account_type": "personal",
        "is_active": true,
        "connected_at": "2026-02-01T09:00:00Z"
      }
    ],
    "total": 3
  }
}

Disconnect a social account

DELETE/v1/accounts/:id

Permanently disconnect a social account from its content group. This deletes the OAuth tokens stored by PostQuickAI and prevents future publishing to this account until it is reconnected through the dashboard.

Existing posts that were already published to the platform are not affected. Scheduled posts targeting that platform will fail with a credentials error unless re-connected. To initiate a new OAuth connection, use the dashboard — the full OAuth redirect flow is not currently exposed via API.

curl -X DELETE https://www.postquick.ai/api/v1/accounts/account-uuid-456 \
  -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "success": true,
  "data": {
    "deleted": true
  }
}

Get usage statistics

GET/v1/usage

Returns your current usage across all PostQuickAI limits and quotas. Includes monthly AI text generation usage, image generation usage, video credits, content group count, and rate limit status.

All limits are shared between dashboard and API usage. Use this endpoint to check remaining capacity before making requests, especially for credit-consuming operations (image generation, video generation, AI text).

Monthly limits reset on the 1st of each month. Daily limits reset at midnight UTC. Video credits are granted monthly and don't roll over.

curl https://www.postquick.ai/api/v1/usage \
  -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "success": true,
  "data": {
    "plan": "Pro",
    "videoCredits": {
      "used": 45,
      "limit": 500,
      "remaining": 455,
      "resetsAt": "2026-04-01T00:00:00Z"
    },
    "imageGeneration": {
      "used": 87,
      "limit": 500,
      "remaining": 413,
      "resetsAt": "2026-04-01T00:00:00Z"
    },
    "aiTextGeneration": {
      "used": 234,
      "limit": 2000,
      "remaining": 1766,
      "resetsAt": "2026-04-01T00:00:00Z"
    },
    "contentGroups": {
      "used": 3,
      "limit": "unlimited"
    },
    "rateLimits": {
      "perMinute": {
        "used": 12,
        "limit": 120,
        "remaining": 108,
        "resetsAt": "2026-03-25T17:01:00Z"
      },
      "perDay": {
        "used": 450,
        "limit": 50000,
        "remaining": 49550,
        "resetsAt": "2026-03-26T00:00:00Z"
      }
    }
  }
}

Plan Comparison

Basic ($8/mo):
  • 100 video credits/month
  • 100 image generations/month
  • 400 AI text requests/month
  • 5 content groups max
  • 30 requests/min, 5K requests/day
Pro ($20/mo):
  • 500 video credits/month
  • 500 image generations/month
  • 2,000 AI text requests/month
  • Unlimited content groups
  • 120 requests/min, 50K requests/day

Authenticated user info

GET/v1/me

Returns the authenticated API user's identity and entitlement metadata. Use this to confirm which account a key belongs to before making content or publishing requests.

curl https://www.postquick.ai/api/v1/me   -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "success": true,
  "data": {
    "user": {
      "id": "user-uuid-123",
      "email": "founder@mybrand.com",
      "plan": "pro",
      "isSubscribed": true,
      "apiEnabled": true
    }
  }
}

Manage API keys

GET/v1/keys

Lists all API keys for your account. Keys are shown with their prefix (pq_live_abc...), name, last used time, and creation date. Full keys are NEVER returned via API — they're only shown once during creation in the dashboard.

This endpoint also returns account-level entitlement metadata: whether API access is enabled, whether the account is subscribed, and the current plan.

To create or delete keys, use the dashboard at /dashboard/api. This endpoint is read-only for security.

curl https://www.postquick.ai/api/v1/keys \
  -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "keys": [
    {
      "id": "key-uuid-123",
      "key_prefix": "pq_live_abc",
      "name": "Production API",
      "last_used_at": "2026-03-25T16:45:00Z",
      "created_at": "2026-01-15T10:00:00Z",
      "revoked_at": null,
      "isActive": true
    },
    {
      "id": "key-uuid-456",
      "key_prefix": "pq_live_xyz",
      "name": "Development",
      "last_used_at": null,
      "created_at": "2026-03-20T14:00:00Z",
      "revoked_at": null,
      "isActive": true
    }
  ],
  "apiEnabled": true,
  "isSubscribed": true,
  "plan": "pro"
}

API analytics

GET/v1/analytics

Returns detailed analytics for your API usage over the past 30 days: requests by endpoint, requests by API key, error rates, average response times, and daily request volume.

Use this for monitoring, debugging, and optimizing your API integration. Filter analytics with the period query parameter. Supported values: 24h, 7d, 30d, and 90d. Default: 7d.

Parameters

periodstring

Analytics window. One of: 24h, 7d, 30d, 90d. Default: 7d.

curl "https://www.postquick.ai/api/v1/analytics?period=30d"   -H "Authorization: Bearer pq_live_your_key_here"
Response
{
  "summary": {
    "totalRequests": 1247,
    "successRate": 96.1,
    "avgResponseTime": 342,
    "uniqueEndpoints": 12,
    "periodStart": "2026-02-24T00:00:00Z",
    "periodEnd": "2026-03-25T23:59:59Z"
  },
  "requestsOverTime": [
    { "date": "2026-03-24", "total": 67, "success": 64, "errors": 3 },
    { "date": "2026-03-25", "total": 89, "success": 86, "errors": 3 }
  ],
  "byEndpoint": [
    { "endpoint": "/v1/posts/generate", "count": 345, "avgMs": 380, "errorRate": 3.5 },
    { "endpoint": "/v1/images/generate", "count": 287, "avgMs": 290, "errorRate": 2.8 }
  ],
  "byStatusCode": [
    { "code": 200, "count": 1198 },
    { "code": 403, "count": 31 },
    { "code": 500, "count": 18 }
  ],
  "byApiKey": [
    { "keyId": "key-uuid-123", "name": "Production API", "count": 892, "lastUsed": "2026-03-25T16:45:00Z" }
  ],
  "recentErrors": [
    { "endpoint": "/v1/videos/generate", "status": 500, "message": "Video generation service failed", "at": "2026-03-25T16:22:00Z" }
  ],
  "rateLimitStatus": {
    "plan": "pro",
    "minuteLimit": 120,
    "minuteUsed": 9,
    "dailyLimit": 50000,
    "dailyUsed": 1247
  }
}

Questions about the API? Email us at support@postquick.ai

Get Your API Key →