Publishing to TikTok via API: A technical guide
Understanding app verification, the Content Posting API, video and photo uploads, creator info queries, and post status tracking for TikTok publishing.
Before you start: App verification
TikTok’s verification process is one of the most rigorous among social platforms. Before your app can publish content publicly, it must pass a thorough audit:
- App Creation — Create an app in the TikTok Developer Portal and configure your redirect URIs
- Scope Request — Request the
video.publishand/orvideo.uploadscopes through the portal - App Review — Submit your app for review. TikTok will evaluate your use case, UX compliance, and content sharing guidelines adherence
- Audit Completion — Once approved, your app can publish content publicly. Until then, all posts are restricted to private visibility (
SELF_ONLY) and limited to 5 users within any 24-hour window
The verification process takes 2–4 weeks. TikTok’s review is rigorous — they require specific UX elements in your app (creator info display, privacy selectors, commercial content disclosures) and will reject apps that don’t meet their content sharing guidelines. Expect multiple rounds of feedback.
Required permissions
TikTok uses OAuth 2.0 scopes to control access:
video.publish— Publish videos and photos directly to a creator’s TikTok accountvideo.upload— Upload content to a creator’s inbox for them to review and post manually
All API requests go to https://open.tiktokapis.com and require these headers:
Authorization: Bearer {USER_ACCESS_TOKEN}Content-Type: application/json; charset=UTF-8Querying creator info
Before publishing, you must query the creator’s info to check their available privacy levels and posting capacity. This is a UX requirement enforced during app review.
POST to /v2/post/publish/creator_info/query/:
{}The request body is empty — the access token identifies the creator.
Response:
{ "data": { "creator_avatar_url": "https://...", "creator_username": "user123", "creator_nickname": "Display Name", "privacy_level_options": ["PUBLIC_TO_EVERYONE", "MUTUAL_FOLLOW_FRIENDS", "SELF_ONLY"], "comment_disabled": false, "duet_disabled": false, "stitch_disabled": false, "max_video_post_duration_sec": 600 }}Use privacy_level_options to populate your privacy selector — the post request will fail if you use a privacy level not in this list. Check max_video_post_duration_sec to validate video length before uploading.
Rate limit: 20 requests per minute per user access token.
Publishing videos
Videos can be published via URL pull or direct file upload. Both use the same initialization endpoint.
Option A: Pull from URL
POST to /v2/post/publish/video/init/:
{ "post_info": { "title": "Your video caption #hashtag", "privacy_level": "PUBLIC_TO_EVERYONE", "disable_duet": false, "disable_stitch": false, "disable_comment": false, "video_cover_timestamp_ms": 1000 }, "source_info": { "source": "PULL_FROM_URL", "video_url": "https://example.com/video.mp4" }}Returns a publish_id to track the post status. TikTok downloads the video from your URL and processes it.
Option B: File upload
POST to /v2/post/publish/video/init/:
{ "post_info": { "title": "Your video caption", "privacy_level": "PUBLIC_TO_EVERYONE", "disable_duet": false, "disable_stitch": false, "disable_comment": false }, "source_info": { "source": "FILE_UPLOAD", "video_size": 50000000, "chunk_size": 10000000, "total_chunk_count": 5 }}Returns a publish_id and an upload_url. Upload the video via PUT to the upload_url with these headers:
Content-Type: video/mp4Content-Length: {CHUNK_SIZE}Content-Range: bytes {FIRST}-{LAST}/{TOTAL}The upload URL expires after 1 hour.
Video requirements: MP4, WebM, or QuickTime format.
Post info fields
| Field | Required | Description |
|---|---|---|
title | No | Caption, max 2,200 characters. Supports hashtags and @mentions |
privacy_level | Yes | Must match a value from the creator info query |
disable_duet | No | Prevent duets with this video |
disable_stitch | No | Prevent stitches with this video |
disable_comment | No | Disable comments |
video_cover_timestamp_ms | No | Frame position in ms for the cover image |
brand_content_toggle | No | Set true for paid partnerships |
brand_organic_toggle | No | Set true for the creator’s own brand promotion |
is_aigc | No | Label as AI-generated content |
Rate limit: 6 requests per minute per user access token.
Publishing photos
Photo posts support up to 35 images in a single post via URL pull.
POST to /v2/post/publish/content/init/:
{ "media_type": "PHOTO", "post_mode": "DIRECT_POST", "post_info": { "title": "Photo title", "description": "Photo description with #hashtags", "privacy_level": "PUBLIC_TO_EVERYONE", "disable_comment": false, "auto_add_music": true }, "source_info": { "source": "PULL_FROM_URL", "photo_images": [ "https://example.com/photo1.jpg", "https://example.com/photo2.jpg" ], "photo_cover_index": 0 }}title is limited to 90 characters. description supports up to 4,000 characters. Photo URLs must be publicly accessible.
Rate limit: 6 requests per minute per user access token.
Checking post status
Publishing is asynchronous. Use the publish_id from the init response to poll for status.
POST to /v2/post/publish/status/fetch/:
{ "publish_id": "{PUBLISH_ID}"}Status values:
PROCESSING_UPLOAD— File upload in progressPROCESSING_DOWNLOAD— TikTok is downloading from your URLSEND_TO_USER_INBOX— Draft sent to creator’s inbox (upload mode only)PUBLISH_COMPLETE— Successfully postedFAILED— Processing failed, checkfail_reason
Processing time varies by file size — under 30 seconds for files up to 512 MB, around a minute for 1 GB. Public posts go through moderation after processing, which typically takes under a minute but can occasionally take hours.
Rate limit: 30 requests per minute per user access token.
Content sharing guidelines
TikTok enforces strict content sharing guidelines that affect both your app’s UX and API usage:
- No watermarks — Apps must not add brand names, logos, watermarks, or promotional text to content. Violations can result in deleted content or disabled accounts
- Creator info display — Your app must show the creator’s nickname before posting
- Privacy and interaction controls — Users must be able to set privacy level, comments, duets, and stitches
- Commercial content disclosure — Provide toggles for branded content and brand promotion, with appropriate legal declarations
- Daily limits — Approximately 15 posts per day per creator, with a daily active creator cap based on your app’s audit estimates
- Security — Never embed your
client_secretin client-side code or open-source projects
The same video, through Postproxy
Here’s how it’s done with Postproxy. One simple request with only what matters:
curl -X POST "https://api.postproxy.dev/api/posts" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "post": { "body": "We just shipped our biggest update this year. Here is what changed and why." }, "profiles": ["tiktok"], "media": ["https://example.com/video.mp4"] }'One request. Postproxy handles creator info validation, privacy level selection, video upload, status polling, and post creation.
What Postproxy handles
Postproxy maintains an audited app and handles the complexity:
- Completed TikTok app audit with all required scopes approved
- OAuth 2.0 token management and refresh
- Creator info queries and privacy level validation
- Video uploads via URL pull with status polling
- Photo posts with multi-image support
- Content sharing guideline compliance
- Rate limit monitoring and backoff handling
- Commercial content disclosure when applicable
Your system sends content. Postproxy handles the TikTok-specific implementation.
Connect your TikTok account and start publishing through the Postproxy API.