TikTok API
Schedule and automate TikTok posts with SocialSyncerAPI — Videos, photo carousels, privacy settings, and AI disclosure.
Quick Reference
- Character limit: 2,200 (video caption), 4,000 (photo desc)
- Photo title: 90 chars (auto-truncated, hashtags stripped)
- Photos per post: 35 (carousel)
- Videos per post: 1
- Photo formats: JPEG, PNG, WebP
- Photo max size: 20 MB
- Video formats: MP4, MOV, WebM
- Video max size: 4 GB
- Video duration: 3 sec – 10 min
- Post types: Video, Photo Carousel
- Scheduling: Yes
Before You Start
- Each creator has account-specific privacy level options
- Content moderation is more aggressive via API than native app
- All posts require consent flags (legal requirement from TikTok)
- No text-only posts (media required)
Quick Start
Post a video to TikTok in under 60 seconds:
Python (httpx)
import httpx
resp = httpx.post(
"https://api.socialsyncerapi.com/v1/posts",
headers={"Authorization": "Bearer sk_your_api_key"},
json={
"content": "Check out this amazing sunset! #sunset #nature",
"mediaItems": [
{"type": "video", "url": "https://cdn.example.com/sunset-video.mp4"}
],
"platforms": [
{"platform": "tiktok", "accountId": "YOUR_ACCOUNT_ID"}
],
"tiktokSettings": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": True,
"allow_duet": True,
"allow_stitch": True,
"content_preview_confirmed": True,
"express_consent_given": True
},
"publishNow": True
}
)
print("Posted to TikTok!", resp.json()["id"]) curl
curl -X POST https://api.socialsyncerapi.com/v1/posts \
-H "Authorization: Bearer sk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"content": "Check out this amazing sunset! #sunset #nature",
"mediaItems": [
{"type": "video", "url": "https://cdn.example.com/sunset-video.mp4"}
],
"platforms": [
{"platform": "tiktok", "accountId": "YOUR_ACCOUNT_ID"}
],
"tiktokSettings": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": true,
"allow_duet": true,
"allow_stitch": true,
"content_preview_confirmed": true,
"express_consent_given": true
},
"publishNow": true
}' Node.js (fetch)
const resp = await fetch("https://api.socialsyncerapi.com/v1/posts", {
method: "POST",
headers: {
"Authorization": "Bearer sk_your_api_key",
"Content-Type": "application/json"
},
body: JSON.stringify({
content: "Check out this amazing sunset! #sunset #nature",
mediaItems: [
{ type: "video", url: "https://cdn.example.com/sunset-video.mp4" }
],
platforms: [
{ platform: "tiktok", accountId: "YOUR_ACCOUNT_ID" }
],
tiktokSettings: {
privacy_level: "PUBLIC_TO_EVERYONE",
allow_comment: true,
allow_duet: true,
allow_stitch: true,
content_preview_confirmed: true,
express_consent_given: true
},
publishNow: true
})
});
const data = await resp.json();
console.log("Posted to TikTok!", data.id); Content Types
Video Post
A single video post. Videos must be between 3 seconds and 10 minutes long. Vertical 9:16 aspect ratio is the only format that works well on TikTok.
Video — Python
import httpx
resp = httpx.post(
"https://api.socialsyncerapi.com/v1/posts",
headers={"Authorization": "Bearer sk_your_api_key"},
json={
"content": "New cooking tutorial #recipe #foodtok",
"mediaItems": [
{"type": "video", "url": "https://cdn.example.com/cooking-tutorial.mp4"}
],
"platforms": [
{"platform": "tiktok", "accountId": "YOUR_ACCOUNT_ID"}
],
"tiktokSettings": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": True,
"allow_duet": True,
"allow_stitch": True,
"video_cover_timestamp_ms": 3000,
"content_preview_confirmed": True,
"express_consent_given": True
},
"publishNow": True
}
) Video — curl
curl -X POST https://api.socialsyncerapi.com/v1/posts \
-H "Authorization: Bearer sk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"content": "New cooking tutorial #recipe #foodtok",
"mediaItems": [
{"type": "video", "url": "https://cdn.example.com/cooking-tutorial.mp4"}
],
"platforms": [
{"platform": "tiktok", "accountId": "YOUR_ACCOUNT_ID"}
],
"tiktokSettings": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": true,
"allow_duet": true,
"allow_stitch": true,
"video_cover_timestamp_ms": 3000,
"content_preview_confirmed": true,
"express_consent_given": true
},
"publishNow": true
}' Video — Node.js
const resp = await fetch("https://api.socialsyncerapi.com/v1/posts", {
method: "POST",
headers: {
"Authorization": "Bearer sk_your_api_key",
"Content-Type": "application/json"
},
body: JSON.stringify({
content: "New cooking tutorial #recipe #foodtok",
mediaItems: [
{ type: "video", url: "https://cdn.example.com/cooking-tutorial.mp4" }
],
platforms: [
{ platform: "tiktok", accountId: "YOUR_ACCOUNT_ID" }
],
tiktokSettings: {
privacy_level: "PUBLIC_TO_EVERYONE",
allow_comment: true,
allow_duet: true,
allow_stitch: true,
video_cover_timestamp_ms: 3000,
content_preview_confirmed: true,
express_consent_given: true
},
publishNow: true
})
}); Photo Carousel
Up to 35 images in a single post. Photos are auto-resized to 1080x1920. The content field becomes the photo title (90 chars max, hashtags and URLs are auto-stripped). Use the description field inside tiktokSettings for a full caption up to 4,000 characters.
Photo Carousel — Python
import httpx
resp = httpx.post(
"https://api.socialsyncerapi.com/v1/posts",
headers={"Authorization": "Bearer sk_your_api_key"},
json={
"content": "My travel highlights",
"mediaItems": [
{"type": "image", "url": "https://cdn.example.com/photo1.jpg"},
{"type": "image", "url": "https://cdn.example.com/photo2.jpg"},
{"type": "image", "url": "https://cdn.example.com/photo3.jpg"}
],
"platforms": [
{"platform": "tiktok", "accountId": "YOUR_ACCOUNT_ID"}
],
"tiktokSettings": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": True,
"media_type": "photo",
"photo_cover_index": 0,
"description": "Full trip recap from our weekend adventure. #travel #roadtrip",
"auto_add_music": True,
"content_preview_confirmed": True,
"express_consent_given": True
},
"publishNow": True
}
) Photo Carousel — curl
curl -X POST https://api.socialsyncerapi.com/v1/posts \
-H "Authorization: Bearer sk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"content": "My travel highlights",
"mediaItems": [
{"type": "image", "url": "https://cdn.example.com/photo1.jpg"},
{"type": "image", "url": "https://cdn.example.com/photo2.jpg"},
{"type": "image", "url": "https://cdn.example.com/photo3.jpg"}
],
"platforms": [
{"platform": "tiktok", "accountId": "YOUR_ACCOUNT_ID"}
],
"tiktokSettings": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": true,
"media_type": "photo",
"photo_cover_index": 0,
"description": "Full trip recap from our weekend adventure. #travel #roadtrip",
"auto_add_music": true,
"content_preview_confirmed": true,
"express_consent_given": true
},
"publishNow": true
}' Photo Carousel — Node.js
const resp = await fetch("https://api.socialsyncerapi.com/v1/posts", {
method: "POST",
headers: {
"Authorization": "Bearer sk_your_api_key",
"Content-Type": "application/json"
},
body: JSON.stringify({
content: "My travel highlights",
mediaItems: [
{ type: "image", url: "https://cdn.example.com/photo1.jpg" },
{ type: "image", url: "https://cdn.example.com/photo2.jpg" },
{ type: "image", url: "https://cdn.example.com/photo3.jpg" }
],
platforms: [
{ platform: "tiktok", accountId: "YOUR_ACCOUNT_ID" }
],
tiktokSettings: {
privacy_level: "PUBLIC_TO_EVERYONE",
allow_comment: true,
media_type: "photo",
photo_cover_index: 0,
description: "Full trip recap from our weekend adventure. #travel #roadtrip",
auto_add_music: true,
content_preview_confirmed: true,
express_consent_given: true
},
publishNow: true
})
}); Video Draft (Creator Inbox)
Set draft: true in tiktokSettings to send the post to the Creator Inbox for review instead of publishing immediately.
Draft — Python
import httpx
resp = httpx.post(
"https://api.socialsyncerapi.com/v1/posts",
headers={"Authorization": "Bearer sk_your_api_key"},
json={
"content": "Draft video for review",
"mediaItems": [
{"type": "video", "url": "https://cdn.example.com/draft.mp4"}
],
"platforms": [
{"platform": "tiktok", "accountId": "YOUR_ACCOUNT_ID"}
],
"tiktokSettings": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": True,
"draft": True,
"content_preview_confirmed": True,
"express_consent_given": True
},
"publishNow": True
}
) Draft — curl
curl -X POST https://api.socialsyncerapi.com/v1/posts \
-H "Authorization: Bearer sk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"content": "Draft video for review",
"mediaItems": [
{"type": "video", "url": "https://cdn.example.com/draft.mp4"}
],
"platforms": [
{"platform": "tiktok", "accountId": "YOUR_ACCOUNT_ID"}
],
"tiktokSettings": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": true,
"draft": true,
"content_preview_confirmed": true,
"express_consent_given": true
},
"publishNow": true
}' Draft — Node.js
const resp = await fetch("https://api.socialsyncerapi.com/v1/posts", {
method: "POST",
headers: {
"Authorization": "Bearer sk_your_api_key",
"Content-Type": "application/json"
},
body: JSON.stringify({
content: "Draft video for review",
mediaItems: [
{ type: "video", url: "https://cdn.example.com/draft.mp4" }
],
platforms: [
{ platform: "tiktok", accountId: "YOUR_ACCOUNT_ID" }
],
tiktokSettings: {
privacy_level: "PUBLIC_TO_EVERYONE",
allow_comment: true,
draft: true,
content_preview_confirmed: true,
express_consent_given: true
},
publishNow: true
})
}); Media Requirements
Images
- Max photos: 35 per carousel
- Formats: JPEG, PNG, WebP
- Max file size: 20 MB per image
- Aspect ratio: 9:16 recommended
- Resolution: Auto-resized to 1080 x 1920 px
Videos
- Max videos: 1 per post
- Formats: MP4, MOV, WebM
- Max file size: 4 GB
- Max duration: 10 minutes
- Min duration: 3 seconds
- Aspect ratio: 9:16 vertical (only format that works well)
- Resolution: 1080 x 1920 px recommended
- Codec: H.264, 30 fps recommended
You cannot mix photos and videos in the same post. Use either all photos (carousel) or one video.
Platform-Specific Data
TikTok settings go in tiktokSettings at the top level of the request body, not inside platformSpecificData. This is a special case unique to TikTok.
privacy_level— string (required) — Must match creator's allowed values. Options: PUBLIC_TO_EVERYONE, MUTUAL_FOLLOW_FRIENDS, FOLLOWER_OF_CREATOR, SELF_ONLYallow_comment— boolean (required) — Enable or disable commentsallow_duet— boolean (required for videos) — Enable or disable duetsallow_stitch— boolean (required for videos) — Enable or disable stitchescontent_preview_confirmed— boolean (required) — Must be true. Legal requirement from TikTok.express_consent_given— boolean (required) — Must be true. Legal requirement from TikTok.video_cover_timestamp_ms— number — Thumbnail frame position in milliseconds. Default: 1000. Ignored when video_cover_image_url is provided.video_cover_image_url— string — Custom thumbnail image URL (JPG/PNG/WebP, max 20MB). Overrides video_cover_timestamp_ms.media_type— "photo" — Set to "photo" for photo carousels.photo_cover_index— number — Which image to use as cover (0-indexed).description— string — Long-form caption for photo carousels, up to 4,000 characters.auto_add_music— boolean — Let TikTok add recommended music. Photo carousels only.video_made_with_ai— boolean — AI-generated content disclosure flag.draft— boolean — Send to Creator Inbox for review instead of publishing.commercialContentType— string — "none", "brand_organic", or "brand_content".
Constraints
- Character limit: 2,200 (video caption), 4,000 (photo description)
- Photo title: 90 chars (auto-truncated, hashtags stripped)
- Photos per carousel: 35
- Videos per post: 1
- Video size: 4 GB max
- Video duration: 3 sec – 10 min
- Photo size: 20 MB each
- Daily post limit: Account-specific, set by TikTok
What You Can't Do
These features are not available through TikTok's API:
- Use TikTok's sound/music library (except auto_add_music for photo carousels)
- Create duets or stitches
- Go Live
- Add effects or filters
- Edit posts after publishing
- View For You Page analytics
- Create playlists
- Read or write comments
- Send or read DMs
- Create text-only posts (media required)
Common Errors
- "You have created too many posts in the last 24 hours via the API." — TikTok's daily API posting limit hit. Wait until limit resets (24h rolling).
- "Publishing failed during platform API call (timeout)" — For large videos this can be normal. Check post status after a few minutes.
- "Selected privacy level 'X' is not available for this creator." — Fetch creator info to get allowed privacy levels.
- "TikTok flagged this post as potentially risky (spam_risk)" — Content moderation flagged the post. TikTok's API moderation is stricter than native app.
- "Missing required TikTok permissions." — Reconnect the TikTok account with all required permissions.