TikTok Data API
| Environment | API / Frontend URL |
|---|---|
| Production | 'https://tiktok-lead-gen.cloud.zoomgtm.com' |
| Staging | 'https://tiktok-lead-gen-staging.cloud.zoomgtm.com' |
Production is ready and should always be used.
Authentication
Two auth methods are supported. All authenticated endpoints accept either.
OfficeX Headers (recommended)
''' x-officex-install-id: x-officex-install-secret: '''
Credentials come from installing the app on OfficeX. AI agents receive 'api_key' and 'install_id' in 'agent_context' automatically on install.
API Key
''' x-api-key: '''
Obtained via '/auth/register' or '/auth/login'.
Routes
| Method | Path | Auth | Description |
|---|---|---|---|
| 'GET' | '/' | None | Web dashboard |
| 'GET' | '/docs' | None | Raw SKILL.md as text |
| 'POST' | '/auth/register' | None | Register with email + password |
| 'POST' | '/auth/login' | None | Login with email + password |
| 'POST' | '/auth/officex-login' | None | Auto-login via OfficeX creds |
| 'POST' | '/webhooks/officex' | OfficeX platform | Lifecycle webhooks (INSTALL, UNINSTALL, RATE_LIMIT_CHANGE) |
| 'POST' | '/api/v1/jobs' | Required | Create a job |
| 'GET' | '/api/v1/jobs' | Required | List your jobs |
| 'GET' | '/api/v1/jobs/{job_id}' | None | Get job status |
| 'PATCH' | '/api/v1/jobs/{job_id}' | None | Update job status (pause/cancel) |
| 'GET' | '/api/v1/jobs/{job_id}/results' | None | Get paginated results |
| 'GET' | '/api/v1/jobs/{job_id}/results/{task_index}' | None | Get single result |
| 'GET' | '/api/v1/jobs/{job_id}/result-rows' | None | Get all bookmarks/notes for a job |
| 'PATCH' | '/api/v1/jobs/{job_id}/results/{task_index}/items/{item_index}' | None | Update item bookmark/notes |
Auth Endpoints
POST /auth/register
'''json { "email": "user@example.com", "password": "min6chars" } '''
Returns '201': '{ "apikey": "rapi...", "installid": "email...", "email": "..." }'
POST /auth/login
'''json { "email": "user@example.com", "password": "..." } '''
Returns '200': '{ "apikey": "rapi...", "install_id": "...", "email": "..." }'
POST /auth/officex-login
'''json { "officex_customer_id": "", "install_id": "", "install_secret": "" } '''
Returns '200' (existing user) or '201' (new user): '{ "apikey": "rapi...", "install_id": "...", "install_secret": "..." }'
POST /api/v1/jobs
Create a new async job. Each job runs one TikTok endpoint against one or many parameter sets.
Request
'''json { "endpoint": "search-video", "params": { "keyword": "fitness tips", "region": "US" }, "prompt_filter": "Looking for fitness influencers with high engagement", "max_records": 100 } '''
| Field | Type | Required | Description |
|---|---|---|---|
| 'endpoint' | string | Yes | One of the 22 TikTok endpoints (see below) |
| 'params' | object or array | Yes | Parameters for the endpoint. Array for bulk jobs. |
| 'prompt_filter' | string | No | AI filter prompt — enables Gemini scoring (0-100) on each result |
| 'max_records' | number | No | Max items to fetch for paginated endpoints (1-1000, default 100). Auto-paginates. |
Bulk jobs
Pass 'params' as an array to create multiple tasks in one job:
'''json { "endpoint": "search-video", "params": [ { "keyword": "fitness tips", "region": "US" }, { "keyword": "cooking recipes", "region": "US" }, { "keyword": "tech reviews", "region": "JP" } ] } '''
Response '202'
'''json { "job_id": "a1b2c3d4-...", "status": "queued", "total_tasks": 3, "estimated_total_tasks": 12, "credits_reserved": 0.48, "max_records": 100, "poll_url": "/api/v1/jobs/a1b2c3d4-..." } '''
'estimated_total_tasks' accounts for auto-pagination (each page of ~25 results = 1 task).
Errors
| Status | Code | Meaning |
|---|---|---|
| '400' | — | Missing/invalid endpoint or params |
| '401' | — | Missing auth headers |
| '402' | 'INSUFFICIENT_FUNDS' | Not enough credits |
| '403' | 'INSTALL_EXPIRED' | OfficeX installation expired |
| '429' | 'RATE_LIMITED' | Usage limit exceeded |
Endpoints (22)
Profile (4)
| Endpoint | Description | Required | Optional |
|---|---|---|---|
| 'user-uniqueid' | Look up user by username | 'uniqueid' | — |
| 'user-profile' | Get profile by uid or sec_uid | 'uid' or 'sec_uid' (at least one) | 'uid', 'sec_uid' |
| 'user-following' | List accounts user follows | 'uid', 'sec_uid' | 'cursor' |
| 'user-follower' | List user's followers | 'uid', 'sec_uid' | 'cursor' |
Video (3)
| Endpoint | Description | Required | Optional |
|---|---|---|---|
| 'video-detail' | Get video details | 'video_id' | — |
| 'user-video' | List user's videos | 'uid', 'sec_uid' | 'cursor' |
| 'user-favorite-video' | List user's favorites | 'uid', 'sec_uid' | 'cursor' |
Search (8)
| Endpoint | Description | Required | Optional |
|---|---|---|---|
| 'search-trending' | Trending searches by region | 'region' | — |
| 'search-video' | Search videos | 'keyword' | 'cursor', 'region' |
| 'search-user' | Search users | 'keyword' | 'cursor', 'region' |
| 'search-music' | Search music/sounds | 'keyword' | 'cursor', 'region' |
| 'search-hashtag' | Search hashtags | 'keyword' | 'cursor', 'region' |
| 'search-live' | Search live streams | 'keyword' | 'cursor', 'region' |
| 'search-photo' | Search photo posts | 'keyword' | 'cursor', 'region' |
| 'search-place' | Search places | 'keyword' | 'cursor', 'region' |
Comment (2)
| Endpoint | Description | Required | Optional |
|---|---|---|---|
| 'video-comment-list' | Get video comments | 'video_id' | 'cursor' |
| 'video-comment-reply' | Get comment replies | 'video_id', 'comment_id' | 'cursor' |
Hashtag (2)
| Endpoint | Description | Required | Optional |
|---|---|---|---|
| 'hashtag-detail' | Get hashtag details | 'hashtag_id' or 'hashtag_name' (at least one) | 'hashtag_id', 'hashtag_name' |
| 'hashtag-video' | Get videos for a hashtag | 'hashtag_id' | 'cursor' |
Creator Trending (3)
| Endpoint | Description | Required | Optional |
|---|---|---|---|
| 'trending-creator' | Trending creators by region | 'region' | — |
| 'trending-topic' | Trending topics by region | 'region' | — |
| 'trending-video' | Trending videos by region | 'region' | — |
Region codes: 'US', 'GB', 'JP', 'BR', 'DE', 'FR', 'ID', 'IN', 'KR', 'MX', 'RU', 'TH', 'VN', etc.
GET /api/v1/jobs
List your jobs, paginated.
| Param | Default | Description |
|---|---|---|
| 'page' | '1' | Page number |
| 'limit' | '20' | Jobs per page |
Response '200'
'''json { "jobs": [ { "job_id": "a1b2c3d4-...", "endpoint": "search-video", "status": "completed", "total_tasks": 3, "completed_tasks": 3, "failed_tasks": 0, "created_at": "2025-01-30T22:00:00.000Z", "prompt_filter": null, "max_records": 100, "credits_per_task": 0.04, "reservation_id": "...", "view_url": "https://dgamh7nm.rpcld.co/dashboard/#/nc/view/...", "nocodb_results_view_url": "https://..." } ], "next_page": null, "nocodb_jobs_view_url": "https://..." } '''
GET /api/v1/jobs/{job_id}
Poll job status.
Response '200'
'''json { "job_id": "a1b2c3d4-...", "vendor": "tokinsight", "endpoint": "search-video", "status": "processing", "total_tasks": 3, "completed_tasks": 1, "failed_tasks": 0, "created_at": "2025-01-30T22:00:00.000Z", "updated_at": "2025-01-30T22:00:05.000Z", "params": { "keyword": "fitness tips", "region": "US" }, "prompt_filter": "Looking for fitness influencers", "max_records": 100, "credits_per_task": 0.04, "credits_charged": 0.04, "latest_cursor": "30", "reservation_id": "...", "view_url": "https://dgamh7nm.rpcld.co/dashboard/#/nc/view/...", "nocodb_results_view_url": "https://dgamh7nm.rpcld.co/dashboard/#/nc/view/...", "warning": null } '''
- 'view_url' — Link to a NocoDB spreadsheet view of this job's results. Show this to the user so they can browse, filter, and sort results in a GUI. Same value as 'nocodb_results_view_url'.
- A 'warning' appears if a 'processing' job has had no progress for 5+ minutes.
Job statuses
| Status | Meaning |
|---|---|
| 'queued' | Job accepted, tasks queued |
| 'processing' | Tasks being executed |
| 'paused' | Job paused by user |
| 'completed' | All tasks finished |
| 'failed' | Job failed |
| 'cancelled' | Job cancelled |
PATCH /api/v1/jobs/{job_id}
Update a job's status.
'''json { "status": "paused" } '''
Valid transitions
| From | Allowed targets |
|---|---|
| 'queued' | 'cancelled' |
| 'processing' | 'paused', 'cancelled' |
| 'paused' | 'processing', 'cancelled' |
| 'completed' | — (terminal) |
| 'failed' | — (terminal) |
| 'cancelled' | — (terminal) |
Response '200'
'''json { "job_id": "...", "status": "paused", "updated_at": "..." } '''
GET /api/v1/jobs/{job_id}/results
Get all results for a job, paginated.
| Param | Default | Description |
|---|---|---|
| 'page' | '1' | Page number |
| 'limit' | '50' | Results per page |
Response '200'
'''json { "job_id": "a1b2c3d4-...", "endpoint": "search-video", "results": [ { "task_index": 0, "status": "completed", "result_url": "https://s3.amazonaws.com/...", "item_urls": ["https://s3.amazonaws.com/.../item-0.json", "..."], "items": [ { "desc": "Best workout routine for beginners", "author_nickname": "FitCoach", "author_unique_id": "fitcoach123", "play_count": 150000, "digg_count": 8500, "comment_count": 320, "tiktok_url": "https://www.tiktok.com/@fitcoach123/video/123456" } ], "error": null, "match_score": 85, "ai_notes": "Fitness creator with 500K followers discussing workout tips", "credits_charged": 0.05 } ], "next_page": null } '''
- 'items' — Parsed fields for each individual record extracted from the API response. One entry per TikTok result (video, user, comment, etc). Fields vary by endpoint type:
- Profile endpoints: 'nickname', 'unique_id', 'follower_count', 'following_count', 'tiktok_url', 'avatar_thumb', 'avatar_url', ...
- Video endpoints: 'desc', 'author_nickname', 'play_count', 'digg_count', 'comment_count', 'tiktok_url', 'cover_url', 'author_avatar', 'music_title', 'music_cover', 'duration', ...
- Comment endpoints: 'text', 'comment_author', 'digg_count', 'reply_comment_total', 'author_avatar', ...
- Search endpoints: 'title', 'desc', 'nickname', 'follower_count', 'view_count', 'avatar_url', ...
- 'result_url' — S3 URL to the full raw API response JSON
- 'item_urls' — S3 URLs to individual extracted items (for multi-result endpoints)
- 'match_score' (0-100) and 'ai_notes' — present only when 'prompt_filter' was set
- 'next_page' — next page number, or 'null' if no more results
GET /api/v1/jobs/{job_id}/results/{task_index}
Get a single task result by 0-based index.
Response '200'
'''json { "task_index": 0, "status": "completed", "result_url": "https://...", "item_urls": ["https://..."], "items": [{ "desc": "...", "author_nickname": "...", "play_count": 150000, "tiktok_url": "..." }], "error": null, "match_score": 85, "ai_notes": "...", "credits_charged": 0.05 } '''
Returns '404' if the task has no result yet.
GET /api/v1/jobs/{job_id}/result-rows
Get all user bookmarks and notes for a job. Returns a list of ResultRow objects from the separate result-rows DynamoDB table.
Response '200'
'''json { "job_id": "abc-123", "result_rows": [ { "job_id": "abc-123", "sk": "0#3", "task_index": 0, "item_index": 3, "user_bookmarked": true, "user_notes": "Follow up", "updated_at": "2026-02-01T12:00:00Z", "ttl": 1743523200 } ] } '''
PATCH /api/v1/jobs/{job_id}/results/{task_index}/items/{item_index}
Update bookmark/notes on an individual result item. Syncs to NocoDB automatically.
Request
'''json { "user_bookmarked": true, "user_notes": "Great engagement, follow up" } '''
| Field | Type | Required | Description |
|---|---|---|---|
| 'user_bookmarked' | boolean | No | Bookmark this item (at least one field needed) |
| 'user_notes' | string | No | Free-text notes for this item |
Response '200'
Returns the ResultRow object:
'''json { "job_id": "abc-123", "sk": "0#3", "task_index": 0, "item_index": 3, "user_bookmarked": true, "user_notes": "Great engagement, follow up", "updated_at": "2026-02-01T12:00:00Z", "ttl": 1743523200 } '''
Billing
| Operation | Credits | USD equivalent |
|---|---|---|
| Task without AI filter | 0.04 | $0.0004 |
| Task with AI filter | 0.05 | $0.0005 |
Credits are reserved upfront when the job is created. Failed tasks are not billed. Unused reserved credits are refunded when the job completes.
For paginated endpoints, each page of ~25 results counts as one task. A 'max_records: 100' job with 1 param set reserves 'ceil(100/25) * 0.04 = 0.16' credits.
Data Retention
Results are stored in S3 for 90 days and automatically expire.
Typical Flow
AI Agents: Always share the 'view_url' with the user. It links to an interactive spreadsheet where they can browse, filter, and sort all results — much easier than reading JSON.
'''
- POST /api/v1/jobs → get job_id + poll_url
- GET /api/v1/jobs/{job_id} → poll until status is "completed"
- The response includes 'view_url' — always share this link with the user so they can view results in a spreadsheet GUI
- GET /api/v1/jobs/{job_id}/results → fetch all results (items array has parsed fields per record) '''
Examples
Search TikTok videos
'''bash
curl -X POST https://46n9u415sc.execute-api.us-east-1.amazonaws.com/api/v1/jobs
-H "Content-Type: application/json"
-H "x-officex-install-id: $INSTALL_ID"
-H "x-officex-install-secret: $INSTALL_SECRET"
-d '{"endpoint":"search-video","params":{"keyword":"fitness tips","region":"US"},"max_records":50}'
'''
Look up a TikTok user by username
'''bash
curl -X POST https://46n9u415sc.execute-api.us-east-1.amazonaws.com/api/v1/jobs
-H "Content-Type: application/json"
-H "x-officex-install-id: $INSTALL_ID"
-H "x-officex-install-secret: $INSTALL_SECRET"
-d '{"endpoint":"user-uniqueid","params":{"uniqueid":"charlidamelio"}}'
'''
Bulk search with AI filter
'''bash
curl -X POST https://46n9u415sc.execute-api.us-east-1.amazonaws.com/api/v1/jobs
-H "Content-Type: application/json"
-H "x-officex-install-id: $INSTALL_ID"
-H "x-officex-install-secret: $INSTALL_SECRET"
-d '{
"endpoint": "search-user",
"params": [
{"keyword": "fitness coach", "region": "US"},
{"keyword": "personal trainer", "region": "US"}
],
"prompt_filter": "Looking for fitness professionals with 10K+ followers who post regularly",
"max_records": 200
}'
'''
Poll and fetch results
'''bash
Poll status
curl https://46n9u415sc.execute-api.us-east-1.amazonaws.com/api/v1/jobs/JOB_ID
-H "x-officex-install-id: $INSTALL_ID"
-H "x-officex-install-secret: $INSTALL_SECRET"
Get results
curl https://46n9u415sc.execute-api.us-east-1.amazonaws.com/api/v1/jobs/JOB_ID/results
-H "x-officex-install-id: $INSTALL_ID"
-H "x-officex-install-secret: $INSTALL_SECRET"
Pause a running job
curl -X PATCH https://46n9u415sc.execute-api.us-east-1.amazonaws.com/api/v1/jobs/JOB_ID
-H "Content-Type: application/json"
-H "x-officex-install-id: $INSTALL_ID"
-H "x-officex-install-secret: $INSTALL_SECRET"
-d '{"status":"paused"}'
Cancel a job
curl -X PATCH https://46n9u415sc.execute-api.us-east-1.amazonaws.com/api/v1/jobs/JOB_ID
-H "Content-Type: application/json"
-H "x-officex-install-id: $INSTALL_ID"
-H "x-officex-install-secret: $INSTALL_SECRET"
-d '{"status":"cancelled"}'
'''
Frontend (web dashboard)
Visit 'GET /' for the web UI. Supports OfficeX autologin via URL params:
Common workflows
Find influencers in a niche:
- 'search-user' with keyword + AI filter for follower count/engagement
- 'user-profile' on top matches to get full stats
- 'user-video' to analyze recent content
Monitor trending content:
- 'trending-video' or 'trending-topic' with region
- 'video-detail' on interesting videos
- 'video-comment-list' to gauge audience reaction
Hashtag research:
- 'search-hashtag' with keyword
- 'hashtag-detail' for view counts
- 'hashtag-video' to see top content