Dashboard

API Documentation

Upload videos to TikTok programmatically using DraftClip.

Authentication

All API requests require authentication using an API key. Include your API key in the Authorization header:

Authorization: Bearer YOUR_API_KEY

Upload Video

POST /api/upload.php

Upload a video to the connected TikTok account.

Parameters

Parameter Type Required Description
video file Yes Video file (MP4, MOV, AVI). Max 500MB
description string Yes Video caption/description (max 2200 characters) - This appears as the video caption on TikTok
privacy_level string No SELF_ONLY, MUTUAL_FOLLOW_FRIENDS, PUBLIC_TO_EVERYONE (default: SELF_ONLY)

Example Request (cURL)

curl -X POST https://drafttok.app/api/upload.php \
  -H "Authorization: Bearer ttapi_YOUR_API_KEY_HERE" \
  -F "video=@/path/to/video.mp4" \
  -F "description=My Awesome Video - Check out this amazing content!" \
  -F "privacy_level=SELF_ONLY"

Example Request (Python)

import requests

url = "https://drafttok.app/api/upload.php"
headers = {
    "Authorization": "Bearer ttapi_YOUR_API_KEY_HERE"
}
files = {
    "video": open("/path/to/video.mp4", "rb")
}
data = {
    "description": "My Awesome Video - Check out this amazing content!",
    "privacy_level": "SELF_ONLY"
}

response = requests.post(url, headers=headers, files=files, data=data)
print(response.json())

Example Request (JavaScript/Node.js)

const FormData = require('form-data');
const fs = require('fs');
const fetch = require('node-fetch');

const form = new FormData();
form.append('video', fs.createReadStream('/path/to/video.mp4'));
form.append('description', 'My Awesome Video - Check out this amazing content!');
form.append('privacy_level', 'SELF_ONLY');

fetch('https://drafttok.app/api/upload.php', {
    method: 'POST',
    headers: {
        'Authorization': 'Bearer ttapi_YOUR_API_KEY_HERE'
    },
    body: form
})
.then(res => res.json())
.then(data => console.log(data));

Success Response

{
    "success": true,
    "message": "Video uploaded successfully",
    "data": {
        "publish_id": "v0201fg0000cg...",
        "description": "My Awesome Video - Check out this amazing content!",
        "status": "PROCESSING_UPLOAD"
    }
}

Error Response

{
    "error": "Error message description"
}

Check Video Status

GET /api/video_status.php?publish_id=YOUR_PUBLISH_ID

Check the processing status of an uploaded video. Use the publish_id returned from the upload endpoint.

Parameters

Parameter Type Required Description
publish_id string Yes Publish ID from upload response

Example Request (cURL)

curl -X GET "https://drafttok.app/api/video_status.php?publish_id=v0201fg0000cg..." \
  -H "Authorization: Bearer ttapi_YOUR_API_KEY_HERE"

Example Request (Python)

import requests

url = "https://drafttok.app/api/video_status.php"
headers = {
    "Authorization": "Bearer ttapi_YOUR_API_KEY_HERE"
}
params = {
    "publish_id": "v0201fg0000cg..."
}

response = requests.get(url, headers=headers, params=params)
print(response.json())

Success Response

{
    "success": true,
    "data": {
        "publish_id": "v0201fg0000cg...",
        "status": "PUBLISH_COMPLETE",
        "status_label": "Published",
        "status_description": "Video has been successfully published",
        "is_complete": true,
        "publicaly_available_post_id": "7123456789012345678"
    },
    "message": "Video has been successfully published"
}

Possible Status Values

Status Description Is Complete?
PROCESSING_UPLOAD Video is being uploaded to TikTok servers No
PROCESSING Video is being processed by TikTok No
PUBLISH_COMPLETE Video has been successfully published Yes
FAILED Video upload/processing failed Yes
SEND_TO_USER_INBOX Video sent to inbox (draft mode) Yes

Polling Recommendations

Error Codes

Code Description
400 Bad Request - Missing or invalid parameters
401 Unauthorized - Invalid or missing API key
405 Method Not Allowed - Wrong HTTP method
429 Too Many Requests - Quota exceeded
500 Internal Server Error - Upload failed

Rate Limits

Please be respectful with API usage. Excessive requests may be rate-limited.

Complete Workflow Example

Here's a complete Python example showing how to upload a video and monitor its status:

Python Complete Example

import requests
import time

API_KEY = "ttapi_YOUR_API_KEY_HERE"
BASE_URL = "https://drafttok.app"

# Step 1: Upload video
print("Uploading video...")
upload_url = f"{BASE_URL}/api/upload.php"
headers = {"Authorization": f"Bearer {API_KEY}"}
files = {"video": open("video.mp4", "rb")}
data = {
    "title": "My Video",
    "description": "Test upload",
    "privacy_level": "SELF_ONLY"
}

response = requests.post(upload_url, headers=headers, files=files, data=data)
result = response.json()

if not result.get("success"):
    print(f"Upload failed: {result}")
    exit(1)

publish_id = result["data"]["publish_id"]
print(f"Upload successful! Publish ID: {publish_id}")

# Step 2: Poll for status
print("Checking video status...")
status_url = f"{BASE_URL}/api/video_status.php"
max_attempts = 60  # Max 5 minutes (60 * 5 seconds)
attempt = 0

while attempt < max_attempts:
    attempt += 1
    
    # Check status
    response = requests.get(
        status_url,
        headers=headers,
        params={"publish_id": publish_id}
    )
    status_result = response.json()
    
    if status_result.get("success"):
        status = status_result["data"]["status"]
        is_complete = status_result["data"]["is_complete"]
        
        print(f"[{attempt}] Status: {status}")
        
        if is_complete:
            if status == "PUBLISH_COMPLETE":
                post_id = status_result["data"].get("publicaly_available_post_id")
                print(f"✓ Video published successfully! Post ID: {post_id}")
            elif status == "FAILED":
                reason = status_result["data"].get("fail_reason", "Unknown")
                print(f"✗ Video processing failed: {reason}")
            break
    else:
        print(f"Status check error: {status_result}")
    
    # Wait before next check
    time.sleep(5)
else:
    print("Timeout: Video is still processing after 5 minutes")

print("Done!")

JavaScript/Node.js Complete Example

const FormData = require('form-data');
const fs = require('fs');
const fetch = require('node-fetch');

const API_KEY = 'ttapi_YOUR_API_KEY_HERE';
const BASE_URL = 'https://drafttok.app';

async function uploadAndMonitor() {
    // Step 1: Upload video
    console.log('Uploading video...');
    
    const form = new FormData();
    form.append('video', fs.createReadStream('video.mp4'));
    form.append('title', 'My Video');
    form.append('description', 'Test upload');
    form.append('privacy_level', 'SELF_ONLY');
    
    const uploadResponse = await fetch(`${BASE_URL}/api/upload.php`, {
        method: 'POST',
        headers: { 'Authorization': `Bearer ${API_KEY}` },
        body: form
    });
    
    const uploadResult = await uploadResponse.json();
    
    if (!uploadResult.success) {
        console.error('Upload failed:', uploadResult);
        return;
    }
    
    const publishId = uploadResult.data.publish_id;
    console.log(`Upload successful! Publish ID: ${publishId}`);
    
    // Step 2: Poll for status
    console.log('Checking video status...');
    
    let attempts = 0;
    const maxAttempts = 60;
    
    while (attempts < maxAttempts) {
        attempts++;
        
        const statusResponse = await fetch(
            `${BASE_URL}/api/video_status.php?publish_id=${publishId}`,
            { headers: { 'Authorization': `Bearer ${API_KEY}` } }
        );
        
        const statusResult = await statusResponse.json();
        
        if (statusResult.success) {
            const { status, is_complete } = statusResult.data;
            console.log(`[${attempts}] Status: ${status}`);
            
            if (is_complete) {
                if (status === 'PUBLISH_COMPLETE') {
                    console.log('✓ Video published successfully!');
                } else if (status === 'FAILED') {
                    console.log('✗ Video processing failed');
                }
                break;
            }
        }
        
        // Wait 5 seconds before next check
        await new Promise(resolve => setTimeout(resolve, 5000));
    }
    
    console.log('Done!');
}

uploadAndMonitor();

Support

For questions or issues, check your dashboard for upload logs and status information.