TypeScript/JavaScript client for the UGC Inc API
npm install ugcincOfficial TypeScript/JavaScript client for the UGC Inc API.
``bash`
npm install ugcinc
`typescript
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);
}
`
To get your API key:
1. Visit ugc.inc
2. Schedule a call with our team
3. 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.
For complete API documentation, including all endpoints, parameters, and examples, visit:
- Picks least recently posted account, must post at exact time
- strict: 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$3
- 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$3
- Get scheduled tasks
- View task history
- Retry tasks
- Delete tasks$3
- 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$3
- Get API keys (metadata only, excludes key values for security)
- Delete API keys
- Edit API key names$3
- 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$3
Get accounts with filters:
`typescript
// Get all accounts
const response = await client.accounts.getAccounts();// Get accounts by status
const response = await client.accounts.getAccounts({
status: 'pending' // 'pending' | 'initialized' | 'setup' | 'replacing'
});
// 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):
`typescript
// 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):
`typescript
// 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:
`typescript
// 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:
`typescript
// 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:
`typescript
const response = await client.org.getApiKeys(); // POST /org/api-keyif (response.ok) {
console.log(response.data); // [{ id: "...", name: "...", created_at: "..." }]
}
`Delete an API key:
`typescript
const response = await client.org.deleteApiKey({
apiKeyId: 'api-key-uuid'
}); // POST /org/api-key/deleteif (response.ok) {
console.log('API key deleted:', response.data.id);
}
`Edit an API key's name:
`typescript
const response = await client.org.editApiKey({
apiKeyId: 'api-key-uuid',
name: 'New Key Name'
}); // POST /org/api-key/editif (response.ok) {
console.log('Updated API key:', response.data); // { id, name, created_at }
}
`Create a video post:
`typescript
// 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:
`typescript
// 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:
`typescript
// 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:
`typescript
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:
`typescript
// 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:
`typescript
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:
`typescript
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:
`typescript
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:
`typescript
// 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:
`typescript
// 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:
`typescript
// 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:
`typescript
import type { Account, Post, Task, ApiKey, ApiResponse } from 'ugcinc';
``MIT