TikTok Direct Post API vs Upload to Inbox: Which to Use
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:
- Query the creator's info to see what this creator is allowed to post.
- Initialize the post with
POST /v2/post/publish/video/init/, sendingpost_info(caption and settings) andsource_info(how the file arrives). - 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.publishdoesn't grantvideo.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_UPLOADfor photos requires TikTok app version 31.8 or later on the creator's phone, or the request fails withapp_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_ONLYonly. 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 withprivacy_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_URLfor delayed posts. AFILE_UPLOADupload_urlexpires 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_POSTvideo publishes to everyone, and any otherprivacy_levelreturns422 privacy_level_unsupportedrather than a post more public than you asked for. Sendpost_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
privacyLevelOptionsand the interaction flags. TikTok publish status returnsPUBLISH_COMPLETE,SEND_TO_USER_INBOX, orFAILEDwith TikTok'sfailureReason. - Draft warnings. A video sent to the inbox comes back with a
video_draft_media_onlywarning, 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.