TikTok Scheduler API: Photo Posts, Audit Gates, Real Limits
If you go looking for a scheduling field in TikTok’s Content Posting API, you will not find one. POST /v2/post/publish/video/init/ publishes when you call it, so the future post has to live in your own queue. The timer is the easy part. The audit gate that pins unaudited clients to SELF_ONLY and the roughly 15-post daily cap shared by every API client are where a queue actually fails.
In short
- No schedule parameter exists in the direct post, photo or getting-started docs. Your scheduler stores the future post and fires the init call at the chosen minute.
- Unaudited clients can post only SELF_ONLY, to at most 5 users in a 24-hour window. Public posting needs an audit, a public account, and Everyone selected per post.
- Direct Post publishing is capped near 15 posts per creator per day and shared across all API clients, so a second tool or a retry spends the same budget.
The API publishes on command and nothing more
The Content Posting API has no scheduling parameter. Video goes through POST /v2/post/publish/video/init/. Photos go through POST /v2/post/publish/content/init/ with media_type set to PHOTO. The content enters TikTok’s pipeline at the moment you make that call, not at a timestamp you pass in. Your database holds the calendar and your worker holds the clock.
A second route exists. POST /v2/post/publish/inbox/video/init/ drops a draft in the creator’s inbox for a human to finish, which is the honest choice when someone still has to pick a cover or a sound.
Creator info decides what the post is allowed to be
TikTok is explicit about order: “To initiate a direct post to a creator’s account, you must first use the Query Creator Info endpoint.” That call is POST /v2/post/publish/creator_info/query/.
It returns privacy_level_options, the comment_disabled, duet_disabled and stitch_disabled flags, max_video_post_duration_sec, the creator’s avatar with a two-hour TTL, plus username and nickname. A public account returns PUBLIC_TO_EVERYONE, MUTUAL_FOLLOW_FRIENDS and SELF_ONLY. A private account returns FOLLOWER_OF_CREATOR in place of PUBLIC_TO_EVERYONE.
You cannot hardcode a privacy value. TikTok requires that “the provided value must match one of the privacy_level_options returned”, and the creator has to select one manually because there is no default. A scheduler that quietly defaults to public fails on a private account; one that defaults to SELF_ONLY publishes invisible videos on a public one. Store the user’s choice, revalidate it at publish time, and stop with a clear error when that option has disappeared. max_video_post_duration_sec is the same kind of field, and it varies by creator.
Four rate ceilings govern any queue you build
TikTok publishes per-token request limits next to the per-creator publishing cap, and the two behave nothing alike. Exceeding a request limit costs a retry. Exceeding the publishing cap costs the day.
| Scope | Limit | Applies to |
|---|---|---|
| Per user access token | 20 requests per minute | creator info query |
| Per user access token | 6 requests per minute | each publish init endpoint |
| Per user access token | 30 requests per minute | status fetch |
| Per creator account, shared | about 15 posts per 24 hours | Direct Post publishing |
The 6 per minute init ceiling is not the bottleneck for scheduled publishing. It is the bottleneck for a worker fanning out retries after a provider incident.
The inbox route has its own bound: at most 5 pending shares in any 24-hour period, enforced with spam_risk_too_many_pending_share. Two codes cover the rest. reached_active_user_cap means your client touched its daily active user allowance, and spam_risk_too_many_posts means that creator’s posting budget is spent. They need different responses, and the publishing error troubleshooting guide covers how to tell them apart before you retry.
Video and photo posts diverge before you reach init
Both post types share a creator info step and a status endpoint, then split hard. Photos take URLs only.
| Constraint | Video | Photo |
|---|---|---|
| Endpoint | /v2/post/publish/video/init/ | /v2/post/publish/content/init/ |
| Transfer | FILE_UPLOAD or PULL_FROM_URL | PULL_FROM_URL only |
| Formats | MP4 recommended, plus WebM and MOV | JPEG or WebP |
| Size | up to 4 GB | 20 MB per image |
| Payload count | one video | up to 35 images |
| Text limits | caption 2200 characters | title 90 UTF-16 runes, description 4000 |
| Duration | from max_video_post_duration_sec, 10 minutes max | not applicable |
| Duet and stitch | available | not supported |
Video encoding is looser than people expect. TikTok recommends MP4 with H.264 but accepts WebM and MOV, H.265, VP8 and VP9, at 23 to 60 fps and 360 to 4096 pixels per side. Duration is the trap: every creator can post 3-minute videos, some have 5 or 10, and the longest a developer can send is 10 minutes.
Direct upload is chunked, 5 MB to 64 MB per chunk with a final chunk up to 128 MB, 1 to 1000 chunks sequentially, against an upload_url valid for one hour. PULL_FROM_URL requires https, no redirects, and a verified domain.
Photos take only PULL_FROM_URL, cap at 1080 pixels per side and 20 MB per image, and support auto_add_music and disable_comment but not duet or stitch. The docs never state an aspect ratio for the API. Vertical 9:16 is the format convention, but I would not attribute that rule to TikTok.
The request sequence is short, and order is not optional
A scheduler performs three calls per post: creator info, publish init, then status polling. Skip the first and you are guessing at privacy. Skip the third and you never learn whether the upload finished.
Creator info runs first, every time, per creator. The avatar URL expires in two hours and the privacy options can change under you, so cache with suspicion.
Init runs at the scheduled minute. A short photo payload looks like this:
POST /v2/post/publish/content/init/
{
"post_info": { "title": "Three frames from the studio", "privacy_level": "SELF_ONLY", "disable_comment": false },
"source_info": { "source": "PULL_FROM_URL", "photo_cover_index": 0, "photo_images": ["https://cdn.example.com/01.jpg"] },
"post_mode": "DIRECT_POST",
"media_type": "PHOTO"
}
Status polling follows. Send the returned publish_id to POST /v2/post/publish/status/fetch/ and read the processing state. Publishing is asynchronous, so the init response is an acknowledgement, not a publication. Poll on a backoff schedule for a bounded period and record the final state.
What you store per attempt decides whether the queue is debuggable later. The record needs the publish_id, the endpoint used, the media type, the creator identifier, the selected privacy value, the intended UTC minute, the attempt count, a hash of the sent payload, and the last known status. The hash separates a genuine retry from a re-rendered post that differs by one character in the caption. The API scheduling walkthrough covers the same discipline on the queue side, including why idempotency keys belong in that record.
The audit gate decides whether public posting exists at all
TikTok states the restriction plainly: “If your API client has not been audited, the following restrictions will apply.” Two of them matter. “Unaudited API Clients can allow up to 5 users to post in a 24 hour window.” And “Unaudited API Clients can only post contents in SELF_ONLY viewership.”
So an unaudited integration is a private-publishing tool with a five-creator ceiling, no matter how good the calendar looks. To publish publicly, the account visibility must be public and each piece of content must be set to Everyone. Even after audit, a 24-hour active creator cap remains, set from the estimates in the audit application.
I would rather a scheduler say “this will publish privately” up front than let someone queue a week of invisible content.
The daily cap is shared, so a queue must count across clients
TikTok’s wording leaves no room for optimism: “There is a limit on the number of posts that can be made to a creator account in a 24-hour window via Direct Post API. The upper limit may vary among creators (typically around 15 posts per day/ creator account) and is shared across all API Clients using Direct Post.”
Shared is the operative word. If a creator also uses another scheduling tool, or your dashboard alongside your API worker, all of it draws from one budget. Your local count is a guess about a number you do not control.
Here is an illustrative example, not a measurement. A workspace queues 20 posts for one creator inside a 24-hour window against a cap of roughly 15. The first 15 publish. The last 5 return spam_risk_too_many_posts, and retrying inside that window will not fix them. A queue that reports “scheduled” for all 20 has told the user something false about 5 of them.
The fix is boring. Order the queue by priority, show remaining capacity before someone adds a 19th post, and treat the cap error as a deferral. Hold the post, retry after the window rolls, keep the content intact. Character limits on every network at least fail loudly when you exceed them; a cap error fails silently unless you count.
Native scheduling exists, and it will not help your API client
TikTok does have scheduling. The web upload page accepts a time from 15 minutes to 10 days ahead, and TikTok says “You’ll need a Business Account in order to access desktop scheduling.” It also warns that once a post is scheduled, you cannot edit the video, captions or the scheduled time.
None of that reaches your API client. There is no published endpoint that writes a TikTok-native scheduled post, so you cannot piggyback on TikTok’s queue to escape the daily cap. Native scheduling gives you 10 days of runway and takes away your ability to fix a typo.
What to do with this
Build the timer, then build the accounting. Query creator info before trusting any privacy value, poll status because init is only an acknowledgement, and count posts per creator across every client, not per token. If your integration is unaudited, say so in the interface rather than letting a private post pass for a success.
PostSider’s TikTok publishing runs on the same API: Direct Post for approved connected accounts, content_posting_method set to DIRECT_POST or UPLOAD, carousels up to 35 photos, and the privacy, duet, stitch, comment, brand content and brand organic toggles in the composer. The same publishing layer is reachable from the dashboard, REST under /public/v1, the MCP server and the Node SDK.
If you want the field guide first, the social media scheduler API rundown covers which limits each one hides. Whatever you build, count the cap before you promise the calendar.
Lukasz builds PostSider, which supports TikTok Direct Post publishing.
Frequently asked questions
Why did only some of my scheduled TikToks publish today?
TikTok caps Direct Post publishing at roughly 15 posts per creator account in a 24-hour window, and that cap is shared across every API client the creator has authorized. Anything past the cap returns spam_risk_too_many_posts. The queue keeps the rest and retries later, but the cap is TikTok's, not the scheduler's.
Does the TikTok Content Posting API support scheduling?
No. The API has no time field: a direct post publishes when the client calls /v2/post/publish/video/init/ or /v2/post/publish/content/init/. Every TikTok scheduler stores the future post in its own queue and fires that call at the chosen minute.
Do I need TikTok's audit before my posts can be public?
Yes. Unaudited API clients can post only to SELF_ONLY viewership, and only for up to 5 users in a 24-hour window. Public posting needs an audited client; the account must also be public and each post set to Everyone.
Can a scheduler queue TikTok photo carousels too?
Yes, through the photo endpoint /v2/post/publish/content/init/ with media_type PHOTO. It accepts up to 35 image URLs, JPEG or WebP only, 20 MB per image, and PULL_FROM_URL transfer only. The API still has no scheduling field, so the queue lives in the tool.
Does TikTok have native scheduling?
Yes, on the web upload page: 15 minutes to 10 days ahead, and TikTok says desktop scheduling needs a Business Account. After scheduling, TikTok says you cannot edit the video, caption or scheduled time. There is no published way to push a TikTok-native scheduled post through the API.