TikTok API — SKILL.md

Raw skill file that agents receive when using this skill

Download
---
name: "TikTok API"
description: "Skill for TikTok API — auto-generated from documentation"
version: "1.0.0"
author: "skynet"
category: "social"
agents: ["claude-code", "codex", "gemini"]
tags: ["tiktok-api", "social", "auto-generated"]
---

# TikTok API

---
name: TikTok API
description: Use when integrating with TikTok's API for content creation, user management, analytics, or social media automation. Essential for building TikTok apps, managing business accounts, or analyzing video performance.
metadata:
  author: skynet
  version: 1.0.0
category: social
---

# TikTok API

## Overview
TikTok API enables developers to build applications that interact with TikTok's platform, including video uploads, user authentication, analytics, and content management.

## Prerequisites
```bash
# Install required dependencies
npm install axios form-data
# or
pip install requests requests-oauthlib
```

## Authentication Setup

### OAuth 2.0 Flow
```javascript
// 1. Redirect user to authorization URL
const authUrl = `https://www.tiktok.com/auth/authorize/
?client_key=${CLIENT_KEY}
&scope=user.info.basic,video.list
&response_type=code
&redirect_uri=${REDIRECT_URI}
&state=${STATE}`;

// 2. Exchange code for access token
const tokenResponse = await fetch('https://open-api.tiktok.com/oauth/access_token/', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({
    client_key: CLIENT_KEY,
    client_secret: CLIENT_SECRET,
    code: authCode,
    grant_type: 'authorization_code'
  })
});
```

### Client Credentials (App-only)
```python
import requests

def get_client_token():
    response = requests.post('https://open-api.tiktok.com/oauth/client_token/', {
        'client_key': CLIENT_KEY,
        'client_secret': CLIENT_SECRET,
        'grant_type': 'client_credentials'
    })
    return response.json()['access_token']
```

## Core API Operations

### User Information
```javascript
// Get user profile
async function getUserProfile(accessToken) {
  const response = await fetch('https://open-api.tiktok.com/user/info/', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      fields: ['open_id', 'union_id', 'avatar_url', 'display_name']
    })
  });
  return response.json();
}
```

### Video Operations
```python
# Upload video
def upload_video(access_token, video_path, description):
    with open(video_path, 'rb') as video_file:
        files = {'video': video_file}
        data = {
            'description': description,
            'privacy_level': 'SELF_ONLY',  # or PUBLIC_TO_EVERYONE
            'disable_duet': False,
            'disable_comment': False,
            'disable_stitch': False,
            'brand_content_toggle': False
        }
        
        response = requests.post(
            'https://open-api.tiktok.com/share/video/upload/',
            headers={'Authorization': f'Bearer {access_token}'},
            files=files,
            data=data
        )
    return response.json()

# Get video list
def get_user_videos(access_token, cursor=0, max_count=20):
    payload = {
        'fields': ['id', 'title', 'video_description', 'duration', 'cover_image_url'],
        'cursor': cursor,
        'max_count': max_count
    }
    
    response = requests.post(
        'https://open-api.tiktok.com/video/list/',
        headers={'Authorization': f'Bearer {access_token}'},
        json=payload
    )
    return response.json()
```

### Analytics and Insights
```javascript
// Get video analytics
async function getVideoAnalytics(accessToken, videoId, dateRange) {
  const response = await fetch('https://open-api.tiktok.com/video/insights/', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      video_ids: [videoId],
      fields: ['views', 'likes', 'comments', 'shares', 'reach'],
      start_date: dateRange.start,
      end_date: dateRange.end
    })
  });
  return response.json();
}

// Get user analytics
async function getUserAnalytics(accessToken, dateRange) {
  const response = await fetch('https://open-api.tiktok.com/user/insights/', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      fields: ['profile_views', 'follower_count', 'video_views'],
      start_date: dateRange.start,
      end_date: dateRange.end
    })
  });
  return response.json();
}
```

## Decision Tree: Choose API Endpoint

```
Need TikTok integration?
├── User Authentication Required?
│   ├── Yes → Use OAuth 2.0 flow
│   │   ├── Need user profile? → /user/info/
│   │   ├── Upload content? → /share/video/upload/
│   │   ├── Get user videos? → /video/list/
│   │   └── Analytics needed? → /user/insights/ or /video/insights/
│   └── No → Use Client Credentials
│       ├── Public data only? → /research/ endpoints
│       └── App functionality? → /webhook/ endpoints
├── Webhook Integration?
│   ├── Real-time updates → Configure webhook URLs
│   └── Batch processing → Use polling with /video/list/
└── Testing/Development?
    ├── Use Sandbox environment
    └── Apply for production access
```

## Common Workflows

### Complete Video Upload Flow
```python
def complete_upload_workflow(access_token, video_path, metadata):
    try:
        # 1. Upload video
        upload_result = upload_video(access_token, video_path, metadata['description'])
        
        if upload_result['error']['code'] != 'ok':
            raise Exception(f"Upload failed: {upload_result['error']['message']}")
        
        share_id = upload_result['data']['share_id']
        
        # 2. Check upload status
        status_result = check_upload_status(access_token, share_id)
        
        # 3. Get video details after processing
        if status_result['data']['status'] == 'PROCESSING_DOWNLOAD':
            video_id = status_result['data']['video_id']
            return get_video_details(access_token, video_id)
            
        return status_result
        
    except Exception as e:
        print(f"Upload workflow failed: {e}")
        return None

def check_upload_status(access_token, share_id):
    response = requests.post(
        'https://open-api.tiktok.com/share/status/',
        headers={'Authorization': f'Bearer {access_token}'},
        json={'share_id': share_id}
    )
    return response.json()
```

### Batch Analytics Collection
```javascript
async function collectBatchAnalytics(accessToken, videoIds, dateRange) {
    const batchSize = 20; // API limit
    const results = [];
    
    for (let i = 0; i < videoIds.length; i += batchSize) {
        const batch = videoIds.slice(i, i + batchSize);
        
        try {
            const analytics = await getVideoAnalytics(accessToken, batch, dateRange);
            results.push(...analytics.data);
            
            // Rate limiting
            await new Promise(resolve => setTimeout(resolve, 1000));
        } catch (error) {
            console.error(`Batch ${i/batchSize + 1} failed:`, error);
        }
    }
    
    return results;
}
```

## Rate Limiting and Best Practices

### Rate Limit Handler
```python
import time
from functools import wraps

def rate_limit_handler(max_retries=3, backoff_factor=2):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_retries):
                response = func(*args, **kwargs)
                
                if response.status_code == 429:  # Rate limited
                    wait_time = backoff_factor ** attempt
                    print(f"Rate limited. Waiting {wait_time} seconds...")
                    time.sleep(wait_time)
                    continue
                    
                return response
            
            raise Exception("Max retries exceeded for rate limiting")
        return wrapper
    return decorator

@rate_limit_handler()
def api_request(url, headers, data):
    return requests.post(url, headers=headers, json=data)
```

## Troubleshooting

### Common Error Messages

**Error: `invalid_scope`**
```bash
# Check scope permissions in app dashboard
# Valid scopes: user.info.basic, user.info.profile, video.list, video.upload
```

**Error: `access_token_expired`**
```javascript
// Refresh token
async function refreshAccessToken(refreshToken) {
  const response = await fetch('https://open-api.tiktok.com/oauth/refresh_token/', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      client_key: CLIENT_KEY,
      refresh_token: refreshToken,
      grant_type: 'refresh_token'
    })
  });
  return response.json();
}
```

**Error: `video_too_large`**
```python
# Check file size (max 4GB) and duration (max 10 minutes)
import os

def validate_video(file_path):
    file_size = os.path.getsize(file_path)
    max_size = 4 * 1024 * 1024 * 1024  # 4GB
    
    if file_size > max_size:
        raise ValueError(f"Video too large: {file_size/1024/1024:.1f}MB > 4GB")
    
    return True
```

**Error: `rate_limit_exceeded`**
```bash
# Implement exponential backoff
# Default limits: 100 requests per minute per app
# User-level: 50 requests per minute per user
```

### Debug Mode
```javascript
const DEBUG = true;

function debugLog(endpoint, request, response) {
  if (DEBUG) {
    console.log(`[${endpoint}] Request:`, request);
    console.log(`[${endpoint}] Response:`, response);
  }
}
```

### Environment Configuration
```bash
# .env file
TIKTOK_CLIENT_KEY=your_client_key
TIKTOK_CLIENT_SECRET=your_client_secret
TIKTOK_REDIRECT_URI=https://yourapp.com/callback
TIKTOK_SANDBOX_MODE=true
```

curl -s https://skills.skynet.ceo/api/skills/tiktok-api/skill.md