Skip to main content
RapidDev - Software Development Agency
API AutomationsTikTokOAuth 2.0

How to Automate TikTok Video Posting using the API

Automate TikTok video posting using the Content Posting API's Direct Post flow: query creator settings with POST /v2/post/publish/creator_info/query/, initialize the upload with POST /v2/post/publish/video/init/, upload video chunks via PUT to the provided upload URL, then poll status with POST /v2/post/publish/status/fetch/. Access tokens expire every 24 hours. Without TikTok audit approval (2-6 weeks), all posts go to SELF_ONLY (private). Daily cap is ~15 posts per creator account.

Need help automating? Talk to an expert
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Advanced7 min read1-2 hoursTikTokMay 2026RapidDev Engineering Team
TL;DR

Automate TikTok video posting using the Content Posting API's Direct Post flow: query creator settings with POST /v2/post/publish/creator_info/query/, initialize the upload with POST /v2/post/publish/video/init/, upload video chunks via PUT to the provided upload URL, then poll status with POST /v2/post/publish/status/fetch/. Access tokens expire every 24 hours. Without TikTok audit approval (2-6 weeks), all posts go to SELF_ONLY (private). Daily cap is ~15 posts per creator account.

API Quick Reference

Auth

OAuth 2.0

Rate limit

6 req/min (publish); 30 req/min (status); ~15 posts/day per account

Format

JSON

SDK

REST only

Understanding the TikTok Content Posting API

TikTok's Content Posting API (Direct Post) is the most restrictive publishing API of any major social platform. Before you can post videos publicly, your app must pass TikTok's Content Posting Audit — a 2-6 week review process. Without it, every post defaults to SELF_ONLY (private) regardless of the privacy_level parameter you set. TikTok explicitly rejects apps described as 'personal account management utilities' — your use case must serve a broad audience.

The upload flow has four steps: (1) call creator_info/query to get allowed settings for the specific creator, (2) initialize the post with video/init/ to receive an upload URL, (3) upload the video in chunks using PUT requests with Content-Range headers, (4) poll status/fetch/ until the post is PUBLISHED. Video upload uses a dedicated upload domain: open-upload.tiktokapis.com. The access token expires every 24 hours — a token refresh job is not optional.

Mandatory UX requirements from TikTok's audit: your app must display the creator's nickname from creator_info, show a Commercial Content checkbox (for Brand Partnerships and Your Brand), and let users consent to music usage. Apps that skip these UI elements fail the audit. Official documentation: https://developers.tiktok.com/doc/content-posting-api-get-started

Base URLhttps://open.tiktokapis.com

Setting Up TikTok Content Posting API Authentication

TikTok OAuth2 v2 uses short-lived access tokens (24h) with a long-lived refresh token (365 days). The video.publish scope enables Direct Post. Unlike most APIs, TikTok requires a mandatory token refresh loop — there is no way to get longer-lived tokens. Missing a refresh means your automation breaks silently.

  1. 1Create a developer account at developers.tiktok.com with a business email
  2. 2Create a new app and add the 'Video: Direct Post' capability to request video.publish scope
  3. 3Submit your app for the Content Posting Audit (required for public posts) — this takes 2-6 weeks
  4. 4Note your client_key and client_secret from the app dashboard
  5. 5Implement OAuth authorization: https://www.tiktok.com/v2/auth/authorize/?client_key={key}&scope=video.publish&response_type=code&redirect_uri={uri}&state={random}
  6. 6Exchange the code for tokens at POST https://open.tiktokapis.com/v2/oauth/token/ with grant_type=authorization_code
  7. 7Store both access_token (24h) and refresh_token (365 days) securely
  8. 8Set up a cron job to call POST /v2/oauth/token/ with grant_type=refresh_token every 18-20 hours
auth.py
1import requests
2import os
3
4CLIENT_KEY = os.environ['TIKTOK_CLIENT_KEY']
5CLIENT_SECRET = os.environ['TIKTOK_CLIENT_SECRET']
6
7def refresh_token(refresh_token_value):
8 """MANDATORY: call every 18-20 hours. 24h expiry is strict."""
9 resp = requests.post(
10 'https://open.tiktokapis.com/v2/oauth/token/',
11 data={
12 'client_key': CLIENT_KEY,
13 'client_secret': CLIENT_SECRET,
14 'grant_type': 'refresh_token',
15 'refresh_token': refresh_token_value,
16 },
17 headers={'Content-Type': 'application/x-www-form-urlencoded'}
18 )
19 resp.raise_for_status()
20 data = resp.json()
21 print(f'Token refreshed. Expires in: {data["expires_in"]}s')
22 return data['access_token'], data.get('refresh_token', refresh_token_value)
23
24def tiktok_api(method, url, access_token, **kwargs):
25 headers = kwargs.pop('headers', {})
26 headers.update({
27 'Authorization': f'Bearer {access_token}',
28 'Content-Type': 'application/json; charset=UTF-8',
29 })
30 resp = getattr(requests, method)(url, headers=headers, **kwargs)
31 resp.raise_for_status()
32 data = resp.json()
33 if data.get('error', {}).get('code', 'ok') != 'ok':
34 raise ValueError(f'TikTok error: {data["error"]}')
35 return data

Security notes

  • Access token expires in 24 hours — automate refresh or your automation breaks every day
  • Store client_key, client_secret, access_token, and refresh_token in environment variables or a secrets manager
  • Never embed API credentials in video files, watermarks, or content visible to users
  • TikTok monitors for IP/geolocation mismatches — use consistent server infrastructure for API calls
  • Never put watermarks, external links, or competitor branding on API-uploaded videos — violates TikTok Terms of Service
  • Log all post publications with publish_id and video_id for audit trail and debugging

Key endpoints

POST/v2/post/publish/creator_info/query/

REQUIRED before every post. Returns the creator's allowed settings: privacy levels, max video duration, whether comments/duets/stitches can be disabled. Your app must display the creator's nickname from this response. This is a hard audit requirement.

Request

json
1{}

Response

json
1{"data": {"creator_username": "creator123", "creator_nickname": "Creator Display Name", "creator_avatar_url": "https://...", "privacy_level_options": ["PUBLIC_TO_EVERYONE", "FOLLOWER_OF_CREATOR", "SELF_ONLY"], "comment_disabled": false, "duet_disabled": false, "stitch_disabled": false, "max_video_post_duration_sec": 180}, "error": {"code": "ok"}}
POST/v2/post/publish/video/init/

Initializes a Direct Post by providing post metadata and video file info. Returns an upload_url for chunked video upload. The publish_id tracks the post through the upload and publish pipeline.

ParameterTypeRequiredDescription
post_info.titlestringrequiredVideo caption. Max 2,200 characters. Can include hashtags and @mentions.
post_info.privacy_levelstringrequiredMust be one of the values from creator_info/query. Without audit approval, posts go SELF_ONLY regardless.
source_info.video_sizenumberrequiredTotal video file size in bytes. Must be exact.
source_info.chunk_sizenumberrequiredSize of each upload chunk in bytes. Recommended: 10MB (10485760). Last chunk can be smaller.
source_info.total_chunk_countnumberrequiredTotal number of chunks. Must equal ceil(video_size / chunk_size).

Request

json
1{"post_info": {"title": "Video caption #fyp", "privacy_level": "PUBLIC_TO_EVERYONE", "disable_duet": false, "disable_comment": false, "disable_stitch": false, "video_cover_timestamp_ms": 1000}, "source_info": {"source": "FILE_UPLOAD", "video_size": 52428800, "chunk_size": 10485760, "total_chunk_count": 5}}

Response

json
1{"data": {"publish_id": "v_pub_url~v2.123456789", "upload_url": "https://open-upload.tiktokapis.com/upload/?upload_id=abc&upload_token=xyz"}, "error": {"code": "ok"}}
PUThttps://open-upload.tiktokapis.com/upload/ (from upload_url)

Uploads video chunks to the TikTok upload server. Each chunk requires Content-Range header specifying the byte range. Upload chunks sequentially.

ParameterTypeRequiredDescription
Content-RangestringrequiredByte range of this chunk. Format: 'bytes {start}-{end}/{total}'. E.g., 'bytes 0-10485759/52428800' for the first 10MB chunk.
Content-TypestringrequiredMust be 'video/mp4' (or video/quicktime for MOV files).

Request

json
1Binary video data (chunk bytes)

Response

json
1{"backend_trace": "abc123"}
POST/v2/post/publish/status/fetch/

Polls the publish status for a video upload. Status progresses: PROCESSING_UPLOAD → PROCESSING_DOWNLOAD → PUBLISH_COMPLETE (or FAILED). Check this after upload completes to confirm the post went live.

ParameterTypeRequiredDescription
publish_idstringrequiredThe publish_id returned from /video/init/.

Request

json
1{"publish_id": "v_pub_url~v2.123456789"}

Response

json
1{"data": {"status": "PUBLISH_COMPLETE", "privacy_level": "PUBLIC_TO_EVERYONE", "share_url": "https://www.tiktok.com/@creator/video/12345", "video_id": "7123456789012345678"}, "error": {"code": "ok"}}

Step-by-step automation

1

Query Creator Info and Prepare Post Metadata

Why: Creator info is required by TikTok's audit — skipping it will cause your audit application to be rejected, and you need the privacy_level_options to set valid privacy.

Call POST /v2/post/publish/creator_info/query/ before every post. Use the response to validate your target privacy_level is available for this creator, and store the creator_nickname to display in your UI (required for audit). Also check max_video_post_duration_sec to validate your video length.

request.sh
1curl -X POST https://open.tiktokapis.com/v2/post/publish/creator_info/query/ \
2 -H "Authorization: Bearer ${ACCESS_TOKEN}" \
3 -H "Content-Type: application/json; charset=UTF-8" \
4 -d '{}'

Pro tip: TikTok's audit specifically checks that your app displays the creator_nickname in the posting UI. Build your front-end to show 'Posting as: {creator_nickname}' before the user confirms publishing.

Expected result: Creator info object including creator_nickname (display in your UI), privacy_level_options (valid values for post_info.privacy_level), and max_video_post_duration_sec.

2

Initialize the Video Post and Get Upload URL

Why: The video/init/ call creates the post record and returns a time-limited upload URL — you must start uploading immediately after receiving it.

Send POST /v2/post/publish/video/init/ with post metadata and video file details. You need the exact video file size in bytes and must calculate total_chunk_count correctly. The response contains a publish_id (track this throughout the flow) and an upload_url with embedded auth credentials that expire.

request.sh
1curl -X POST https://open.tiktokapis.com/v2/post/publish/video/init/ \
2 -H "Authorization: Bearer ${ACCESS_TOKEN}" \
3 -H "Content-Type: application/json; charset=UTF-8" \
4 -d '{
5 "post_info": {
6 "title": "My video #fyp #trending",
7 "privacy_level": "PUBLIC_TO_EVERYONE",
8 "disable_duet": false,
9 "disable_comment": false,
10 "disable_stitch": false
11 },
12 "source_info": {
13 "source": "FILE_UPLOAD",
14 "video_size": 52428800,
15 "chunk_size": 10485760,
16 "total_chunk_count": 5
17 }
18 }'

Pro tip: Use 10MB chunk size for reliable uploads. Smaller chunks mean more HTTP requests; larger chunks risk timeout on slow connections. TikTok recommends 5-64MB chunks.

Expected result: publish_id for status tracking, upload_url for chunked upload, and video_size for calculating byte ranges.

3

Upload Video in Chunks

Why: TikTok uses chunked upload to handle large video files — you cannot POST the full video in one request.

Split the video file into chunks and PUT each one to the upload_url with appropriate Content-Range headers. The Content-Range format is 'bytes {start}-{end}/{total}'. Upload chunks sequentially — TikTok does not support parallel chunk uploads. Include retry logic for individual chunks.

request.sh
1# Upload the first 10MB chunk (bytes 0-10485759 of a 52428800-byte file)
2curl -X PUT "${UPLOAD_URL}" \
3 -H "Content-Range: bytes 0-10485759/52428800" \
4 -H "Content-Type: video/mp4" \
5 --data-binary @/path/to/chunk_0.bin

Pro tip: TikTok's upload URL contains embedded credentials with a time limit — start uploading immediately after calling video/init/. If upload takes too long, the URL may expire and you'll need to re-initialize.

Expected result: All chunks uploaded successfully. TikTok begins processing the video for publishing.

4

Poll Publish Status Until Complete

Why: Video processing takes time and may fail at multiple stages — polling confirms the video actually went live and gives you the video_id for tracking.

After upload completes, poll POST /v2/post/publish/status/fetch/ with the publish_id every 10-30 seconds. Status progresses: PROCESSING_UPLOAD → PROCESSING_DOWNLOAD → PUBLISH_COMPLETE (or FAILED). Store the video_id from the PUBLISH_COMPLETE response.

request.sh
1curl -X POST https://open.tiktokapis.com/v2/post/publish/status/fetch/ \
2 -H "Authorization: Bearer ${ACCESS_TOKEN}" \
3 -H "Content-Type: application/json; charset=UTF-8" \
4 -d '{"publish_id": "${PUBLISH_ID}"}'

Pro tip: Always check the privacy_level in the PUBLISH_COMPLETE response — it confirms whether your audit approval is active. A post appearing as SELF_ONLY despite setting PUBLIC_TO_EVERYONE means your audit is still pending.

Expected result: Status PUBLISH_COMPLETE with video_id and share_url. If privacy_level is SELF_ONLY, the app needs audit approval.

Complete working code

Complete TikTok video posting pipeline: refreshes the token, queries creator info, initializes the post, uploads video in chunks, polls publish status, and logs the result. Handles the full flow from video file on disk to published TikTok post.

automate_tiktok_posting.py
1#!/usr/bin/env python3
2"""TikTok Direct Post Video Publisher."""
3import os
4import math
5import time
6import logging
7import requests
8
9logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s')
10log = logging.getLogger(__name__)
11
12CLIENT_KEY = os.environ['TIKTOK_CLIENT_KEY']
13CLIENT_SECRET = os.environ['TIKTOK_CLIENT_SECRET']
14REFRESH_TOKEN = os.environ['TIKTOK_REFRESH_TOKEN']
15CHUNK_SIZE = 10 * 1024 * 1024 # 10MB
16
17def get_fresh_token():
18 resp = requests.post('https://open.tiktokapis.com/v2/oauth/token/',
19 data={'client_key': CLIENT_KEY, 'client_secret': CLIENT_SECRET,
20 'grant_type': 'refresh_token', 'refresh_token': REFRESH_TOKEN},
21 headers={'Content-Type': 'application/x-www-form-urlencoded'})
22 resp.raise_for_status()
23 return resp.json()['access_token']
24
25def tt(method, url, token, **kwargs):
26 headers = kwargs.pop('headers', {})
27 headers.update({'Authorization': f'Bearer {token}', 'Content-Type': 'application/json; charset=UTF-8'})
28 resp = getattr(requests, method)(url, headers=headers, **kwargs)
29 resp.raise_for_status()
30 data = resp.json()
31 if data.get('error', {}).get('code', 'ok') != 'ok':
32 raise ValueError(f'TikTok API error: {data["error"]}')
33 return data['data']
34
35def query_creator(token):
36 return tt('post', 'https://open.tiktokapis.com/v2/post/publish/creator_info/query/', token, json={})
37
38def init_post(token, video_path, title, privacy_level):
39 video_size = os.path.getsize(video_path)
40 return tt('post', 'https://open.tiktokapis.com/v2/post/publish/video/init/', token, json={
41 'post_info': {'title': title, 'privacy_level': privacy_level, 'disable_duet': False, 'disable_comment': False, 'disable_stitch': False},
42 'source_info': {'source': 'FILE_UPLOAD', 'video_size': video_size, 'chunk_size': CHUNK_SIZE, 'total_chunk_count': math.ceil(video_size / CHUNK_SIZE)}
43 }), video_size
44
45def upload_chunks(upload_url, video_path, video_size):
46 n = math.ceil(video_size / CHUNK_SIZE)
47 with open(video_path, 'rb') as f:
48 for i in range(n):
49 start = i * CHUNK_SIZE
50 end = min(start + CHUNK_SIZE - 1, video_size - 1)
51 f.seek(start)
52 data = f.read(end - start + 1)
53 resp = requests.put(upload_url, data=data,
54 headers={'Content-Range': f'bytes {start}-{end}/{video_size}', 'Content-Type': 'video/mp4'}, timeout=120)
55 resp.raise_for_status()
56 log.info(f'Chunk {i+1}/{n} uploaded')
57
58def poll_status(publish_id, token, timeout=600):
59 deadline = time.time() + timeout
60 delay = 10
61 while time.time() < deadline:
62 data = tt('post', 'https://open.tiktokapis.com/v2/post/publish/status/fetch/', token, json={'publish_id': publish_id})
63 status = data.get('status')
64 log.info(f'Status: {status}')
65 if status == 'PUBLISH_COMPLETE':
66 if data.get('privacy_level') == 'SELF_ONLY':
67 log.warning('Post is PRIVATE — audit approval needed for public posts')
68 return data
69 if status == 'FAILED':
70 raise ValueError(f'Publish failed: {data}')
71 delay = min(delay * 1.5, 60)
72 time.sleep(delay)
73 raise TimeoutError('Polling timeout')
74
75def publish_video(video_path, title, privacy_level='PUBLIC_TO_EVERYONE'):
76 log.info('Refreshing token...')
77 token = get_fresh_token()
78 log.info('Querying creator info...')
79 creator = query_creator(token)
80 log.info(f'Creator: {creator["creator_nickname"]}')
81 if privacy_level not in creator.get('privacy_level_options', []):
82 log.warning(f'{privacy_level} not available; using SELF_ONLY')
83 privacy_level = 'SELF_ONLY'
84 log.info('Initializing post...')
85 (post_data, video_size) = init_post(token, video_path, title, privacy_level)
86 publish_id = post_data['publish_id']
87 upload_url = post_data['upload_url']
88 log.info(f'Uploading video ({video_size/1024/1024:.1f}MB)...')
89 upload_chunks(upload_url, video_path, video_size)
90 log.info('Polling publish status...')
91 result = poll_status(publish_id, token)
92 log.info(f'Done! Video ID: {result.get("video_id")}')
93 return result
94
95if __name__ == '__main__':
96 result = publish_video('/path/to/video.mp4', 'My TikTok video #fyp')
97 print(f'Published: {result}')

Error handling

401{"error": {"code": "access_token_invalid", "message": "Access token is invalid or expired"}}
Cause

The 24-hour access token has expired. This is the most common error in TikTok automation.

Fix

Call POST /v2/oauth/token/ with grant_type=refresh_token immediately before every API operation. Build token refresh into the start of every automation run.

Retry strategy

Refresh token, then retry the original request.

403{"error": {"code": "unaudited_client_only_self_visibility"}}
Cause

Your TikTok app has not passed the Content Posting API audit. All posts are forced to SELF_ONLY (private).

Fix

Apply for the Content Posting Audit at developers.tiktok.com. Takes 2-6 weeks. Your app must demonstrate broad audience utility — TikTok rejects 'personal account utilities'. While waiting, test with SELF_ONLY posts.

Retry strategy

Cannot bypass — audit approval required.

400{"error": {"code": "video_duration_exceeds_max"}}
Cause

The video is longer than the creator's maximum allowed duration from creator_info/query.

Fix

Always call creator_info/query first and validate duration against max_video_post_duration_sec. Trim video with ffmpeg: `ffmpeg -i input.mp4 -t {max_duration} output.mp4`.

Retry strategy

Trim video and retry.

400{"error": {"code": "unsupported_format", "message": "Video format not supported"}}
Cause

Video is not in a supported format. TikTok requires MP4, MOV, WEBM, or AVI. Recommended: MP4 with H.264 codec and AAC audio.

Fix

Re-encode: `ffmpeg -i input.mp4 -c:v libx264 -c:a aac output.mp4`. Check codec with ffprobe.

Retry strategy

Re-encode and retry.

429{"error": {"code": "rate_limit_exceeded"}}
Cause

Exceeded 6 requests per minute on publish endpoints.

Fix

Add 10-second minimum delays between publish API calls. Monitor X-RateLimit-Remaining header.

Retry strategy

Wait 60 seconds, then retry with exponential backoff.

Rate Limits for TikTok Content Posting API

ScopeLimitWindow
Per user access_token (publish endpoints: init, creator_info)6 requestsper minute
Per user access_token (status fetch)30 requestsper minute
Daily posting cap~15 posts per creator accountper 24 hours (shared across all API clients)
retry-handler.ts
1import time
2import requests
3
4def tiktok_post_with_retry(url, token, body, max_retries=3):
5 for attempt in range(max_retries):
6 resp = requests.post(url,
7 headers={'Authorization': f'Bearer {token}', 'Content-Type': 'application/json; charset=UTF-8'},
8 json=body, timeout=30)
9 remaining = int(resp.headers.get('X-RateLimit-Remaining', '3'))
10 if resp.status_code == 429:
11 reset = int(resp.headers.get('X-RateLimit-Reset', '60'))
12 print(f'Rate limited. Waiting {reset + 5}s')
13 time.sleep(reset + 5)
14 continue
15 resp.raise_for_status()
16 return resp.json()
17 raise Exception('Max retries exceeded')
  • Always refresh the access token before starting a post flow — the 24-hour expiry is non-negotiable
  • Add 10-second minimums between publish endpoint calls to stay well within 6 req/min
  • Monitor the daily posting cap (~15 posts/account) in your own database — TikTok returns an error when exceeded
  • Upload chunks as quickly as the upload URL allows — it has an expiry and slow networks can cause failures
  • Use 10MB chunk size for the optimal balance of reliability and upload speed on typical server connections

Security checklist

  • Store client_key, client_secret, access_token, and refresh_token in environment variables or a secrets manager
  • Never embed credentials in video files or visible UI elements
  • Implement automated token refresh every 18-20 hours with failure alerts
  • Log all publish operations with publish_id, video_id, and timestamp for audit purposes
  • Use consistent server IP addresses for API calls — TikTok monitors for IP/geolocation anomalies
  • Never include competitor watermarks, third-party logos, or external links in API-uploaded videos
  • Validate video content for Terms of Service compliance before uploading to avoid account bans

Automation use cases

Content Calendar Publisher

advanced

Queue videos with metadata in a database, fire a cron job at scheduled times to check for due posts, and execute the full upload-and-publish flow automatically.

Cross-Platform Video Syndicator

advanced

After publishing to Instagram or YouTube, automatically repost the same video to TikTok using the Content Posting API with adapted captions.

Batch Product Video Publisher

advanced

For e-commerce brands, automatically publish product demo videos to TikTok when new products launch in Shopify, using auto-generated captions.

No-code alternatives

Don't want to write code? These platforms can automate the same workflows visually.

Zapier

Free tier; Starter from $19.99/month

Zapier has limited TikTok integration and cannot post videos through the Content Posting API flow — it's mainly for lead generation forms.

Pros
  • + No code
  • + Easy setup for other platforms
Cons
  • - No video upload support via TikTok API
  • - Same audit requirements
  • - Very limited TikTok module

Make (formerly Integromat)

Free tier (1,000 ops/month); Core from $9/month

Make has some TikTok support but the chunked video upload flow requires direct API access that no-code tools cannot easily abstract.

Pros
  • + Visual workflow builder
  • + More affordable than Zapier
Cons
  • - Chunked upload not supported natively
  • - Same audit requirements apply
  • - Complex setup

n8n

Free (self-hosted); Cloud from $20/month

n8n can implement the full TikTok posting pipeline via HTTP request nodes, including chunked uploads, making it the most capable no-code alternative.

Pros
  • + Free self-hosted
  • + Full HTTP API support including chunked upload
  • + Complete flow control
Cons
  • - Requires server setup
  • - More complex than Zapier
  • - Same audit requirements

Best practices

  • Always call creator_info/query before every post and display creator_nickname in your UI — this is a hard TikTok audit requirement
  • Apply for the Content Posting Audit early in development (it takes 2-6 weeks) — test with SELF_ONLY during the wait
  • Always refresh the access token at the start of every posting flow — the 24-hour expiry is strict
  • Use exactly 10MB chunk size for reliable uploads — smaller increases HTTP overhead, larger risks timeouts
  • Start uploading immediately after receiving the upload_url from video/init/ — the URL has a time limit
  • Track the daily posting cap (~15/account) in your own database and build queue management to distribute posts across days
  • Store publish_id and the resulting video_id for every post — this is your audit trail and debugging data

Ask AI to help

Copy one of these prompts to get a personalized, working implementation.

ChatGPT / Claude Prompt

I'm building a TikTok video poster using the Content Posting API v2. The flow is: POST /v2/post/publish/creator_info/query/ → POST /v2/post/publish/video/init/ → PUT chunked upload to upload_url → POST /v2/post/publish/status/fetch/. My access tokens expire every 24 hours. Help me: 1) implement a robust token refresh system using the refresh_token that runs automatically every 18 hours, 2) build the chunked upload with proper Content-Range headers and retry logic for failed chunks, 3) handle the case where the poll returns SELF_ONLY privacy (app not yet audited) and alert the operator.

Lovable / V0 Prompt

Build a React video scheduling dashboard for TikTok. It needs: a queue of scheduled TikTok posts with video thumbnail preview, caption, scheduled time, and status (queued, uploading, published, failed); a post creation form with video file upload, caption editor with hashtag suggestions, privacy level selector (showing options from creator_info), and datetime picker; an 'Audit Status' banner that prominently shows whether the app has TikTok audit approval with instructions if not; and a token health indicator showing when the access token was last refreshed. Use Supabase for storage and Edge Functions for the TikTok API calls.

Frequently asked questions

Why are my TikTok posts private (SELF_ONLY) even when I set PUBLIC_TO_EVERYONE?

Your app has not passed TikTok's Content Posting Audit. Without audit approval, all posts are forced to SELF_ONLY mode regardless of the privacy_level parameter you set. The audit takes 2-6 weeks and requires demonstrating that your app serves a broad audience. Apply at developers.tiktok.com under Content Posting API. During development, test with SELF_ONLY intentionally to validate your flow works before the audit completes.

What happens when my TikTok access token expires?

You'll get error code 'access_token_invalid' (HTTP 401) on all API calls. TikTok access tokens expire every 24 hours without exception. You must call POST /v2/oauth/token/ with grant_type=refresh_token and your 365-day refresh_token to get a new access_token. Set up an automated cron job that runs every 18-20 hours to refresh before expiry. Alert if the refresh fails — a failed refresh means your next post attempt will also fail.

How does TikTok's chunked video upload work?

After calling /video/init/, you receive an upload_url. Split your video into chunks (10MB recommended) and PUT each one with a Content-Range header in the format 'bytes {start}-{end}/{total}'. For example, for a 30MB video: first chunk is 'bytes 0-10485759/31457280', second is 'bytes 10485760-20971519/31457280', third is 'bytes 20971520-31457279/31457280'. Upload chunks sequentially — TikTok does not support parallel chunk uploads. Start uploading immediately after receiving the upload_url as it has a time limit.

What is the daily posting limit for TikTok's API?

TikTok's official documentation states: 'The upper limit may vary among creators (typically around 15 posts per day per creator account) and is shared across all API Clients using Direct Post.' This is not a hard published number — it depends on the creator account's settings agreed upon during your audit application. The limit is shared across all apps using the Direct Post API for that creator, not per-app.

What video formats does the TikTok API accept?

Supported formats: MP4, MOV, WEBM, AVI. Recommended: MP4 with H.264 video codec and AAC audio codec, 9:16 aspect ratio, 1080x1920px, 23-60 FPS. File size up to 1GB via API. Minimum duration: 3 seconds. Maximum duration: varies per creator (from creator_info/query). Re-encode with ffmpeg if needed: `ffmpeg -i input.mp4 -c:v libx264 -c:a aac -vf scale=1080:1920 output.mp4`.

Can RapidDev help navigate the TikTok audit process?

Yes — RapidDev has experience with the TikTok Content Posting Audit process and building compliant applications. We help structure your app's use case to pass the audit, build the required UX elements (creator nickname display, commercial content checkbox), and implement the full posting pipeline. Book a free consultation at rapidevelopers.com.

What are the mandatory UX requirements for TikTok's audit?

TikTok's audit requires: (1) display the creator's nickname from creator_info/query in your posting UI, (2) include a Commercial Content checkbox with two options — 'Your Brand' and 'Branded Content (Paid Partnership)' — for posts containing branded content, and (3) let users consent to music usage for their post. Skipping these UI elements is grounds for audit rejection. The audit reviewer will test your app's actual interface.

RapidDev

Need this automated?

Our team has built 600+ apps with API automations. We can build this for you.

Book a free consultation

Skip the coding — we'll build it for you

Our experts have built 600+ API automations. From prototype to production in days, not weeks.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.