Skip to content

Node.js SDK reference

@revokegpt/node is the RevokeGPT server SDK for Node.js 26 or later. It sends a response token to siteverify and applies every relying-party check: success must be the boolean true, the hostname (or app) and the action must match exactly, and the score must meet your threshold. It also wraps assessments, account protection, password and credential pair checks, payments and erase. For a walkthrough, see the Node.js quickstart.

Terminal window
npm install @revokegpt/node # after the first release; Node.js 26 or later

createClient(options) takes:

Option Type Default Meaning
secret string required Your site’s secret key (rgsk_...). A management key (rgmk_...) is refused.
endpoint string required The full siteverify URL. https:, or http: only on localhost or 127.0.0.1; no username, password, query or fragment.
timeoutMs number 5000 An integer from 1 to 60000.
fetch typeof fetch global fetch A WHATWG-compatible fetch: its response body must be a web ReadableStream. A node-fetch v2 style body is not supported and every verification fails closed as network-error.

An invalid secret throws TypeError('invalid secret key'); the message never includes the key. For the assessment and password calls, endpoint must end in /siteverify (the other URLs are derived from it).

function createClient(options: ClientOptions): Client

Create the client once and reuse it.

verify(token: string, options: VerifyOptions): Promise<VerifyOutcome>
Option Type Meaning
expectedHostname string For web tokens. Canonical: lowercase, no trailing dot, no port. Compared exactly.
expectedApp { platform: 'android' | 'ios'; id: string } For mobile app tokens. Android: the package name. iOS: the bare bundle id, no Team ID.
expectedAction string Omit only if you use no actions; then a token that carries an action is refused.
minScore number In [0, 1]. Always pass it: without it every verified result fails with threshold-missing.
remoteip string The end user’s IPv4 or IPv6 address, sent only when given and not empty. An address with a zone id is invalid.
sitekey string The site key the token must belong to, sent only when given and not empty.

Give exactly one of expectedHostname and expectedApp. Returns:

type VerifyOutcome =
| { ok: true; result: SiteverifyResult }
| { ok: false; reason: VerifyFailureReason; result: SiteverifyResult };

result is the parsed siteverify result (score, action, hostname, errorCodes, reasons, and the app id fields), for logging. Gate on outcome.ok alone.

import { createClient } from '@revokegpt/node';
const revokegpt = createClient({
secret: process.env.REVOKEGPT_SECRET!, // rgsk_...
endpoint: 'https://<api host>/v1/siteverify',
});
const outcome = await revokegpt.verify(token, {
expectedHostname: 'shop.example',
expectedAction: 'signup',
minScore: 0.5,
remoteip: clientIp, // from your trusted proxy, not req.socket.remoteAddress
});
if (!outcome.ok) return reject(outcome.reason);

For mobile tokens, pass expectedApp: { platform: 'android', id: 'com.example.app' } instead of a hostname.

createAssessment(input: CreateAssessmentInput): Promise<Assessment>

input fields: token?, expectedAction?, express?, userIpAddress?, userAgent?, headers?, userInfo?, accountVerification?, transactionData?, fraudPrevention? ('ENABLED', 'DISABLED' or 'FRAUD_PREVENTION_UNSPECIFIED'). A token assessment spends the token. An invalid token is still a 200 with tokenProperties.valid: false and score 0, so check valid. Express (express: true, no token) scores the IP address alone, so pass the real end-user address.

const a = await revokegpt.createAssessment({ token, expectedAction: 'login' });
if (a.tokenProperties.valid && a.riskAnalysis.score >= 0.5) allow();
annotate(aidOrName: string, input?: AnnotateInput): Promise<void>

Labels an assessment. Accepts assessments/<aid> or the bare aid. input: annotation? ('LEGITIMATE' or 'FRAUDULENT'), reasons?, accountId? or hashedAccountId?, transactionEvent?. Annotate with ground truth you learn later, not guesses.

await revokegpt.annotate(a.name, { annotation: 'FRAUDULENT', reasons: ['CHARGEBACK'] });
isPasswordLeaked(password: string): Promise<PasswordCheckResult> // { leaked, count }

Hashes with SHA-1 locally and sends only the first 5 hex characters. A 503 throws RevokeGPTUnavailable, which means “could not check”, never “not leaked”. See password check.

checkCredentialPair(username: string, password: string): Promise<CredentialPairResult> // { leaked }

Beta; off until enabled, otherwise RevokeGPTError with status: 403 and code: 'feature-disabled'. An RFC 9497 OPRF: neither value reaches the service. A username holding an unassigned code point is refused with a RangeError and no request.

eraseAccount(input: { accountId: string } | { hashedAccountId: string }): Promise<void>

Erases what the service holds for an account. Use the same account id form you used to assess and annotate.

function cardFields(i: { bin?: string; last4?: string }): { cardBin?: string; cardLastFour?: string }

Builds the only card fields a payment assessment accepts (BIN of 6 or 8 digits and last four). Throws RevokeGPTError('bad-request', 0) for anything else. Every string of transactionData is also scanned for a card number before sending.

verify never throws or rejects. Every failure is an outcome with a reason:

Reason Meaning
invalid-expectation The expectation is invalid. Nothing was sent.
invalid-options A given remoteip or sitekey is invalid. Nothing was sent.
invalid-token-format Not 1 to 2048 characters of A-Z a-z 0-9 - _. Nothing was sent.
network-error The request failed or timed out.
http-error Siteverify answered with a status other than 200 (redirects included), or a body over 64 KiB.
not-verified Siteverify did not verify the token, or its body was malformed. result.errorCodes says why.
hostname-mismatch The token was issued for another hostname.
app-mismatch The token was issued to another app, a web page or the other platform.
action-mismatch Another action, or an action when you expect none.
score-missing You set minScore and the result has no score.
threshold-missing The result has a score and you set no minScore.
score-below-threshold The score is below minScore.
score-invalid The score is not a number in [0, 1].

Treat every reason as “do not accept”. A token is single use, and after network-error or http-error it may already be spent, so a retry needs a new token from the widget.

All other methods throw RevokeGPTError on failure, and its subclass RevokeGPTUnavailable for HTTP 503. Fields: code (for example unauthorized, feature-disabled, not-found, expired, rate-limited, payload-too-large, unsupported-media-type, service-unavailable, network-error, invalid-response), status (0 when no response), requestId, and retryAfterSeconds for a 429. See errors.

The SDK reads no environment variables. Read the secret from your secret store and pass it to createClient (the examples use REVOKEGPT_SECRET). Redirects are never followed, nothing is retried, and at most 64 KiB of response is read.

  • The secret is held privately by the client: logging or serializing the client never shows it. It is sent only in the POST body (siteverify) or the Authorization header, never in a URL.
  • The SDK form-encodes the siteverify body. If you call siteverify yourself, never build the body by string concatenation.
  • Behind a proxy, pass the client address from your trusted proxy as remoteip, not req.socket.remoteAddress.
  • Never choose between the hostname and the app expectation from anything the client controls.