The TikTok Content Posting API publishes video and photo content on behalf of a creator, through an init call, an upload or URL pull, and a status poll. The single most important fact before you start: until your client passes TikTok’s audit, everything you post is restricted to private viewing. You can build and test the whole integration and still not be able to make one public post.
What can the Content Posting API publish, and what is blocked?
The API covers direct posting of video and photo content, plus a draft path that sends content to the creator’s inbox for them to finish. The endpoints are POST /v2/post/publish/video/init/ for video, POST /v2/post/publish/content/init/ for photos, and POST /v2/post/publish/status/fetch/ to check the result. There is also POST /v2/post/publish/creator_info/query/, which you are expected to call first to learn what the creator’s account permits.
The blocker is the audit. TikTok’s own wording: “All content posted by unaudited clients will be restricted to private viewing mode.” The docs are equally direct on the direct-post reference page, where unaudited clients “can only post to a private account”, with the attempt blocked at /publish/video/init/.
| Concern | What the docs say |
|---|---|
| Required scope | video.publish, approved for your app and authorised by the user |
| Unaudited apps | Content restricted to private viewing mode |
| Privacy levels | PUBLIC_TO_EVERYONE, MUTUAL_FOLLOW_FRIENDS, FOLLOWER_OF_CREATOR, SELF_ONLY |
| Media source | FILE_UPLOAD or PULL_FROM_URL |
| URL pull | Requires verifying ownership of the URL prefix or domain |
SELF_ONLY is the value you will live with during development. It is also worth noting that the set of privacy levels a given creator can use is not fixed: you query creator_info and use what comes back, rather than hardcoding PUBLIC_TO_EVERYONE and hoping.
Note: Figures here were verified against TikTok’s Content Posting API documentation as of September 2026. Platforms change these without notice.
How does auth work, and how long does the audit take?
Standard OAuth to obtain a user access token carrying video.publish. Two approvals stack on top of each other: your app must be granted the scope, and the individual creator must authorise it at connect time. Neither one alone is enough.
The audit is separate again. It happens after you have a working integration, because TikTok expects you to have tested the flow before requesting it. TikTok does not state a review duration in the Content Posting API documentation, so treat the timeline as unpublished and unknown. Plan your launch date around an approval you do not control.
What is the publishing call sequence?
POST /v2/post/publish/creator_info/query/to check the creator’s allowed privacy levels and interaction settings.POST /v2/post/publish/video/init/withpost_info(title,privacy_level, the disable flags,video_cover_timestamp_ms, the commercial-content toggles) andsource_info.- If
sourceisFILE_UPLOAD,PUTthe bytes to theupload_urlreturned by init, in chunks matching thechunk_sizeandtotal_chunk_countyou declared. IfsourceisPULL_FROM_URL, TikTok fetches it from your verified domain instead. POST /v2/post/publish/status/fetch/with thepublish_idfrom init, and poll.- Treat
PUBLISH_COMPLETEas success andFAILEDas terminal. Nothing before that is a published post.
# 1. init a direct post
curl -X POST "https://open.tiktokapis.com/v2/post/publish/video/init/" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{
"post_info": { "title": "Ship it.", "privacy_level": "SELF_ONLY" },
"source_info": { "source": "PULL_FROM_URL",
"video_url": "https://verified.example.com/clip.mp4" }
}'
# -> { "data": { "publish_id": "v_pub_url~..." } }
# 2. poll
curl -X POST "https://open.tiktokapis.com/v2/post/publish/status/fetch/" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{ "publish_id": "v_pub_url~..." }'
The documented status values are PROCESSING_UPLOAD (file upload path), PROCESSING_DOWNLOAD (URL pull path), SEND_TO_USER_INBOX (draft handed to the creator), PUBLISH_COMPLETE and FAILED.
What are the rate limits?
Two numbers are stated plainly in the reference docs, both per user access token:
- Direct post init: 6 requests per minute.
- Status fetch: 30 requests per minute.
Six inits per minute per user is generous for a scheduler and tight for a bulk import. Thirty status fetches per minute sounds like plenty until you have hundreds of in-flight posts sharing a poller, at which point you need backoff per token rather than a global loop.
We could not confirm a documented per-user daily posting quota, a maximum video file size or a maximum duration from the Content Posting API pages we read. The creator info response is the intended source for the per-account video duration cap, so read it rather than hardcoding a number.
Note: Figures here were verified against TikTok’s Content Posting API documentation as of September 2026. Platforms change these without notice.
What will actually cost you three weeks?
The audit. This is the big one, and it is unlike Instagram or LinkedIn review in a specific way: you can ship code, connect accounts and publish, and still have every post be invisible. Nothing in your logs will look wrong. Do not let a stakeholder see a successful PUBLISH_COMPLETE in staging and conclude the feature is done.
Domain verification for PULL_FROM_URL. Letting TikTok fetch your media is much simpler than chunked uploads, but it requires proving you own the URL prefix. If your media lives on a bucket with a generated hostname, you will be adding a custom domain to your storage before you can use the easy path.
Token refresh. TikTok access tokens are refreshed with a refresh token, and an expired connection means the creator has to reconnect. As with every platform, the work is not the refresh call, it is the state machine and the notification when refresh fails.
Async failure handling. Init returning a publish_id is not a publish. Neither is a successful upload. Only PUBLISH_COMPLETE is, and FAILED can arrive minutes later for reasons like unsupported encoding. Store the publish_id, keep a processing state, and reconcile. Our social media scheduling API guide covers the state model this needs.
If you are also writing the captions, the TikTok character counter will tell you where the title gets cut.
The short version
- Init, upload or pull, then poll status.
PUBLISH_COMPLETEis the only success. - Unaudited clients can only post privately. Audit is required for public posts.
video.publishscope needs approval for your app and consent from the creator.- 6 init requests per minute and 30 status fetches per minute, per user token.
- Review and audit durations are not published by TikTok.
Publishing to TikTok without owning the audit
One way around the setup cost is to publish through an API that has already been through it. BulkPublish covers TikTok alongside 14 other platforms through one REST API, so the init, the upload, the polling and the retry are on our side and your call is a single create-post request with a channel ID. The same call targets Instagram Reels and YouTube Shorts if you are cross-posting. Endpoints are documented at /developers/, and the REST integration overview is at /integrations/rest-api/.