TikTok privacy_level_option_mismatch 400: fix the Direct Post value

Direct Post returns 400 privacy_level_option_mismatch when privacy_level is not one of the creator's own options. Read the options first, then pass one.

5 min readSume
All posts

TikTok's Direct Post endpoint answers 400 privacy_level_option_mismatch when the privacy_level you send is not one of the options available to that creator. The fix is to stop hardcoding a value: read the creator's allowed options first, let the user choose one, and send exactly that string.

Sume does not post to TikTok for you. Sume makes the video, you host or upload it, and your own app calls TikTok. So this error lives in your integration, not in a Sume job, but it is easy to hit when an AI-video pipeline ends in an automated post.

What does the error actually mean?

On the Direct Post reference I read today, post_info.privacy_level must match the creator's available options. The values listed there are PUBLIC_TO_EVERYONE, MUTUAL_FOLLOW_FRIENDS, FOLLOWER_OF_CREATOR and SELF_ONLY. Not every creator is offered every value, so a request that names one the creator does not have is rejected with the 400 above.

The same page lists two neighbouring errors that are easy to confuse with it:

Direct Post errors that look alike (read 2026-10-02)
StatusCodeMeaning
400privacy_level_option_mismatchChosen privacy level is not in the creator's available options
403unaudited_client_can_only_post_to_private_accountsYour client is unaudited, so posts are restricted to private viewing
429rate_limit_exceededMore than 6 requests per minute on one user access token

Why does an unaudited client make it worse?

The reference states that all content posted by unaudited clients is restricted to private viewing mode until the audit is complete. That means a test app can be correct about the options list and still be limited to private posts. Treat the two errors separately: the mismatch is a bad value, the unaudited error is an account-of-your-app status. Our post on the unaudited-client error covers the second one.

How do I pick the value safely?

The Content Sharing Guidelines require that users choose the privacy status themselves, with no default applied for them. So the safe pattern is: fetch the creator's options, show them, let the user pick, and validate the choice before you call Direct Post.

A tiny guard is enough to turn a runtime 400 into a clear message in your own UI:

def pick_privacy(available, chosen):
    """available: the option strings TikTok returned for this creator."""
    if not chosen:
        raise ValueError("user must choose a privacy level; no default")
    if chosen not in available:
        raise ValueError(f"{chosen} not offered; options: {sorted(available)}")
    return chosen

print(pick_privacy(["SELF_ONLY", "PUBLIC_TO_EVERYONE"], "SELF_ONLY"))

Where does Sume fit in this flow?

Generate and prepare the clip first. For a talking video, Avatar video takes 4-60 seconds of script and returns a media.sume.com artifact when the job completes; read it through jobs and results. Only after the file is final should your app ask the creator for privacy, title and consent.

Doing the creator-facing step last matters because the options belong to the creator, not to your batch job. A scheduled run that picked PUBLIC_TO_EVERYONE at 2 a.m. for an account that only offers private posting will fail every time.

What Sume does not do: it does not store TikTok tokens, read a creator's options, or retry a post. If your pipeline needs those, they belong in your app.

Quick checklist

Before you ship the post step, confirm each item.

  • Fetch the creator's options at post time, not at install time.
  • Show the options and require a user choice; never default one.
  • Validate the choice against the fetched list before calling Direct Post.
  • Handle unaudited_client_can_only_post_to_private_accounts separately from the mismatch.
  • Keep the Sume job id with your TikTok request so a failed post can be traced back to the exact video.

Sources

Related posts

More in Integrations

All Integrations posts

Written by Sume