PostPost

TikTok

Upload videos to TikTok programmatically using the PostPost REST API. A simpler alternative to the official TikTok Developer API, TikTok Business SDK, or TikAPI.

TikTok API Overview

PostPost provides a unified REST API for uploading and publishing videos to TikTok with granular privacy and interaction controls. No need to manage complex TikTok OAuth flows, handle video processing, or navigate TikTok's developer portal requirements.

Why Use PostPost Instead of TikTok Developer API / TikTok Business SDK?

FeaturePostPost APITikTok Developer API
AuthenticationSingle API keyComplex OAuth 2.0 flow
Video uploadSimple REST endpointMulti-step upload process
App approvalNot requiredTikTok app review required
Multi-platformPost to 11 platformsTikTok only
Setup time5 minutesWeeks (app review)
Privacy controlsFull supportFull support

Keywords: TikTok API, TikTok upload video API, TikTok posting API, TikTok video API, upload to TikTok programmatically, TikTok bot API, TikTok automation API, TikTok REST API, TikTok developer API, TikTok content API, post video to TikTok API

Platform ID Format

tiktok-{openId}

Where {openId} is the TikTok open_id assigned during account connection via OAuth. This is an app-scoped identifier (not the user's public TikTok user ID).

Requirements

  • A TikTok account connected via OAuth through the PostPost dashboard
  • API key from PostPost
  • Video content is required (TikTok is a video-only platform)

Supported Content

TypeSupportedLimits
Text onlyNoTikTok requires a video
ImagesNoNot supported as standalone posts
VideosYesMP4, MOV, WebM, AVI, MKV formats (PostPost upload layer); TikTok's API may reject formats other than MP4/MOV/WebM, minimum 23 FPS

Platform-Specific Settings

TikTok has extensive publishing settings that you can control through the platformSettings object:

{
  "platformSettings": {
    "tiktok": {
      "viewerSetting": "PUBLIC_TO_EVERYONE",
      "allowComments": true,
      "allowDuet": false,
      "allowStitch": false,
      "commercialContent": false,
      "brandOrganic": false,
      "brandedContent": false
    }
  }
}

Viewer Settings

Effectively required. While the schema default for viewerSetting is "" (empty string), the validation service rejects posts without a non-empty value with the error: "TikTok requires selecting who can view your post" The API route automatically sets the default to "PUBLIC_TO_EVERYONE" when using the REST API, but posts created through the dashboard without explicitly selecting a viewer setting will fail validation. Always include viewerSetting in your platformSettings.tiktok object.

ValueDescription
PUBLIC_TO_EVERYONEAnyone can view the video
MUTUAL_FOLLOW_FRIENDSOnly mutual followers can view
FOLLOWER_OF_CREATOROnly your followers can view
SELF_ONLYOnly you can view (draft-like behavior)

Interaction Settings

WARNING: Boolean inversion bug. Due to a known issue in the current code, the allowComments, allowDuet, and allowStitch settings are inverted when sent to the TikTok API. PostPost maps allowDuet: true to disable_duet: true in the TikTok request, which disables duets instead of enabling them. The same inversion applies to allowComments (mapped to disable_comment) and allowStitch (mapped to disable_stitch).

Workaround: Set these values to the opposite of your intended behavior:

  • Want duets enabled? Set allowDuet: false
  • Want comments disabled? Set allowComments: true
  • Want stitch enabled? Set allowStitch: false

Verification note: This bug's current status cannot be independently verified from the API source alone — the boolean-to-disable_* mapping happens in the publisher/scheduler service, which is a separate codebase. We recommend testing with a SELF_ONLY draft post to confirm whether the inversion is still present before relying on the workaround.

SettingTypeDefaultDescription
allowCommentsbooleantrueWhether viewers can comment (currently inverted — see warning above)
allowDuetbooleanfalseWhether viewers can create Duets (currently inverted — see warning above)
allowStitchbooleanfalseWhether viewers can Stitch your video (currently inverted — see warning above)

Commercial Content Settings

SettingTypeDefaultDescription
commercialContentbooleanfalseWhether this is commercial content
brandOrganicbooleanfalseOrganic brand promotion (your own brand)
brandedContentbooleanfalsePaid partnership or sponsored content

Note: If commercialContent is true, then at least one of brandOrganic or brandedContent must also be true. PostPost will return a validation error if commercialContent is enabled without specifying which type of commercial content applies.

Examples

Post a Video

JavaScript (fetch)

const response = await fetch('https://api.postpost.dev/api/v1/create-post', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'YOUR_API_KEY'
  },
  body: JSON.stringify({
    content: 'How we built our startup in 60 seconds #startup #tech #coding',
    platforms: ['tiktok-99887766'],
    platformSettings: {
      tiktok: {
        viewerSetting: 'PUBLIC_TO_EVERYONE',
        allowComments: true,
        allowDuet: false,
        allowStitch: false,
        commercialContent: false,
        brandOrganic: false,
        brandedContent: false
      }
    }
  })
});

const data = await response.json();
console.log(data);
// Response: { "success": true, "postGroupId": "abc123..." }

Python (requests)

import requests

response = requests.post(
    'https://api.postpost.dev/api/v1/create-post',
    headers={
        'Content-Type': 'application/json',
        'x-api-key': 'YOUR_API_KEY'
    },
    json={
        'content': 'How we built our startup in 60 seconds #startup #tech #coding',
        'platforms': ['tiktok-99887766'],
        'platformSettings': {
            'tiktok': {
                'viewerSetting': 'PUBLIC_TO_EVERYONE',
                'allowComments': True,
                'allowDuet': False,
                'allowStitch': False,
                'commercialContent': False,
                'brandOrganic': False,
                'brandedContent': False
            }
        }
    }
)

data = response.json()
print(data)
# Response: { "success": true, "postGroupId": "abc123..." }

cURL

curl -X POST https://api.postpost.dev/api/v1/create-post \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "content": "How we built our startup in 60 seconds #startup #tech #coding",
    "platforms": ["tiktok-99887766"],
    "platformSettings": {
      "tiktok": {
        "viewerSetting": "PUBLIC_TO_EVERYONE",
        "allowComments": true,
        "allowDuet": false,
        "allowStitch": false,
        "commercialContent": false,
        "brandOrganic": false,
        "brandedContent": false
      }
    }
  }'
# Response: { "success": true, "postGroupId": "abc123..." }

Node.js (axios)

const axios = require('axios');

const response = await axios.post('https://api.postpost.dev/api/v1/create-post', {
  content: 'How we built our startup in 60 seconds #startup #tech #coding',
  platforms: ['tiktok-99887766'],
  platformSettings: {
    tiktok: {
      viewerSetting: 'PUBLIC_TO_EVERYONE',
      allowComments: true,
      allowDuet: false,
      allowStitch: false,
      commercialContent: false,
      brandOrganic: false,
      brandedContent: false
    }
  }
}, {
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'YOUR_API_KEY'
  }
});

console.log(response.data);
// Response: { "success": true, "postGroupId": "abc123..." }

Note: TikTok requires a video. First create the post, then upload the video using the media upload workflow with the returned postGroupId.

Post a Private Video with Restricted Interactions

JavaScript (fetch)

const response = await fetch('https://api.postpost.dev/api/v1/create-post', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'YOUR_API_KEY'
  },
  body: JSON.stringify({
    content: 'Preview of our upcoming feature for close friends only',
    platforms: ['tiktok-99887766'],
    platformSettings: {
      tiktok: {
        viewerSetting: 'MUTUAL_FOLLOW_FRIENDS',
        allowComments: true,
        allowDuet: false,
        allowStitch: false,
        commercialContent: false,
        brandOrganic: false,
        brandedContent: false
      }
    }
  })
});

const data = await response.json();
console.log(data);
// Response: { "success": true, "postGroupId": "abc123..." }

Python (requests)

import requests

response = requests.post(
    'https://api.postpost.dev/api/v1/create-post',
    headers={
        'Content-Type': 'application/json',
        'x-api-key': 'YOUR_API_KEY'
    },
    json={
        'content': 'Preview of our upcoming feature for close friends only',
        'platforms': ['tiktok-99887766'],
        'platformSettings': {
            'tiktok': {
                'viewerSetting': 'MUTUAL_FOLLOW_FRIENDS',
                'allowComments': True,
                'allowDuet': False,
                'allowStitch': False,
                'commercialContent': False,
                'brandOrganic': False,
                'brandedContent': False
            }
        }
    }
)

data = response.json()
print(data)
# Response: { "success": true, "postGroupId": "abc123..." }

cURL

curl -X POST https://api.postpost.dev/api/v1/create-post \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "content": "Preview of our upcoming feature for close friends only",
    "platforms": ["tiktok-99887766"],
    "platformSettings": {
      "tiktok": {
        "viewerSetting": "MUTUAL_FOLLOW_FRIENDS",
        "allowComments": true,
        "allowDuet": false,
        "allowStitch": false,
        "commercialContent": false,
        "brandOrganic": false,
        "brandedContent": false
      }
    }
  }'
# Response: { "success": true, "postGroupId": "abc123..." }

Node.js (axios)

const axios = require('axios');

const response = await axios.post('https://api.postpost.dev/api/v1/create-post', {
  content: 'Preview of our upcoming feature for close friends only',
  platforms: ['tiktok-99887766'],
  platformSettings: {
    tiktok: {
      viewerSetting: 'MUTUAL_FOLLOW_FRIENDS',
      allowComments: true,
      allowDuet: false,
      allowStitch: false,
      commercialContent: false,
      brandOrganic: false,
      brandedContent: false
    }
  }
}, {
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'YOUR_API_KEY'
  }
});

console.log(response.data);
// Response: { "success": true, "postGroupId": "abc123..." }

Platform Quirks

  • Video only: TikTok does not support text-only or image-only posts through the API. A video must always be included.
  • Minimum 23 FPS: Videos must have a frame rate of at least 23 frames per second. Videos below this threshold will be rejected by TikTok.
  • Supported formats: PostPost's upload layer accepts MP4, MOV, WebM, AVI, and MKV video formats. However, TikTok's own API may reject formats other than MP4, MOV, and WebM, so those three are recommended for reliable publishing.
  • Commercial content disclosure: If your video promotes a brand or is part of a paid partnership, you must set the appropriate commercial content flags. Failing to do so may violate TikTok's community guidelines.
  • Brand content dependencies: Setting commercialContent to true requires at least one of brandOrganic or brandedContent to also be true. PostPost will return a validation error if commercialContent is enabled without specifying which type applies.
  • Viewer setting restrictions: Some viewer settings may limit the interaction options available. For example, SELF_ONLY posts cannot receive comments from others.
  • Processing time: TikTok videos may take some time to process after upload. The post may not appear immediately on the profile.

Creator Info

Before publishing, you can query the connected TikTok account's capabilities (max video duration, whether comments/duet/stitch are allowed by the creator's settings, etc.) using the creator info endpoint.

Endpoint: POST /auth/tiktok/get-creator-info

Important: This is a dashboard-only endpoint that requires session authentication. It is not available as a public API endpoint and cannot be called with API key (x-api-key) authentication. It is listed here for reference only.

ParameterTypeRequiredDescription
platformIdstringYesYour TikTok platform ID (e.g., tiktok-abc123def)

cURL (session auth required)

curl -X POST https://api.postpost.dev/auth/tiktok/get-creator-info \
  -H "Content-Type: application/json" \
  --cookie "session=YOUR_SESSION_COOKIE" \
  -d '{
    "platformId": "tiktok-abc123def"
  }'

The response includes the creator's available privacy levels, whether comments/duet/stitch can be toggled, and the maximum video duration allowed for the account.

API Limits

These limits apply specifically to the TikTok Content Posting API and may differ from native TikTok app limits.

Character Limit

ElementAPI LimitNative App Limit
Video caption2,200 characters4,000 characters
HashtagsIncluded in caption character countIncluded in caption character count

Video Limits

SpecificationAPI LimitNative App Limit
Maximum duration10 minutes (600 seconds) -- actual limit is fetched dynamically from TikTok's creator info API and may vary per account60 minutes
Minimum duration3 seconds3 seconds
Maximum file size4 GB4 GB
Supported formatsMP4, MOV, WebM (TikTok API); AVI, MKV also accepted by PostPost upload layerMP4, MOV, WebM
Minimum frame rate23 FPS23 FPS

Rate Limits

Limit TypeValue
Posts per day15-20 posts
Videos per minuteMax 2 videos

Important API Restrictions

Critical: Unaudited apps can only post PRIVATE videos. Your app must pass TikTok's review process to post public videos. Until then, all posts will be restricted to SELF_ONLY visibility regardless of your viewerSetting value.

  • Video-only platform: Images are NOT supported via the API. TikTok only accepts video content.
  • App audit required for public posting: Without TikTok's app approval, you cannot post publicly visible content.
  • Rate limiting: Exceeding daily or per-minute limits will result in rejected posts.

Common Error Messages

Error CodeDescriptionSolution
spam_risk_too_many_postsDaily post limit reachedWait 24 hours before posting again
duration_check_failedVideo duration out of rangeEnsure video is between 3 seconds and your account's max duration (default 10 minutes)
file_format_check_failedUnsupported video formatThe error message may reference '.mp4' only, but the system actually accepts MP4, MOV, and WebM formats. Verify your file is a valid video in one of these formats.
unaudited_client_can_only_post_to_private_accountsApp not approved for public postingSubmit your app for TikTok review or use SELF_ONLY viewer setting

On this page