How to Schedule TikTok Posts via API: Complete Developer Guide
Automating TikTok posts shouldn't require business verification or complex OAuth flows. (Learn why in our TikTok API vs scraping guide.) If you're building an AI agent, content automation pipeline, or agency dashboard, you need a TikTok post scheduling API that works with simple HTTP requests and static keys.
This guide walks you through programmatic TikTok scheduling using the Postqued REST API. By the end, you'll have working code to upload videos, schedule posts, and check publishing status — all without touching a browser.
What You'll Build
- Upload videos and photos to Postqued via API
- Schedule TikTok posts for future dates
- Check publishing status and handle webhooks
- Build recurring content schedules
Prerequisites
Before you start scheduling TikTok posts via API, you'll need:
- Postqued account — Sign up for free
- Connected TikTok account — Link your TikTok profile in the dashboard
- API key — Generate from your account settings
- Video or image file — The content you want to schedule
Step 1: Get Your API Key
Navigate to your Postqued dashboard and create an API key. Keys start with pq_ and should be treated as secrets.
export POSTQUED_API_KEY="pq_your_api_key_here"
All API requests require this key in the Authorization header:
Authorization: Bearer pq_your_api_key_here
Step 2: Upload Your Content
The upload process has three steps: request a presigned URL, upload the file, and confirm completion.
Request Upload URL
curl -X POST https://api.postqued.com/v1/content/upload \
-H "Authorization: Bearer $POSTQUED_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "my-video.mp4",
"contentType": "video/mp4",
"fileSize": 52428800
}'
Response:
{
"contentId": "550e8400-e29b-41d4-a716-446655440000",
"upload": {
"url": "https://storage.postqued.com/presigned-url...",
"method": "PUT",
"headers": {
"Content-Type": "video/mp4"
}
}
}
Upload File
Use the presigned URL to upload your content:
curl -X PUT "https://storage.postqued.com/presigned-url..." \
-H "Content-Type: video/mp4" \
--data-binary @my-video.mp4
Confirm Upload
After the upload completes, confirm it:
curl -X POST https://api.postqued.com/v1/content/upload/complete \
-H "Authorization: Bearer $POSTQUED_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contentId": "550e8400-e29b-41d4-a716-446655440000",
"key": "content/user-id/content-id.mp4",
"filename": "my-video.mp4",
"contentType": "video/mp4",
"size": 52428800,
"width": 1080,
"height": 1920,
"durationMs": 45000
}'
Save the contentId — you'll need it to schedule the post.
Step 3: Schedule the TikTok Post
Now comes the actual TikTok post scheduling API call. You'll need:
- Your
contentIdfrom the upload step - The
accountIdof your connected TikTok account - A unique idempotency key (prevents duplicate posts)
Get Your TikTok Account ID
curl https://api.postqued.com/v1/platform-accounts?platform=tiktok \
-H "Authorization: Bearer $POSTQUED_API_KEY"
Response:
{
"accounts": [{
"id": "660e8400-e29b-41d4-a716-446655440001",
"platform": "tiktok",
"username": "@yourusername",
"displayName": "Your Name"
}]
}
Schedule the Post
This is where programmatic TikTok scheduling happens. Set dispatchAt to a future UTC timestamp:
curl -X POST https://api.postqued.com/v1/content/publish \
-H "Authorization: Bearer $POSTQUED_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"contentIds": ["550e8400-e29b-41d4-a716-446655440000"],
"targets": [{
"platform": "tiktok",
"accountId": "660e8400-e29b-41d4-a716-446655440001",
"intent": "draft",
"caption": "Scheduled via API! #automation #tiktokapi",
"dispatchAt": "2026-03-15T14:00:00Z",
"options": {
"privacyLevel": "PUBLIC_TO_EVERYONE",
"disableDuet": false,
"disableStitch": false,
"disableComment": false,
"videoCoverTimestampMs": 1000
}
}]
}'
Response:
{
"id": "770e8400-e29b-41d4-a716-446655440002",
"status": "pending",
"targets": [{
"id": "880e8400-e29b-41d4-a716-446655440003",
"platform": "tiktok",
"status": "scheduled"
}]
}
The post is now scheduled. Save the publish request id — that's how you'll track status.
Code Examples
JavaScript (Node.js)
const fs = require('fs');
const API_KEY = process.env.POSTQUED_API_KEY;
const BASE_URL = 'https://api.postqued.com';
async function uploadAndSchedule(videoPath, caption, scheduleTime) {
// Step 1: Get upload URL
const stats = fs.statSync(videoPath);
const uploadRes = await fetch(`${BASE_URL}/v1/content/upload`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
filename: 'video.mp4',
contentType: 'video/mp4',
fileSize: stats.size
})
});
const { contentId, upload } = await uploadRes.json();
// Step 2: Upload file
const fileBuffer = fs.readFileSync(videoPath);
await fetch(upload.url, {
method: upload.method,
headers: upload.headers,
body: fileBuffer
});
// Step 3: Confirm upload
await fetch(`${BASE_URL}/v1/content/upload/complete`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
contentId,
key: `content/user/${contentId}.mp4`,
filename: 'video.mp4',
contentType: 'video/mp4',
size: stats.size,
width: 1080,
height: 1920
})
});
// Step 4: Schedule post
const idempotencyKey = crypto.randomUUID();
const scheduleRes = await fetch(`${BASE_URL}/v1/content/publish`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': idempotencyKey
},
body: JSON.stringify({
contentIds: [contentId],
targets: [{
platform: 'tiktok',
accountId: 'YOUR_ACCOUNT_ID',
intent: 'draft',
caption,
dispatchAt: scheduleTime.toISOString(),
options: {
privacyLevel: 'PUBLIC_TO_EVERYONE',
videoCoverTimestampMs: 1000
}
}]
})
});
return await scheduleRes.json();
}
// Usage
uploadAndSchedule(
'./video.mp4',
'Posted via JavaScript API!',
new Date('2026-03-15T14:00:00Z')
).then(console.log);
Python
import os
import uuid
import requests
from datetime import datetime
API_KEY = os.environ['POSTQUED_API_KEY']
BASE_URL = 'https://api.postqued.com'
def upload_and_schedule(video_path, caption, schedule_time):
headers = {
'Authorization': f'Bearer {API_KEY}',
'Content-Type': 'application/json'
}
# Step 1: Get upload URL
file_size = os.path.getsize(video_path)
upload_res = requests.post(
f'{BASE_URL}/v1/content/upload',
headers=headers,
json={
'filename': 'video.mp4',
'contentType': 'video/mp4',
'fileSize': file_size
}
)
upload_data = upload_res.json()
content_id = upload_data['contentId']
# Step 2: Upload file
with open(video_path, 'rb') as f:
requests.put(
upload_data['upload']['url'],
headers=upload_data['upload']['headers'],
data=f
)
# Step 3: Confirm upload
requests.post(
f'{BASE_URL}/v1/content/upload/complete',
headers=headers,
json={
'contentId': content_id,
'key': f'content/user/{content_id}.mp4',
'filename': 'video.mp4',
'contentType': 'video/mp4',
'size': file_size,
'width': 1080,
'height': 1920
}
)
# Step 4: Schedule post
idempotency_key = str(uuid.uuid4())
schedule_headers = headers.copy()
schedule_headers['Idempotency-Key'] = idempotency_key
schedule_res = requests.post(
f'{BASE_URL}/v1/content/publish',
headers=schedule_headers,
json={
'contentIds': [content_id],
'targets': [{
'platform': 'tiktok',
'accountId': 'YOUR_ACCOUNT_ID',
'intent': 'draft',
'caption': caption,
'dispatchAt': schedule_time.isoformat() + 'Z',
'options': {
'privacyLevel': 'PUBLIC_TO_EVERYONE',
'videoCoverTimestampMs': 1000
}
}]
}
)
return schedule_res.json()
# Usage
result = upload_and_schedule(
'./video.mp4',
'Posted via Python API!',
datetime(2026, 3, 15, 14, 0)
)
print(result)
cURL (Complete Flow)
#!/bin/bash
API_KEY="$POSTQUED_API_KEY"
ACCOUNT_ID="YOUR_ACCOUNT_ID"
VIDEO_FILE="./video.mp4"
FILE_SIZE=$(stat -f%z "$VIDEO_FILE" 2>/dev/null || stat -c%s "$VIDEO_FILE")
# Step 1: Get upload URL
UPLOAD_RESPONSE=$(curl -s -X POST https://api.postqued.com/v1/content/upload \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"filename\": \"video.mp4\",
\"contentType\": \"video/mp4\",
\"fileSize\": $FILE_SIZE
}")
CONTENT_ID=$(echo $UPLOAD_RESPONSE | jq -r '.contentId')
UPLOAD_URL=$(echo $UPLOAD_RESPONSE | jq -r '.upload.url')
echo "Content ID: $CONTENT_ID"
# Step 2: Upload file
curl -X PUT "$UPLOAD_URL" \
-H "Content-Type: video/mp4" \
--data-binary @$VIDEO_FILE
echo "File uploaded"
# Step 3: Confirm upload
curl -X POST https://api.postqued.com/v1/content/upload/complete \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"contentId\": \"$CONTENT_ID\",
\"key\": \"content/user/$CONTENT_ID.mp4\",
\"filename\": \"video.mp4\",
\"contentType\": \"video/mp4\",
\"size\": $FILE_SIZE,
\"width\": 1080,
\"height\": 1920
}"
echo "Upload confirmed"
# Step 4: Schedule post
IDEMPOTENCY_KEY=$(uuidgen)
SCHEDULE_RESPONSE=$(curl -s -X POST https://api.postqued.com/v1/content/publish \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
-d "{
\"contentIds\": [\"$CONTENT_ID\"],
\"targets\": [{
\"platform\": \"tiktok\",
\"accountId\": \"$ACCOUNT_ID\",
\"intent\": \"draft\",
\"caption\": \"Scheduled via cURL! #api\",
\"dispatchAt\": \"2026-03-15T14:00:00Z\",
\"options\": {
\"privacyLevel\": \"PUBLIC_TO_EVERYONE\",
\"videoCoverTimestampMs\": 1000
}
}]
}")
echo "Scheduled: $SCHEDULE_RESPONSE"
Step 4: Check Status and Webhooks
After scheduling, you can poll for status or use webhooks for real-time updates.
Poll for Status
curl https://api.postqued.com/v1/content/publish/PUBLISH_REQUEST_ID \
-H "Authorization: Bearer $POSTQUED_API_KEY"
Response:
{
"id": "770e8400-e29b-41d4-a716-446655440002",
"status": "processing",
"targets": [{
"id": "880e8400-e29b-41d4-a716-446655440003",
"platform": "tiktok",
"status": "sent"
}]
}
Status flow: queued → processing → sent (success) or failed
Webhook Integration
Configure webhooks in your dashboard to receive real-time updates:
// Webhook payload example
{
"event": "publish.status_changed",
"data": {
"publishId": "770e8400-e29b-41d4-a716-446655440002",
"targetId": "880e8400-e29b-41d4-a716-446655440003",
"status": "sent",
"platform": "tiktok",
"timestamp": "2026-03-15T14:00:05Z"
}
}
Common Errors & Troubleshooting
| Error | Cause | Solution |
|---|---|---|
MISSING_IDEMPOTENCY_KEY | No idempotency header | Add Idempotency-Key header to publish request |
IDEMPOTENCY_CONFLICT | Duplicate idempotency key | Generate a new UUID for each request |
SUBSCRIPTION_REQUIRED | Free plan limitation | Upgrade to a paid plan |
ACCOUNT_NOT_CONNECTED | TikTok not linked | Connect your TikTok account in dashboard |
| Upload fails | File too large | Max video size is 500MB |
| Rate limited | Too many requests | Respect 10 req/min for publishing |
Advanced: Recurring Schedules
For TikTok REST API posting at regular intervals, combine the API with a cron job:
// Schedule weekly posts
cron.schedule('0 9 * * 1', async () => {
const nextWeek = new Date();
nextWeek.setDate(nextWeek.getDate() + 7);
await uploadAndSchedule(
'./weekly-content.mp4',
'Weekly update!',
nextWeek
);
});
Next Steps
You've learned how to schedule TikTok posts via API using the Postqued REST API. For a complete Python implementation, see How to Post to TikTok with Python, and check the best TikTok scheduler with API for tool comparisons. Here's what to do next:
- Build an AI agent — Use our MCP skill to let Claude post directly to TikTok
- Create bulk uploads — Schedule entire content calendars programmatically
- Add photo carousels — Upload 2-35 images for carousel posts
- Set up webhooks — Get real-time notifications without polling
Ready to automate your TikTok posting? Get your API key and make your first API call in under five minutes.
Keywords covered: schedule tiktok posts api, tiktok post scheduling api, programmatic tiktok scheduling, tiktok rest api posting
Last updated: March 2026