You wire up TikTok's Content Posting API, send a video, and every call comes back clean. The upload finishes. The status endpoint reports PUBLISH_COMPLETE. The video is on the account. Then the client asks why nobody has seen it, and you find out it was posted private — and that it could not have been posted any other way.
This is not a bug in your integration, and it is not something you can fix in code. It is the gate TikTok puts in front of every new API client, and it is the single most expensive thing to discover late.
The success that nobody sees
Direct Post is a four-step handshake. Before you may show a posting interface at all, you ask TikTok what the account is allowed to do — its nickname, its maximum video length, and the privacy levels it may publish at. For a client that has not been through the audit, that last list comes back with a single entry: SELF_ONLY. Private to the creator.
Nothing later in the sequence errors. You declare the privacy level you were offered, upload the bytes, poll until it completes, and every response is a success, because it is one. The video published exactly as instructed. TikTok told you the constraint at step one, in a field most people read past.
Two smaller edges live in the same sequence. video/init refuses outright if you ask for a privacy level the account was not offered, so "just send PUBLIC and see" is not a route. And if you hand TikTok a URL to pull the file from rather than uploading it yourself, the domain has to be verified with TikTok first — a step that catches people who assumed their CDN would do.
The audit reviews your interface, not your code
Unlocking public posting means submitting your app for review against TikTok's content sharing guidelines. The review is measured in weeks, and — this is the part people underestimate — most of what is being reviewed is your user interface, not your API usage.
The requirements are prescriptive. Show the creator which TikTok account they are posting to, by nickname. Let them set the privacy level explicitly rather than defaulting it. Respect the interaction settings the account already has, so a creator who has comments off does not see a comments toggle. Carry TikTok's own disclosure text and links for branded and commercial content. Do not claim the post succeeded before the status endpoint says so.
This is enforceable enough that a real, widely used open-source scheduler was rejected for it — Postiz has a public issue tracking a "missing required UX compliance" rejection. If you are choosing a tool, that issue is a more useful signal than any feature page: it tells you the vendor is subject to a review they do not control.
The quota belongs to the creator, not to your integration
Suppose you clear the audit. Now you meet the ceilings.
There is a per-token request rate — around six requests a minute — which is easy to design around. The one that hurts is the daily posting ceiling: roughly 15 posts per creator per 24 hours through Direct Post. Read that phrase carefully. It is not fifteen posts per app. It is fifteen posts for that creator, across every API client posting to that account.
So if your client also uses a second scheduler, or a video tool with a "publish to TikTok" button, or an agency dashboard somebody set up last year, those posts come out of the same allowance — and your integration has no way to see them. You find out when a post you queued fails for a reason your own counters say is impossible.
What this means if you post for other people
For one brand posting twice a day, none of this matters. The API is the right answer: it is cheap, it is stable, and fifteen posts is more than enough.
For an agency it changes the risk. Your reliability is now coupled to a queue you cannot see, held by a third party, shared with tools your client bought without telling you, and gated by a review of your own interface that can be re-opened when the guidelines change. None of those are things you can engineer away. They are things you accept.
The other route, and what it costs
There is a second way to get a video onto TikTok, and it is the one almost nobody writes up: the TikTok app, on a phone you own, signed into the account it belongs to. The audit gate does not apply, because there is no API client to audit. The shared Direct Post quota does not apply, because nothing is going through Direct Post. What applies is whatever the account itself is subject to, the same as if a person had tapped the buttons — which is what happened, only the tapping was automated.
Now the honest half. This route costs real things, and any vendor who does not list them is selling you a surprise.
- A physical phone, and a Mac it is plugged into. Video and USB, not a browser tab in a data centre.
- A real login, done by hand, once. The account holder signs in and accepts TikTok's terms themselves. That is not a workflow gap we intend to close — accepting terms of service on somebody's behalf is a decision with legal weight and it is not the software's to make.
- Maintenance, because the app changes. This is the real recurring cost, and it is worth being specific about.
Why UI automation needs maintaining
When we mapped TikTok 46.3.3 on our own handsets, the first screen's view hierarchy came back with resource ids like a2y, u1k, yk7, uc1 and f07. Those are R8-minified names, assigned by TikTok's build. They change between releases, and sometimes between builds of the same release. Any automation that matches on them works until the next app update and then fails on every phone at once.
So you match on what survives minification: the accessibility label first, because those are written by hand and translated deliberately, then the visible text, and only then position. That is why NOISEY keeps selectors in versioned configuration delivered from the server rather than compiled into the app — an app update that renames everything has to be fixable without shipping a desktop release. The longer version of that argument is in why your automation breaks on a Tuesday.
There is a second, sillier tax worth knowing about. Android's own full-screen confirmation overlay appears the first time an app goes full-screen, and its hierarchy contains no button and nothing tappable — five nodes, one of which is a wall of text. Automation does not fail against it, it simply stalls. It has to be turned off once per phone as part of preparing the device, which is what the desktop app's Prepare for automation action does.
Which one to pick
Genuinely both, for different jobs.
- Use the API when you post for one brand, a few times a day, you can absorb a multi-week review, and you would rather maintain nothing.
- Use a phone when the audit gate or the shared quota is the actual blocker, when the account must post more than the API allows, or when the account holder will not hand a third-party app publishing rights over their account.
The comparison across every platform, not just TikTok, is in what each social posting API will actually let you do.
Where NOISEY actually is with this
Being specific, because a blog post is the easiest place for a promise to outrun the code. NOISEY drives the real TikTok app on phones you own. That is the whole architecture: the desktop app is always the executor and our servers never touch a device, which is the split between the desktop app and the website. A routine is what the phone does, an automation decides when it runs, and the difference between those words is load-bearing.
The packaged TikTok posting routine is not finished. It reaches the app's first-run consent screen and stops there deliberately — a routine that silently accepts terms of service on twenty handsets is the wrong behaviour, so preparing a phone stays a human step and the routine picks up afterwards. When that ships, this paragraph changes. Until then, treat any claim of unattended TikTok posting from us as not yet true.
If you want the mechanics rather than the argument, the fastest path to a first automated post is five minutes of setup and one phone.