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

@ruptjs/api

v3.0.0

Published

Server-side SDK for Rupt — know which users and agents you can trust.

Readme

@ruptjs/api

The server-side SDK for Rupt. Use it from your backend to fetch evaluations, look up users and their devices, and read challenge details. It signs requests with your project secret, so keep it on the server.

Built for Node and any other runtime with global fetch. If you want the browser-side SDK that fingerprints users and runs the evaluate flow, install @ruptjs/javascript instead.

Install

yarn add @ruptjs/api
# or
npm install @ruptjs/api

Quick start

import { RuptAPI } from "@ruptjs/api";

const rupt = new RuptAPI(process.env.RUPT_SECRET);

const evaluation = await rupt.getEvaluation(evaluationId);
if (evaluation.verdict === "deny") {
  // block the action
}

Your project secret lives in the Rupt dashboard. The browser-safe @ruptjs/javascript SDK is the right counterpart on your frontend.

Configuration

const rupt = new RuptAPI(process.env.RUPT_SECRET, {
  domain: "api.rupt.dev",   // default; HTTPS is added automatically
  timeout: 10_000,          // ms before a request times out (default 10s)
  retries: 3,               // retry attempts on network errors and 5xx (default 3)
  maxRetryDelay: 5_000,     // cap on the exponential backoff between retries
});

domain accepts a bare host (api.rupt.dev) and prepends https://. If you pass a value that already starts with http:// or https://, it's used as-is. That's how you point at a local API:

new RuptAPI(secret, { domain: "http://localhost:8007" });

Retries kick in for network errors and 5xx responses. 4xx errors and timeouts do not retry; you get the typed error back so your code can decide what to do.

Methods

Get an evaluation

const evaluation = await rupt.getEvaluation(evaluationId);
// {
//   _id, action, verdict, reasons, checks, risks,
//   policy, challenge, fingerprint, projectUser,
//   geolocation, metadata, ...
// }

The full server-side payload, including verdict, risk breakdown, policy that matched, and the populated user document. This data is not exposed to the browser SDK.

Get a challenge

const challenge = await rupt.getChallenge(challengeId);
// { _id, status, delivery_status, challenge_mode, user, createdAt, ... }

Returns the customer-safe projection that the Rupt-hosted challenge page reads. The API strips server-only fields like api_key and code before responding.

List a user's devices

const devices = await rupt.getUserDevices({ user: "user_123" });
// [{ _id, user, status, info, metadata, attachedAt, ... }, ...]

Update a user

await rupt.updateUser({
  user: "user_123",
  email: "[email protected]",
  phone: "+15555550100",
  metadata: { plan: "pro" },
  groups: [{ id: "workspace_42", name: "Acme" }],
});

Only the fields you pass are written. Anything you leave out is untouched.

Errors

Every method throws on non-2xx responses, network failures, and timeouts. Error subclasses let you branch without parsing message strings.

import {
  RuptApiError,
  RuptNetworkError,
  RuptTimeoutError,
} from "@ruptjs/api";

try {
  await rupt.getEvaluation(id);
} catch (err) {
  if (err instanceof RuptApiError) {
    // 4xx or 5xx response. err.status and err.body are populated.
  } else if (err instanceof RuptNetworkError) {
    // The request never reached the server. err.cause has the underlying error.
  } else if (err instanceof RuptTimeoutError) {
    // The timeout fired before we got a response.
  } else {
    throw err;
  }
}

Continuing after a timeout

When a request times out, the SDK aborts the wait but lets the underlying fetch keep running. If you want to wait for it anyway, await the continue promise on the timeout error:

try {
  await rupt.updateUser({ user, metadata });
} catch (err) {
  if (err instanceof RuptTimeoutError) {
    // Give the request another shot before giving up.
    const eventual = await err.continue;
  }
}

You can ignore continue and the dangling request will resolve or reject quietly. The SDK attaches a no-op handler so you won't see unhandled-rejection warnings.

Types

Challenge, Device, Evaluation, EvaluationRisk, Group, and RuptAPIOptions are all exported. Bring them in directly if you want to type your wrappers around the client.