Get started

Node.js SDK

Send messages from your JavaScript or TypeScript backend.

Use it on your server with Node.js 22+, ESM or CommonJS.

Get started

Install

npm install @appkeeprhq/node

Follow Quickstart to create a signups channel and set APPKEEPR_API_TOKEN.

Send a message

send-signup.mjs
import { Appkeepr } from "@appkeeprhq/node";

const token = process.env.APPKEEPR_API_TOKEN;
if (!token) throw new Error("Set APPKEEPR_API_TOKEN.");
const appkeepr = new Appkeepr({ token });

const result = await appkeepr.messages.send(
  {
    channel: "signups",
    body: "Ada created an account.",
    title: "New signup",
    icon: "👋",
  },
  { idempotencyKey: "signup-1042" },
);
console.log(result.messageId, result.outcome);

send returns {messageId, outcome}. See the API reference for all message fields.

Optional project

Create a checkout project in Projects, then use it as the default:

const checkout = new Appkeepr({ token, project: "checkout" });

await checkout.messages.send({ channel: "signups", body: "Ada signed up." });
await checkout.messages.send({
  channel: "signups",
  body: "A signup was recorded.",
  project: null,
});

Set project per message to override the default, or use null to leave it out.

Notification sounds

Choose a preset for each message:

await appkeepr.messages.send(
  { channel: "sales", body: "Ada upgraded to Pro.", sound: "cash" },
  { idempotencyKey: "purchase-1044" },
);

Leave out sound for the default tone, or use "none" for no sound. See Notification sounds for all presets and device support.

Timeouts and errors

Requests time out after 10 seconds. Pass an abort signal for a shorter timeout:

import { AppkeeprError } from "@appkeeprhq/node";

try {
  await appkeepr.messages.send(
    { channel: "signups", body: "A new account was created." },
    { idempotencyKey: "signup-1043", signal: AbortSignal.timeout(3_000) },
  );
} catch (error) {
  if (error instanceof AppkeeprError) {
    console.error(error.status, error.code, error.message);
    // Honor error.retryAfterSeconds when present.
  } else {
    throw error; // Network or abort error.
  }
}

Retry safely

The SDK doesn't retry automatically. A timeout may still mean your message arrived, so retry with the same idempotency key and content.

Next.js

Use a Node.js server module with a private environment variable:

lib/appkeepr.ts
import "server-only";

import { Appkeepr } from "@appkeeprhq/node";

export function getAppkeepr() {
  const token = process.env.APPKEEPR_API_TOKEN;
  if (!token) throw new Error("Set APPKEEPR_API_TOKEN.");
  return new Appkeepr({ token });
}

Call and await getAppkeepr().messages.send(...) from a Route Handler, Server Action or server job. Use the Node.js runtime and keep your token out of NEXT_PUBLIC_ variables.

On this page