Skip to contentNew: schedule straight from DaVinci Resolve with the Reelport plugin →

Developers · API v1 · MCP

An API and an MCP server

Script your own pipeline or hand the queue to an agent. Everything the Resolve plugin and the Claude extension do runs on these public endpoints, with the same rules as the composer.

Base URL
https://api.reelport.io/v1
Auth
Authorization: Bearer rp_…
Format
JSON in and out, Accept: application/json
MCP
https://reelport.io/mcp (Streamable HTTP)

Authentication

Every request carries a personal API token as a Bearer token. Create one under Settings › API tokens, tick its abilities (channels:read, media:write, posts:read, posts:write, brand:read, brand:write) and copy it: it is shown once. A token acts as its user inside one team; revoke stops it at once.

GET /v1/meExample
curl https://api.reelport.io/v1/me \
  -H "Authorization: Bearer rp_…" \
  -H "Accept: application/json"

{"data": {
  "user": {"id": 1, "name": "Flo", "email": "flo@example.com"},
  "team": {"id": 3, "name": "Studio Nord", "slug": "studio-nord"},
  "plan": {"slug": "creator", "name": "Creator", "status": "active",
           "renews_at": "2026-12-07T10:00:00+00:00", "ends_at": null,
           "trial_ends_at": null},
  "token": {"name": "Reelport plugin", "client": "reelport-plugin",
            "abilities": ["channels:read", "media:write",
                          "posts:read", "posts:write"]}
}}

Device flow

For apps that shouldn’t handle a password: the OAuth 2.0 device authorization grant (RFC 8628). Show the user_code, open verification_uri_complete, then poll every interval seconds. On slow_down, add 5 seconds. A code lives 15 minutes and its token can be collected once. No token is needed for these two calls.

POST /v1/device/code · /device/tokenExample
POST /v1/device/code
{"client_id": "reelport-plugin"}

200 {"device_code": "…48 chars…", "user_code": "BCDF-GHJK",
     "verification_uri": "https://reelport.io/device",
     "verification_uri_complete": "https://reelport.io/device?code=BCDF-GHJK",
     "interval": 5, "expires_in": 900}

POST /v1/device/token
{"device_code": "…"}

200 {"access_token": "rp_…", "token_type": "Bearer", "team_id": 3}
400 {"error": "authorization_pending", "error_description": "…"}

Channels

channels:read

The team’s connected channels. TikTok channels include the creator’s live posting options: offer only those privacy levels and don’t preselect one. status "needs_reconnect" means the user has to reconnect that channel in reelport.io first. Pass ?include=none to skip the TikTok lookup.

GET /v1/channelsExample
{"data": [
  {"id": 12, "platform": "tiktok", "name": "Flo", "handle": "flo.drone",
   "status": "active", "takes": ["video"],
   "tiktok": {"nickname": "Flo",
              "privacy_level_options": ["PUBLIC_TO_EVERYONE",
                "MUTUAL_FOLLOW_FRIENDS", "SELF_ONLY"],
              "comment_disabled": false, "duet_disabled": true,
              "stitch_disabled": false,
              "max_video_post_duration_sec": 600}},
  {"id": 13, "platform": "youtube", "name": "Studio Nord",
   "handle": "@studionord", "status": "active", "takes": ["video"]},
  {"id": 14, "platform": "instagram", "name": "studionord",
   "handle": "studionord", "status": "active",
   "takes": ["video", "image"]}
]}

Media uploads

media:write

Direct upload sends the file straight to storage without passing through reelport.io: ask for a signed URL, PUT the raw bytes with exactly the given headers within 2 hours, then complete. For small files, a plain multipart POST /v1/media with a file field works too. Videos: MP4 or MOV up to 1 GB and 10 minutes. Photos: JPEG, PNG or WebP up to 8 MB.

POST /v1/media/uploadsExample
POST /v1/media/uploads
{"filename": "drone-variation-2.mp4", "size": 312456789,
 "content_type": "video/mp4"}

201 {"data": {"upload_id": "9b2f…", "method": "PUT",
              "url": "https://…signed…",
              "headers": {"Content-Type": "video/mp4"},
              "expires_at": "2026-11-07T19:30:00+00:00"}}

POST /v1/media/uploads/9b2f…/complete

201 {"data": {"id": 41, "kind": "video",
              "name": "drone-variation-2.mp4", "size": 312456789,
              "duration_seconds": 28.4, "width": 1080, "height": 1920}}

Posts

posts:write · posts:read

Give scheduled_at in ISO 8601 with an offset, or "next_free_slot": true with a timezone; "publish_now": true or "draft": true also work. The composer’s rules apply: TikTok needs a privacy_level from the channel’s options, YouTube needs title, privacy and made_for_kids. GET /v1/posts/{id} returns the same shape, with each target’s status, url and error.

POST /v1/postsExample
{
  "media_id": 41,
  "channel_ids": [12, 13, 14],
  "caption": "Sunrise over the harbour #drone",
  "scheduled_at": "2026-11-10T18:00:00+01:00",
  "options": {
    "tiktok": {"privacy_level": "PUBLIC_TO_EVERYONE",
               "allow_comment": true, "allow_duet": false,
               "allow_stitch": false, "brand_organic": false,
               "brand_content": false},
    "youtube": {"title": "Sunrise over the harbour",
                "privacy": "public", "made_for_kids": false},
    "instagram": {"share_to_feed": true}
  }
}

201 {"data": {"id": 88, "status": "scheduled",
     "scheduled_at": "2026-11-10T17:00:00+00:00", "media_id": 41,
     "url": "https://reelport.io/studio-nord/posts/88/edit",
     "targets": [{"channel_id": 12, "platform": "tiktok",
                  "status": "pending", "url": null, "error": null,
                  "published_at": null}]}}

Slots

posts:read

The next free queue slots: 09:00, 12:30 and 18:00 daily in your timezone, minus those that already have a post within 30 minutes. Use them to spread variations over the coming days.

GET /v1/slotsExample
GET /v1/slots?count=3&timezone=Europe/Berlin&channel=12

200 {"data": ["2026-11-10T18:00:00+01:00",
              "2026-11-11T09:00:00+01:00",
              "2026-11-11T12:30:00+01:00"]}

Errors

Every error has the same shape, with a message you can show the user as it is. For validation errors, fields uses the request’s own names, such as options.youtube.made_for_kids or channel_ids.1.

Status Code When
401unauthenticatedThe token is missing, wrong or revoked.
402no_planThe team has no active plan. Drafts still work.
403forbiddenThe token lacks the ability the endpoint needs.
404not_foundThe item doesn’t exist or belongs to another team.
422validation_failedSee fields.
429rate_limitedMore than 120 requests a minute, or 60 uploads an hour, per token.
5xxserver_errorTry again later.
422 validation_failedExample
{"error": {"code": "validation_failed",
           "message": "Choose who can watch this video.",
           "fields": {"options.tiktok.privacy_level":
             ["The privacy level field is required."]}}}

Rate limits

120
requests a minute, per token
60
uploads an hour, per token

Above either, the API answers 429 rate_limited. The platforms’ own limits still apply to what gets published: TikTok, YouTube and Instagram each cap uploads per day.

MCP tools

The same actions as tools for Claude and other agents, over Streamable HTTP at https://reelport.io/mcp, with the same token and the same validation.

The Reelport Claude extension uses these
list-channels
The team’s channels, with TikTok’s live posting options.
next-slots
The next free queue slots in a timezone, optionally for one channel.
schedule-post
Schedule a post at a time or the next free slot, or save a draft, with per-platform options.
get-post
A post’s status and each channel’s result, link or error.

Get a token. Schedule your first post.

Connect a channel, schedule your first post and watch it depart.

Start your free trial
  • 7 days free
  • No card needed
  • Hosted in the EU
  • GDPR-ready