Yes. TikTok's Content Posting API publishes video and photo posts. But there is a rule that catches almost everyone: until your app passes TikTok's audit, every post it creates is forced to private (SELF_ONLY) — visible to the account owner and nobody else. Your integration will look broken when it is working exactly as designed. This is the single most confusing thing about building on TikTok, and it is not prominently signposted.
#Quick answer
- Is there a posting API? Yes — the Content Posting API, for video and photo posts.
- Can I post publicly right away? No. Unaudited apps can only post privately, to accounts that are themselves set to private.
- How do I fix that? Pass TikTok's audit. Until then,
SELF_ONLYis the only privacy level that works, and the TikTok account must be private. - What does
unaudited_client_can_only_post_to_private_accountsmean? TikTok blocked the post at the init call (/publish/video/init/for video,/publish/content/init/for photos) because your unaudited app tried to post to an account that is not private. Fix below. - Is upload one call? No. It is initialise, upload, then poll for status.
#The audit gate, in detail
When you register a TikTok app and request the Content Posting scopes, you are unaudited. In that state:
- You may only publish with
privacy_levelset toSELF_ONLY. - The TikTok account you post to must itself be set to private when you post. If it is public, TikTok blocks the post at initialisation with
unaudited_client_can_only_post_to_private_accounts. - At most 5 users can post through your app in any 24-hour window.
- The post still appears in the account. It is simply private.
So the classic first-integration experience is: the API returns success, the video is on TikTok, and the creator swears nobody can see it. Both things are true.
Because of this we hard-gate the privacy level behind a config flag rather than trusting the creator's choice. Unaudited means SELF_ONLY, full stop:
1if (! config('services.tiktok.audited', false)) {
2 return 'SELF_ONLY';
3}
4
5// Audited apps may honour the creator's choice — but only from the
6// privacy options TikTok reports for that specific creator.
7$allowed = $creator->json('data.privacy_level_options', []);
That second part matters too. Even after audit, you cannot simply pass whatever level you like. You query the creator's allowed options first and pick from what TikTok returns for that account, because a private TikTok account has a different set than a public one.
#unaudited_client_can_only_post_to_private_accounts: what it means and how to fix it
TikTok's Direct Post API reference defines the error in one line: "Unaudited clients can only post to a private account. The publish attempt will be blocked when calling /publish/video/init/." The photo post reference has the same error for /publish/content/init/.
So the error is about the account, not only the privacy level you send. TikTok's content sharing guidelines set two rules for every app that has not passed the audit:
| Rule for unaudited apps | TikTok's wording |
|---|---|
| The account must be private | "All user accounts using the API client to post must be set to private at the time of posting." |
| The post must be private | "Unaudited API Clients can only post contents in SELF_ONLY viewership." |
| Five posting users a day | "Unaudited API Clients can allow up to 5 users to post in a 24 hour window." |
How to fix it, in order:
- For testing: in the TikTok app, set the test account to private (Profile → Menu ☰ → Settings and privacy → Privacy → Private account). Then post with
privacy_level: SELF_ONLY. The init call should now pass. - To make a test post public later: TikTok says the account owner must first switch the account back to public, then change each post's privacy to "Everyone".
- For real users: apply for the audit. Until it passes, nobody can post publicly through your app, and only five users a day can post at all.
Two audit rules catch people out. TikTok's guidelines list "a utility tool to help upload contents to the account(s) you or your team manages" as not acceptable, so an internal upload script will not pass. And your posting screen must let the creator choose the privacy level, with "no default value".
Even after the audit, every app shares TikTok's posting cap: "typically around 15 posts per day" per creator account, across all apps that use Direct Post.
#The upload flow
There is no single "post this video" call. Video posting is three stages:
1. Initialise. Declare the post — caption, privacy level, and how the media will arrive. For direct publishing to the feed you use a direct-post init with source: FILE_UPLOAD, and TikTok returns an upload URL and a publish ID.
2. Upload. Send the bytes to that URL. TikTok's chunking rules are strict: each chunk must be between 5MB and 64MB, and the chunk count has to line up with the file size. Get the arithmetic wrong and the upload is rejected with an unhelpful error. The file limits themselves (4 GB, 360 to 4096 px, 23 to 60 fps) are listed in our TikTok video size and format guide.
3. Poll. Publishing is asynchronous. You call the status endpoint until TikTok reports the post has finished processing. A response at step 1 means "accepted", not "published" — TikTok is still transcoding.
Photo posts work differently again: they use PULL_FROM_URL, where you give TikTok publicly reachable image URLs and it fetches them. There is no chunked upload path for photos. If your media is behind auth, TikTok cannot retrieve it and the post fails.
That asynchronous tail is why a TikTok post can take up to a minute to flip from "sent" to "published" in any tool built on this API, including every TikTok scheduler that auto-posts for you. It is TikTok's processing time, not the tool being slow.
#Sandbox and scopes
You need video.publish (direct posting) and/or video.upload (upload to drafts). Sandbox mode lets you test against a small number of nominated accounts before review.
Two practical notes. First, the audit is about your app, not your account — a personal creator account does not change anything. Second, TikTok's review expects you to demonstrate a genuine product, so a bare test harness tends not to pass.
#What you can post
- Video — the primary case, via direct post or upload-to-draft.
- Photo posts — carousels, via
PULL_FROM_URLonly. - Captions with hashtags and mentions.
- Privacy level — but constrained as described above.
- Interaction toggles — comment, duet and stitch settings, subject to the creator's account-level restrictions.
You cannot schedule through the API. As with LinkedIn, scheduling means your own queue holds the post and calls TikTok at the right time. For the creator's view of the same limits, including TikTok Studio's built-in scheduler, see scheduling TikTok posts without code.
#Should you build it yourself?
TikTok is the most involved platform we have built for. The audit process, the three-stage upload, the chunk arithmetic, the photo/video split and the asynchronous polling add up to considerably more than a weekend.
Build it directly if TikTok is strategically central and you are prepared to go through audit. Otherwise use an API that has already been through it. With Schedule & Chill, TikTok is one of the networks you can post to today, and posting is the same call as anywhere else:
1curl -X POST https://schedulenchill.com/api/posts \
2 -H "Authorization: Bearer YOUR_API_KEY" \
3 -H "Content-Type: application/json" \
4 -H "Accept: application/json" \
5 -d '{
6 "content": "Behind the scenes of this week build.",
7 "social_account_ids": [792],
8 "media_ids": [456]
9 }'
Poll GET /api/posts/{id} for per-account status — TikTok's processing tail means it will sit in publishing for a bit before it lands.
#Frequently Asked Questions
Does TikTok have a public API? Yes. The Content Posting API publishes video and photo posts, and there are separate APIs for account info and analytics. Access requires a registered app and approved scopes.
Why are my TikTok API posts private?
Because your app has not passed TikTok's audit. Unaudited apps can only post with privacy_level: SELF_ONLY. The post is published correctly — it is just visible only to the account owner until you are audited.
What does unaudited_client_can_only_post_to_private_accounts mean?
Your app has not passed TikTok's audit, and it tried to post to a TikTok account that is not set to private. TikTok blocks the init call (/publish/video/init/ or /publish/content/init/). Set the account to private and post with SELF_ONLY, or complete the audit to unlock public posting.
Can I schedule TikTok posts through the API? No. TikTok publishes immediately. Any scheduling feature is your own queue holding the post until the scheduled time.
How do I upload video to TikTok via the API? Three steps: initialise the post to get an upload URL and publish ID, upload the file in chunks of 5MB–64MB, then poll the status endpoint until processing completes.
Can I post photo carousels to TikTok?
Yes, but only by giving TikTok publicly reachable image URLs (PULL_FROM_URL). There is no chunked upload path for photos, so media behind authentication will fail.
Why does a TikTok post take so long to publish? TikTok transcodes asynchronously. The API accepts the post immediately and finishes processing afterwards, so any tool built on it has to poll for the final status.
#Where to go next
- Does LinkedIn have an API? — the other big permissions maze
- All supported platforms
- Quickstart
- Pricing
