ugcinc
v4.1.32
Published
TypeScript/JavaScript client for the UGC Inc API
Maintainers
Readme
ugcinc
Official TypeScript/JavaScript client for the UGC Inc API.
Installation
npm install ugcincQuick Start
import { UGCClient } from 'ugcinc';
const client = new UGCClient({
apiKey: 'your-api-key-here'
});
// Example: Get accounts
const response = await client.accounts.getAccounts();
if (response.ok) {
console.log(response.data);
}Get Your API Key
To get your API key:
- Visit ugc.inc
- Schedule a call with our team
- You'll receive your API key after the call
Important: Keep your API key secure! Never commit it to version control or expose it in client-side code.
Documentation
For complete API documentation, including all endpoints, parameters, and examples, visit:
API Features
Accounts
- Get accounts with filters (tag, org_group, user_group, status)
- Get account status (tasks)
- Update account info (tags, groups, keywords, profiles)
- Update social profile (avatar, nickname, bio)
- Delete all posts from accounts (automated batch deletion)
- Reset warmup activity (reset or delete tasks)
Posts
- Create video posts (with specific account or auto-select)
- Create slideshow posts (with specific account or auto-select)
- Auto-selection modes:
strict: true- Picks least recently posted account, must post at exact timestrict: false- Picks account with closest available time slot
- Auto-account selection supports filtering by tag, user_group, and org_group
- Get post status (includes platform URL when complete - TikTok or Instagram)
- Get posts with filters (by accountIds, postIds, date range)
- Get post statistics
Comments
- Create comment tasks (comment on TikTok posts using your accounts)
- Get comment task status (check if comment was posted successfully)
- Returns comment URL when completed
Tasks
- Get scheduled tasks
- View task history
- Retry tasks
- Delete tasks
Statistics
- Get account statistics (latest or date range)
- Get post statistics (latest or date range)
- Get daily aggregated stats (for charts/dashboards)
- Get top accounts by metric (followers, views, likes, etc.)
- Get top posts by metric (views, likes, comments, etc.)
- Refresh statistics
Organization
- Get API keys (metadata only, excludes key values for security)
- Delete API keys
- Edit API key names
Render
- Render videos from editor configurations (supports video, audio, text, image segments)
- Render static images from editor configurations (supports text and image segments only)
- Check render job status
- Download rendered files (MP4 for videos, PNG/JPEG for images)
- Type-safe methods enforce correct segment types at compile time
Examples
Get accounts with filters:
// Get all accounts
const response = await client.accounts.getAccounts();
// Get accounts by status
const response = await client.accounts.getAccounts({
status: 'pending' // 'pending' | 'initialized' | 'setup' | 'error'
});
// Get accounts with multiple filters
const response = await client.accounts.getAccounts({
tag: 'production',
org_group: 'group1',
status: 'setup'
});
if (response.ok) {
response.data.forEach(account => {
console.log(`Account ${account.id}: ${account.username} (${account.status})`);
});
}Update account info (tags, groups, keywords, profiles, description, warmup version):
// Update multiple accounts at once
const response = await client.accounts.updateInfo({
updates: [
{
accountId: 'account-uuid-1',
tag: 'production',
org_group: 'team-a',
user_group: 'creators',
keywords: 'fitness,health,workout',
profiles: '@fitinfluencer1,@healthguru2',
description: 'health and wellness content',
warmupVersion: 'v1_smart' // 'original' or 'v1_smart'
},
{
accountId: 'account-uuid-2',
tag: 'staging',
warmupVersion: 'original'
}
]
});
if (response.ok) {
console.log(`Updated ${response.data.successful} accounts`);
if (response.data.failed > 0) {
console.log('Failed updates:', response.data.results.filter(r => !r.success));
}
}Update social profile (avatar, nickname, bio):
// Update social profiles for multiple accounts at once
// Note: Rate limits apply per account:
// - Nickname: once every 7 days
// - Avatar: once every 24 hours
// - Bio: once every 24 hours
const response = await client.accounts.updateSocial({
updates: [
{
accountId: 'account-uuid-1',
nickName: 'Cool Creator ✨',
bio: 'Content creator 🎥 | Follow for daily tips'
},
{
accountId: 'account-uuid-2',
avatarUrl: 'https://example.com/new-avatar.jpg'
}
]
});
if (response.ok) {
console.log(`Profile updates scheduled for ${response.data.successful} accounts`);
if (response.data.failed > 0) {
response.data.results.filter(r => !r.success).forEach(r => {
console.log(`Account ${r.accountId} failed: ${r.error}`);
});
}
}Reset warmup activity:
// Reset warmup (tasks will re-run)
const response = await client.accounts.resetWarmup({
accountId: 'account-uuid',
delete_activity: false // Default: resets run count so tasks re-execute
});
if (response.ok) {
console.log(response.data.message); // "Successfully reset warmup for account (tasks will re-run)"
console.log(`Tasks affected: ${response.data.tasks_affected}`);
console.log(`Action: ${response.data.action}`); // "reset"
}
// Delete all warmup activity (removes tasks completely)
const response = await client.accounts.resetWarmup({
accountId: 'account-uuid',
delete_activity: true // Deletes all warmup tasks
});
if (response.ok) {
console.log(response.data.message); // "Successfully deleted all warmup activity for account"
console.log(`Tasks affected: ${response.data.tasks_affected}`);
console.log(`Action: ${response.data.action}`); // "deleted"
}Delete all posts from accounts:
// Delete all posts from one or more accounts
// This creates a clear_posts task that automatically:
// - Finds all complete posts with a social_id
// - Deletes them one by one from the platform
// - Verifies each deletion using the platform API
// - Continues until all posts are deleted
const response = await client.accounts.deleteAllPosts({
accountIds: ['account-uuid-1', 'account-uuid-2']
});
if (response.ok) {
console.log(`Deletion scheduled for ${response.data.successful} account(s)`);
if (response.data.failed > 0) {
console.log(`Failed for ${response.data.failed} account(s)`);
response.data.errors?.forEach(err => {
console.log(` - ${err.accountId}: ${err.error}`);
});
}
}
// Monitor deletion progress using account status
const statusResponse = await client.accounts.getStatus({
accountIds: ['account-uuid-1']
});
if (statusResponse.ok) {
const clearPostsTask = statusResponse.data.find(task => task.type === 'clear_posts');
if (clearPostsTask) {
console.log(`Deletion task status: ${clearPostsTask.status}`);
}
}Get your organization's API keys:
const response = await client.org.getApiKeys(); // POST /org/api-key
if (response.ok) {
console.log(response.data); // [{ id: "...", name: "...", created_at: "..." }]
}Delete an API key:
const response = await client.org.deleteApiKey({
apiKeyId: 'api-key-uuid'
}); // POST /org/api-key/delete
if (response.ok) {
console.log('API key deleted:', response.data.id);
}Edit an API key's name:
const response = await client.org.editApiKey({
apiKeyId: 'api-key-uuid',
name: 'New Key Name'
}); // POST /org/api-key/edit
if (response.ok) {
console.log('Updated API key:', response.data); // { id, name, created_at }
}Create a video post:
// Create video post with specific account
const response = await client.posts.createVideo({
accountId: 'account-uuid',
videoUrl: 'https://example.com/video.mp4',
caption: 'Check out this video!',
});
// Auto-select with strict=true: picks least recently posted account, must post at exact time
const response = await client.posts.createVideo({
accountId: null,
videoUrl: 'https://example.com/video.mp4',
caption: 'Auto-selected account!',
postTime: '2024-01-15T10:00:00Z',
strict: true // Will error if that account can't post at exactly 10:00 AM
});
// Auto-select with strict=false: picks account with closest available time slot
const response = await client.posts.createVideo({
accountId: null,
videoUrl: 'https://example.com/video.mp4',
caption: 'Posts as soon as possible!',
postTime: '2024-01-15T10:00:00Z',
strict: false // Finds account that can post closest to 10:00 AM
});
// Auto-select with filters (tag, user_group, org_group)
const response = await client.posts.createVideo({
accountId: null,
videoUrl: 'https://example.com/video.mp4',
caption: 'Filtered auto-selection!',
tag: 'production',
org_group: 'group1',
strict: false
});Create a slideshow post:
// Create slideshow with specific account
const response = await client.posts.createSlideshow({
accountId: 'account-uuid',
imageUrls: [
'https://example.com/image1.jpg',
'https://example.com/image2.jpg',
'https://example.com/image3.jpg'
],
caption: 'Amazing slideshow!',
});
// Auto-select with strict=true: picks least recently posted account
const response = await client.posts.createSlideshow({
accountId: null,
imageUrls: ['image1.jpg', 'image2.jpg'],
caption: 'Posts at exact time or errors',
postTime: '2024-01-15T14:00:00Z',
strict: true,
user_group: 'creators'
});
// Auto-select with strict=false: picks account with closest available time
const response = await client.posts.createSlideshow({
accountId: null,
imageUrls: ['image1.jpg', 'image2.jpg'],
caption: 'Posts at nearest available time',
postTime: '2024-01-15T14:00:00Z',
strict: false
});Get posts with filters:
// Get specific posts by ID
const response = await client.posts.getPosts({
postIds: ['post-uuid-1', 'post-uuid-2']
});
// Get posts by account
const response = await client.posts.getPosts({
accountIds: ['account-uuid']
});
if (response.ok) {
response.data.forEach(post => {
console.log(`Post ${post.id}: ${post.status}`);
// For complete posts, postUrl will contain the platform URL
// TikTok: https://www.tiktok.com/@username/video/social_id
// Instagram: https://www.instagram.com/p/social_id/
if (post.postUrl) {
console.log(`Watch at: ${post.postUrl}`);
}
});
}Check post status:
const response = await client.posts.getStatus({
postId: 'post-uuid'
});
if (response.ok) {
console.log(`Status: ${response.data.status}`);
// postUrl is available when status is "complete"
// Format depends on platform (TikTok or Instagram)
if (response.data.postUrl) {
console.log(`Post URL: ${response.data.postUrl}`);
}
}Create a comment task:
// Create a comment on a TikTok post
const response = await client.comments.createComment({
accountId: 'account-uuid',
postUrl: 'https://www.tiktok.com/@user/video/1234567890',
commentText: 'Great video! 🔥'
});
if (response.ok) {
console.log('Comment task created:', response.data.taskId);
// Use taskId to check status later
}Check comment task status:
const response = await client.comments.getStatus({
taskId: 'task-uuid'
});
if (response.ok) {
console.log(`Status: ${response.data.status}`);
if (response.data.status === 'completed') {
console.log(`Comment URL: ${response.data.commentUrl}`);
} else if (response.data.status === 'failed') {
console.log(`Error: ${response.data.error}`);
} else if (response.data.status === 'pending' || response.data.status === 'running') {
console.log('Comment is still being processed...');
}
}Retry tasks:
const response = await client.tasks.retryTasks({
taskIds: ['task-uuid-1', 'task-uuid-2']
});
if (response.ok) {
console.log(`Retried ${response.data.retried} task(s)`);
}Delete tasks:
const response = await client.tasks.deleteTasks({
taskIds: ['task-uuid-1', 'task-uuid-2']
});
if (response.ok) {
console.log(`Deleted ${response.data.deleted} task(s)`);
}Render a video:
// Submit a video render job
const videoJob = await client.render.renderVideo({
editor: {
width: 1080,
height: 1920,
fps: 30,
duration: 5000,
channels: [
{
id: 'background',
segments: [
{
id: 'bg-video',
type: 'video', // All segment types allowed for video
source: 'https://example.com/video.mp4',
order: 0,
offset: { type: 'absolute', value: 0 },
xOffset: 0,
yOffset: 0,
width: 1080,
height: 1920
}
]
},
{
id: 'text-layer',
segments: [
{
id: 'title',
type: 'text',
source: '',
text: 'My Video',
order: 0,
offset: { type: 'absolute', value: 0 },
fontSize: 80,
color: '#FFFFFF'
}
]
}
]
}
});
// Poll for completion
let status;
do {
await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds
const statusResponse = await client.render.getStatus(videoJob.data.job_id);
if (statusResponse.ok) {
status = statusResponse.data;
console.log(`Status: ${status.status} - ${status.message}`);
}
} while (status?.status === 'pending' || status?.status === 'processing');
if (status?.status === 'completed') {
console.log('Video ready:', status.download_url);
}Render a static image:
// Submit an image render job (text and images only, no video/audio)
const imageJob = await client.render.renderImage({
editor: {
width: 1080,
height: 1920,
fps: 30, // Required but not used for images
duration: 1000, // Required but not used for images
channels: [
{
id: 'background',
segments: [
{
id: 'bg-image',
type: 'image', // Only image and text segments allowed
source: 'https://example.com/background.jpg',
order: 0,
offset: { type: 'absolute', value: 0 },
xOffset: 0,
yOffset: 0,
width: 1080,
height: 1920
}
]
},
{
id: 'text-layer',
segments: [
{
id: 'title',
type: 'text',
source: '',
text: 'Thumbnail Title',
order: 0,
offset: { type: 'absolute', value: 0 },
fontSize: 100,
fontWeight: 'bold',
color: '#FFFFFF',
strokeColor: '#000000',
strokeWidth: 4
}
]
}
]
},
image_format: 'png' // or 'jpeg'
});
// Check status
const statusResponse = await client.render.getStatus(imageJob.data.job_id);
if (statusResponse.ok && statusResponse.data.status === 'completed') {
console.log('Image ready:', statusResponse.data.download_url);
}Statistics:
// Get latest stats (one record per account/post)
const latestAccountStats = await client.stats.getAccountStats();
const latestPostStats = await client.stats.getPostStats();
// Get stats for a date range
const rangeStats = await client.stats.getAccountStats({
startDate: '2024-01-01',
endDate: '2024-01-31',
tag: 'fitness'
});
// Get daily aggregated stats for charts
const dailyStats = await client.stats.getDailyAggregated({
startDate: '2024-01-01',
endDate: '2024-01-31',
org_group: 'group1'
});
if (dailyStats.ok) {
dailyStats.data.forEach(day => {
console.log(`${day.date}: +${day.followers} followers, +${day.views} views, ${day.posts} posts`);
});
}
// Get top 5 accounts by followers
const topAccounts = await client.stats.getTopAccounts({
metric: 'followers',
limit: 5,
tag: 'fitness'
});
// Get top 10 posts by views
const topPosts = await client.stats.getTopPosts({
metric: 'views',
limit: 10
});
// Refresh stats (fetch live data from platforms)
// Can only be called once per hour per organization
const refreshResult = await client.stats.refresh({
org_group: 'optional-group-filter'
});
if (refreshResult.ok) {
console.log(`Refreshed ${refreshResult.data.accounts_refreshed} accounts`);
console.log(`New account stats: ${refreshResult.data.account_stats.length}`);
console.log(`New post stats: ${refreshResult.data.post_stats.length}`);
}TypeScript Support
This package is written in TypeScript and provides full type definitions:
import type { Account, Post, Task, ApiKey, ApiResponse } from 'ugcinc';License
MIT
