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.
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
{"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.
{"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/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.
{
"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/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 |
|---|---|---|
| 401 | unauthenticated | The token is missing, wrong or revoked. |
| 402 | no_plan | The team has no active plan. Drafts still work. |
| 403 | forbidden | The token lacks the ability the endpoint needs. |
| 404 | not_found | The item doesn’t exist or belongs to another team. |
| 422 | validation_failed | See fields. |
| 429 | rate_limited | More than 120 requests a minute, or 60 uploads an hour, per token. |
| 5xx | server_error | Try again later. |
{"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.
- 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