Reelspan posts to TikTok through TikTok's Content Posting API. You send the video or photos once; Reelspan checks what the account may post, uploads the file in chunks, waits for TikTok to finish processing and returns the post's link.
What you can post
| Post | How | Notes |
|---|---|---|
| Video | POST /v1/posts/video |
Posted directly, or sent to the TikTok inbox as a draft |
| Photo post | POST /v1/posts/photos |
Up to 35 photos, swiped like a carousel |
TikTok has no text-only posts and no documents. Reelspan handles for you:
- The creator check. TikTok asks apps to read the account's current options before every direct post. Reelspan does it on each post: the privacy levels the account allows, the interactions the creator has turned off, and the longest video it may post.
- Chunked upload. Videos up to 64 MB go up in one piece; larger ones in 10 MB chunks.
- Photo formats. TikTok takes JPEG and WebP only. Other formats, and photos over 20 MB, are converted to JPEG first (the result says so in
warnings). - Waiting. Reelspan follows the post until TikTok reports it published, for up to 10 minutes.
Connect the account
TikTok connects with an OAuth sign-in: in the dashboard go to Accounts → TikTok, or send your client a white-label connect link. Any TikTok account works, personal or business.
Until Reelspan's TikTok app passes TikTok's audit, TikTok only accepts private posts. Reelspan posts them as private (Only me) and says so in
warnings; you make them public in the TikTok app. If TikTok refuses because the account itself is public, set it to private in TikTok (Settings → Privacy → Private account), or send the post to the inbox withpost_mode=MEDIA_UPLOAD.
Example
A video with a caption, visible to everyone, with duets turned off:
curl -X POST https://api.reelspan.com/v1/posts/video \
-H "Authorization: Bearer $REELSPAN_API_KEY" \
-F "user=my-brand" \
-F "platform[]=tiktok" \
-F "tiktok_title=Three ways to fold a shirt #laundry #lifehack" \
-F "privacy_level=PUBLIC_TO_EVERYONE" \
-F "disable_duet=true" \
-F "cover_timestamp=1500" \
-F "[email protected]"import { Reelspan } from 'reelspan';
import { readFile } from 'node:fs/promises';
const reelspan = new Reelspan();
const post = await reelspan.posts.video({
user: 'my-brand',
platforms: ['tiktok'],
video: { data: await readFile('launch.mp4'), name: 'launch.mp4', type: 'video/mp4' },
extra: {
tiktok_title: 'Three ways to fold a shirt #laundry #lifehack',
privacy_level: 'PUBLIC_TO_EVERYONE',
disable_duet: true,
cover_timestamp: 1500,
},
});from reelspan import Reelspan
reelspan = Reelspan()
post = reelspan.posts.video(
"my-brand", ["tiktok"], "launch.mp4",
extra={
"tiktok_title": "Three ways to fold a shirt #laundry #lifehack",
"privacy_level": "PUBLIC_TO_EVERYONE",
"disable_duet": True,
"cover_timestamp": 1500,
},
)A photo post works the same way with POST /v1/posts/photos: add photo_cover_index to pick the cover and auto_add_music=true to let TikTok add a track.
Check the account first
GET /v1/tiktok/creator-info?profile=my-brand returns what this TikTok account may post right now. Use it to offer only the privacy levels TikTok allows, and to warn before a video is too long.
curl "https://api.reelspan.com/v1/tiktok/creator-info?profile=my-brand" \
-H "Authorization: Bearer $REELSPAN_API_KEY"const info = await reelspan.request('GET', '/v1/tiktok/creator-info', { query: { profile: 'my-brand' } });info = reelspan.request("GET", "/v1/tiktok/creator-info", query={"profile": "my-brand"}){
"success": true,
"nickname": "My Brand",
"username": "mybrand",
"avatar": "https://p16-sign.tiktokcdn.com/…",
"privacy_options": ["PUBLIC_TO_EVERYONE", "MUTUAL_FOLLOW_FRIENDS", "SELF_ONLY"],
"comment_disabled": false,
"duet_disabled": false,
"stitch_disabled": true,
"max_video_post_duration_sec": 600
}It answers 404 when the profile has no TikTok account, and 409 with reauth_required when the account needs to be connected again.
Fields
Send these as form fields next to the usual ones (user, platform[], the media). Booleans take true or false.
| Field | Type | Values | What it does |
|---|---|---|---|
tiktok_title |
string | up to 2,200 characters | The caption. Falls back to title. On a photo post, the first line (up to 90 characters) becomes the post's title. |
tiktok_description |
string | up to 4,000 characters | Photo posts only: the description under the photos. Defaults to the caption. |
privacy_level |
string | PUBLIC_TO_EVERYONE, MUTUAL_FOLLOW_FRIENDS, FOLLOWER_OF_CREATOR, SELF_ONLY |
Who can see the post. Must be one of the account's privacy_options. Without it, Reelspan uses PUBLIC_TO_EVERYONE when allowed, otherwise the first allowed option. |
post_mode |
string | DIRECT_POST (default), MEDIA_UPLOAD |
MEDIA_UPLOAD sends the post to the creator's TikTok inbox to finish in the app. |
tiktok_upload_to_draft |
boolean | default false |
Same as post_mode=MEDIA_UPLOAD. upload_to_draft works too. |
disable_comment |
boolean | default false |
Turns comments off. Always on when the creator has turned comments off. |
disable_duet |
boolean | default false |
Videos only: turns duets off. Always on when the creator has turned them off. |
disable_stitch |
boolean | default false |
Videos only: turns stitches off. Always on when the creator has turned them off. |
cover_timestamp |
number | milliseconds | Videos only: the frame TikTok uses as the cover. |
photo_cover_index |
number | 0-based, default 0 |
Photo posts only: which photo is the cover. |
auto_add_music |
boolean | default false |
Photo posts only: TikTok adds music to the photos. |
brand_organic_toggle |
boolean | default false |
Discloses that the post promotes your own business ("Promotional content"). |
brand_content_toggle |
boolean | default false |
Discloses a paid partnership with another brand ("Paid partnership"). Branded content can't be private. |
is_aigc |
boolean | default false |
Videos only: adds TikTok's AI-generated label. tiktok_is_ai_generated and is_ai_generated work too. |
The privacy, interaction, disclosure and AI settings apply to direct posts only. A video sent to the inbox carries only the video, not the caption; a photo post sent to the inbox keeps its title and description. The creator sets the rest in the TikTok app.
Limits
- Caption: 2,200 characters for a video. A photo post has a 90-character title (the caption's first line) and a description up to 4,000 characters.
- Video length: whatever TikTok allows this account, shown as
max_video_post_duration_secin the creator check. A longer video fails before it is uploaded. - Video size: your plan's upload limit (see Plans and limits).
- Photos: up to 35 per post, JPEG or WebP (other formats are converted), up to 20 MB each.
- Shape: vertical 9:16.
Good to know
- Processing. TikTok processes every post before it goes live. Reelspan waits up to 10 minutes. When TikTok has published the post but is still reviewing it, the result has no
urlyet and says so inwarnings. - Inbox posts come back with
url: nulland a warning: the creator finishes them in TikTok's notifications. - Result extras:
publish_id(TikTok's id for the upload) andstatus(PUBLISH_COMPLETEorSEND_TO_USER_INBOX). - Covers. TikTok's cover is a frame of the video, picked with
cover_timestamp; an uploaded cover image is not sent to TikTok. - First comment: TikTok's API has no comments, so
first_commentisn't posted; the result saysfirst_comment: "unsupported". - Analytics: account numbers (followers, following, likes, videos) when your Reelspan workspace has TikTok statistics turned on. An account connected before that has to be reconnected. There are no per-post numbers.
- TikTok's own limits apply on top: a daily post limit per account, and a daily limit on how many people one app can post for.
Errors
error_code |
What happened | What to do |
|---|---|---|
tiktok_privacy_unavailable |
privacy_level isn't one the account allows |
Read privacy_options from the creator check and send one of those. |
tiktok_duration_too_long |
The video is longer than this account may post | Trim it under max_video_post_duration_sec. |
tiktok_unaudited_client_can_only_post_to_private_accounts |
The TikTok account is public, and TikTok only takes posts to private accounts from unaudited apps | Make the account private, or post with post_mode=MEDIA_UPLOAD. |
tiktok_spam_risk_too_many_posts |
The account reached TikTok's daily post limit | Post again tomorrow. |
tiktok_spam_risk_user_banned_from_posting |
TikTok has blocked this account from posting | Sort it out with TikTok. |
tiktok_reached_active_user_cap |
The app reached TikTok's daily limit of posting accounts | Retry later. |
tiktok_url_ownership_unverified |
TikTok hasn't verified the domain Reelspan serves photos from | Photo posts work once it is verified; videos are not affected. |
tiktok_processing_timeout |
TikTok took more than 10 minutes | Reelspan retries it; check the post in TikTok before posting again. |
tiktok_… (other) |
TikTok refused the post or failed to process it; the code carries TikTok's reason | Read error for TikTok's message. |
reauth_required |
The connection expired or lost a permission | Reconnect TikTok. |