Vertueal Docs

Device Trust & MFA API Endpoints

Register hardware fingerprints, dispatch MFA verification codes, verify devices, list trusted hardware, and revoke compromised devices.

Device Trust & MFA API Endpoints

The Device Trust API enforces Zero-Trust Hardware Quarantine by evaluating hardware fingerprints, dispatching time-bounded email verification codes, and promoting verified devices to trusted status. These endpoints work together to ensure that even a compromised master password cannot be exploited from unauthorized hardware.

Loading diagram...

1. Check Device Trust Status

POST /api/auth/device-check

Submits hardware fingerprint signals for a given user and returns whether the device is already trusted or requires MFA verification.

Rate Limit

WindowMaximum RequestsScope
60 seconds20Per IP address

Request Headers

Content-Type: application/json

Request Body Schema

FieldTypeRequiredDescription
userIdstringYesThe authenticated user's unique identifier.
signalsobjectYesHardware fingerprint signals object (see below).

signals Object Schema

FieldTypeRequiredDescription
clientDeviceUUIDstringNoPersistent UUID generated and stored in the client's localStorage. Highest priority identifier when present.
userAgentstringNoBrowser navigator.userAgent string.
languagestringNoBrowser navigator.language value (e.g., en-US).
screenResolutionstringNoDisplay dimensions (e.g., 1920x1080).
timezonestringNoIANA timezone identifier (e.g., Africa/Johannesburg).
platformstringNoOperating system platform (e.g., macOS, Win32).

Code Examples

cURL
curl -X POST "https://passwordmanager.vertueal.com/api/auth/device-check" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "usr_01j8m2k9p3x4y5z6",
    "signals": {
      "clientDeviceUUID": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...",
      "language": "en-US",
      "screenResolution": "2560x1440",
      "timezone": "Africa/Johannesburg",
      "platform": "macOS"
    }
  }'
TypeScript (fetch)
const response = await fetch(
  "https://passwordmanager.vertueal.com/api/auth/device-check",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      userId: "usr_01j8m2k9p3x4y5z6",
      signals: {
        clientDeviceUUID: localStorage.getItem("clientDeviceUUID") ?? undefined,
        userAgent: navigator.userAgent,
        language: navigator.language,
        screenResolution: `${screen.width}x${screen.height}`,
        timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
        platform: navigator.platform,
      },
    }),
  }
);

const result = await response.json();

if (result.verified) {
  // Device is trusted — proceed to vault unlock
} else {
  // Device requires MFA — trigger /api/auth/mfa/send
}

Success Responses

Device Already Trusted (200 OK):

{
  "verified": true,
  "deviceId": "client-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "message": "Device verified"
}

Device Quarantined — MFA Required (200 OK):

{
  "verified": false,
  "deviceId": "client-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "reason": "Device pending verification",
  "requiresMfa": true
}

Error Responses

StatusBodyCause
400{ "error": "Invalid request data", "details": {...} }Request body failed Zod schema validation (e.g., missing userId).
429{ "error": "Too many requests. Please try again later." }Exceeded 20 requests per 60-second window.
500{ "error": "Internal Server Error" }Server-side failure (e.g., database or Fingerbank API error).

Note

Device Fingerprint Priority: When a clientDeviceUUID is provided, it is used as the primary device identifier (client-{uuid}). If absent, the server queries the Fingerbank API for hardware profiling. If Fingerbank is unavailable, a fallback Base64 hash of local signals is computed.


2. Send MFA Verification Code

POST /api/auth/mfa/send

Generates a random 6-digit verification code, stores it with a 5-minute TTL, and dispatches it to the user's registered email address via SMTP.

Rate Limit

WindowMaximum RequestsScope
60 seconds3Per IP address

Request Body Schema

FieldTypeRequiredDescription
emailstringYesThe user's registered email address. Must be a valid email format.

Code Examples

cURL
curl -X POST "https://passwordmanager.vertueal.com/api/auth/mfa/send" \
  -H "Content-Type: application/json" \
  -d '{ "email": "user@example.com" }'
TypeScript (fetch)
await fetch("https://passwordmanager.vertueal.com/api/auth/mfa/send", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ email: "user@example.com" }),
});

Success Response (200 OK)

{
  "success": true,
  "message": "Code sent"
}

Error Responses

StatusBodyCause
400{ "error": "Invalid email" }Email field missing or fails format validation.
429{ "error": "Too many codes sent. Try again later." }Exceeded 3 code dispatches per 60-second window.
500{ "error": "Failed to send code" }SMTP delivery failure or database error.

Info

Verification codes expire after 5 minutes (300 seconds). If the code is not used within this window, a new one must be requested. Previous unused codes for the same email are automatically overwritten.


3. Verify MFA Code & Promote Device

POST /api/auth/mfa/verify

Validates the 6-digit verification code against the stored OTP record and, if correct, promotes the device from quarantined to trusted status. Also triggers a New Device Login security alert email.

Rate Limit

WindowMaximum RequestsScope
60 seconds3Per IP address

Request Body Schema

FieldTypeRequiredDescription
userIdstringYesThe authenticated user's unique identifier.
userEmailstringYesThe user's registered email address.
deviceIdstringYesThe deviceId returned by the /api/auth/device-check endpoint.
codestringYesThe 6-digit verification code from the user's email. Must be exactly 6 characters.

Code Examples

cURL
curl -X POST "https://passwordmanager.vertueal.com/api/auth/mfa/verify" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "usr_01j8m2k9p3x4y5z6",
    "userEmail": "user@example.com",
    "deviceId": "client-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "code": "849201"
  }'
TypeScript (fetch)
const response = await fetch(
  "https://passwordmanager.vertueal.com/api/auth/mfa/verify",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      userId: "usr_01j8m2k9p3x4y5z6",
      userEmail: "user@example.com",
      deviceId: deviceIdFromCheckResponse,
      code: userEnteredCode, // 6-digit string
    }),
  }
);

if (response.ok) {
  // Device is now trusted — proceed to unlock vault
}

Success Response (200 OK)

{
  "success": true
}

Note

Upon successful verification, the system automatically dispatches a New Device Login security alert email to the user's registered address, containing the device name, IP address, and geographic location.

Error Responses

StatusBodyCause
400{ "error": "Invalid or expired code" }Code does not match, has already been consumed, or has expired (5-minute TTL).
400{ "error": "Invalid data" }Request body failed Zod validation (e.g., code not exactly 6 digits).
429{ "error": "Too many attempts" }Exceeded 3 verification attempts per 60-second window.
500{ "error": "Verification failed" }Internal server error.

4. List Trusted Devices

GET /api/devices

Returns all registered devices for a given user, sorted by most recently active.

Query Parameters

ParameterTypeRequiredDescription
userIdstringYesThe authenticated user's unique identifier.

Code Examples

cURL
curl -X GET "https://passwordmanager.vertueal.com/api/devices?userId=usr_01j8m2k9p3x4y5z6"
TypeScript (fetch)
const response = await fetch(
  `https://passwordmanager.vertueal.com/api/devices?userId=${userId}`
);
const { devices } = await response.json();

devices.forEach((device) => {
  console.log(`${device.device_name} — ${device.is_verified ? "Trusted" : "Quarantined"}`);
});

Success Response (200 OK)

{
  "devices": [
    {
      "_id": "66e3f8a1b2c3d4e5f6789012",
      "user_id": "usr_01j8m2k9p3x4y5z6",
      "device_fingerprint_hash": "client-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "device_name": "Mozilla/5.0 (Macintosh; In...",
      "is_verified": true,
      "ip_address": "203.0.113.195",
      "location": "Cape Town, South Africa",
      "isp": "Vodacom",
      "os": "macOS",
      "last_used_at": "2026-09-20T18:30:00.000Z",
      "created_at": "2026-09-15T10:00:00.000Z"
    },
    {
      "_id": "66e3f8a1b2c3d4e5f6789013",
      "user_id": "usr_01j8m2k9p3x4y5z6",
      "device_fingerprint_hash": "client-b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "device_name": "Mozilla/5.0 (iPhone; CPU ...",
      "is_verified": true,
      "ip_address": "198.51.100.42",
      "location": "Johannesburg, South Africa",
      "isp": "MTN",
      "os": "iOS",
      "last_used_at": "2026-09-19T14:22:00.000Z",
      "created_at": "2026-09-10T08:15:00.000Z"
    }
  ]
}

Error Responses

StatusBodyCause
400{ "error": "Missing userId" }The userId query parameter was not provided.
500{ "error": "Failed to fetch devices" }Internal server error during database query.

5. Revoke a Trusted Device

DELETE /api/devices

Permanently removes a device from the user's trusted device list. Any future login from the revoked hardware will be quarantined and require full MFA verification again.

Query Parameters

ParameterTypeRequiredDescription
userIdstringYesThe authenticated user's unique identifier.
deviceHashstringYesThe device_fingerprint_hash of the device to revoke.

Code Examples

cURL
curl -X DELETE "https://passwordmanager.vertueal.com/api/devices?userId=usr_01j8m2k9p3x4y5z6&deviceHash=client-b2c3d4e5-f6a7-8901-bcde-f12345678901"
TypeScript (fetch)
await fetch(
  `https://passwordmanager.vertueal.com/api/devices?userId=${userId}&deviceHash=${deviceHash}`,
  { method: "DELETE" }
);

Success Response (200 OK)

{
  "success": true
}

Warning

Device revocation is immediate and irreversible. The revoked device's trust token is permanently invalidated. Anyone currently signed in on that hardware will be locked out upon their next vault sync and must complete full MFA verification to regain access.

Error Responses

StatusBodyCause
400{ "error": "Missing parameters" }Either userId or deviceHash query parameter was not provided.
500{ "error": "Delete failed" }Internal server error during database deletion.

On this page