TikTok Direct Post API vs Upload to Inbox: Which to Use

By Mika ReyesPublished 7 min read

The short answer

The TikTok Direct Post API is the lane of TikTok's Content Posting API that publishes straight to a creator's profile. It needs the video.publish scope, and until TikTok audits your app every post is SELF_ONLY. The other lane, upload to inbox, uses video.upload and sends a draft the creator finishes in the TikTok app. Adeli supports both lanes through one API.

The TikTok Direct Post API is one of two lanes in TikTok's Content Posting API. Direct Post publishes a video or photo post straight to the creator's profile. Upload to inbox sends it to the creator's TikTok inbox as a draft, and the creator finishes and posts it in the app. The lane you pick decides which scope you request, whether TikTok's audit applies, and how much of the post your app controls.

This post is about that choice. For the call-by-call flow (init, chunked upload, status polling), see how to post to TikTok via API.

What is the TikTok Direct Post API?

Direct Post is the publishing lane of TikTok's Content Posting API, on TikTok for Developers. Your app sets the caption, privacy level, and interaction settings, and TikTok publishes the post without the creator opening the app.

TikTok's Direct Post reference describes three steps:

  1. Query the creator's info to see what this creator is allowed to post.
  2. Initialize the post with POST /v2/post/publish/video/init/, sending post_info (caption and settings) and source_info (how the file arrives).
  3. Send the video, either by uploading it or by letting TikTok pull it from your URL, then poll the status.

To use it, your app needs the Content Posting API product, Direct Post enabled in that product's configuration, and the video.publish scope approved and authorized by the user (get-started guide).

Direct Post vs upload to inbox: what's the difference?

Direct Post publishes; upload to inbox drafts. The rest of the table follows from that.

Direct Post Upload to inbox (draft)
Scope video.publish video.upload
Video endpoint /v2/post/publish/video/init/ /v2/post/publish/inbox/video/init/
Photo endpoint /v2/post/publish/content/init/ with post_mode DIRECT_POST Same endpoint with post_mode MEDIA_UPLOAD
Caption and privacy Your app sends them The creator sets them in TikTok (photo drafts can carry a title and description)
Who publishes Your app The creator, from an inbox notification
Final status PUBLISH_COMPLETE SEND_TO_USER_INBOX
Before the audit Posts are SELF_ONLY, to private accounts only No audit restriction in TikTok's upload docs
Volume cap About 15 posts per creator per day 5 pending shares per creator in any 24 hours
Rate limit 6 init requests per minute per token 6 init requests per minute per token

Sources: the Direct Post, upload, photo post, and status references, and the Content Sharing Guidelines.

Two details catch teams out:

  • The scopes are separate. Approval for video.publish doesn't grant video.upload. A product that offers both a "post now" button and a "send to drafts" button needs both scopes approved.
  • Photo drafts need a recent TikTok app. MEDIA_UPLOAD for photos requires TikTok app version 31.8 or later on the creator's phone, or the request fails with app_version_check_failed.

What happens to Direct Post before TikTok audits your app?

Every Direct Post from an unaudited app is private. TikTok's Content Sharing Guidelines set three limits until your app passes the Content Posting API audit:

  • SELF_ONLY only. Only the creator can see the post.
  • Private accounts only. Posting to a public account fails with unaudited_client_can_only_post_to_private_accounts.
  • Five users per 24 hours. At most 5 accounts can post through your app in any 24-hour window.

A creator can make those posts public later, but only by switching their account to public and then changing each post's privacy to "Everyone" in the app.

The caps stay after the audit. Audited apps still have a daily quota of active posting users (reached_active_user_cap), and creators still hit the daily post cap (spam_risk_too_many_posts). The audit itself checks your posting screen against the guidelines, which our TikTok API access guide walks through.

Which lane should I use?

Use Direct Post when your product publishes for the user. Use upload to inbox when the creator should have the last word in TikTok.

You're building Lane Why
A scheduler or content calendar Direct Post Posts have to go out without the creator opening TikTok
An AI tool that writes and publishes Direct Post The caption and settings come from your product
A video editor or export button Upload to inbox Creators want to add TikTok sounds, effects, and text before posting
A review step for an agency client Upload to inbox The client approves inside their own TikTok app
A prototype before the audit Upload to inbox TikTok's docs apply the private-only rule to Direct Post, not to drafts

You can ship both. Direct Post covers the automated path, and the draft lane works as a fallback when the creator's privacy options, a branded-content rule, or the daily cap block a direct post.

Why query creator_info before every Direct Post?

Because privacy_level has to match what this creator allows right now. Call POST /v2/post/publish/creator_info/query/ before each Direct Post. The creator info reference returns:

  • privacy_level_options. Send a value outside this list and init fails with privacy_level_option_mismatch. A private account gets a shorter list than a public one.
  • comment_disabled, duet_disabled, stitch_disabled. If the creator turned an interaction off, your UI has to grey out that toggle.
  • max_video_post_duration_sec. Reject longer videos before you upload them.

Don't cache it for long. Creators change their account privacy and interaction settings in the app, and the same call returns spam_risk_too_many_posts once they've hit the daily cap. Upload to inbox doesn't need this call, because the creator picks those settings in TikTok.

How do photo posts work with PULL_FROM_URL?

Photo posts only accept PULL_FROM_URL. You can't upload image bytes. You send up to 35 image URLs, and TikTok downloads them from a domain you've verified. Both lanes use the same endpoint, per the photo post reference:

curl --location 'https://open.tiktokapis.com/v2/post/publish/content/init/' \
--header 'Authorization: Bearer act.example12345Example12345Example' \
--header 'Content-Type: application/json' \
--data-raw '{
  "post_info": {
    "title": "Backyard birds",
    "description": "Cardinal, titmouse, and robin #birds",
    "privacy_level": "PUBLIC_TO_EVERYONE",
    "disable_comment": false,
    "auto_add_music": true
  },
  "source_info": {
    "source": "PULL_FROM_URL",
    "photo_cover_index": 0,
    "photo_images": [
      "https://media.example-verified.com/cardinal.webp",
      "https://media.example-verified.com/robin.webp"
    ]
  },
  "post_mode": "DIRECT_POST",
  "media_type": "PHOTO"
}'

The rules from the photo reference and the media transfer guide:

  • Verify the domain or URL prefix first. Add it as a URL property in the developer portal. A domain is verified with a signature string in its DNS records and covers every subdomain. A URL prefix covers only URLs that start with that exact prefix.
  • HTTPS, no redirects. Any 3xx response makes the URL invalid.
  • JPEG or WebP, up to 1080p and 20 MB per image.
  • Title up to 90 characters, description up to 4,000. Both are counted in UTF-16 runes.

Photo failures show up at two different stages, and the stage tells you what to fix:

Error When What it means
url_ownership_unverified At init (403) The domain or prefix isn't verified for your app
photo_pull_failed In the status response TikTok couldn't download the image: a private URL, bandwidth limits, or a download past one hour
picture_size_check_failed In the status response The image is outside TikTok's size limits

TikTok's status reference says to retry photo_pull_failed once you've confirmed the URL is publicly reachable.

Can you schedule a TikTok post through the API?

Not in TikTok's API itself. The Direct Post reference has no field for a future publish time, and neither does the publish endpoint in TikTok API for Business. A post goes out when you call init.

To publish at a set time, your system has to hold the post and call init when it's due:

  • Use PULL_FROM_URL for delayed posts. A FILE_UPLOAD upload_url expires one hour after init, so you can't upload early and publish later.
  • Query creator info at publish time, not when the post was queued. The creator's privacy options may have changed in between.
  • Drafts can't be scheduled. Upload to inbox ends with the creator pressing post, whenever they get to it.

How does Adeli handle Direct Post and drafts?

Adeli exposes both lanes as one field, post_mode, on the same publish endpoint every network uses. Adeli publishes to TikTok through TikTok API for Business, holds the TikTok app, and refreshes every connected account's tokens. Here's a public video through Publish to TikTok:

curl -X POST "https://app.tryadeli.com/api/v1/posts" \
  -H "Authorization: Bearer $ADELI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "platform": "tiktok",
    "accountId": "00000000-0000-0000-0000-000000000000",
    "post_mode": "DIRECT_POST",
    "tiktok_title": "Morning chorus #birds",
    "privacy_level": "PUBLIC_TO_EVERYONE",
    "music_usage_confirmed": true,
    "video": { "url": "https://media.example/video.mp4" }
  }'

What changes compared with building it yourself:

  • Videos are public or drafts. A DIRECT_POST video publishes to everyone, and any other privacy_level returns 422 privacy_level_unsupported rather than a post more public than you asked for. Send post_mode: "MEDIA_UPLOAD" to put it in the creator's inbox instead.
  • Photos take any privacy level the creator allows, from 1 to 35 images, sent as base64 or multipart files.
  • No domain verification on your side. Whatever you send (base64, multipart, or a URL), Adeli stages it on its own verified media host before TikTok pulls it.
  • Creator info and status are endpoints too. TikTok creator info returns privacyLevelOptions and the interaction flags. TikTok publish status returns PUBLISH_COMPLETE, SEND_TO_USER_INBOX, or FAILED with TikTok's failureReason.
  • Draft warnings. A video sent to the inbox comes back with a video_draft_media_only warning, because TikTok ignores the caption and settings on video drafts.

TikTok's limit of 15 API posts per account per day still applies. The TikTok API page shows what Adeli supports on TikTok, the posting API shows how the same request reaches Instagram, YouTube, Facebook, X, and Bluesky, and your first 3 connected accounts are free on pricing.

faq

Frequently asked questions

Does TikTok's upload to inbox need the Content Posting API audit?

TikTok's docs tie the audit and the private-only restriction to Direct Post. The upload guide asks for an approved video.upload scope and doesn't mention an audit. Your app still goes through TikTok's app review to get that scope, and drafts are capped at 5 pending shares per creator in any 24 hours.

What does SEND_TO_USER_INBOX mean in TikTok's post status?

It means TikTok delivered the draft and sent the creator an inbox notification. It only appears in the upload flow. The post isn't live until the creator opens that notification, finishes editing in TikTok, and publishes it.

Can I set the caption on a TikTok draft?

For video drafts, no. The inbox video endpoint takes no post_info, so the creator writes the caption and picks privacy in TikTok. Photo drafts are different: the photo endpoint accepts a title and description in MEDIA_UPLOAD mode.

Why does my TikTok photo post fail with photo_pull_failed?

TikTok couldn't download one of your images. The URL may be private, bandwidth-limited, or slow enough to pass the one-hour download window. If the domain isn't verified you'll see url_ownership_unverified at init instead, so photo_pull_failed points at hosting, not ownership.

Power your next project
with one social media API

Give your users publishing, scheduling, and analytics through one integration your team can actually maintain.

Try with agents

Start with free credits. No credit card required.