TikTok API

How to post on TikTok
via the API

Post and schedule on TikTok programmatically using the API. Create a key, connect TikTok, and upload the video.

the whole flow

Five steps, then it is scheduled

You call PostWing. PostWing publishes to TikTok at the time you set. The post also shows up on your calendar.

  1. 01Create an API key
  2. 02Connect TikTok
  3. 03Create the video
  4. 04Cross-post to more channels
  5. 05Confirm it
01

Create an API key

Open Dashboard → AI & API and create a key. Copy it once. It starts with pw_live_. Send it on every request:

Header

Authorization: Bearer pw_live_…

Every URL below starts at https://postwing.io/api/v1.

02

Connect TikTok

Connect the TikTok account you want to post from. You only do this once.

The simple way is in the dashboard. Open Accounts, choose TikTok, and finish the TikTok login.

From the API, start that same login. Send platform tiktok. The response includes a url. Open it and approve TikTok.

Start connect

curl -s -X POST "https://postwing.io/api/v1/accounts" \
  -H "Authorization: Bearer pw_live_…" \
  -H "Content-Type: application/json" \
  -d '{ "platform": "tiktok" }'

After you finish in the browser, sync. This imports the account into your workspace and returns the account id.

Sync

curl -s -X POST "https://postwing.io/api/v1/accounts/sync" \
  -H "Authorization: Bearer pw_live_…"

In the response, find the object where platform is tiktok or tiktok_business and copy account_id. That is the id you send when you create the post.

Sync response

{
  "synced_count": 1,
  "accounts": [
    {
      "account_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
      "platform": "tiktok_business",
      "handle": "brand",
      "display_name": "Brand",
      "status": "connected"
    }
  ]
}

Connected TikTok in the dashboard instead? List accounts and copy the same field:

List accounts

curl -s -X GET "https://postwing.io/api/v1/accounts" \
  -H "Authorization: Bearer pw_live_…"
03

Create the video

TikTok needs a video or images. A caption by itself is not enough. Send the video, the caption, a future time, and the TikTok account_id from sync. This call creates the post. TikTok does not publish until you confirm in the next step. scheduled_at is UTC.

Create a video

curl -s -X POST "https://postwing.io/api/v1/posts/preview" \
  -H "Authorization: Bearer pw_live_…" \
  -H "Content-Type: application/json" \
  -d '{
  "caption": "A 15-second look at the new menu.",
  "scheduled_at": "2026-10-12T15:00:00Z",
  "targets": [
    { "account_id": "c3d4e5f6-a7b8-9012-cdef-123456789012" }
  ],
  "media_items": [
    { "url": "https://cdn.example.com/menu.mp4", "type": "video" }
  ]
}'

You get back three things that matter:

  • preview: the caption, time, video, and TikTok account. Check this before you confirm.
  • confirmation_token: you send this in the next step
  • expires_in_seconds: 300, so the token lasts 5 minutes

Response

{
  "preview": {
    "caption": "A 15-second look at the new menu.",
    "scheduled_at": "2026-10-12T15:00:00.000Z",
    "post_type": "video",
    "targets": [
      {
        "account_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
        "platform": "tiktok_business",
        "handle": "brand"
      }
    ]
  },
  "confirmation_token": "eyJ…signature",
  "expires_in_seconds": 300
}

One video per post. The video URL has to be public HTTPS, and videos imported from a URL need to be 100MB or smaller. A caption is capped at about 2,200 characters. Leave the TikTok options off for a public post that allows comments, duets, and stitch.

04

Cross-post to all 8 platforms

The same video can go to Instagram and YouTube. Connect each channel, then copy its account_id from the sync response.

Connect Instagram

curl -s -X POST "https://postwing.io/api/v1/accounts" \
  -H "Authorization: Bearer pw_live_…" \
  -H "Content-Type: application/json" \
  -d '{ "platform": "instagram" }'

Connect YouTube

curl -s -X POST "https://postwing.io/api/v1/accounts" \
  -H "Authorization: Bearer pw_live_…" \
  -H "Content-Type: application/json" \
  -d '{ "platform": "youtube" }'

Open each url, finish the login, then sync once. Copy account_id where platform is instagram, and where platform is youtube.

Add those ids to targets on the create call. YouTube still needs a title on its own target. One request, one confirm. Every account publishes at the same scheduled_at. Leave caption off a target to use the shared caption. Set caption when that channel needs different text.

Create one video for three channels

curl -s -X POST "https://postwing.io/api/v1/posts/preview" \
  -H "Authorization: Bearer pw_live_…" \
  -H "Content-Type: application/json" \
  -d '{
  "caption": "A 15-second look at the new menu.",
  "scheduled_at": "2026-10-12T15:00:00Z",
  "targets": [
    { "account_id": "c3d4e5f6-a7b8-9012-cdef-123456789012" },
    { "account_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901" },
    {
      "account_id": "a7b8c9d0-e1f2-3456-0123-567890123456",
      "platform_options": {
        "title": "The new menu",
        "made_for_kids": false
      }
    }
  ],
  "media_items": [
    { "url": "https://cdn.example.com/menu.mp4", "type": "video" }
  ]
}'

Facebook, LinkedIn, X, and Threads can use this video too. Pinterest needs board_ids on its own target. TikTok still needs the video or images.

05

Confirm the post

When the TikTok preview looks right, confirm with the token from that response. Use the token as-is. Do not invent one.

Confirm

curl -s -X POST "https://postwing.io/api/v1/posts/confirm" \
  -H "Authorization: Bearer pw_live_…" \
  -H "Content-Type: application/json" \
  -d '{ "confirmation_token": "eyJ…signature" }'

The response includes view_url. Open it to see the post on your calendar. TikTok publishes at the time you set. Instagram and YouTube publish then too, when you added them. You can edit or cancel later from the dashboard or with the same API.

If confirm says the token expired, create the post again and confirm the new token within 5 minutes.

images

Post images

An image post uses type image. title is for image posts only. A video does not use it.

Create an image post

curl -s -X POST "https://postwing.io/api/v1/posts/preview" \
  -H "Authorization: Bearer pw_live_…" \
  -H "Content-Type: application/json" \
  -d '{
  "caption": "Three looks from the new drop.",
  "scheduled_at": "2026-10-12T18:00:00Z",
  "targets": [
    {
      "account_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
      "platform_options": { "title": "New drop" }
    }
  ],
  "media_items": [
    { "url": "https://cdn.example.com/look-1.jpg", "type": "image" },
    { "url": "https://cdn.example.com/look-2.jpg", "type": "image" }
  ]
}'

Add more image objects in media_items, up to 30. A title is capped at 90 characters. Leave title off when you do not need one.

options

Privacy, drafts, and AI

These fields are optional. Leave them off for a public post. Set them on the TikTok target when you need control.

Save a private draft

curl -s -X POST "https://postwing.io/api/v1/posts/preview" \
  -H "Authorization: Bearer pw_live_…" \
  -H "Content-Type: application/json" \
  -d '{
  "caption": "Holding this until we are ready.",
  "scheduled_at": "2026-10-12T18:00:00Z",
  "targets": [
    {
      "account_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
      "platform_options": {
        "privacy_status": "private",
        "is_draft": true
      }
    }
  ],
  "media_items": [
    { "url": "https://cdn.example.com/menu.mp4", "type": "video" }
  ]
}'

privacy_status is public or private. The default is public. is_draft saves a draft in the TikTok app, and you finish it there.

allow_comment, allow_duet, and allow_stitch default to true. Set any of them to false to turn that off. is_ai_generated defaults to false. Set it to true to mark the post as AI-generated.

A file on your computer uses the direct upload URL, covered in the API docs.

Details worth knowing

  • scheduled_at has to be a future time in ISO 8601, usually UTC.
  • Creating the post does not publish it. Confirm is the step that schedules it.
  • TikTok needs a video or images. A caption by itself is not enough.
  • title is for image posts only. A video does not use it.
  • privacy_status defaults to public. Comments, duets, and stitch default to allowed.
  • is_draft saves a draft in the TikTok app. is_ai_generated marks the post as AI-generated.
  • The confirmation token expires in 5 minutes and only works for the user who created the post.
  • API access is included on every plan, from $9.99/mo. Posts count as normal posts on your account.

questions

TikTok API FAQ

No. TikTok needs a video or images in media_items, plus the TikTok account_id. Then confirm with the token.

ready when you are

Schedule your next TikTok post from the API

Create a key, connect TikTok, and upload the video.