Guide

Overview Quickstart Authentication Rate limits & timeouts Errors Pagination Idempotency Versioning Changelog

Accounts

/accounts

Posts

/posts /posts /posts/{id} /posts/{id}/analytics /analytics/summary /channels/{accountId}/insights /channels/{accountId}/best-times /posts/top /competitors/comparison /posts/{id}/retry /posts/scheduled /scheduled-posts /scheduled-posts/{id} /scheduled-posts/{id}

Comments & Replies

/comments /comments/reply /comments/dismiss /replies/pending /replies/pending/{id}/approve /replies/pending/{id}/reject /replies/pending/{id}/regenerate /replies/pending/{id}

Credits

/credits

AI Video Generation

/videos /videos /videos/{id} /videos/{id}

Webhooks

Guide & signing /webhooks /webhooks /webhooks/{id} /webhooks/{id}/deliveries

RSS Auto-Post

/rss-feeds /rss-feeds /rss-feeds/{id} /rss-feeds/{id} /rss-feeds/{id}/check-now

Content Recycling

/recycling-rules /recycling-rules /recycling-rules/{id} /recycling-rules/{id} /recycling-rules/{id}/run-now

Tools

OpenAPI & Postman MCP server n8n node Zapier

What's not here yet

Roadmap

GetMulticast API

Publish, schedule, and manage replies across every platform GetMulticast connects to — programmatically. Built for Zapier, n8n, Make, and your own scripts.

Base URL: https://getmulticast.com/api/v1 — every path below is relative to this.

This is the same engine the GetMulticast dashboard itself runs on, not a separate or lighter reimplementation — every endpoint here calls the identical internal logic a click in the dashboard would trigger, so behavior never drifts between the two. A UI redesign never changes what these endpoints do; only a real, documented change to this reference does.

Official SDKs: none published yet — JavaScript, Python and PHP clients are planned, not built. Until then, any HTTP client works fine: every example on this page is plain curl, and translates directly to fetch, requests, axios, Guzzle, or whatever you already use.

Quickstart

Zero to a real published post, in order:

  1. Get an API key — Dashboard → Settings → Developer. This one step is UI-only; everything after it is a plain HTTP call.
  2. Find a real account id — every id used below ("1784..." etc.) comes from this call, not made up:
curl https://getmulticast.com/api/v1/accounts \
  -H "Authorization: Bearer gmc_live_..."
  1. Publish — using a real mediaUrl you already have hosted somewhere public, and a real account id from step 2:
curl -X POST https://getmulticast.com/api/v1/posts \
  -H "Authorization: Bearer gmc_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "mediaUrl": "https://example.com/clip.mp4",
    "mediaType": "video",
    "caption": "Hello from the API",
    "selections": { "instagram": ["1784..."] }
  }'

That returns 202 immediately with a runId — see Rate limits & timeouts for why it's 202 and not 201, and GET /posts/{id} below for how to check the real result once publishing finishes.

Authentication

Every request needs an API key in the Authorization header, as a Bearer token. Create one from Dashboard → Settings → Developer — the raw key is shown exactly once at creation and can't be retrieved again (we only ever store a one-way hash of it, the same way Stripe and GitHub handle API keys).

# every request
curl https://getmulticast.com/api/v1/accounts \
  -H "Authorization: Bearer gmc_live_XXXXXXXXXXXXXXXXXXXXXXXX"

Each key carries its own scopes, checked directly against this real list — nothing here is aspirational:

ScopeGrants
accounts:readRead connected social accounts
posts:readRead posts, publish results and scheduled posts
posts:writePublish, schedule, reschedule, delete and retry posts
analytics:readRead real per-post metrics (YouTube, X, Pinterest, Bluesky only — see GET /posts/{id}/analytics)
comments:readRead recent comments and the pending-reply review queue
comments:writeDraft, edit, approve, reject and send comment replies
credits:readRead the account's AI credit balance
webhooks:readList registered webhooks and their delivery history
webhooks:writeRegister and delete webhooks
rss:readList RSS auto-post feeds
rss:writeRegister, update and delete RSS auto-post feeds
recycling:readList content recycling rules
recycling:writeCreate, update and delete content recycling rules

A request to an endpoint outside a key's granted scopes returns 403 insufficient_scope. Create narrowly-scoped keys for anything you hand to a third-party tool.

Keep your key secret. It authenticates as your full account — anyone with it can publish, reply, and read your data within its scopes. Revoke a key immediately from Settings → Developer if it ever leaks.

Rate limits & timeouts

LimitValue
Requests per minute, per key60
Requests per day, per key5,000
Request timeout30s
Max request body10MB

Every response carries rate-limit headers so you can self-throttle before hitting the ceiling:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1757980800   # unix epoch seconds

Exceeding a limit returns 429 with a Retry-After header (seconds to wait). POST /posts and POST /posts/scheduled queue the real publish work in the background and return immediately (202) — the actual per-platform publishing (which can genuinely take minutes, e.g. Instagram/TikTok video processing) happens after the response, same as the dashboard's own "Post Now" button. Poll GET /posts/{id} for the final result, or use a webhook (see below) instead of polling.

Typical timing (not a contractual SLA — real, observed behavior): the 202 response itself comes back in well under a second — it only queues the job. The actual publish that follows in the background is the part that varies: seconds for platforms with simple APIs, up to a couple of minutes for platforms that process video server-side before it's live (Instagram and TikTok in particular). That's why this endpoint returns 202 before publishing is done, not 201 after it.

Errors

Every error — auth, validation, rate limit, or an unexpected failure — returns the same JSON envelope, so you can always branch on error.code rather than parsing text:

{
  "error": {
    "code": "insufficient_scope",
    "message": "This API key doesn't have the 'posts:write' scope required for this endpoint.",
    "requestId": "a1b2c3d4e5f6a1b2"
  }
}
HTTP statuserror.codeMeaning
400invalid_requestMissing/malformed field — see message for which one.
401missing_api_key / invalid_api_key / revoked_api_keyNo, wrong, or revoked Bearer token.
403insufficient_scope / forbiddenKey lacks the scope, or the resource belongs to someone else.
404not_foundNo such resource, or wrong method for a real path.
405method_not_allowedPath exists, wrong HTTP method.
409failed_preconditionValid request, wrong state (e.g. approving an already-sent reply).
429rate_limit_exceeded / resource_exhaustedRate limit hit, or (for posts) out of AI credits.
500internal_errorSomething broke on our end — logged server-side by requestId; include it if you contact support.

Two real mistakes worth calling out

An empty selections object on POST /posts is rejected up front, before anything is queued:

{ "error": { "code": "invalid_request", "message": "selections is required", "requestId": "..." } }

A misspelled or unsupported platform key inside selections (e.g. "instagrm", or a real platform you just haven't connected yet) behaves differently, and it's easy to get caught out by this: it is not rejected up front. The request still returns 202 like any other, but that platform's entry in the eventual publishResults (see GET /posts/{id}) comes back as a real, specific per-platform failure instead of a request-level error:

"publishResults": {
  "instagrm": [{ "ok": false, "error": "No connected instagrm account found." }]
}

If a platform key never shows up publishing successfully, check it against GET /accounts first — that's the exact, real set of platform keys and account ids you have to work with.

Pagination

List endpoints accept limit (1–100, default 25) and cursor, and return a nextCursor — pass it back as cursor to fetch the next page; null means you're on the last page.

curl "https://getmulticast.com/api/v1/posts?limit=50&cursor=abc123" \
  -H "Authorization: Bearer gmc_live_..."

Idempotency

Send an Idempotency-Key header on POST /posts, POST /posts/scheduled, or POST /comments/reply to make a retried request safe — if you send the same key twice (e.g. your client timed out and retried), the second call returns the exact same result as the first instead of publishing/replying twice. Keys are scoped per API key and remembered for 24 hours. Use a UUID you generate per logical action, same convention as Stripe.

curl -X POST https://getmulticast.com/api/v1/posts \
  -H "Authorization: Bearer gmc_live_..." \
  -H "Idempotency-Key: 8f14e45f-ceea-4f9f-9b0f-3c1e2e6a1a11" \
  -H "Content-Type: application/json" \
  -d '{ ... }'

Versioning

This is v1 — the path itself (/api/v1/...) is the version. Once you're integrated, this contract won't change under you: no field is removed or repurposed, no endpoint's meaning changes. Real new capability ships as new, additive fields or endpoints within v1 where possible; a genuine breaking change ships as /api/v2/... alongside v1, not in place of it.

Accounts

GET/accountsaccounts:readGet a key to try it →

Every connected social account across every platform.

curl https://getmulticast.com/api/v1/accounts \
  -H "Authorization: Bearer gmc_live_..."
{
  "accounts": {
    "instagram": [{ "id": "1784...", "label": "Main Instagram" }],
    "youtube": [{ "id": "UCxx...", "label": "My Channel" }],
    "x": [{ "id": "14582...", "label": "@handle" }]
    // ...one array per connected platform: facebook, threads, tiktok,
    // linkedin, bluesky, pinterest, googlebusiness
  },
  "requestId": "..."
}

Posts

POST/postsposts:writeGet a key to try it →

Publish now to one or more connected accounts across one or more platforms. Returns 202 immediately with a post id — publishing itself happens in the background (see Rate limits above). Upload your media somewhere public first (or use mediaUrl from your own storage) — this endpoint never accepts raw file bytes.

FieldTypeRequiredNotes
mediaUrlstringyesA public URL to the video or image file.
mediaTypestringyes"video" or "image". Text-only posts aren't supported yet.
selectionsobjectyes{ "instagram": ["accountId1"], "x": ["accountId2"] } — platform → array of account ids from GET /accounts.
captionstringnoShared caption for every selected account.
captionOverridesobjectno{ "x": "Shorter caption for X" } — per-platform override.
hashtagsstring[]noAppended to the caption.
firstCommentstringnoAuto-posted as the first comment (Facebook & Instagram only today).
curl -X POST https://getmulticast.com/api/v1/posts \
  -H "Authorization: Bearer gmc_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "mediaUrl": "https://example.com/clip.mp4",
    "mediaType": "video",
    "caption": "New drop 🚀",
    "hashtags": ["launch","newproduct"],
    "selections": { "instagram": ["1784..."], "youtube": ["UCxx..."] }
  }'
{ "runId": "8fJ2k...", "queued": true, "requestId": "..." }
GET/postsposts:readGet a key to try it →

Lists your posts, newest first. Paginated (see Pagination above).

{
  "posts": [
    { "id": "8fJ2k...", "status": "published", "caption": "New drop 🚀",
      "publishResults": { "instagram": [{ "accountId": "1784...", "ok": true, "postId": "..." }] },
      "createdAt": "2026-09-12T10:03:00Z" }
  ],
  "nextCursor": null,
  "requestId": "..."
}
GET/posts/{id}posts:readGet a key to try it →

One post's full status and per-account publish results. status is processing, published, or publish_failed.

GET/posts/{id}/analytics?platform=analytics:readGet a key to try it →

Real, live metrics for one post on one platform. Only youtube, x, pinterest, and bluesky are wired — every other platform returns a real 400 not_supported naming the exact missing permission (e.g. Instagram needs a permission this app doesn't have granted yet), never a fake zero.

curl "https://getmulticast.com/api/v1/posts/8fJ2k.../analytics?platform=x" \
  -H "Authorization: Bearer gmc_live_..."
{
  "platform": "x", "postId": "18472...",
  "metrics": { "likes": 42, "reposts": 5, "replies": 3, "quotes": 0, "impressions": 1204 },
  "requestId": "..."
}
GET/analytics/summary?accountId=&days=analytics:readGet a key to try it →

Totals (views, interactions, posts, engagement rate) and your top 3 posts by views, across one channel or every connected channel. Both params optional — omit accountId to summarize everything; days defaults to 30 (max 90).

curl "https://getmulticast.com/api/v1/analytics/summary?days=7" \
  -H "Authorization: Bearer gmc_live_..."
GET/channels/{accountId}/insights?days=analytics:readGet a key to try it →

One channel's own totals, plus which content formats and hashtags actually perform (medians, not averages, so one viral post doesn't skew it).

GET/channels/{accountId}/best-timesanalytics:readGet a key to try it →

This channel's best times/day/format/posting-frequency to post, computed from its own real post history. Returns "basedOn": "general" with generic guidance if there isn't 5+ posts of real history yet — never presented as personalized when it isn't.

GET/posts/top?accountId=&metric=&days=&limit=analytics:readGet a key to try it →

Your best-performing posts, ranked by views (default), likes, or comments. All params optional.

GET/competitors/comparisonanalytics:readGet a key to try it →

Every competitor you're tracking (Analytics → Competitor tracking), with their latest followers, posting frequency, and engagement per post.

POST/posts/{id}/retryposts:writeGet a key to try it →

Retries only the accounts that failed on a given platform for this post.

curl -X POST https://getmulticast.com/api/v1/posts/8fJ2k.../retry \
  -H "Authorization: Bearer gmc_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "platform": "instagram" }'
POST/posts/scheduledposts:writeGet a key to try it →

Same fields as POST /posts, plus:

FieldTypeRequiredNotes
datestringyes"2026-09-20"
timestringno"09:00", defaults to 09:00.
timezonestringnoIANA name, e.g. "America/New_York". Defaults to UTC.

Returns 201 with the scheduled post's id and resolved UTC time.

GET/scheduled-postsposts:readGet a key to try it →

Lists posts still waiting to publish, soonest first. Paginated.

PATCH/scheduled-posts/{id}posts:writeGet a key to try it →

Reschedules a still-pending post. Body: { "scheduledAtUtc": "2026-09-21T14:00:00Z" }, or { "date": "...", "time": "..." } in the post's original timezone.

DELETE/scheduled-posts/{id}posts:writeGet a key to try it →

Cancels a still-pending scheduled post.

Comments & Replies

GET/commentscomments:readGet a key to try it →

Recent comments (last 7 days) across your monitored accounts on Instagram, Facebook, Threads, YouTube, LinkedIn and Bluesky, including whether each already has a reply. X/Twitter works at the mentions level instead — see /replies/pending, which covers every platform including X.

POST/comments/replycomments:writeGet a key to try it →

Replies to one comment surfaced by GET /comments. Send directText to send your own exact text immediately (no AI, no review step), or omit it to have GetMulticast's AI draft a reply into your Review queue (/replies/pending) instead of sending it directly.

FieldRequiredNotes
platform, accountId, commentIdyesFrom GET /comments.
textyesThe original comment's text (used for the AI draft).
directTextnoSend exactly this, no AI involved.
instructionnoOne-off AI instruction, e.g. "mention our discount code".
postUrnLinkedIn onlyRequired for LinkedIn.
rootUri, rootCid, commentCidBluesky onlyRequired for Bluesky (AT Protocol reply refs).
POST/comments/dismisscomments:writeGet a key to try it →

Marks a comment as handled without replying (e.g. spam). Body: { "platform", "accountId", "commentId" }.

GET/replies/pendingcomments:readGet a key to try it →

Your Review Inbox — AI-drafted replies (from review-mode automations, across every platform including X) waiting for approval.

POST/replies/pending/{id}/approvecomments:writeGet a key to try it →

Sends the pending reply — the AI draft as-is, or pass { "editedText": "..." } to send different text instead.

POST/replies/pending/{id}/rejectcomments:writeGet a key to try it →

Discards a pending reply without sending it.

POST/replies/pending/{id}/regeneratecomments:writeGet a key to try it →

Asks the AI to revise the current draft. Body: { "context": "make it shorter and friendlier" } (required).

PATCH/replies/pending/{id}comments:writeGet a key to try it →

Overwrites the draft text without sending it. Body: { "text": "..." }.

Credits

GET/creditscredits:readGet a key to try it →

Your remaining AI credit balance — spent by POST /videos below (never by the post/comment/webhook/RSS/recycling endpoints above, which only move media you already have).

{ "credits": 847, "requestId": "..." }

AI Video Generation

Generates a real AI video — the same engine the dashboard's own "Generate Video" button calls, not a separate or lighter version. A short text-to-video clip is generated per scene (Agnes), with an optional AI-narrated voiceover track. Generation happens in the background and can take minutes: POST /videos returns 202 immediately with a videoId; poll GET /videos/{id} until status is "ready" (then videoUrl is set — pass it straight into POST /posts or POST /posts/scheduled to publish it) or "failed" (statusMessage explains why; any charged credits are automatically refunded). Honest current limitation: there is no compositing step — with multiple scenes, the first scene that produced a clip becomes videoUrl, every scene's own clip is kept on scenes[i].mediaUrl, and a voiceover track (if requested) is a separate file, not muxed into the video.

POST/videosvideos:writeGet a key to try it →

Starts generating a video. Charges AI credits immediately (see GET /credits) unless saveAsDraft is true — an insufficient balance returns 429 resource_exhausted before anything is charged or generation starts.

FieldTypeRequiredNotes
promptstringnoWhat the video should be about — becomes a single implicit scene when scenes is omitted. Needed unless every scene in scenes supplies its own aiPrompt.
scenesarraynoAdvanced: multiple scenes instead of one prompt. Each: { "mediaSource": "ai"|"upload", "aiPrompt", "mediaUrl", "voiceoverScript" } — "upload" scenes need mediaUrl, "ai" scenes need aiPrompt or a top-level prompt.
aspectRatiostringno"9:16" (default), "1:1", or "16:9".
aiVoiceoverbooleannoAdds an AI-narrated voiceover track (edge-tts), synthesized from each scene's voiceoverScript or the top-level prompt.
voiceIdstringnoVoiceover voice id. Defaults to the account's default voice.
saveAsDraftbooleannoSaves the video's settings without generating or charging credits — generate later from the dashboard.
curl -X POST https://getmulticast.com/api/v1/videos \
  -H "Authorization: Bearer gmc_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "A cinematic drone shot flying over a mountain lake at sunrise",
    "aspectRatio": "9:16",
    "aiVoiceover": true
  }'
{ "videoId": "vX9k2...", "creditsRemaining": 823, "requestId": "..." }
GET/videosvideos:readGet a key to try it →

Lists your videos, newest first. Paginated (see Pagination above).

GET/videos/{id}videos:readGet a key to try it →

One video's generation status. status is draft, processing, ready, or failed; progressPct and statusMessage update live while processing.

{
  "id": "vX9k2...", "status": "ready", "progressPct": 100,
  "videoUrl": "https://storage.googleapis.com/.../vX9k2....mp4",
  "voiceoverUrl": "https://storage.googleapis.com/.../vX9k2....mp3",
  "requestId": "..."
}
DELETE/videos/{id}videos:writeGet a key to try it →

Permanently deletes a video.

Webhooks

Register a URL to get a real HTTP POST the moment something happens — no polling. Delivery is durable: every event is queued and a background worker attempts delivery, retrying on a real backoff schedule (1m → 5m → 30m → 2h → 6h → 24h, 7 attempts total) if your endpoint doesn't return a 2xx — after which the delivery is marked failed and stops retrying. Every delivery is signed so you can verify it actually came from GetMulticast, and carries the same X-GetMulticast-Delivery id across every retry attempt so you can safely dedupe on your end.

EventFires when
post.publishedA post finished publishing to at least one account.
post.failedA post failed on every selected account.
comment.receivedA new comment/mention was fetched on a monitored account.
reply.sentA reply — auto-sent or approved from the Review queue — actually went out.
// POST to your url, Content-Type: application/json
{
  "id": "a5e0...",
  "event": "post.published",
  "createdAt": "2026-09-12T10:04:12Z",
  "data": { "runId": "8fJ2k...", "results": { "...": "..." }, "okCount": 2, "total": 2 }
}

Headers on every delivery:

X-GetMulticast-Event: post.published
X-GetMulticast-Signature: sha256=<hmac hex digest of the raw body, using your webhook secret>
X-GetMulticast-Delivery: a5e0f21c-...   # unique per delivery attempt

Verify it (Node example — same HMAC-SHA256-over-raw-body pattern Stripe/GitHub webhooks use):

const crypto = require("crypto");
function verify(rawBody, signatureHeader, secret) {
  const expected = "sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(signatureHeader), Buffer.from(expected));
}
POST/webhookswebhooks:writeGet a key to try it →

Registers a webhook. Body: { "url": "https://...", "events": ["post.published","reply.sent"] }. The response's secret field is shown exactly once — store it to verify future deliveries.

GET/webhookswebhooks:readGet a key to try it →

Lists your registered webhooks (never returns the secret again).

DELETE/webhooks/{id}webhooks:writeGet a key to try it →

Removes a webhook.

GET/webhooks/{id}/deliverieswebhooks:readGet a key to try it →

Real delivery history for one webhook, newest first — every attempt's status and error, useful for debugging a receiver that isn't seeing events.

{
  "deliveries": [
    { "id": "d9c1...", "event": "post.published", "status": "delivered", "attempts": 1, "lastError": null, "createdAt": "..." },
    { "id": "a2e0...", "event": "reply.sent", "status": "pending", "attempts": 2, "lastError": "http_503", "nextAttemptAt": "..." }
  ],
  "requestId": "..."
}

RSS Auto-Post

Point GetMulticast at an RSS or Atom feed and it checks for new items on a schedule (15 minutes minimum), posting each new one to the accounts you choose — the same automation Zapier/IFTTT "RSS → social" recipes provide, built in.

Real limitation, stated plainly: every platform here needs an actual image or video to post — there's no text-only post support anywhere yet. An RSS item is only posted if it has a usable image/video, found in this order: (1) a real <enclosure>/Atom enclosure link, (2) Media RSS (<media:content>/<media:thumbnail>), (3) the first <img> found in the item's full HTML body. Items with none of these are skipped, not force-posted as text. Only facebook, instagram, threads, pinterest, and bluesky support image posts today, so those are the only valid targets for an RSS feed.
POST/rss-feedsrss:writeGet a key to try it →
FieldRequiredNotes
urlyesThe feed's URL (RSS 2.0 or Atom).
selectionsyesSame shape as POST /posts — { "instagram": ["accountId"] }. Only image-capable platforms are accepted.
captionTemplatenoDefaults to "{title}\n\n{link}" — {title} and {link} are the only placeholders substituted.
checkIntervalMinutesnoDefaults to 60, floor of 15.
curl -X POST https://getmulticast.com/api/v1/rss-feeds \
  -H "Authorization: Bearer gmc_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/feed/",
    "selections": { "instagram": ["1784..."], "facebook": ["1029..."] },
    "captionTemplate": "New post: {title}\n\nRead more: {link}",
    "checkIntervalMinutes": 30
  }'
GET/rss-feedsrss:readGet a key to try it →

Lists your feeds, including lastCheckedAt, lastError (if the last check failed) and postedCount.

PATCH/rss-feeds/{id}rss:writeGet a key to try it →

Updates any of active, selections, captionTemplate, checkIntervalMinutes. Set active: false to pause a feed without deleting it.

DELETE/rss-feeds/{id}rss:writeGet a key to try it →
POST/rss-feeds/{id}/check-nowrss:writeGet a key to try it →

Queues an immediate check instead of waiting for the next scheduled interval — picked up within about a minute.

Content Recycling

Pick one of your own already-published posts and set up a rule to automatically re-publish it again every N days — optionally with the caption AI-rewritten each time so it doesn't read as a verbatim repeat. Checked every 6 hours.

Real limitation, stated plainly: there's no "auto-detect my best post" selector — real per-post analytics only cover 4 of 9 platforms today (see GET /posts/{id}/analytics above), so an automatic best-post picker would either ignore most platforms or invent numbers. You choose the source post explicitly.
POST/recycling-rulesrecycling:writeGet a key to try it →
FieldRequiredNotes
sourcePostIdyesA post id from GET /posts that already published successfully.
selectionsnoDefaults to the accounts the source post actually succeeded on.
intervalDaysnoDefaults to 30, floor of 1.
rewriteCaptionnoIf true, AI rewrites the caption on each recycle instead of reusing it verbatim.
curl -X POST https://getmulticast.com/api/v1/recycling-rules \
  -H "Authorization: Bearer gmc_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "sourcePostId": "8fJ2k...", "intervalDays": 14, "rewriteCaption": true }'
GET/recycling-rulesrecycling:readGet a key to try it →

Lists your rules, including lastRecycledAt, nextRecycleAt, and recycleCount.

PATCH/recycling-rules/{id}recycling:writeGet a key to try it →

Updates any of active, selections, intervalDays, rewriteCaption. Set active: false to pause without deleting.

DELETE/recycling-rules/{id}recycling:writeGet a key to try it →
POST/recycling-rules/{id}/run-nowrecycling:writeGet a key to try it →

Queues an immediate recycle instead of waiting for the next scheduled interval.

OpenAPI spec & Postman collection

Every endpoint on this page, machine-readable — generate a client in any language, or import straight into Postman/Insomnia instead of building requests by hand.

Download OpenAPI 3.0 spec (.yaml)
Download Postman collection (.json)

The collection ships with base_url and api_key as collection variables — set api_key once (Postman → collection → Variables) and every request in it authenticates automatically.

MCP server

A Model Context Protocol server that exposes this entire API as tools an MCP-compatible AI client (ChatGPT, Claude, etc.) can call directly — "post this to Instagram and Facebook," "what's in my review queue," "reply to that comment," said in plain language. Two ways to connect, use whichever fits your client — GetMulticast never sees your MCP client's traffic either way, it's just another caller of the same public API documented on this page.

Remote server (no install) — for ChatGPT, Claude Code, and claude.ai

Server URL: https://getmulticast.com/mcp — every request needs your API key as a normal bearer header: Authorization: Bearer gmc_live_...

ChatGPT (Settings → Connectors → Advanced → Developer mode, then Add MCP server):

Claude Code, one command, no download:

claude mcp add getmulticast -t http \
  --header "Authorization: Bearer gmc_live_..." \
  -- https://getmulticast.com/mcp

claude.ai (web or desktop app) — no API key needed, real sign-in instead:

  1. Settings → Connectors → Add custom connector
  2. URL: https://getmulticast.com/mcp
  3. Authentication: Sign in now
  4. Click Add — Claude opens a GetMulticast login/approve screen, click Approve, done

Local server (download & run) — Claude Desktop's other option

Download the server (.zip) — current version: v1.3.0 · Released Sept 2026 — unzip, then:

cd getmulticast-mcp-server
npm install
GETMULTICAST_API_KEY=gmc_live_... node index.js   # test it starts cleanly

Then point your MCP client at it. For Claude Desktop, add to its config file (Settings → Developer → Edit Config):

{
  "mcpServers": {
    "getmulticast": {
      "command": "node",
      "args": ["/full/path/to/getmulticast-mcp-server/index.js"],
      "env": { "GETMULTICAST_API_KEY": "gmc_live_..." }
    }
  }
}
Replace /full/path/to/ with wherever you actually unzipped the file — that literal placeholder will fail. On Mac/Linux it typically looks like /Users/yourname/getmulticast-mcp-server/index.js; on Windows, C:\Users\yourname\getmulticast-mcp-server\index.js.

Claude Code can use this local server too, if you'd rather run it yourself than use the remote URL above:

claude mcp add getmulticast \
  --env GETMULTICAST_API_KEY=gmc_live_... \
  -- node /full/path/to/getmulticast-mcp-server/index.js

Same rule applies — replace /full/path/to/ with your own real unzip location, same as above.

37 tools total, one per API endpoint on this page, verified against the real route table — once connected, ask your MCP client to list its tools, or just describe what you want done ("generate a video about our new product launch and post it to Instagram and TikTok," "what's in my review queue right now").

n8n community node

Two real nodes covering the whole API — published on npm as n8n-nodes-getmulticast — current version: v1.4.0 · Released Sept 2026. Install it directly from n8n: Settings → Community Nodes → Install → enter n8n-nodes-getmulticast. Source on GitHub; submitted to n8n for official Verified-node review.

GetMulticast (action node) covers every resource in this API — Video, Post (including Analytics), Comment, Pending Reply, Webhook, RSS Feed, Recycling Rule, Account, Credits. The Video resource (Create/Get/List/Delete) plays the same role Blotato's "Visual" resource plays in their own n8n node: generate an AI video, poll until it's ready, then feed the result into Post > Create — the same shape as Blotato's own "idea in Telegram → AI video → approve → publish everywhere" workflow templates.

GetMulticast Trigger (trigger node) starts a workflow on a real event (post.published, post.failed, comment.received, reply.sent) with full webhook lifecycle management — activating the workflow registers the webhook automatically (POST /webhooks), deactivating it removes the registration (DELETE /webhooks/{id}), and every delivery is HMAC-signature-verified before reaching your workflow. No manual URL-copying step, though n8n's own generic Webhook node still works too if you'd rather register the URL yourself.

Zapier

A Zapier integration isn't listed on the Zapier App Directory yet — that requires Zapier's own developer review process (their own account, their own submission/review cycle — the same shape as any platform app review). In the meantime, Zapier's built-in Webhooks by Zapier action/trigger works against this API directly with no custom app needed: use a "Custom Request" action for any endpoint on this page (set the Authorization header to your API key), and a "Catch Hook" trigger + this API's POST /webhooks to receive events in real time.

What's not here yet

Built honestly, not oversold — here's what v1 deliberately doesn't include yet:

Changelog

VersionDateChanges
v1.1Sept 2026Added AI Video Generation — POST/GET /videos, GET/DELETE /videos/{id} — same engine as the dashboard's Generate Video button. MCP server bumped to v1.3.0 (37 tools).
v1.0Sept 2026Initial public release — every endpoint on this page, all real, all live from day one.

Questions or found a bug? support@getmulticast.com