Introduction

Welcome to the Riskguard Nexus Risk Evaluation API. This service provides a real-time risk score for authentication and transaction events by analyzing device and network signals and combining them with. It is designed for fast integration with modern web and mobile apps.

Logical Integration Architecture

The recommended integration pattern is:

  1. Frontend (browser / mobile) — locally generate a persistent device identifier (GUID) and collect lightweight signals (user agent, optionally fingerprint.js payload). The frontend sends these signals to the application backend (never directly to the Risk API).
  2. App Backend — receives the frontend payload, enriches it (server-side IP detection), and calls the Riskguard Nexus /v1/evaluate-risk endpoint with an x-api-key header tied to your account.
  3. Risk Evaluation API — validates API key, enriches IP, runs the scoring engine, persists the event and returns the risk result.
  4. Action — the application backend decides to allow, challenge, or block the action (e.g., require MFA), based on the risk response.

Base URL

https://ekycsybdfbhrhrlgixrl.supabase.co/functions

Data Analyzed & Risk Indicators

The service ingests the following data and derives the risk signals listed below.

Input Data

  • userId — application user identifier (string)
  • ipAddress — IPv4 or IPv6 address
  • deviceId — persistent GUID generated by the user's frontend (preferred)
  • userAgent — browser user agent string
  • customAttributes — ad-hoc string-to-string key-values (business context)

Derived Fields & Enrichment

  • geo — country, city, latitude, longitude, ASN
  • os / browser — parsed from userAgent

Risk Indicators Implemented

Each indicator below is automatically evaluated whenever an event is processed. Every triggered condition contributes a fixed number of risk points, which are then aggregated into a final risk score. This cumulative model allows the service to weigh multiple weak signals together, making the overall detection more resilient and accurate. The total risk score is capped at 100 and mapped to Low/Medium/High levels for easier consumption by client applications.

  • New device — deviceId not seen before for the user (+25 risk points)
  • New location — a country change vs last known country (+25 risk points)
  • Unusual location — location far (>500km) from recent locations or majority mismatch (+20 risk points)
  • Geo-velocity anomaly — travel speed > thresholds (200/500/900 km/h lead to +20/+40/+60 risk points)
  • IP velocity — excessive events per IP in a short window (+20/+40 risk points)
    • Moderate: >5 events in 10 minutes → +20
    • High: >10 events in 10 minutes → +40
  • User velocity — excessive events per user in a short window (+15/+30 points)

Scores are summed and capped at 100. Risk levels are mapped as:

  • Low: score < 40
  • Medium: 40 ≤ score < 70
  • High: score ≥ 70

Authentication

All API calls to Riskguard Nexus must include an API key provided in the x-api-key header. API keys are associated with an admin user and a tenant and generated in the Admin UI.

Security

Do not embed the API key in client-side code. Calls to /v1/evaluate-risk should be made from your backend so the API key remains secret.

API: POST /v1/evaluate-risk

POST /v1/evaluate-risk

Headers

  • x-api-key: <YOUR_API_KEY>
  • Content-Type: application/json

Request Body

Field Type Required Description
userId string Yes Application user identifier
ipAddress string Yes IPv4 or IPv6 address
deviceId string No Persistent GUID generated by frontend (preferred)
userAgent string No Browser user agent
customAttributes object No String-to-string key-value map with business context
timestamp ISO8601 No Event time in UTC; if omitted server time is used

Successful Response (200)

{
                            "riskScore": 0,
                            "riskLevel": "low",
                            "reasons": [
                                "No significant risk factors detected"
                            ],
                            "eventId": "5bedd7f9-47b5-4d57-8163-9f94de1bf493",
                            "timestamp": "2025-10-09T08:18:12.590787+00:00",
                            "userId": "user-555",
                            "ipAddress": "8.8.8.8",
                            "ipInfo": {
                                "country": "US",
                                "city": "Mountain View",
                                "region": "California",
                                "asn": "AS15169",
                                "org": "AS15169 Google LLC",
                                "latitude": 37.4056,
                                "longitude": -122.0775
                            },
                            "deviceId": "12345",
                            "userAgent": "Mozilla/5.0 (Linux; Android 15; SM-S931B Build/AP3A.240905.015.A2; wv) AppleWebKit/537.36 (KHTML, like
                            Gecko) Version/4.0 Chrome/127.0.6533.103 Mobile Safari/537.36",
                            "indicators": {
                                "ipVelocity": {
                                    "score": 0,
                                    "reasons": []
                                },
                                "userVelocity": {
                                    "score": 0,
                                    "reasons": []
                                },
                                "geoVelocity": {
                                    "score": 0,
                                    "reasons": [],
                                    "distanceKm": 0,
                                    "velocityKmh": 0
                                },
                                "locationAnomaly": {
                                    "score": 0,
                                    "reasons": []
                                },
                                "networkRisk": {
                                    "score": 0,
                                    "reasons": []
                                },
                                "deviceChange": {
                                    "score": 0,
                                    "reasons": []
                                }
                            }
                        }

Errors

  • 401 — Missing or invalid x-api-key
  • 400 — Invalid request payload (missing required fields)
  • 500 — Internal server error

JavaScript Integration (Device ID)

It is critical that the frontend generates and persists a stable deviceId so that the service can detect new devices. Below is a safe, dependency-free snippet that:

  1. Generates a UUIDv4 if none exists
  2. Stores it in localStorage (falls back to cookie)
  3. Exposes a helper to attach the deviceId to your backend payload
JavaScript
// Device ID helper (client-side)
function getOrCreateDeviceId() {
  try {
    const key = 'rgx_device_id';
    let id = localStorage.getItem(key);
    if (id) return id;
    // RFC4122-compliant UUIDv4
    id = ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,c=>
      (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
    );
    try { localStorage.setItem(key, id); } catch(e) { /* fallback */ }
    // also set a cookie fallback
    document.cookie = `${key}=${id}; path=/; max-age=${60*60*24*365*2}; samesite=lax; secure`;
    return id;
  } catch (e) {
    // In restricted contexts, fall back to a short random id
    return 'dev-' + Math.random().toString(36).slice(2, 10);
  }
}

Security note: deviceId is not a secret — it is used for identity linking. Do not store sensitive PII in localStorage.

Node.js (Server-side) Integration

Examples to call the Riskguard Nexus /v1/evaluate-risk API from your server. Keep the x-api-key secret.

Node.js (fetch)
// Minimal Node.js example using fetch (node 18+)
import fetch from 'node-fetch';

export async function assessRiskServerSide(payload) {
  const res = await fetch('https://ekycsybdfbhrhrlgixrl.supabase.co/functions/v1/evaluate-risk', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': process.env.RG_API_KEY
    },
    body: JSON.stringify(payload)
  });
  if (!res.ok) throw new Error('Risk API error: ' + await res.text());
  return res.json();
}

// Usage in an express handler
app.post('/login', async (req, res) => {
  const payload = {
    userId: req.body.userId,
    ipAddress: req.ip,
    deviceId: req.body.deviceId,
    userAgent: req.get('User-Agent'),
    customAttributes: req.body.customAttributes || {}
  };
  const result = await assessRiskServerSide(payload);
  // act on result.riskScore
});

Python Integration

Python
import os
import requests

BASE = 'https://ekycsybdfbhrhrlgixrl.supabase.co/functions/v1/evaluate-risk'
API_KEY = os.getenv('RG_API_KEY')

def assess_risk(user_id, ip_address, device_id=None, user_agent=None, custom_attributes=None):
    payload = {
        'userId': user_id,
        'ipAddress': ip_address,
        'deviceId': device_id,
        'userAgent': user_agent,
        'customAttributes': custom_attributes or {}
    }
    headers = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}
    r = requests.post(f'{BASE}/evaluate-risk', json=payload, headers=headers, timeout=5)
    r.raise_for_status()
    return r.json()

# Usage
# result = assess_risk('user_123', '203.0.113.5', device_id='guid-...')

Java Integration

Java (HttpClient)
import java.net.http.*;
import java.net.URI;
import java.time.Duration;

HttpClient client = HttpClient.newHttpClient();

String payload = "{\"userId\":\"user_123\",\"ipAddress\":\"203.0.113.5\",\"deviceId\":\"guid-...\"}";
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://ekycsybdfbhrhrlgixrl.supabase.co/functions/v1/evaluate-risk"))
    .timeout(Duration.ofSeconds(5))
    .header("Content-Type", "application/json")
    .header("x-api-key", System.getenv("RG_API_KEY"))
    .POST(HttpRequest.BodyPublishers.ofString(payload))
    .build();

HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
    System.out.println(response.body());
} else {
    throw new RuntimeException("Risk API error: " + response.body());
}