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

usesend-js

v1.6.0

Published

- [useSend API key](https://app.usesend.com/dev-settings/api-keys) - [Verified domain](https://app.usesend.com/domains)

Readme

useSend SDK

Prerequisites

Installation

NPM

npm install usesend

Yarn

yarn add usesend

PNPM

pnpm add usesend

Bun

bun add usesend

Usage

import { UseSend } from "usesend";

const usesend = new UseSend("us_12345");

// for self-hosted installations you can pass your base URL
// const usesend = new UseSend("us_12345", "https://app.usesend.com");

usesend.emails.send({
  to: "[email protected]",
  from: "[email protected]",
  subject: "useSend email",
  html: "<p>useSend is the best open source product to send emails</p>",
  text: "useSend is the best open source product to send emails",
});

// Safely retry sends with an idempotency key
await usesend.emails.send(
  {
    to: "[email protected]",
    from: "[email protected]",
    subject: "useSend email",
    html: "<p>useSend is the best open source product to send emails</p>",
  },
  { idempotencyKey: "signup-123" },
);

// Works for bulk sends too
await usesend.emails.batch(
  [
    {
      to: "[email protected]",
      from: "[email protected]",
      subject: "Welcome",
      html: "<p>Hello A</p>",
    },
    {
      to: "[email protected]",
      from: "[email protected]",
      subject: "Welcome",
      html: "<p>Hello B</p>",
    },
  ],
  { idempotencyKey: "bulk-welcome-1" },
);
// Reusing the same key with a different payload returns HTTP 409.

Campaigns

Create and manage email campaigns:

import { UseSend } from "usesend";

const usesend = new UseSend("us_12345");

// Create a campaign
const campaign = await usesend.campaigns.create({
  name: "Welcome Series",
  from: "[email protected]",
  subject: "Welcome to our platform!",
  contactBookId: "cb_12345",
  html: "<h1>Welcome!</h1><p>Thanks for joining us.</p>",
  sendNow: false,
});

// Schedule a campaign
await usesend.campaigns.schedule(campaign.data.id, {
  scheduledAt: "2024-12-01T09:00:00Z",
  batchSize: 1000,
});

// Get campaign details
const details = await usesend.campaigns.get(campaign.data.id);

// Pause a campaign
await usesend.campaigns.pause(campaign.data.id);

// Resume a campaign
await usesend.campaigns.resume(campaign.data.id);

Webhooks

Verify webhook signatures and get typed events:

import { UseSend } from "usesend";

const usesend = new UseSend("us_12345");
const webhooks = usesend.webhooks(process.env.USESEND_WEBHOOK_SECRET!);

// In a Next.js App Route
export async function POST(request: Request) {
  try {
    const rawBody = await request.text(); // important: raw body, not parsed JSON
    const event = webhooks.constructEvent(rawBody, {
      headers: request.headers,
    });

    if (event.type === "email.delivered") {
      // event.data is strongly typed here
    }

    return new Response("ok");
  } catch (error) {
    return new Response((error as Error).message, { status: 400 });
  }
}

You can also use the Webhooks class directly:

import { Webhooks } from "usesend";

const webhooks = new Webhooks(process.env.USESEND_WEBHOOK_SECRET!);
const event = webhooks.constructEvent(rawBody, { headers: request.headers });

Need only signature verification? Use the verify method:

const isValid = webhooks.verify(rawBody, { headers: request.headers });

if (!isValid) {
  return new Response("Invalid signature", { status: 401 });
}

Express example (ensure raw body is preserved):

import express from "express";
import { Webhooks } from "usesend";

const webhooks = new Webhooks(process.env.USESEND_WEBHOOK_SECRET!);

const app = express();
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
  try {
    const event = webhooks.constructEvent(req.body, {
      headers: req.headers,
    });

    if (event.type === "email.bounced") {
      // handle bounce
    }

    res.status(200).send("ok");
  } catch (error) {
    res.status(400).send((error as Error).message);
  }
});

Headers sent by UseSend:

  • X-UseSend-Signature: v1= + HMAC-SHA256 of ${timestamp}.${rawBody}
  • X-UseSend-Timestamp: Unix epoch in milliseconds
  • X-UseSend-Event: webhook event type
  • X-UseSend-Call: unique webhook attempt id

By default, signatures are only accepted within 5 minutes of the timestamp. Override with toleranceMs if needed.