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.

Posting

Publishing is the one thing here that a person cannot undo. It needs the posts:write scope, which is granted separately from everything else on purpose, and it is worth being deliberate about.

The loop that works:

  1. GET /api/v1/connections to see what the brand can post to at all.
  2. POST /api/v1/posts/validate with the exact body you intend to send.
  3. Read every verdict. Fix what is wrong, or drop the account that is broken.
  4. POST /api/v1/posts.
  5. Read every result. A partial run is normal, not an error to retry wholesale.

Platform rules

These come from the same values the code enforces, so a caption that fits here fits at the platform.

PlatformAcceptsTitle capCaption capPosting modesPosting cap
TikTokvideo and photos90 characters4000 charactersdraft, direct15 posts per 24 hours
YouTubevideo only100 characters5000 charactersdirectno cap enforced here
Instagramvideo onlyno title2200 charactersdirectno cap enforced here
LinkedInvideo onlyno title3000 charactersdirectno cap enforced here
  • TikTok. Slideshows go out as a photo post. Draft mode drops the post into the TikTok inbox so a person finishes it in the app.
  • YouTube. Uploads are published publicly unless the brand changed its YouTube visibility setting in ReelMoney.
  • Instagram. Posts publish as reels from a public video URL, so render the video before you post it.
  • LinkedIn. LinkedIn rejects a video smaller than 75 KB or larger than 500 MB.

A slideshow and a video are not interchangeable. TikTok takes a slideshow as a photo post directly, with no render needed. Instagram, YouTube and LinkedIn take video, so render the slideshow first with POST /api/v1/slideshows/{id}/render and post it when the render job succeeds.

Connecting an account

An account is connected once, by a person, in a browser. The API cannot do it alone and does not pretend to.

curl -X POST https://reel.money/api/v1/connections/link \
  -H "Authorization: Bearer rm_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "platform": "tiktok" }'

The response carries connect_url, the instructions to relay and a note that the link goes stale. Then:

  1. Give the link to the person who owns the account. Do not open it yourself.
  2. They sign in on the platform and approve the permissions ReelMoney asks for.
  3. They land back on ReelMoney with the account attached to this brand.
  4. Call GET /api/v1/connections and confirm the account appears with a healthy token.

What each platform expects of the person:

  • TikTok. The account they want to post from. ReelMoney asks for permission to upload and publish videos and photo posts, and to read the account's basic profile.
  • YouTube. A Google account with the channel they want to upload to. ReelMoney asks for upload and read access, nothing else.
  • Instagram. A business or creator account. Personal accounts cannot publish through the platform's API at all, which is a rule on their side.
  • LinkedIn. A member account, and the organization pages they are an admin of if they want to post as a company.

Build the link when the person is ready to click it, because authorize links expire in minutes. A platform this deployment has no client id for answers 503 platform_not_configured, in which case connect from the dashboard instead.

Validate before you post

POST /api/v1/posts/validate takes the same body as the post, needs only posts:read, enqueues nothing and touches nothing. It checks the things that actually go wrong:

  • Does the short exist, and does it have a video or slides to publish yet.
  • Is each account connected, and is its token still fresh.
  • Are the caption and the title inside that platform's caps.
  • Is there posting headroom left for that account right now.
  • Is scheduled_at at least 5 minutes ahead.
{
  "ok": false,
  "short_id": 8842,
  "scheduled_at": "2026-08-19T15:00:00Z",
  "issues": [],
  "verdicts": [
    {
      "social_data_id": 55,
      "platform": "tiktok",
      "account_name": "northwindcoffee",
      "token_status": "expired",
      "rate_limit": { "used": 3, "max": 15, "remaining": 12, "limited": false, "label": "15 posts per 24 hours" },
      "ok": false,
      "issues": [
        { "code": "token_expired", "message": "The tiktok connection reports expired and needs a fresh connect link.", "retryable": false }
      ]
    }
  ]
}

ok at the top is true only when every verdict is true. A validate that costs one request saves a post that half worked.

Publishing

curl -X POST https://reel.money/api/v1/posts \
  -H "Authorization: Bearer rm_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "short_id": 8842,
    "platforms": ["tiktok"],
    "scheduled_at": "2026-08-19T15:00:00Z"
  }'
FieldNotes
short_idRequired. The short must have a rendered video or slides.
social_data_idsSpecific connected accounts, from GET /api/v1/connections.
platformsEvery connected account of these platforms. Use this or social_data_ids.
scheduled_atISO 8601. Leave it out to publish now. At least 5 minutes ahead when present.
post_formatFor example video or slideshow. ReelMoney picks a sensible default per short type.
posting_modeTikTok only. direct publishes, draft drops the post into the TikTok inbox for a person to finish in the app.
auto_add_musicTikTok photo posts. Lets TikTok add music.
platform_customizationsPer account title and caption overrides, keyed by social_data_id as a string.

Send an Idempotency-Key header. A create that timed out is then safe to retry without posting twice.

Scheduling

A scheduled post needs at least 5 minutes of lead time, which is what the queue needs to pick it up reliably. Anything sooner, or in the past, answers schedule_too_soon. Send the time in ISO 8601 with an explicit zone, and remember the platform caps still apply at the moment the post goes out, not at the moment you scheduled it.

Scheduled posts show up in GET /api/v1/posts with status scheduled and their scheduled_at.

Cancelling

DELETE /api/v1/posts/{id} pulls back a post that has not gone out. Posts in draft, pending or scheduled can be cancelled. Anything already publishing or published answers 409 not_cancellable, because the platform has it now and we cannot take it back.

Partial success

Posting to several accounts is not all or nothing. One expired token never stops the other accounts.

{
  "short_id": 8842,
  "overall_status": "partial",
  "results": [
    { "social_data_id": 55, "platform": "tiktok", "account_name": "northwindcoffee", "share_id": 9901, "status": "pending", "scheduled_at": null },
    { "social_data_id": null, "platform": "instagram", "share_id": null, "status": "failed",
      "error": { "code": "platform_not_connected", "message": "No instagram account is connected.", "retryable": false } }
  ]
}
  • overall_status is success when every account worked, partial when some did, failed when none did.
  • Walk results and handle each entry on its own. Retry only the accounts that failed, and only when their error is retryable.
  • Never resend the whole request because one account failed. That is how the same video ends up on TikTok twice.
  • A share_id is the handle for that account's post. It is what DELETE /api/v1/posts/{id} takes and what shows up in GET /api/v1/posts.

Watching what happened

GET /api/v1/posts lists posts newest first, filtered by short_id, status or platform. Statuses are draft, pending, scheduled, retrying, success, failed and cancelled. A successful post carries the link on the platform once it lands.

A day or two later, GET /api/v1/analytics reports how it did. TikTok is the platform with an analytics adapter today, and the payload says so in supported_platforms.

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