TikTok video publishing
Upload, publish, schedule, and track a public TikTok video through the REST API.
Use an account connected through TikTok for Business Developers and a video in the same workspace. Each request supports one account, one video, and one caption. Videos are published with privacyLevel: "PUBLIC_TO_EVERYONE". Photo publishing, inbox transfers, and reposting are not supported by this workflow.
The API key chooses the workspace for every request. Retrieve the account ID from GET /api/v1/accounts and check capabilities.publishPosts or capabilities.schedulePosts.
Choose or upload a video
For a video already in your media library, list available videos and use a returned mediaId:
curl "https://www.posteady.com/api/v1/media?limit=20&offset=0" \
-H "Authorization: Bearer $POSTEADY_API_KEY"The response contains media, total, and hasMore. Each video includes its mediaId, fileName, mimeType, fileSize, url, and available duration and dimensions. Only supported active MP4 and QuickTime videos visible in the workspace library are listed. limit defaults to 20 and accepts 1–100; offset accepts 0–10,000.
For a new file, create an upload reservation. This example assumes video.mp4 is exactly 10,485,760 bytes; replace fileSize with your file's actual byte count:
curl -X POST https://www.posteady.com/api/v1/media/uploads \
-H "Authorization: Bearer $POSTEADY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"fileName": "video.mp4",
"contentType": "video/mp4",
"fileSize": 10485760
}'This returns mediaId, fileKey, uploadUrl, expiresInSeconds, and requiredHeaders. MP4 (video/mp4) and QuickTime (video/quicktime) files up to 2 GiB are accepted. The file name must end in .mp4 or .mov, contain at most 255 characters, and contain no directory path or control characters. The reserved file size counts toward the organization's media storage quota.
Upload the file bytes to uploadUrl within 300 seconds, using the exact headers from requiredHeaders. The storage PUT uses the returned URL and headers:
curl --request PUT "<uploadUrl>" \
--header "Content-Type: video/mp4" \
--header "Content-Length: 10485760" \
--upload-file video.mp4After the PUT succeeds, confirm with the returned fileKey within 24 hours of creating the upload:
curl -X POST https://www.posteady.com/api/v1/media/uploads/confirm \
-H "Authorization: Bearer $POSTEADY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"fileKey": "<fileKey>"
}'You may include a positive duration in seconds, and width and height as integers from 1–32,768 pixels as client hints. Confirm with the same user and workspace that created the upload. Posteady verifies the stored file's size, content type, signature, and object version, then measures supported MP4/QuickTime duration and dimensions before making the video available. Use mediaId from the confirmation response for publishing. Reserving an ID or uploading bytes alone does not make the video ready.
Confirmation uses the reserved storage and does not count the file size again. Expired unconfirmed uploads are cleaned up and cannot be published.
Publish now
Generate a UUID once for this publishing operation and pass it as video.requestId. Keep it when retrying the same request.
curl -X POST https://www.posteady.com/api/v1/posts \
-H "Authorization: Bearer $POSTEADY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountIds": ["<tiktok-account-uuid>"],
"posts": ["A look behind the scenes"],
"video": {
"mediaId": "<confirmed-media-uuid>",
"requestId": "<request-uuid>",
"privacyLevel": "PUBLIC_TO_EVERYONE",
"disableComment": false,
"disableDuet": false,
"disableStitch": false,
"brandOrganicToggle": false,
"brandContentToggle": false
}
}'The five boolean fields are optional. Set brandOrganicToggle when promoting your own brand and brandContentToggle for branded content. Review the caption, public visibility, and these settings before submitting. Captions are limited to 2,200 UTF-16 code units; emoji may use two units. The account's video duration limit is checked during publishing.
An accepted publishing job returns HTTP 202:
{
"results": [
{
"accountId": "<tiktok-account-uuid>",
"provider": "tiktok",
"username": "example",
"success": true,
"postIds": [],
"jobId": "<job-uuid>",
"status": "queued"
}
],
"summary": { "succeeded": 1, "failed": 0 }
}Here success: true and summary.succeeded mean the job was accepted. They do not confirm that TikTok published the video. Store jobId and check its status.
Track publishing
curl "https://www.posteady.com/api/v1/publish-jobs/<job-uuid>" \
-H "Authorization: Bearer $POSTEADY_API_KEY"The response includes jobId, scheduledPostId, platform, accountId, username, status, postId, permalink, and scheduledAt. Immediate jobs have scheduledAt: null. Native postId and permalink remain null until available. A failure may include an error with code and message.
| Status | Meaning |
|---|---|
queued | Waiting for processing to start |
scheduled | Waiting for the requested scheduled time |
processing | Publishing is in progress |
published | Publication is confirmed and a native post ID is available |
failed | A known failure prevented completion |
canceled | The job was canceled before submission |
unknown | The submission outcome could not be established |
Retry an interrupted API request with the same requestId and unchanged input. Posteady returns the existing job. Reusing that key with different input, including a different account, video, caption, or schedule, returns 409 REQUEST_CONFLICT.
For unknown, Posteady does not automatically submit another video. Check the TikTok account before deciding whether to create a new request: a new key could duplicate a video that was already submitted.
Schedule and cancel
Send the same accountIds, posts, and video fields to POST /api/v1/scheduled-posts, adding a future scheduledAt and optional IANA timezone:
{
"accountIds": ["<tiktok-account-uuid>"],
"posts": ["A look behind the scenes"],
"video": {
"mediaId": "<confirmed-media-uuid>",
"requestId": "<new-request-uuid>",
"privacyLevel": "PUBLIC_TO_EVERYONE"
},
"scheduledAt": "<future-time-with-offset>",
"timezone": "Asia/Seoul"
}A successful scheduling response is HTTP 200 with results[0].scheduledPostIds, jobId, and status. Track it using jobId. List TikTok schedules with:
curl "https://www.posteady.com/api/v1/scheduled-posts?provider=tiktok" \
-H "Authorization: Bearer $POSTEADY_API_KEY"Cancel using a returned scheduledPostId:
curl -X DELETE "https://www.posteady.com/api/v1/scheduled-posts/<scheduled-post-uuid>?platform=tiktok" \
-H "Authorization: Bearer $POSTEADY_API_KEY"Successful cancellation returns { "canceled": 1 }. Once TikTok publishing has started, cancellation returns 409 POST_NOT_CANCELLABLE. Cancellation does not delete a published video.
Use MCP
The equivalent tools are list_media, create_media_upload, confirm_media_upload, publish_post, schedule_post, get_publish_status, list_scheduled_posts, and cancel_scheduled_post. Media tools use workspaceId, or your default workspace when omitted. Publishing and scheduling derive the workspace from the account; publishing status derives it from the job. An optional workspaceId must match that resource. The file bytes still require a PUT to the issued upload URL. See What you can do.