Skip to content
postpeg

· 6 min read · postpeg team

Why TikTok API posts come out private (and how the audit fixes it)

Why videos posted through TikTok's Content Posting API land as private, what the audit changes, the UX TikTok requires, and a checklist for debugging.

If your videos posted through TikTok's API only show up as private, the most likely reason is that your API client has not passed TikTok's audit. TikTok's docs are direct about it: anything an unaudited client posts is limited to private viewing. It is not a bug in your code, and no request parameter will get around it. The fix is the audit, plus a posting UI that meets TikTok's guidelines so you pass it.

What "unaudited" actually limits

Every new app that uses the Content Posting API starts unaudited. TikTok's content sharing guidelines list the restrictions:

RestrictionUnaudited client
Who can postUp to 5 users in a 24-hour window
Account stateEvery posting account must be set to private at the time of posting
Post visibilitySELF_ONLY only
Making posts public laterThe owner switches the account to public, then changes each post's privacy to "Everyone" by hand

Two further caps apply to audited clients as well. The same guidelines describe a 24-hour active creator cap per client, based on the usage estimates you give in the audit application, and a per-creator posting limit that TikTok says varies but is typically around 15 posts a day through Direct Post.

The "account must be private" rule surprises people. It means an unaudited client posting to a public test account is not just downgraded to private: the Direct Post reference lists an unaudited_client_can_only_post_to_private_accounts error for exactly that case. So while you are testing, set the TikTok test account itself to private.

Direct Post vs Upload

TikTok offers two ways to get a video onto an account, and they behave differently.

Direct Post publishes straight to the creator's profile. It uses POST /v2/post/publish/video/init/, needs the video.publish scope, and takes a post_info object where you set the caption, privacy and interaction settings (Get started: Direct Post). This is the flow the private-until-audited rule is written about.

Upload sends the video to the creator's TikTok inbox as a draft. It uses POST /v2/post/publish/inbox/video/init/ and the video.upload scope. TikTok's Upload guide says you should tell users to open the inbox notification, finish editing in TikTok and post it themselves. Privacy is then chosen inside the TikTok app, not by your API call.

If you want videos to go live without the creator opening TikTok, you need Direct Post, which means you need the audit.

Ask TikTok what the creator is allowed to do first

Before a Direct Post, call the query creator info endpoint, POST /v2/post/publish/creator_info/query/. It returns the creator's nickname, username and avatar URL, whether comments, duets and stitches are switched off, the longest video they can post (max_video_post_duration_sec), and privacy_level_options.

Those options depend on the account. A public account gets PUBLIC_TO_EVERYONE, MUTUAL_FOLLOW_FRIENDS and SELF_ONLY. A private account gets FOLLOWER_OF_CREATOR, MUTUAL_FOLLOW_FRIENDS and SELF_ONLY. Sending a value that is not in the list is refused with privacy_level_option_mismatch (Direct Post reference). Note that the endpoint is rate limited to 20 requests per minute per user token, so fetch it when the user opens your posting screen, not in a tight loop.

A Direct Post init body

Here is the shape of a Direct Post init request. The field names and privacy values come from TikTok's Direct Post reference; the values are illustrative.

http
POST /v2/post/publish/video/init/ HTTP/1.1
Host: open.tiktokapis.com
Authorization: Bearer act.example-user-token
Content-Type: application/json; charset=UTF-8

{
  "post_info": {
    "title": "Behind the scenes at the workshop #woodworking",
    "privacy_level": "PUBLIC_TO_EVERYONE",
    "disable_comment": false,
    "disable_duet": true,
    "disable_stitch": true,
    "video_cover_timestamp_ms": 1000,
    "brand_content_toggle": false,
    "brand_organic_toggle": false
  },
  "source_info": {
    "source": "PULL_FROM_URL",
    "video_url": "https://media.example.com/videos/workshop.mp4"
  }
}

On an unaudited client, PUBLIC_TO_EVERYONE will not work: the only visibility you can get is SELF_ONLY. PULL_FROM_URL also needs the URL to be on a domain or prefix you have verified with TikTok; the alternative is FILE_UPLOAD.

The UX TikTok requires before you post

The audit checks your posting screen against the "Required UX implementation" section of the content sharing guidelines. In short, your app must:

  1. Show which account is posting. Display the creator's nickname from creator info, fetched fresh when the posting page loads.
  2. Let the user pick privacy, with no default. A dropdown built from privacy_level_options, empty until the user chooses.
  3. Offer interaction toggles. Comment, Duet and Stitch (only Comment for photos), none ticked by default, and greyed out when creator info says the creator has disabled them.
  4. Handle commercial content disclosure. A toggle for whether the post promotes a brand, with two options: "Your brand" (labelled as promotional content) and "Branded content" (labelled as a paid partnership). If the toggle is on, at least one must be chosen before posting is allowed. Branded content cannot be set to private, only public or friends.
  5. Show the right consent declaration. Before the post button, a line such as "By posting, you agree to TikTok's Music Usage Confirmation", with the Branded Content Policy added when branded content is selected.
  6. Show a preview and get express consent. The user sees the content, can edit any preset caption, and actively confirms the upload. No watermarks added by your app.
  7. Respect limits and report status. Check video length against max_video_post_duration_sec, stop and ask the user to try later if the creator cannot post more today, tell them processing can take a few minutes, and poll the status endpoint so they see the result.

The guidelines also rule out some products entirely. An app that copies arbitrary content from other platforms to TikTok is not acceptable, and neither is a utility for uploading to accounts you or your own team manage. If that describes your app, the audit is unlikely to pass however good the UI is.

Applying for the audit

Once your integration works in testing, you submit the Content Posting API audit from the developer portal; the guidelines link to it where they explain that an audit lifts the visibility restriction. The application asks for usage estimates, which feed the creator cap mentioned above.

TikTok's app review guidelines describe what reviewers look for across products: a demo video showing the complete end-to-end flow with every requested scope clearly used, a real, fully built website (not a landing page) with Privacy Policy and Terms of Service links visible without opening a menu, a sandbox to demonstrate the integration on first submission, and only the scopes you actually need. TikTok does not publish a review timeline in these pages, so plan for some back and forth.

Debugging checklist: "my post is private"

Work through these in order.

  1. Is the client audited? If not, every Direct Post will be SELF_ONLY. Nothing else on this list matters until it is.
  2. What privacy_level did you send? Log the actual request body. A hard-coded SELF_ONLY left over from testing is a common culprit.
  3. Is the creator account private? A private account never offers PUBLIC_TO_EVERYONE; its widest option is FOLLOWER_OF_CREATOR, which looks private to anyone who doesn't follow them.
  4. Did the value come from privacy_level_options? If you cached options from an earlier query and the creator has since changed their account, you may get privacy_level_option_mismatch or a narrower audience than expected.
  5. Did you use the Upload flow? Inbox drafts are not published until the creator finishes them in TikTok, and visibility is whatever they pick there.
  6. Was it branded content? It can't be private, so if you see a refusal rather than a private post, check the disclosure settings.

Where postpeg fits

postpeg publishes TikTok videos (TikTok is video-only) through the official platform APIs, and you set visibility with platform_options.tiktok.privacy: public, friends or private, where private is sent as SELF_ONLY. The option defaults to public, but TikTok's rules still apply to you: showing the account, the privacy choice with no default, the preview and the consent text to your end users is your obligation under our terms, so pass the user's explicit choice rather than relying on the default. See the TikTok API page and publishing docs for the full option list.

Publishing from your own product?

postpeg is one API for posting and scheduling on ten networks, with each network’s rules checked before anything is sent. The 7-day trial needs no card.