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

@novatorius/siren

v0.1.0

Published

Official Siren SDK for Node.js and TypeScript — affiliate and incentive tracking for any commerce stack.

Readme

Siren SDK for Node.js

Record affiliate and incentive events, and verify signed webhooks, in a few lines of TypeScript.

npm version CI License: MIT Node

What is Siren?

Siren is headless affiliate and incentive tracking for any commerce stack. It tracks the full lifecycle from customer interaction to payout — clicks, sales, signups, course completions — and computes rewards from flexible rules you define. Affiliate programs, referral programs, partner and reseller commissions, creator royalties, sales commissions, and loyalty rewards all run on the same engine.

What this SDK does

This SDK is the Node.js and TypeScript integration point for Siren. In a few lines you can:

  • Record events (events.sale, events.refund, events.siteVisited) so conversions and payouts compute.
  • Verify signed webhooks (webhooks.constructEvent) so you can trust inbound deliveries.

It runs on Node 18+ with zero runtime dependencies (it uses the global fetch), and ships ESM, CJS, and full type declarations.

Install

npm install @novatorius/siren

Quickstart: record a sale

Mint an API key in the Siren dashboard (Settings → API Keys), then:

import { Siren } from '@novatorius/siren';

const siren = new Siren({ apiKey: process.env.SIREN_API_KEY! });

// Record a completed sale so conversions and payouts compute.
// `total` is in MAJOR currency units: 49.99 means $49.99.
const { opportunityId } = await siren.events.sale({
  source: 'stripe',                 // your commerce source
  externalId: 'cs_test_a1b2c3',     // your order id — used to match refunds later
  total: 49.99,
  trackingId: 4021,                 // opportunity id from the Siren tracking cookie
});

console.log(`Recorded against opportunity ${opportunityId}`);

With line items (per-unit amount; a missing quantity defaults to 1):

await siren.events.sale({
  source: 'woocommerce',
  externalId: 'order-88',
  total: 159.97,
  trackingId: 4021,
  items: [
    { name: 'Pro Plan (annual)', amount: 49.99 },                 // quantity defaults to 1
    { externalId: 'sku-2', name: 'Add-on seat', quantity: 3, amount: 36.66 },
  ],
});

Refunds and referred visits work the same way:

await siren.events.refund({ source: 'stripe', externalId: 'cs_test_a1b2c3' });
await siren.events.siteVisited({ collaboratorId: 88, userId: 12345 });
await siren.events.ingest('loyalty-points-earned', { userId: 42, points: 100 });

Quickstart: verify a webhook

Siren signs every delivery with X-Siren-Signature: sha256=<hmac> — an HMAC-SHA256 of the raw request body keyed by your subscription's signing secret. constructEvent verifies the signature (constant-time) and parses the event in one call.

⚠️ You MUST pass the RAW request body bytes to constructEvent. Body parsers like express.json() re-serialize the payload, and the HMAC will never match a re-serialized body. Use express.raw() (or your framework's raw-body equivalent) on the webhook route so you hand constructEvent the exact bytes Siren sent.

import express from 'express';
import { Siren, SignatureVerificationError } from '@novatorius/siren';

const siren = new Siren({ apiKey: process.env.SIREN_API_KEY! });
const app = express();

app.post('/webhooks/siren', express.raw({ type: 'application/json' }), (req, res) => {
  let event;
  try {
    event = siren.webhooks.constructEvent(
      req.body,                              // raw Buffer — exact bytes received
      req.header('X-Siren-Signature'),
      process.env.SIREN_WEBHOOK_SECRET!,
    );
  } catch (err) {
    if (err instanceof SignatureVerificationError) {
      return res.status(400).send('invalid signature');
    }
    throw err;
  }

  switch (event.type) {
    case 'conversion.approved':
      // ...
      break;
    case 'payout.paid':
      // ...
      break;
  }

  res.sendStatus(200);
});

Create the subscription (the signingSecret is returned once — store it):

import { WebhookEventType } from '@novatorius/siren';

const sub = await siren.webhooks.subscriptions.create({
  targetUrl: 'https://example.com/webhooks/siren',
  events: [WebhookEventType.ConversionApproved, WebhookEventType.PayoutPaid],
  // or: events: [WebhookEventType.All]
});
await saveSecretSomewhereSafe(sub.signingSecret);

Features

  • Event ingestion — record sales, refunds, referred visits, and custom event types (events.sale, events.refund, events.siteVisited, events.ingest). Ingestion is auto-retried on network errors and 429/5xx.
  • Signed-webhook verification and subscriptions — constant-time signature checks (webhooks.constructEvent, webhooks.verifySignature) plus subscription management (webhooks.subscriptions.create / list / delete).
  • API keys — mint, list, and revoke keys (apiKeys.create / list / revoke). The raw key is returned once and cannot be retrieved later.
  • Reconciliation reads — thin paginated readers over Siren's ledger for conversions, transactions, obligations, and payouts.
  • Typed errors — every failure throws a typed subclass of SirenError carrying message, code, and statusCode (NotFoundError, RateLimitError, ValidationError, and more).
const conversions = await siren.conversions.list({ page: 1, perPage: 50 });
console.log(conversions.estimatedCount); // total across all pages, if known

const key = await siren.apiKeys.create({ label: 'Production server' });
// key.rawKey (sk_live_...) is returned ONCE and cannot be retrieved later.

Configuration

const siren = new Siren({
  apiKey: 'sk_live_...',                                 // required
  baseUrl: 'https://api.sirenaffiliates.com/siren/v1',   // default; point at staging/local as needed
  timeout: 30_000,                                       // ms, default 30s
  maxRetries: 2,                                         // default 2
});

Idempotent reads and event ingestion automatically retry network errors and 429/5xx responses with exponential backoff (honoring Retry-After). Management writes — apiKeys.create and webhooks.subscriptions.create — are never auto-retried, so a flaky connection can't mint duplicate credentials.

Other SDKs

Siren ships official SDKs in three languages, all built against the same API:

  • Node.js / TypeScript — this repository
  • Python — https://github.com/Novatorius/siren-python
  • PHP — https://github.com/Novatorius/siren-php

Links

  • Siren — https://sirenaffiliates.com
  • OpenAPI specification — ./openapi.yaml
  • Issues — https://github.com/Novatorius/siren-node/issues

Contributing

Contributions are welcome. See CONTRIBUTING.md for how to clone, build, test, and open a pull request. Please also review our Code of Conduct.

License

MIT © 2026 Novatorius LLC