Quick reference
Connect an account
POST /v1/accounts/connect/tiktok. OAuth 2.0 with PKCE. After the callback the provider:
- Calls
GET /v2/user/info/to pinplatformAccountIdto the real TikTokopen_id. - Calls
POST /v2/post/publish/creator_info/query/to snapshot the privacy allowlist; accounts with onlySELF_ONLYare flagged asauditState: "audit"and the publisher forcesSELF_ONLYon every post until that flips.
Scopes
video.publish (Direct Post), video.list.
Token lifecycle
24-hour access tokens; 365-day refresh tokens that roll on every use. The provider refreshes 1 hour before expiry; subscribe totoken.expiring to know when a re-auth window is coming.
Post a video
tiktok-video-post.json
Privacy
privacy accepts three values: public_to_everyone, mutual_follow_friend, self_only. Audit / sandbox accounts always end up as SELF_ONLY regardless of what you pass — letmepost rewrites the request and attaches a tiktok.audit.self_only warning so the caller knows we did so.
Branded content
brandContentToggle: true flags the post as a paid partnership. brandOrganicToggle: true flags it as content for your own brand. TikTok rejects requests that set both — preflight catches it with tiktok.branded_content.mutual_exclusive.
Code samples
How publishing works under the hood
TikTok’s Content Posting API is asynchronous. The publisher:- Calls
POST /v2/post/publish/inbox/video/init/withsource: "FILE_UPLOAD",video_size,chunk_size,total_chunk_count. Returnsupload_url+publish_id. - PUTs the video bytes to
upload_url. Files under 64 MiB go in one request; larger files chunk at 10 MiB with explicitContent-Rangeheaders. - Returns
status: "publishing"with thepublish_idstamped oncidso the caller can correlate by id. - A BullMQ worker polls
POST /v2/post/publish/status/fetch/on a bucketed schedule (5 s → 30 s → 2 min) until TikTok reaches a terminal state. - Terminal
PUBLISH_COMPLETE→post.publishedwebhook with the public TikTok URL. TerminalFAILED→post.failedwith the upstream reason. The 30-minute deadline turns intopost.failedwithtiktok.publish.pending.
SEND_TO_USER_INBOX state is also treated as terminal-published — TikTok’s upload-inbox flow IS the documented end-state for audit-mode posts. The user confirms publish in their TikTok app; we have no API signal for that final tap.
Wisdom (platform-specific things that bite)
Common errors
What you can’t do (yet)
- Photo carousels (unaudited apps).
- Direct Post (public publishing without user confirmation) until
video.publishclears review. - pull_by_url uploads (domain verification gate).
- Reading post engagement, comments, or analytics.
- TikTok Live, Shop, DMs.
API reference
POST /v1/posts— primary publish.POST /v1/media— upload video bytes formediaIdreferences.POST /v1/accounts/connect/tiktok— start a TikTok OAuth flow.

