npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@uploadad/sdk

v0.2.0

Published

Typed TypeScript SDK for the upload.ad API

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/sdk

Quickstart

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 });