TikTok API Error Codes: Causes and Fixes

TikTok's Content Posting API names its errors with strings, not numbers, and reports them in two places: error.code on the request you sent, and fail_reason on the post's status once TikTok has the file. spam_risk_too_many_posts means the creator has reached the daily cap for posts made through the API, unaudited_client_can_only_post_to_private_accounts means your app has not passed TikTok's audit, url_ownership_unverified means the media sits on a domain you have not verified, and picture_size_check_failed means the video or photo is outside the accepted dimensions. Most are fixed by changing the request, the file or the app's standing with TikTok. Only a server error, a rate limit after a wait, and a failed pull from a URL you know is good are worth sending again unchanged. The tables below list each code and fail reason in TikTok's reference with its cause, its fix and whether a retry is safe.

By · · 9 min read

Drafted with AI assistance from our own research and Search Console data, and reviewed by Rahul A before publishing. Rules and prices change; check the linked official source before you act.

PostWharf, the tool we make, takes this work off your side. One API call publishes to TikTok through an audited client, so the post goes out public, and a refusal lands on the post's delivery receipt as a plain sentence.

Where TikTok puts the error

Outside the file upload itself, every response from the API carries an error object with a code, a message and a log id. On success the code is ok, and any other value means the request did not go through. TikTok asks for all three when you contact its support team, so store them with your record of the attempt.

Three things about that object catch people out:

  • A post can fail after the request succeeded. The init call answers ok with a publish_id as soon as TikTok accepts the job. The file is checked afterwards, and the result is on /v2/post/publish/status/fetch/ as status: FAILED with a fail_reason, or on the post.publish.failed webhook as reason.
  • The HTTP status is not the whole answer. Query Creator Info returns spam_risk_too_many_posts, spam_risk_user_banned_from_posting and reached_active_user_cap with status 200, which TikTok's own table marks as intentional. The direct post and photo init calls return the same three with 403, and the draft video init returns the ban code alone. Branch on the code string.
  • Two names are spelled two ways. The endpoint pages list invalid_param and the v2 error list has invalid_params, so handle both. The log id is log_id in the example responses and logid in the field tables.

TikTok Content Posting API error codes, by cause

The codes come from TikTok's Content Posting API reference (Direct Post, Upload, Photo, Query Creator Info, Get Post Status and the Media Transfer Guide) and its v2 error list, all read on 10 November 2026. "Init" means one of the three calls that start a post: /v2/post/publish/video/init/ for a video posted directly, /v2/post/publish/inbox/video/init/ for a video sent to the creator's inbox as a draft, and /v2/post/publish/content/init/ for photos. "Retry as is" means sending the same request again with nothing changed.

Sign-in and permission errors

Error codeWhere it comes backWhat it meansFixRetry as is?
access_token_invalid401, on every endpoint in the referenceThe access token is invalid, expired or missing from the request.Refresh the token, then send the request again.No, refresh first
scope_not_authorized401, on every endpoint in the referenceThe creator has not granted the scope the call needs: video.publish for a direct post, video.upload for a draft.Ask the creator to authorize your app again with that scope.No
scope_permission_missed400, in the v2 error listSome fields in the request need scopes the token does not carry.Read the message for what is missing and request that scope.No
token_not_authorized_for_specified_publish_id400, on status fetch and cancelThe access token is not authorized for that publish_id.Send the request with the token that started the post.No
auth_removedfail_reasonThe creator removed your app's access while the file was still uploading or downloading, so TikTok ended the post.Nothing to send again. The creator has to authorize the app first.No

Caps and spam-risk refusals

Error codeWhere it comes backWhat it meansFixRetry as is?
rate_limit_exceeded429, on every endpoint in the referenceToo many requests on one user access token. The init calls allow 6 a minute, Query Creator Info 20 and status fetch 30.Wait, then send fewer requests.Yes, after a wait
spam_risk_too_many_posts403 on a direct post or photo init, 200 on Query Creator Info, and a fail_reasonThe creator has reached the daily cap for posts made through the API.Wait for the 24 hours to pass, or post from the TikTok app, which is TikTok's own suggestion.No, wait
spam_risk_too_many_pending_share403 on a draft video init or a photo initToo many uploads are waiting for the creator to finish them. TikTok allows at most 5 pending shares in any 24 hours.Wait, and do not queue more than five unfinished drafts for one creator in 24 hours.No, wait
reached_active_user_cap403 on a direct post or photo init, 200 on Query Creator InfoYour app has reached its daily quota of creators publishing through it.The quota belongs to the app, not to this creator. Wait for it to reset.No, wait
spam_risk_user_banned_from_posting403 on any init, 200 on Query Creator Info, and a fail_reasonTikTok has banned the creator from making new posts.Nothing in the request fixes it, and TikTok says not to retry.No
spam_risk_textfail_reasonTikTok judged the caption text risky or spammy and ended the post.Do not send the same text again.No
spam_riskfail_reasonTikTok judged the publishing request itself risky and ended it.TikTok gives no fix and says not to retry.No

App audit, privacy level and URL ownership errors

Error codeWhere it comes backWhat it meansFixRetry as is?
unaudited_client_can_only_post_to_private_accounts403 on a direct post or photo initYour app has not passed TikTok's audit, and an unaudited app can post only to a private account.While you build, test with an account set to private. To post publicly, pass the audit.No
privacy_level_option_mismatch403 on a direct post or photo initprivacy_level is missing, or is not one of the options Query Creator Info returned for this creator.Call Query Creator Info first and send one of its privacy_level_options.No
url_ownership_unverified403 on any init that uses PULL_FROM_URL, and on cancelThe media URL is on a domain or URL prefix your app has not verified.Verify the domain or prefix in TikTok for Developers, or send a video with FILE_UPLOAD.No
app_version_check_failed400 on a photo init with MEDIA_UPLOADThe creator's TikTok app is older than version 31.8, which photo drafts need.The creator updates the TikTok app.No

Request and upload errors

TikTok's guide lists the answers to the upload PUT by HTTP status alone, with no code string, so those rows are listed by status.

Error codeWhere it comes backWhat it meansFixRetry as is?
invalid_param or invalid_params400, on any initA field in the request is wrong, and the message says which.Correct the field.No
invalid_file_upload400, in the v2 error listThe uploaded file does not meet the API's specifications.Correct the file and upload it again.No
invalid_publish_id400, on status fetch and cancelNo post exists with that publish_id.Use the id the init call returned.No
publish_not_cancellable400, on cancelThe post has already reached a final state.Nothing to cancel. Read its status.No
none400 on the upload PUTThe headers are malformed, or Content-Length does not match the bytes in the body.Correct the headers for that chunk.No
none403 on the upload PUTThe upload_url has expired. It lasts one hour.Start over with a new init call.No, new init
none404 on the upload PUTTikTok has no upload task for that upload_url.Use the whole URL the init call returned, query string included.No
none416 on the upload PUTContent-Range does not match how much TikTok has received.Read the Content-Range header on TikTok's response, which reports the bytes it has, and send the chunk that follows.No
internal_error, or any 5xxEvery endpoint in the referenceA fault on TikTok's side or on the network.Try again later. On an upload, send the same chunk again.Yes

Media check failures and failed pulls

All of these arrive as a fail_reason on the post's status, after the init call has succeeded.

Fail reasonWhat it meansFixRetry as is?
file_format_check_failedThe file is in a format TikTok does not take.Send video as MP4, WebM or MOV (H.264, H.265, VP8 or VP9), and photos as WebP or JPEG.No
duration_check_failedThe video does not meet TikTok's duration limits. Every creator can post 3 minutes, and some can post 5 or 10.Read max_video_post_duration_sec from Query Creator Info before you send.No
frame_rate_check_failedThe frame rate is outside 23 to 60 FPS.Export the video again inside that range.No
picture_size_check_failedA video is under 360 pixels or over 4,096 pixels in height or width, or a photo is over 1080p.Export it again at an accepted size.No
video_pull_failed, photo_pull_failedTikTok could not download the file, or the download did not finish within one hour.Check that the URL is public and not bandwidth-limited. If it is, send it again.Yes, if the URL is good
internalPart of TikTok's service was unavailable. TikTok calls this one retryable.Send it again.Yes
publish_cancelledYou cancelled the download yourself with /v2/post/publish/cancel/.Nothing to fix.No

TikTok's Media Transfer Guide also caps a video at 4 GB and a photo at 20 MB. It does not say which fail reason a larger file gets.

Which TikTok errors are safe to retry

A TikTok post moves through three stages: the init call, the transfer of the file (your PUT requests, or TikTok pulling it from your URL), and TikTok's own processing. The stage where it failed decides what a retry does.

  • A refusal at init made nothing. No publish_id came back, so a second call cannot double the post. It will be refused again until the cause changes, which is why nearly every init code in the tables says no.
  • A failed chunk is retried by itself. A 5xx on the upload PUT means sending that one chunk again. Chunks have to go up in order.
  • A FAILED status ends that publish_id. TikTok's wording is that the entire process has failed, so trying again means a new init call. Do that unchanged for internal and for a failed pull from a URL you have checked. TikTok says not to retry auth_removed, spam_risk_user_banned_from_posting, spam_risk_text or spam_risk.
  • A slow post is not a failed post. TikTok guarantees no time limit. Processing averages under half a minute for a 512 MB file and more than two minutes for 4 GB, and moderation of a public post usually finishes within a minute but can take a few hours. The post id is held back until moderation approves it, so an empty publicaly_available_post_id (TikTok's spelling) is not an error.

An init call that times out leaves you with no publish_id, and so with nothing to poll. Treat the result as unknown: look at the account, or at your webhook events, before sending the post again. The wider rule for unknown outcomes on any network is in our guide to publishing retry rules.

The three caps behind the spam-risk and user-cap codes

Three different limits sit behind these codes, and two of the names start the same way. spam_risk_too_many_posts counts the creator's posts through the API in the last 24 hours. spam_risk_too_many_pending_share counts drafts that are waiting in the creator's inbox to be finished in TikTok. reached_active_user_cap counts the creators publishing through your app in a day, so no change to one creator's post clears it.

TikTok's reference gives a number for only one of the three, the 5 pending drafts. For the daily post cap there is nothing to hard-code, but there is an early warning. A direct post has to call Query Creator Info first to get the creator's privacy options, and that call returns spam_risk_too_many_posts once the cap is reached. Read it there and you find out before the file is sent.

Posts stay private until the app is audited

TikTok's Direct Post reference says all content posted by an unaudited client is restricted to private viewing, and that the restriction lifts only after the app passes an audit against TikTok's terms of service. The code unaudited_client_can_only_post_to_private_accounts is the stricter half of the same rule: an unaudited app can post only to a private account, and the attempt is blocked at the init call. An integration under construction therefore needs a test account set to private, and a refusal with this code is about the app's standing, not about the post. How long to budget for the audit, next to the reviews other networks ask for, is in social API approval timelines.

privacy_level_option_mismatch sits beside it and is easier to fix. A public account can be sent PUBLIC_TO_EVERYONE, MUTUAL_FOLLOW_FRIENDS or SELF_ONLY. A private account can be sent FOLLOWER_OF_CREATOR, MUTUAL_FOLLOW_FRIENDS or SELF_ONLY. A hard-coded PUBLIC_TO_EVERYONE therefore fails for a private account. TikTok expects the app to show the creator the options from Query Creator Info and send the one they picked, and its reference says that occurrences of this error suggest the app is violating its product-use guidance.

Pulled media needs a verified URL

PULL_FROM_URL works only for a domain or URL prefix that your app has verified in TikTok for Developers. The rules are narrower than they look:

  • Verifying a domain covers that domain and the subdomains under it. Verify static.example.com and video.static.example.com is covered, while example.com is not.
  • Verifying a URL prefix covers only URLs that begin with exactly that prefix.
  • The URL has to use https and must not redirect. A URL that answers with a 3xx counts as invalid.
  • The file has to stay reachable for the whole download, which times out one hour after it starts.

Photos have no other route. A photo post accepts PULL_FROM_URL only, with up to 35 image URLs, so url_ownership_unverified on a photo post cannot be avoided by uploading the file. A video can go by FILE_UPLOAD.

What PostWharf shows when TikTok refuses a post

With PostWharf you send one post to the TikTok scheduling API and read the result on its delivery receipt, where each network the post went to has its own row. There is no audit for you to wait out. Publishing goes through an audited client, so a TikTok post goes out public instead of being held private.

Some refusals are stopped before TikTok sees them. A caption over 2,200 characters is refused when you create the post, and so is a set of files TikTok will not carry: more than 35 images, more than one video, or images and a video together. The 422 that comes back names the network and the limit that was passed.

When TikTok itself refuses a post, its row carries the reason as a sentence. A failure in transit is sent again with backoff. A rejection is left alone, because it would fail the same way on the third attempt. If the post reached your other networks and not TikTok, it is marked partial, not published. Published posts are checked again afterwards, so a TikTok post that is removed later stops reporting as live.

The same detail is on the API. GET /v1/posts/:id returns one delivery per channel with its status, attempts, live URL and error text, and a failure event carries an action field that names the next step. PostWharf's own API errors are a different and much shorter list, a JSON error field with an HTTP status from 401 to 503, set out in the API reference. For failures on any network, not TikTok alone, start with social media publishing API errors and fixes.

A workspace is one brand, with its own channels and API key, and the API is part of every plan.

Sources consulted: TikTok for Developers (developers.tiktok.com), all read on 10 November 2026: · Direct Post, Photo and Query Creator Info, each updated 27 October 2026 · Upload, Get Post Status, Media Transfer Guide, Error Handling and Get Started with Direct Post, each updated 4 August 2026 · Check them again before you hard-code a rule.

Common questions

Where does TikTok's API report a failed post?

In two places. A refused request carries the reason in the error code of its response, and a post that fails after the request was accepted shows a failed status with a fail reason when you fetch its publish status, or on the failed-publish webhook.

Which TikTok API errors are safe to retry?

A failed upload chunk can be sent again by itself, and a failed status with an internal error can be tried again with a new init call. A refusal at init is refused again until its cause changes, and TikTok says not to retry a removed authorisation or its spam-risk refusals.

Why do posts from my TikTok app stay private?

TikTok's Direct Post reference says all content posted by an unaudited client is restricted to private viewing until the app passes an audit against TikTok's terms of service. An unaudited app can also post only to a private account.

PostWharf is priced per workspace rather than per connected channel, and every plan carries unlimited channels. See per-brand pricing.