Zum Hauptinhalt springen
Version: Guardian v0.2.1 (deprecated)

NPM Package

@surtai/guardian-web · v0.1.0

The @surtai/guardian-web SDK runs Guardian's collect() flow in any modern browser. It gathers device signals, encrypts them locally, and returns an opaque payload your backend sends to Surt's evaluate endpoint. The SDK itself makes no network calls: there are no API keys in the browser, no preflight, no telemetry.

npm install @surtai/guardian-web
Web is collect-only

Unlike the native SDKs (iOS / Android / React Native), the web SDK does not expose a verify() method. All risk decisions happen server-side once your backend forwards the payload. See Collect (Server-to-Server) for the full backend flow.

Usage

TypeScript
import { collect } from '@surtai/guardian-web';

// Collects device data and returns an encrypted payload.
// No init, no API key, no network calls.
const { payload } = await collect({ collectLocation: false });

// Forward the payload to your backend.
await fetch('https://your-api.com/verify-device', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ userId: 'user_123', payload }),
});

That's the entire client-side API surface, one function, one option.

Options

OptionTypeRequiredDefaultDescription
collectLocationbooleanNofalseWhen true, prompts the browser's Geolocation API. The only thing in collect() that can trigger a permission prompt.

CollectResult

interface CollectResult {
/** Base64 payload. Pass as `payload.data` in the evaluate request shown below. */
payload: string;
}

Backend: forward to Surt

Your backend receives the payload from the browser and posts to Surt's evaluate endpoint:

POST https://api.surt.com/geolocation/transactions/evaluate
Content-Type: application/json
Authorization: Bearer YOUR_SURT_API_KEY
{
"customer_id": "user_123",
"transaction_type": "login",
"transaction_name": "Sign in",
"payload": {
"type": "encrypted",
"data": "<payload from collect()>"
},
"config": {
"response": {
"address": { "type": "include" }
}
}
}

The request shape, supported transaction_type values, config options, and response schema are identical across all Guardian SDKs. See Collect (Server-to-Server) for the complete reference, including Node / Java / Python examples.

Errors

collect() throws a single GuardianError for three conditions:

import { collect, GuardianError } from '@surtai/guardian-web';

try {
const { payload } = await collect();
} catch (err) {
if (err instanceof GuardianError) {
switch (err.code) {
case 'CRYPTO_UNAVAILABLE': /* not in a secure context */ break;
case 'ENCRYPTION_FAILED': /* encryption failed (rare) */ break;
case 'INVALID_OPTIONS': /* bad arguments */ break;
}
}
}
CodeMeaning
CRYPTO_UNAVAILABLEwindow.crypto.subtle is missing. The SDK requires a secure context (HTTPS or localhost).
ENCRYPTION_FAILEDThe encryption step failed. Treat as a bug: capture and report.
INVALID_OPTIONSThe argument to collect() is not an object.

Individual collectors (fingerprint, battery, geolocation, network, etc.) never throw: they fail soft. A revoked permission or unsupported API just means the corresponding field is omitted from the payload. The backend tolerates sparse payloads.

Browser support

  • Any evergreen browser with window.crypto.subtle (Chrome, Edge, Firefox, Safari, Opera).
  • Secure context required: HTTPS in production, localhost for development. The SDK throws CRYPTO_UNAVAILABLE outside a secure context.
  • Geolocation, Battery Status, NetworkInformation, and other optional APIs degrade gracefully when unavailable.

Framework examples

VerifyButton.tsx
import { useState } from 'react';
import { collect } from '@surtai/guardian-web';

export function VerifyButton({ userId }: { userId: string }) {
const [loading, setLoading] = useState(false);

const handleClick = async () => {
setLoading(true);
try {
const { payload } = await collect({ collectLocation: false });
await fetch('/api/verify-device', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ userId, payload }),
});
} finally {
setLoading(false);
}
};

return (
<button onClick={handleClick} disabled={loading}>
{loading ? 'Verifying...' : 'Continue'}
</button>
);
}

What's different from the native SDKs

@surtai/guardian-web@surtai/guardian-rn / iOS / Android
verify() methodNoYes
collect() methodYes (only API)Yes
App-level initializationNoneinitialize(apiKey, options)
setCustomer() lifecycleNoYes
API key in clientNoYes
Network calls from SDKNoneYes
Hardware attestationNo (no browser equivalent)Yes
Persists per-customer stateNo (stateless per call)Yes

Web is intentionally lean: a single static function that produces an encrypted payload. Customer binding, transaction metadata, and decisions all happen in your backend.