@uploadad/sdk
v0.2.0
Published
Typed TypeScript SDK for the upload.ad API
Maintainers
Readme
@uploadad/sdk
Typed TypeScript SDK for the upload.ad API: creative library, review and approvals, ad launching, comments, and performance on Meta and TikTok. Zero runtime dependencies, ESM, works on Node 20+ (uses global fetch and FormData), Bun, Deno, and edge runtimes.
Install
npm install @uploadad/sdkQuickstart
import { readFile } from 'node:fs/promises';
import { UploadAd } from '@uploadad/sdk';
// Reads UPLOADAD_API_KEY from the environment when apiKey is omitted.
const client = new UploadAd({ apiKey: 'ua_...' });
// Upload a file (platform picks the ad account: meta default, or tiktok),
// then wait for the job to finish.
const [job] = await client.uploads.create(
[{ name: 'banner.png', data: await readFile('banner.png'), type: 'image/png' }],
{ platform: 'meta' }
);
const upload = await client.uploads.waitFor(job.id, { intervalMs: 3000, timeoutMs: 120_000 });
if (upload.status === 'completed') {
console.log('Facebook image hash:', upload.facebook.imageHash);
} else {
console.error('Upload failed:', upload.error);
}
// Attach ad copy to a creative.
const { creatives } = await client.creatives.list({ limit: 1 });
const copyId = await client.copy.create(creatives[0].id, {
headline: 'Summer sale',
primaryText: 'Up to 50% off, this week only.'
});Completed uploads carry both facebook and tiktok platform references; upload.platform ('meta' | 'tiktok') says which one the asset was uploaded to.
Reliability
Rate limits (429, honoring retry-after), transient server errors, and network failures are retried with exponential backoff. Mutating calls generate an Idempotency-Key automatically (or take one via { idempotencyKey }), so retries replay the original result instead of running twice. Every request times out (60s default, 10 minutes for uploads) and every method accepts { signal, timeoutMs }.
Pagination
List methods return { ..., nextCursor }; the iterate helpers page automatically:
for await (const creative of client.creatives.iterate()) {
console.log(creative.id);
}Tools
The same catalog of tools the assistant and MCP server use is callable directly. destructive marks tools that spend money or make irreversible changes; readOnly marks pure reads.
const tools = await client.tools.list();
const result = await client.tools.call('upload_creatives', {
urls: ['https://example.com/banner.png']
});Errors from the API throw UploadAdError with the HTTP status, the stable machine code (for example rate_limited or not_found), and the API's message. Timeouts throw UploadAdTimeoutError.
Webhook verification
Verify the uploadad-signature header against the raw request body exactly as received:
import { verifyWebhookSignature } from '@uploadad/sdk';
const rawBody = await request.text();
const ok = await verifyWebhookSignature(
rawBody,
request.headers.get('uploadad-signature') ?? '',
process.env.UPLOADAD_WEBHOOK_SECRET!
);
if (!ok) return new Response('invalid signature', { status: 401 });