API Guide

Create posts, manage accounts, upload media, and schedule content programmatically.

Base URL: https://authorautomations.social/api/v1

Most users don't need the raw API.

If you're using Claude Cowork or Claude Code, the connect guide walks you through the connector setup — no curl required. This page is for Make.com / Zapier / n8n / custom-script users who need direct REST access.

Authentication

All requests require a Bearer token in the Authorization header.

Authorization: Bearer aa_sk_your_api_key_here

Get your API key from Settings > API Key in the dashboard. The key is shown once when created — store it securely.

Multi-profile access: If your account has access to multiple profiles, pass the X-Profile-Id header to specify which profile to use. Otherwise your default profile is used automatically.

Quick Start

1. List your connected accounts to get account IDs
curl -H "Authorization: Bearer aa_sk_..." \
  https://authorautomations.social/api/v1/accounts
2. Create a post using an account ID from step 1
curl -X POST \
  -H "Authorization: Bearer aa_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Hello from the API!",
    "accountIds": ["682..."],
    "publishNow": true
  }' \
  https://authorautomations.social/api/v1/posts

Accounts

List Accounts

GET/accounts

Returns all connected social media accounts. Use the _id field from each account as the accountIds value when creating posts.

ParameterTypeDescription
platformstringFilter by platform (e.g., instagram, twitter, facebook)
Response
{
  "accounts": [
    {
      "_id": "682a1b2c3d4e5f6a7b8c9d0e",
      "platform": "instagram",
      "username": "mybookaccount",
      "displayName": "My Book Account",
      "profileUrl": "https://instagram.com/mybookaccount",
      "isActive": true
    }
  ],
  "hasAnalyticsAccess": false
}

Get Account

GET/accounts/:id

Returns a single account by its ID.

Posts

List Posts

GET/posts
ParameterTypeDescription
statusstringscheduled, published, or failed
dateFromstringISO 8601 date
dateTostringISO 8601 date
pagenumberPage number
limitnumberResults per page

Create Post

POST/posts
ParameterTypeDescription
contentstringPost text (max 25,000 chars)
accountIds*string[]Array of account _id values
publishNowbooleanPublish immediately (default: true)
scheduledAtstringISO 8601 datetime for scheduling
mediaItemsarrayMedia attachments: [{ "type": "image", "url": "..." }]
timezonestringIANA timezone (e.g., America/Chicago)
tiktokOptionsobjectTikTok-specific settings — draft, privacy, cover frame, allow duet/stitch (see TikTok section)
instagramOptionsobjectInstagram-specific — Reels/Stories/Trial Reels, cover image, collaborators, user tags (see Instagram section)
threadsOptionsobjectThreads-specific — topicTag for discovery, threadItems for chains (see Threads section)
youtubeOptionsobjectYouTube-specific — title (REQUIRED for video posts), visibility, AI disclosure (see YouTube section)
redditOptionsobjectReddit-specific — subreddit + title (BOTH REQUIRED), self vs link, flair (see Reddit section)
facebookOptionsobjectFacebook-specific — Stories/Reels, page targeting, draft mode
pinterestOptionsobjectPinterest-specific — title, board, link, cover image
linkedinOptionsobjectLinkedIn-specific — document title, company page, first comment
platformOptionsobjectRaw passthrough for fields not covered by the typed *Options above. Keys are platform names; values use the platform's verbatim field names. See Platform Options Reference below.
Publish now
{
  "content": "Check out my new book!",
  "accountIds": ["682a1b2c3d4e5f6a7b8c9d0e"],
  "publishNow": true
}
Schedule for later
{
  "content": "Coming soon!",
  "accountIds": ["682a1b2c3d4e5f6a7b8c9d0e"],
  "publishNow": false,
  "scheduledAt": "2026-03-20T14:00:00Z",
  "timezone": "America/Chicago"
}

Get Post

GET/posts/:id

Update Post

PATCH/posts/:id

Update a scheduled post's content or scheduled time.

ParameterTypeDescription
contentstringNew post text
scheduledAtstringNew ISO 8601 scheduled datetime

Delete Post

DELETE/posts/:id

Platforms

All connected platforms accepted by the API. Use the API value when filtering accounts (GET /accounts?platform=instagram) or as the key in platformOptions. Each platform’s guide section below documents the options the API exposes.

PlatformAPI ValueGuide
Twitter / XtwitterTwitter / X Guide
InstagraminstagramInstagram Guide
FacebookfacebookFacebook Guide
LinkedInlinkedinLinkedIn Guide
TikToktiktokTikTok Guide
YouTubeyoutubeYouTube Guide
PinterestpinterestPinterest Guide
RedditredditReddit Guide
BlueskyblueskyBluesky Guide
ThreadsthreadsThreads Guide
Google BusinessgooglebusinessGoogle Business Guide
TelegramtelegramTelegram Guide
SnapchatsnapchatSnapchat Guide
WhatsAppwhatsappWhatsApp Guide
DiscorddiscordDiscord Guide

Coming soon

  • DMs, Comments & Inbox reply to comments and DMs across platforms from a single API surface.
  • Analytics reach, impressions, engagement, and follower growth per post.
  • Ads Meta, Google, LinkedIn, TikTok, Pinterest, and X Ads — schedule and manage paid promotion alongside organic posts.

TikTok Options

TikTok posts support additional options via the tiktokOptions field when creating a post. By default, TikTok posts are published live. Set draft: true to send the post to your TikTok Creator Inbox for review before publishing.

ParameterTypeDescription
draftbooleanSend to TikTok Inbox instead of publishing live (default: false)
privacyLevelstringPUBLIC_TO_EVERYONE, MUTUAL_FOLLOW_FRIENDS, or SELF_ONLY
allowCommentbooleanAllow comments (default: true)
allowDuetbooleanAllow duets — video posts only (default: true)
allowStitchbooleanAllow stitches — video posts only (default: true)
commercialContentTypestringnone, brand_organic, or brand_content
autoAddMusicbooleanLet TikTok add trending music to photo posts. TikTok auto-selects from currently trending tracks for max reach. Photo posts only.
videoCoverTimestampMsnumberPick the cover frame from a specific timestamp (milliseconds into the video).
videoCoverImageUrlstringUse a separate image as the cover (overrides videoCoverTimestampMs).
photoCoverIndexnumberFor photo posts: which image (0-based) is the cover.
videoMadeWithAibooleanTikTok requires this be true if the video was AI-generated.
descriptionstringLong-form description (separate from caption).
Publish live to TikTok (default)
{
  "content": "New book trailer!",
  "accountIds": ["tiktok_account_id"],
  "publishNow": true
}
Send to TikTok Inbox as draft
{
  "content": "New book trailer!",
  "accountIds": ["tiktok_account_id"],
  "publishNow": true,
  "tiktokOptions": {
    "draft": true,
    "privacyLevel": "PUBLIC_TO_EVERYONE",
    "allowComment": true
  }
}
Post with restricted privacy
{
  "content": "Sneak peek for friends only",
  "accountIds": ["tiktok_account_id"],
  "publishNow": true,
  "tiktokOptions": {
    "privacyLevel": "MUTUAL_FOLLOW_FRIENDS",
    "allowDuet": false,
    "allowStitch": false
  }
}

TikTok Draft vs Live

  • Live (default): Post is published directly to your TikTok profile at the scheduled time.
  • Draft: Post is sent to your TikTok app's Creator Inbox (under Profile > Creator tools > Posts from apps). You review and publish manually from the TikTok app.

Instagram Options

Instagram supports Feed posts (default), Stories, Reels, and Trial Reels (shown to non-followers first). Aspect-ratio rules differ by product: Feed accepts 0.75:1 to 1.91:1; Stories and Reels require 9:16 vertical.

ParameterTypeDescription
contentTypestring'story' | 'reel'. Omit for a Feed post (default). Stories accept single media only; Reels require a single video.
coverImagestringURL of a 9:16 image to use as the Reel cover. Wins over coverFromTimestamp when both are set.
coverFromTimestampnumberPick the Reel cover from a video frame (milliseconds into the video). Ignored when coverImage is set.
trialParamsobjectTrial Reel — { graduationStrategy: 'MANUAL' | 'SS_PERFORMANCE' }. The reel is shown only to non-followers first; graduates manually (in IG app) or auto when engagement is good.
shareToFeedbooleanReel appears on both the main feed grid AND the Reels tab (default true), or just the Reels tab.
collaboratorsstring[]Up to 3 IG handles invited as collaborators on the post.
firstCommentstringAuto-posted as the first comment after publish (Feed/Reels — not Stories).
audioNamestringCustom name for original audio in Reels. Replaces 'Original Audio'.
userTagsarray[{ username, x, y, mediaIndex? }] — tag IG users in image posts. x/y are 0–1 coordinates from top-left.
Trial Reel with auto-graduation
{
  "content": "First chapter teaser — what do you think?",
  "accountIds": ["ig_account_id"],
  "scheduledAt": "2026-05-01T14:00:00Z",
  "mediaItems": [{ "type": "video", "url": "https://...", "width": 1080, "height": 1920 }],
  "instagramOptions": {
    "contentType": "reel",
    "coverImage": "https://media.../cover-1080x1920.png",
    "trialParams": { "graduationStrategy": "SS_PERFORMANCE" }
  }
}
Story with single 9:16 image
{
  "content": "Behind the scenes",
  "accountIds": ["ig_account_id"],
  "mediaItems": [{ "type": "image", "url": "https://...", "width": 1080, "height": 1920 }],
  "instagramOptions": { "contentType": "story" }
}

Aspect Ratio Pre-flight

Pass width and height on each imagemediaItemwhen known. The server validates against Instagram's rules locally and returns a 422 with a clear suggestion (e.g., “Image is 1080×1920 — too tall for Feed. Crop to 4:5 OR set contentType: 'story'and split into separate Stories.”) before we ever round- trip to Instagram. If dimensions are omitted the server probes the image URL with a small Range request.

Threads Options

Threads supports topic tags (for discovery via Meta's topic feed) and thread chains (a root post plus a sequence of replies, all from your account).

ParameterTypeDescription
topicTagstring1–50 chars, no '.' or '&'. Files the post under a discoverable topic. Overrides Threads' hashtag auto-extraction. Leave empty if your caption already has the right hashtag.
Threads post with topic tag
{
  "content": "Three years to write this novel. Here's what I learned. #BookThreads",
  "accountIds": ["threads_account_id"],
  "threadsOptions": { "topicTag": "Book Threads" }
}

First Thread (Thread Chains)

For multi-part threads, use platformOptions.threads.threadItems. The first item becomes the root post; subsequent items chain as replies. When threadItems is provided, the top-level contentfield is used for display/search ONLY — the first thread item is what gets published. Make the first item your strongest hook.

Thread chain (root + 2 replies)
{
  "content": "A Threads chain about my writing process",
  "accountIds": ["threads_account_id"],
  "threadsOptions": { "topicTag": "Writing Community" },
  "platformOptions": {
    "threads": {
      "threadItems": [
        { "content": "I finished my first novel after 3 years. Here's what nobody tells you." },
        { "content": "Year 1: I wrote 200,000 words I'd later cut. Painful, but necessary." },
        { "content": "Year 3: I learned that revision is where the book actually gets written." }
      ]
    }
  }
}

YouTube Options

YouTube requires a titlefor video posts — the API returns 422 if youtubeOptions.title is missing. The top-level content becomes the video description. YouTube Shorts are auto-detected when the video is 9:16 and under 60 seconds (you can add #Shorts to the title to make routing explicit).

ParameterTypeDescription
titlestringREQUIRED for video posts. 1–100 chars. Separate from caption (caption becomes the description).
visibilitystring'public' | 'private' | 'unlisted'. Default: 'public'.
madeForKidsbooleanCOPPA flag. Default: false. Disables comments and changes monetization when true — almost never what indie authors want.
containsSyntheticMediabooleanRequired by YouTube's 2024 policy if the video has AI-generated humans, voices, or events. Set true for AI-generated video (Magnific, fal.ai, etc.) to stay on the right side of policy.
firstCommentstringAuto-posted as the pinned first comment after publish.
categoryIdstringYouTube category ID (e.g., '22' for People & Blogs).
playlistIdstringAdd the video to an existing playlist on your channel.
YouTube Short (auto-detected from 9:16 + duration)
{
  "content": "After 3 years of writing, my first fantasy novel is here. Pre-order link in the channel description.",
  "accountIds": ["yt_account_id"],
  "scheduledAt": "2026-05-03T19:00:00Z",
  "mediaItems": [{ "type": "video", "url": "https://..." }],
  "youtubeOptions": {
    "title": "3 Years of Writing — My First Fantasy Novel #Shorts",
    "visibility": "public",
    "madeForKids": false,
    "containsSyntheticMedia": true,
    "playlistId": "PLxxxxxxxx"
  }
}

Reddit Options

Reddit requires both a subreddit and a title. The API returns 422 if either is missing. Reddit titles are the headline visible in feeds; the top-level content becomes the body text (for self posts) or the link description (for link posts).

ParameterTypeDescription
subreddit*stringSubreddit name without the 'r/' prefix. e.g., 'Fantasy', 'BookRecommendations'.
title*string1–300 chars. The headline visible in feeds and search.
urlstringExternal URL for link posts. Set forceSelf: false to use this.
forceSelfbooleantrue (default for indie author book promo) = self/text post; false + url set = link post. Self posts perform much better for engagement.
flairIdstringFlair ID from the target subreddit. Required by most large subs (AutoMod removes posts without correct flair). Flair IDs are per-subreddit; ask the subreddit's mods or read their wiki.
Self post to r/Fantasy
{
  "content": "After 3 years of writing, I finally finished my fantasy novel. The hardest part was knowing when to stop revising. AMA.",
  "accountIds": ["reddit_account_id"],
  "redditOptions": {
    "subreddit": "Fantasy",
    "title": "Just published my first fantasy novel — what I wish I knew when I started",
    "forceSelf": true,
    "flairId": "abc123-def456"
  }
}

Flair tips

Most large subreddits (r/Fantasy, r/books, r/writing, r/SelfPublishing) auto-remove posts without correct flair. If you don't know the flair ID for a subreddit yet, post once manually first to find the IDs the mods use, then save them for API calls. Without flair, posts get held by AutoModerator.

Platform Options — Raw Passthrough

For platforms or fields not covered by the typed *Options blocks above, use platformOptions.<platform>. Field names match the underlying provider's docs verbatim. Anything in here is forwarded directly to the platform without local validation, so you trade off clearer error messages for full feature access.

Twitter reply with poll
{
  "content": "What's your next read?",
  "accountIds": ["twitter_account_id"],
  "platformOptions": {
    "twitter": {
      "replyToTweetId": "1234567890",
      "poll": { "options": ["Fantasy", "Sci-fi", "Mystery", "Romance"], "duration_minutes": 1440 }
    }
  }
}
Discord forum post with applied tags
{
  "content": "New chapter posted!",
  "accountIds": ["discord_account_id"],
  "platformOptions": {
    "discord": {
      "channelId": "987654321",
      "forumThreadName": "Chapter 12 discussion",
      "forumAppliedTags": ["new-chapter", "fantasy"]
    }
  }
}
Telegram with markdown
{
  "content": "**New post!** Check it out at https://...",
  "accountIds": ["telegram_account_id"],
  "platformOptions": {
    "telegram": {
      "parseMode": "Markdown",
      "disableWebPagePreview": false
    }
  }
}

Twitter / X

Twitter posts use the raw platformOptions.twitter block. Supported fields: replyToTweetId, replySettings (following | mentionedUsers | subscribers | verified), threadItems (multi-tweet threads), poll, and longVideo. See the raw passthrough section above for examples.

Facebook Options

ParameterTypeDescription
contentTypestring'story' | 'reel'. Omit for a feed post (default).
titlestringReel title (only for contentType=reel). Separate from the caption.
firstCommentstringAuto-posted as first comment (feed posts and Reels, not Stories). Skipped when draft is true.
pageIdstringTarget Facebook Page ID for multi-page accounts. Defaults to your primary page.
draftbooleanSave as unpublished draft visible in Facebook Publishing Tools. Drafts expire after ~30 days. Not supported for Stories.

LinkedIn Options

ParameterTypeDescription
documentTitlestringTitle for document/article posts. Up to 100 chars.
organizationUrnstringPost as a company page instead of personal. Use the URN from your LinkedIn organization (e.g., 'urn:li:organization:12345').
firstCommentstringAuto-posted as first comment after publish. Up to 1,250 chars.
disableLinkPreviewbooleanSkip LinkedIn's auto link-preview card. Useful when the link in the post is already covered by other media.

Pinterest Options

ParameterTypeDescription
titlestringPin title. 1–100 chars.
boardIdstringTarget board ID. Required if you have multiple boards.
linkstringDestination URL when the pin is clicked.
coverImageUrlstringCover image for video pins.
coverImageKeyFrameTimenumberPick the cover frame from a specific timestamp in the video (ms).

Bluesky

Bluesky uses raw platformOptions.bluesky. Supports threadItems for multi-skeet threads. Caption limit is 300 chars per skeet.

Google Business

Posts to your Google Business Profile. Use raw platformOptions.googlebusiness: topicType (STANDARD | EVENT | OFFER), callToAction, event (with start/end dates), and offer (with terms/redemption details).

Telegram

Telegram uses raw platformOptions.telegram: parseMode (HTML | Markdown | MarkdownV2), disableWebPagePreview, disableNotification, and protectContent (prevents forwarding/saving).

Snapchat

Snapchat uses raw platformOptions.snapchat: contentType (story | saved_story | spotlight). Spotlight is Snap's answer to TikTok — algorithmic feed for non-followers.

WhatsApp

WhatsApp Status posts use raw platformOptions.whatsapp. Status is the 24-hour ephemeral content visible to your contacts.

Discord

Discord uses raw platformOptions.discord: channelId (required), embeds (rich embed array), poll, crosspost (announce to following servers), forumThreadName + forumAppliedTags for forum channels, tts, plus webhook overrides (webhookUsername, webhookAvatarUrl).

Queue

The queue lets you set up recurring time slots so posts are automatically scheduled at your preferred times. Instead of picking a specific date and time for each post, you add posts to the queue and they fill the next available slot.

How Queuing Works

  1. Queue schedules define recurring time slots (e.g., "Monday at 9:00 AM, Wednesday at 2:00 PM").
  2. Preview shows you the next available times in your queue.
  3. Queue a post by creating a post without scheduledAt or publishNow— it will be placed in the next available queue slot.

List Queue Schedules

GET/queue

Returns your queue configuration with all time slots.

ParameterTypeDescription
allstringSet to "true" to list all queues
queueIdstringGet a specific queue by ID
Response — single queue
{
  "exists": true,
  "schedule": {
    "_id": "queue_abc123",
    "name": "Default Queue",
    "timezone": "America/Chicago",
    "active": true,
    "isDefault": true,
    "slots": [
      { "dayOfWeek": 1, "time": "09:00" },
      { "dayOfWeek": 1, "time": "14:00" },
      { "dayOfWeek": 3, "time": "09:00" },
      { "dayOfWeek": 5, "time": "11:00" }
    ]
  },
  "nextSlots": [
    "2026-03-17T09:00:00-05:00",
    "2026-03-17T14:00:00-05:00",
    "2026-03-19T09:00:00-05:00"
  ]
}

Days of week:0 = Sunday, 1 = Monday, … 6 = Saturday. Times are in 24-hour format in the queue's timezone.

Response — all queues (GET /queue?all=true)
{
  "queues": [
    {
      "_id": "queue_abc123",
      "name": "Morning Posts",
      "active": true,
      "isDefault": true,
      "slots": [...]
    },
    {
      "_id": "queue_def456",
      "name": "Evening Content",
      "active": true,
      "isDefault": false,
      "slots": [...]
    }
  ],
  "count": 2
}

Preview Queue

GET/queue/preview

Shows the next available posting times in your queue. Use this to see when your next posts will go out.

ParameterTypeDescription
countnumberNumber of upcoming slots to show
queueIdstringPreview a specific queue (default queue if omitted)
Response
{
  "profileId": "69821296e40fdedc04fa993f",
  "count": 5,
  "slots": [
    "2026-03-17T09:00:00-05:00",
    "2026-03-17T14:00:00-05:00",
    "2026-03-19T09:00:00-05:00",
    "2026-03-21T11:00:00-05:00",
    "2026-03-24T09:00:00-05:00"
  ]
}

Media Upload

Uploading media is a two-step process: get a presigned URL from the API, then upload your file directly to that URL.

Step 1: Get Presigned URL

POST/media/presign
ParameterTypeDescription
filename*stringName of your file
contentType*stringMIME type (see supported types below)
sizenumberFile size in bytes (max 5 GB)
TypeSupported MIME Types
Imagesimage/jpeg, image/png, image/webp, image/gif
Videosvideo/mp4, video/mpeg, video/quicktime, video/webm
Documentsapplication/pdf
Request
{
  "filename": "book-cover.jpg",
  "contentType": "image/jpeg",
  "size": 245000
}
Response
{
  "uploadUrl": "https://storage.example.com/presigned-put-url...",
  "publicUrl": "https://cdn.example.com/media/book-cover.jpg",
  "key": "media/abc123/book-cover.jpg",
  "type": "image"
}

Step 2: Upload Your File

Upload your file to the uploadUrl using an HTTP PUT request with the file as the body. The presigned URL expires after 1 hour.

Upload via curl
curl -X PUT \
  -H "Content-Type: image/jpeg" \
  --data-binary @book-cover.jpg \
  "https://storage.example.com/presigned-put-url..."

Step 3: Use in a Post

Use the publicUrl from step 1 in your post's mediaItems array. Each item needs a type (image or video) and the url.

Create post with uploaded media
curl -X POST \
  -H "Authorization: Bearer aa_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "content": "My new book is here!",
    "accountIds": ["682a1b2c3d4e5f6a7b8c9d0e"],
    "publishNow": true,
    "mediaItems": [
      {
        "type": "image",
        "url": "https://cdn.example.com/media/book-cover.jpg"
      }
    ]
  }' \
  https://authorautomations.social/api/v1/posts

Content Guides

Read the author's brand voice, prose style, copywriting principles, and social media strategy. Integrations that generate captions on the author's behalf should fetch these first so the output matches the voice the author has defined in their dashboard.

Get Guides

GET/guides
Response
{
  "prose_guide": "Short punchy sentences. First-person. Never use em-dashes.",
  "brand_guide": "Cozy paranormal mystery. Coastal-town-with-secrets vibe. Always tease, never spoil.",
  "copywriting_guide": "Concrete details over adjectives. Specific character names. Questions that open loops.",
  "social_media_guide": "Instagram: 5-8 hashtags. TikTok: trending-sound hooks. LinkedIn: skip.",
  "image_style_prompt": "Dreamy golden-hour lighting, watercolor bleeds, coastal palette"
}

Any field may be nullif the author hasn't set it yet. Responses are cached for a few minutes — guides change infrequently.

AI Campaigns

Campaigns are multi-day content plans the author builds in the dashboard. The API exposes the full lifecycle so integrations can create a campaign, save an AI-generated plan, queue media generation, and schedule every post to the calendar.

List Campaigns

GET/campaigns

Returns all campaigns under the authenticated profile, newest first. Each campaign includes its id, name, objective, duration, platforms, status (draft, generating, review, scheduled, active, completed), and content mix.

Create Campaign

POST/campaigns
ParameterTypeDescription
name*stringShown in the author's campaign list
objective*stringOne or two sentences describing what this campaign is promoting
post_countnumberHow many posts the campaign generates. Default 14. The dashboard picker offers 1 / 3 / 7 / 14 (AI generation gets slow beyond ~14).
platformsstring[]Lowercase platform slugs — e.g. ["instagram", "tiktok"]
content_mixstringOne of: mixed (default), images_only, mostly_images, videos_only, user_decides
Example
curl -X POST \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Spring launch — Curses and Currents",
    "objective": "Build pre-order buzz for Curses and Currents launching May 1",
    "post_count": 14,
    "platforms": ["instagram", "tiktok", "threads"],
    "content_mix": "mostly_images"
  }' \
  https://authorautomations.social/api/v1/campaigns

Save Plan

POST/campaigns/:id/save-plan

Attach a content plan to a campaign. Use when your integration generates the plan client-side (e.g. the Claude plugin has Claude write each post) and just needs to store it. Creates one campaign_post record per post.

ParameterTypeDescription
plan*CampaignPost[]Array of post objects. Each has: index (1-based number), theme (string), captions (object keyed by platform), imagePrompt, optional imagePrompts for carousels, slideTexts for carousel overlays, videoPrompt, musicPrompt, contentType (image|carousel|video), hashtags

Generate Media

POST/campaigns/:id/generate-media

Kicks off server-side media generation for every campaign post using whichever provider you've configured per task type (Magnific, fal.ai, or Google Nano Banana). Returns immediately with { "status": "started" }. Poll the GET variant to watch progress.

GET/campaigns/:id/generate-media

Returns progress: { total, completed, failed, inProgress, isRunning, posts }. Safe to poll every 5 seconds.

Schedule Campaign

POST/campaigns/:id/schedule

Drops every campaign post into the author's per-platform queues in one pass. The queues decide when each post publishes — there is no campaign start date or per-post time. Returns per-post success / failure counts.

ParameterTypeDescription
timezonestringIANA timezone for the queue calculations. Default UTC
accountMap*objectMap of platform slug → account ID. Platforms without an account are counted as failures instead of silently skipped
Response
{
  "scheduled": 13,
  "failed": 1,
  "total": 14,
  "errors": [
    { "day": 5, "error": "All selected platforms are video-only but this post is image content." }
  ]
}

The errors[].day key is a 1-based post index (legacy field name). startDate, scheduleMode, and postTimes are accepted-but-ignored on this endpoint.

Full Workflow Example

Upload an image and schedule a post to your next queue slot:

# 1. Get your accounts
ACCOUNTS=$(curl -s -H "Authorization: Bearer $API_KEY" \
  https://authorautomations.social/api/v1/accounts)

ACCOUNT_ID=$(echo $ACCOUNTS | jq -r '.accounts[0]._id')

# 2. Get a presigned upload URL
PRESIGN=$(curl -s -X POST \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filename":"promo.jpg","contentType":"image/jpeg"}' \
  https://authorautomations.social/api/v1/media/presign)

UPLOAD_URL=$(echo $PRESIGN | jq -r '.uploadUrl')
PUBLIC_URL=$(echo $PRESIGN | jq -r '.publicUrl')

# 3. Upload the file
curl -X PUT -H "Content-Type: image/jpeg" \
  --data-binary @promo.jpg "$UPLOAD_URL"

# 4. Check queue for next available time
curl -s -H "Authorization: Bearer $API_KEY" \
  https://authorautomations.social/api/v1/queue/preview?count=3

# 5. Create the post with the uploaded image
curl -X POST \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"content\": \"New release day! Grab your copy now.\",
    \"accountIds\": [\"$ACCOUNT_ID\"],
    \"scheduledAt\": \"2026-03-20T14:00:00Z\",
    \"publishNow\": false,
    \"mediaItems\": [{\"type\": \"image\", \"url\": \"$PUBLIC_URL\"}]
  }" \
  https://authorautomations.social/api/v1/posts

Rate Limits

The API allows 100 requests per hour per API key. When exceeded, you'll receive a 429 response with a resetAt timestamp.

Error Responses

All errors follow this format:

{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable description",
    "requestId": "req_abc123"
  }
}
StatusCodeMeaning
400VALIDATION_ERRORInvalid request body or params
401UNAUTHORIZEDMissing or invalid API key
403FORBIDDENSubscription inactive or expired
404NOT_FOUNDResource not found
429RATE_LIMITEDToo many requests
500INTERNAL_ERRORServer error
502BAD_GATEWAYUpstream API unavailable

Claude Code / Cowork Plugin

Create posts and run AI campaigns directly from Claude Code or Claude Cowork. The plugin lets Claude write your captions using the full context of your conversation — it reads your brand guides, knows what you're working on, and crafts platform-specific content in your voice.

Install the Plugin

The plugin lives in its own Claude marketplace. Two commands in Claude Code or Claude Cowork:

In any Claude conversation
/plugin marketplace add https://github.com/chellehoniker/claude-code-author-automations
/plugin install author-automations-social@author-automations

No git clone, no npm install, no build step. Claude Code downloads the plugin on demand.

Setup

The plugin uses our hosted MCP server, so there's no local configuration. The first time Claude calls a plugin tool, a browser window opens to /authorize on our site — click Approveand the token is stored in Claude Code's credential store.

If Claude Code asks for Client ID and Client Secret instead of opening a browser window, generate a credential pair from Settings → Cowork Connector and paste them. Same credentials work for both Cowork and Claude Code.

For the canonical step-by-step walkthrough, see /docs/connect#cli.

Quick Post

Create a single post with a slash command or natural language:

Slash command
/author-automations-social:aa-post My new book is available for pre-order!
Or just tell Claude
"Create an Instagram and TikTok post about my book launch"

Claude reads your content guides, writes unique captions for each platform, and schedules the post — all in one conversation.

AI Campaign

Run a full campaign from the CLI:

Slash command
/author-automations-social:aa-campaign 14 posts for my spring book launch
Or describe what you need
"Create a 14-post social media campaign to promote Curses and Currents across Instagram, TikTok, and Facebook"

Claude will walk you through the full flow:

1. Ask about your objective, how many posts (1/3/7/14), and target platforms

2. Read your brand, prose, and social media guides

3. Write a platform-specific caption set for each post (Claude writes these, not a server-side AI)

4. Present the plan for your review and edits

5. Generate images and videos via your configured providers (Magnific, fal.ai, or Google Nano Banana)

6. Drop every post into your per-platform queues, which decide the timing

The Hybrid AI Model

Unlike typical integrations, Claude writes your captions directly — not a server-side AI. This means Claude has the full context of your conversation: what book you're working on, what chapter you just finished, what your audience cares about. Media generation (images, videos, music) happens server-side through whichever media provider you've configured per task type — Magnific, fal.ai, or Google Nano Banana — using API keys you store in Settings → AI.

Available Tools

ToolDescription
aa_list_accountsList your connected social accounts
aa_get_guidesRead your content guides (brand, prose, social)
aa_create_postCreate and schedule a post
aa_list_postsView scheduled/published posts
aa_update_postEdit a scheduled post
aa_delete_postRemove a post
aa_upload_mediaGet a presigned URL for media upload
aa_queue_previewSee upcoming queue slots
aa_create_campaignStart a new campaign
aa_save_campaign_planSave Claude-generated content plan
aa_generate_mediaGenerate images/videos for campaign
aa_check_media_statusPoll media generation progress
aa_schedule_campaignSchedule all campaign posts
aa_list_campaignsView your campaigns

Content Guides

For the best results, set up your content guides in the dashboard under Settings > AI Configuration:

Prose Guide — your writing tone, style, and voice preferences

Brand Guide — your brand identity, values, and personality

Copywriting Guide — principles for persuasive copy and CTAs

Social Media Guide — platform-specific strategies, hashtag usage, posting frequency

Claude reads all four guides before writing any caption. The more detail you provide, the better the output matches your voice.

Plugin Source

The plugin is open source: github.com/chellehoniker/claude-code-author-automations