Skip to content

Node SDK

Careful: This package is coming soon and not published yet, so the install command below does not work today. Until it is, use the plain HTTP request from the quickstart.

One call from any Node server. No dependencies, Node 18 or newer, ESM and CommonJS, TypeScript types included.

Careful: Server-side only. Never put an API key in browser or mobile code.

Install

shell
npm install pingloom
export PINGLOOM_API_KEY=<your key>
export PINGLOOM_BASE_URL=https://api.pingloom.dev

Set PINGLOOM_BASE_URL to the PingLoom API origin shown in your dashboard. The SDKs have no built-in default, so a key can never be sent to the wrong host by accident. The same package ships the pingloom command line tool.

Send

send() returns the event ID. Only title is required. The limits are the same as the API reference: title 120 characters, body 2,000, data 8 KB.

javascript
import { PingLoom } from "pingloom"; // or: const { PingLoom } = require("pingloom");

const pl = new PingLoom(); // reads PINGLOOM_API_KEY and PINGLOOM_BASE_URL
const eventId = await pl.send({
  title: "Payment received: $49.00",
  body: "Order 1042 was paid.",
  channel: "payments",
  priority: "normal",
  data: { order_id: "1042" },
  actionUrl: "https://example.com/orders/1042",
  idempotencyKey: "order-1042-paid",
});

Without idempotencyKey the SDK generates a random one per call, so its own retries never create duplicates. Pass a key derived from the business event, like order-1042-paid, to make repeated calls of your own safe too.

Check the status

status() needs a key with the events:read scope.

javascript
const event = await pl.status(eventId);
console.log(event.status); // provider_accepted means FCM accepted it

Errors and retries

Every API error becomes a typed error with status, code, message, requestId and details. Options: maxRetries (default 3), backoffMs, timeoutMs. Retries use exponential backoff or Retry-After and always reuse the same idempotency key.

API responseExceptionRetried automatically
400, 413, 415, 422InvalidRequestErrorNo. Fix the request, see details.
401AuthenticationErrorNo. The key is missing, revoked or invalid.
403PermissionDeniedErrorNo. The key lacks the scope.
404NotFoundErrorNo.
409ConflictErrorNo. Same idempotency key with a different body.
429 RATE_LIMITEDRateLimitErrorYes, after Retry-After.
429 QUOTA_EXCEEDEDQuotaExceededErrorNo. The monthly quota is used.
5xxServerErrorYes, with the same idempotency key.
No responseNetworkErrorYes.
Missing key or base URLConfigurationErrorNot sent.
javascript
import { PingLoom, QuotaExceededError, PingLoomError } from "pingloom";

try {
  await pl.send({ title: "Backup finished" });
} catch (e) {
  if (e instanceof QuotaExceededError) {
    // the monthly quota is used; do not retry
  } else if (e instanceof PingLoomError) {
    console.error(e.status, e.code, e.requestId); // the key is never in the message
  }
}

The key is masked when you print the client, in error text and in logs as pl_live_****abcd.