Skip to Content
SDK & LibrariesNode.js SDK

Node.js SDK

Install

npm install multi-upload-tool

Requires Node.js 18+. Zero dependencies.

Quick Start

import { MultiUploadClient } from 'multi-upload-tool'; const client = new MultiUploadClient({ apiToken: 'your-api-token' }); // Upload a video to one account const upload = await client.uploads.upload({ accountId: 123, filePath: '/path/to/video.mp4', title: 'My Video', description: 'Check this out!', }); console.log(upload);

Use environment variables in production:

const client = new MultiUploadClient({ apiToken: process.env.MULTI_UPLOAD_API_TOKEN, });

CommonJS usage:

const { MultiUploadClient } = require('multi-upload-tool');

Uploads

Upload a video

const upload = await client.uploads.upload({ accountId: 123, filePath: '/path/to/video.mp4', title: 'My Video', description: 'Check this out!', tags: ['marketing', 'launch'], // Converted to comma-separated string scheduledFor: '2025-03-01T14:00:00Z', // ISO 8601 for scheduling });

Pass an array of file paths. The SDK auto-detects images vs videos by extension.

const upload = await client.uploads.upload({ accountId: 456, filePath: [ '/path/to/photo1.jpg', '/path/to/photo2.jpg', '/path/to/photo3.jpg', ], title: 'Summer Collection', });

Bulk upload to multiple accounts

Pass an array of account IDs to upload the same content to all of them at once.

const accounts = await client.accounts.list({ platform: 'tiktok', status: 'active' }); const accountIds = accounts.map(a => a.id); const upload = await client.uploads.upload({ accountId: accountIds, filePath: '/path/to/video.mp4', title: 'Broadcast Video', });

Sync mode

By default, uploads are async (return immediately). Set asyncMode: false to wait for completion:

const upload = await client.uploads.upload({ accountId: 123, filePath: '/path/to/video.mp4', asyncMode: false, // Blocks until done });

YouTube-specific options

const upload = await client.uploads.upload({ accountId: 789, filePath: '/path/to/video.mp4', title: 'My YouTube Video', privacyStatus: 'unlisted', // 'private', 'unlisted', or 'public' categoryId: '22', // YouTube category thumbnailPath: '/path/to/thumb.jpg', tags: ['tech', 'tutorial'], });

Upload a Buffer

const fs = require('fs'); const buffer = fs.readFileSync('/path/to/video.mp4'); const upload = await client.uploads.upload({ accountId: 123, filePath: buffer, title: 'From Buffer', });

List and manage uploads

// List with filters and pagination const uploads = await client.uploads.list({ page: 1, limit: 50, platform: 'tiktok', status: 'completed' }); // Get details const upload = await client.uploads.get(456); // Update await client.uploads.update(456, { title: 'New Title', scheduledFor: '2025-04-01T10:00:00Z' }); // Check limits for an account const limits = await client.uploads.limits(123);

Accounts

// List all accounts const accounts = await client.accounts.list(); // Filter by platform and status const tiktok = await client.accounts.list({ platform: 'tiktok', status: 'active' }); // Get one account const account = await client.accounts.get(123); // Get LinkedIn Pages for a connected LinkedIn account const pages = await client.accounts.linkedinPages(123); // Disconnect an account await client.accounts.delete(123);

Platforms: tiktok, youtube, instagram, facebook, pinterest, linkedin, snapchat, etc.

Statuses: active, revoked, disconnected


Teams

// Get current team const team = await client.teams.getCurrent(); // List members const members = await client.teams.listMembers(); // Invite (roles: 'MEMBER' or 'ADMIN') const invite = await client.teams.invite({ email: '[email protected]', role: 'MEMBER' }); // Update role await client.teams.updateMemberRole(102, { role: 'ADMIN', isActive: true }); // Remove await client.teams.removeMember(102);

// List const links = await client.shortLinks.list(); // Create const link = await client.shortLinks.create({ url: 'https://example.com/campaign', slug: 'summer-2025', title: 'Summer Campaign', }); console.log(link.short_url); // Get const detail = await client.shortLinks.get(201); // Update await client.shortLinks.update(201, { destination: 'https://example.com/new', is_active: false }); // Delete await client.shortLinks.delete(201);

Webhooks

// List const webhooks = await client.webhooks.list(); // Create const webhook = await client.webhooks.create({ url: 'https://my-app.com/webhooks/uploads', events: ['upload.completed', 'upload.failed'], description: 'Upload notifications', }); // Test await client.webhooks.test(301); // Delete await client.webhooks.delete(301);

Events: upload.started, upload.processing, upload.completed, upload.failed, upload.scheduled

Webhook payload

{ "id": "evt_123456", "event": "upload.completed", "timestamp": "2025-01-27T12:00:00Z", "data": { "upload_id": 456, "account_id": 123, "title": "My Video", "status": "completed", "platform": "tiktok", "url": "https://www.tiktok.com/@user/video/123" } }

Verify webhook signature (Express example)

const crypto = require('crypto'); function verifyWebhook(payload, signature, secret) { const expected = crypto.createHmac('sha256', secret).update(payload).digest('hex'); return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected)); } app.post('/webhooks/uploads', (req, res) => { const signature = req.headers['x-webhook-signature']; if (!verifyWebhook(req.rawBody, signature, WEBHOOK_SECRET)) { return res.status(401).json({ error: 'Invalid signature' }); } const { event, data } = req.body; console.log(`${event}: upload ${data.upload_id}`); res.json({ ok: true }); });

White Label

// List connection links const links = await client.whitelabel.list(); // Create a connection link const link = await client.whitelabel.create({ platform: 'tiktok', // 'tiktok' or 'youtube' expiresInHours: 24, logoUrl: 'https://...', title: 'Connect Your Account', redirectUrl: 'https://my-app.com/connected', tags: ['campaign-a'], }); // Delete await client.whitelabel.delete(1);

Pinterest

// Get boards for a connected Pinterest account const boards = await client.pinterest.boards(123);

Error Handling

const { MultiUploadClient, AuthenticationError, APIError } = require('multi-upload-tool'); try { const upload = await client.uploads.upload({ ... }); } catch (err) { if (err instanceof AuthenticationError) { console.error('Invalid or expired API token'); } else if (err instanceof APIError) { console.error(`API error ${err.statusCode}: ${err.message}`); } else { throw err; } }

Exception hierarchy

ErrorWhen
MultiUploadErrorBase class for all SDK errors
AuthenticationErrorInvalid, expired, or revoked token (401)
APIErrorAPI returned an error (4xx/5xx). Has .statusCode and .response properties
ValidationErrorInput validation failed

Common status codes

CodeMeaning
400Bad request / invalid parameters
401Invalid API token
403Permission denied
404Resource not found
429Rate limited — back off and retry
500Server error — try again later

Retry on rate limit

const { APIError } = require('multi-upload-tool'); async function withRetry(fn, retries = 3) { for (let i = 0; i < retries; i++) { try { return await fn(); } catch (err) { if (err instanceof APIError && err.statusCode === 429) { await new Promise(r => setTimeout(r, 2 ** i * 1000)); } else { throw err; } } } }