ReelMoney API

Built for agents

Generate slideshows and videos, publish them to TikTok, YouTube, Instagram and LinkedIn, and read the numbers back. Over REST, or over MCP.

MCP server

ReelMoney runs a Model Context Protocol server at https://reel.money/mcp. Point Claude, Cursor, or any MCP client at it and the model gets 18 tools that do the same work as the REST API, calling the same code underneath, so the two surfaces can never drift.

Endpointhttps://reel.money/mcp
TransportStreamable HTTP, stateless. One self contained exchange per POST.
AuthAuthorization: Bearer rm_your_key, the same key the REST API takes.
ProtocolJSON-RPC 2.0: initialize, tools/list, tools/call.

There is no OAuth flow yet. The key goes in the header, which every client below supports.

Connect a client

Claude Code, one line in a terminal:

claude mcp add reelmoney --transport http https://reel.money/mcp --header "Authorization: Bearer rm_your_key"

Claude Desktop, Cursor and anything else that reads a JSON config:

{
  "mcpServers": {
    "reelmoney": {
      "type": "http",
      "url": "https://reel.money/mcp",
      "headers": {
        "Authorization": "Bearer rm_your_key"
      }
    }
  }
}

A raw check with curl, useful when a client is quiet about why it failed:

curl -X POST https://reel.money/mcp \
  -H "Authorization: Bearer rm_your_key" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

The tools

ToolWhat it doesKindScope
get_accountRead the account behind this API key: masked email, plan name and capabilities (slideshow quota used and remaining), credits when the plan shows them, brands and key scopes.read onlybrand:read
get_brandRead the brand this key belongs to: name, description, website, language, categories, slideshow settings (default context, slide overrides, append slots) and which social platforms are connected.read onlybrand:read
list_mediaBrowse media: source own (this brand's uploads), packs (media pack contents) or stock (the shared catalog, searched semantically when you pass a query).read onlymedia:read
upload_mediaUpload a file in two steps.writesmedia:write
create_slideshowStart an AI slideshow generation for this brand and get back a job.writescontent:write
update_slideshowEdit a generated slideshow: title, caption, tags, aspect ratio, gradient settings or the slides themselves (text overlays are normalized server side).writescontent:write
create_videoStart a hook and demo (UGC) video: an avatar clip speaks the hook_text, then your product demo clips play.writescontent:write
render_videoRender a generated slideshow into an MP4 video.writescontent:write
get_jobPoll a generation or render job by the job_id a create tool returned.read onlybrand:read
list_shortsList this brand's shorts (slideshows and videos), newest first.read onlybrand:read
get_shortRead one short in full: status, URLs, type_data (slides and overlays for a slideshow) and its shares (posts) so far.read onlybrand:read
list_connectionsList the social accounts connected to this brand with token status, posting rate limit headroom and a ready_to_post verdict per account.read onlybrand:read
create_connection_linkBuild the OAuth authorize URL a person opens once in a browser to connect a social account to this brand.read onlybrand:read
validate_postDry run a post before you commit to it: same arguments as schedule_post, returns a per-account verdict (postable short, fresh tokens, caption and title lengths, platform rate limits, schedule sanity).read onlyposts:read
schedule_postPublish a short now, or schedule it, to connected accounts.destructive, ask a person firstposts:write
cancel_postCancel a scheduled post (a share id from schedule_post results or get_short) before it goes out.destructive, ask a person firstposts:write
get_analyticsRead post analytics.read onlyanalytics:read
explain_errorLook up any error code another tool or the REST API returned and get its cause, whether a retry can help, and the concrete fix.read onlyany key

Every tool carries a title and the standard annotations, so a client can tell a read from a write before it calls anything.

Rules a client should know

  • A missing scope does not hide a tool. Every key sees all 18 tools. A tool the key lacks the scope for answers at call time with a structured missing_scope error that names the scope and how to add it. Predictable beats surprising.
  • **brand_id picks the brand, when the key allows it.** Every brand facing tool takes an optional brand_id argument. Omit it and the tool works on the key's own brand. A key with the brands:all scope may pass any brand id the account owns (get_account lists them); without the scope a foreign brand_id answers a structured missing_scope error, and an id the account does not own answers not_found.
  • Two tools are marked destructive. schedule_post and cancel_post carry destructiveHint and _meta: {"anthropic/requiresUserInteraction": true}. Publishing to an audience and pulling a post back are decisions a person should confirm. Treat the prompt as the point of the annotation, not as a formality.
  • GET /mcp answers 405. The server is stateless, so there is no session to attach a server sent event stream to. Use POST. DELETE /mcp answers 200 and does nothing, since there is no session to end.
  • Bad key, 401 at the transport. Authentication happens before any protocol handling, so an invalid key answers HTTP 401 with WWW-Authenticate: Bearer realm="ReelMoney", error="invalid_token" and the usual error envelope, not a JSON-RPC error.
  • Rate limits are shared with REST. The same per key ceilings apply. See authentication.

Result size and pagination

Tool results are token budgeted, around 25k tokens in Claude Code, and a blown budget wastes a whole turn. So:

  • Lists come back capped at 20 items with a note. Pass page to walk further instead of asking for everything.
  • Prefer a list tool with a filter over a list tool without one. list_shorts with short_type and status beats reading the whole library.
  • get_short returns full detail including slides and overlays. Call it for one record, not in a loop over a list.
  • get_analytics without arguments returns account summaries; add social_data_id only when you need post by post numbers.

A working loop

  1. get_account. Read the plan and how much quota is left. Stop here if there is not enough.
  2. get_brand and, when you need a specific look or a media pack, list_media.
  3. create_slideshow or create_video. Both answer with a job_id.
  4. get_job, no faster than poll_after_seconds, until it reads succeeded or failed.
  5. render_video when a caller wants an MP4 of a slideshow. Never create a second slideshow for that.
  6. list_connections, then validate_post, then schedule_post. Read every verdict before you post, and every result after.
  7. get_analytics a day or two later to see what it did.
  8. explain_error for any code you do not recognise, instead of guessing from the message.

Reading this as an agent? Every page is also plain markdown: /api-docs/mcp.md