@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/apiQuick 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.
