Integration Documentation · V1.1

Voice-Auth
Integration Guide.

Full setup guide, server-side verification instructions, and SDK reference for @helix-id/voice-auth — everything your engineers need to go live.

Package

@helix-id/voice-auth

Version

1.1.0

Updated

24 Apr 2026

1

Contents & Overview

The @helix-id/voice-auth package provides a lightweight backend SDK for integrating Helix Biometric MFA and Bot Management into any Node.js application.

Authentication follows a redirect-based flow: your server generates a signed URL, the user is sent to the Helix portal to speak a short numeric challenge, and Helix redirects back with an HMAC-signed callback result. The nonce stored in the user session prevents replay attacks. The HMAC signature ensures the callback has not been tampered with.

Every request runs through Helix's edge bot defense — synthetic-voice detection and proof-of-work — before any biometric work happens. See Section 2 Services included for what each layer does and what verdicts to expect.


2

Services Included

A single integration of @helix-id/voice-auth bundles two products that share one redirect, one callback, and one verdict. You do not call them separately — the SDK orchestrates Bot Management before Biometric MFA, and the result reaches your callback as a single statusCode.

Product 01 · Runs First

Bot Management

Edge defense that filters non-human and synthetic traffic before any biometric work is done. Two layers run in series — a proof-of-work challenge gates the redirect, then synthetic-voice detection inspects the audio in real time.

Proof-of-work challenge~30ms

Product 02 · Runs Second

Biometric MFA

Voice-ID enrollment and passwordless re-authentication. The user speaks a short numeric challenge displayed on the Helix portal; the SDK matches against the enrolled profile and returns a verdict.

Enrollment time~6s
Re-auth time~2s
Replay protectionnonce + HMAC

What you receive on the callback

The combined verdict is exposed as a single statusCode on the callback result. Bot-management failures short-circuit before biometric matching runs:

LayerVerdict surfaces asWhat it means
Bot Management (first line of defense)failedRequest flagged as bot, synthetic, or otherwise non-human. The user never reaches the voice prompt; biometric match is skipped.
Voice Auth (runs after Bot Management passes)verifiedfailedSpecific status codes (voice_verified, voice_enrolled, synthetic_voice_detected, voice_mismatch, etc.) are listed in Section 6 Status Codes.

Service-level commitments (latency, availability) are governed by your Helix order form. Targets above describe typical observed performance, not contractual SLAs.


3

Installation & Prerequisites

Prerequisites

  • Node.js 16 or later
  • An active Helix Space ID
  • A shared secret from the Helix admin panel
  • HTTPS-served callback endpoint (production)

Step 1 · Install the package

Install via npm — or your package manager of choice:

bash
npm install @helix-id/voice-auth

Step 2 · Configure environment variables

Add your Space ID and shared secret to your environment. Never commit either to source control.

bash
# .env
HELIX_SPACE_ID=a1b2c3d4-e5f6-7890-abcd-ef1234567890
HELIX_SECRET=tk_live_hx_…

NOTE

The default portal URL is https://capsule.helix.id. You only need to override it if your contract specifies a regional or self-hosted portal — see baseUrl in Section 5.

Step 3 · Confirm the integration

With credentials in place, follow Section 4 Quick Start Flow to wire the redirect and callback. Local development can use the test credentials in Section 8 Testing in lieu of a real Space.


4

Quick Start Flow

Step 1 · Generate the redirect URL (backend)

Call createAuthUrl() on your backend to generate a unique, signed URL and a cryptographic nonce. Store the nonce in the user's session before redirecting.

js
import { createAuthUrl } from "@helix-id/voice-auth";

app.get("/auth/start", (req, res) => {
  const state = Buffer.from(
    JSON.stringify({ action: "approve_tx", txId: "abc123", returnTo: "/dashboard" })
  ).toString("base64");

  const { url, nonce } = createAuthUrl({
    spaceId: process.env.HELIX_SPACE_ID,
    state,
  });

  req.session.helixNonce = nonce;
  res.json({ url });
});

Step 2 · Redirect the user (frontend)

Fetch the URL from your backend and redirect the user's browser to the Helix portal.

UX Note

Consider showing a brief in-product message before the redirect, e.g. "You'll be briefly redirected to Helix to verify your identity, then brought back here." This sets expectations and reduces drop-off when users land on the Helix portal.

js
const { url } = await fetch("/auth/start").then((r) => r.json());
window.location.href = url;

Step 3 · Verify the callback (backend)

After the user completes the voice challenge, Helix redirects to your callback endpoint. Call verifyCallback() to validate the HMAC signature, nonce, and timestamp.

js
import {
  verifyCallback,
  InvalidSignatureError,
  NonceMismatchError,
  ExpiredTimestampError,
} from "@helix-id/voice-auth";

app.get("/auth/callback", (req, res) => {
  // verifyCallback expects every field to be a plain string.
  // Express may parse duplicate query params as arrays —
  // normalize req.query before passing it in.
  const query = Object.fromEntries(
    Object.entries(req.query).map(
      ([k, v]) => [k, Array.isArray(v) ? v[0] : String(v)]
    )
  );

  try {
    const result = verifyCallback(query, {
      nonce: req.session.helixNonce,
      secret: process.env.HELIX_SECRET,
    });

    req.session.helixNonce = null;
    const state = JSON.parse(Buffer.from(result.state, "base64").toString());

    if (result.status === "verified") {
      res.redirect(state.returnTo);
    } else {
      res.redirect(`${state.returnTo}?error=${result.statusCode}`);
    }
  } catch (error) {
    if (error instanceof InvalidSignatureError)
      return res.status(401).json({ error: "Invalid signature" });
    if (error instanceof NonceMismatchError)
      return res.status(401).json({ error: "Nonce mismatch" });
    if (error instanceof ExpiredTimestampError)
      return res.status(401).json({ error: "Callback expired" });
    throw error;
  }
});

5

API Reference

createAuthUrl(options)

Generates a signed redirect URL and a cryptographic nonce.

OptionTypeRequiredDescription
spaceIdstringYesYour Space ID (UUID) from the Helix admin panel.
statestringYesOpaque base64 payload echoed back in the callback.
baseUrlstringNoOverride Helix portal URL. Defaults to https://capsule.helix.id when omitted.

Returns { url: string, nonce: string } — store nonce in the user session.

verifyCallback(query, options)

Verifies the HMAC-signed callback payload and returns the parsed result.

OptionTypeRequiredDescription
noncestringYesNonce returned by createAuthUrl, stored in the session.
secretstringYesShared secret from the Helix admin panel.

Returns { status, statusCode, logId, state }

Throws InvalidSignatureError, NonceMismatchError, ExpiredTimestampError, MalformedCallbackError.


6

Status Codes

The callback result includes a statusCode and a high-level status field.

status_codestatusdescription
voice_verifiedverifiedVoice matched the enrolled profile successfully.
voice_enrolledverifiedFirst-time user — voice profile created during this session.
challenge_mismatchfailedSpoken digits did not match the displayed challenge.
synthetic_voice_detectedfailedAudio was flagged as AI-generated or spoofed (Bot Management).
voice_mismatchfailedVoice biometrics did not match the enrolled profile.

7

Error Handling

Handle each error class specifically to return appropriate HTTP responses:

Error ClassHTTPCause
InvalidSignatureError401HMAC does not match — possible tampering or wrong secret.
NonceMismatchError401Nonce in callback does not match the session nonce.
ExpiredTimestampError401Callback timestamp is outside the accepted time window.
MalformedCallbackError400Required callback fields are missing or unparseable.

8

Testing & Credentials

Use the built-in test credentials for local development. Import them from the @helix-id/voice-auth/testing sub-path.

js
import { createAuthUrl } from "@helix-id/voice-auth";
import { HELIX_TEST_SPACE_ID, HELIX_TEST_SECRET } from "@helix-id/voice-auth/testing";

const { url, nonce } = createAuthUrl({
  spaceId: HELIX_TEST_SPACE_ID,
  state: "test",
});
CredentialValue
Space IDa1b2c3d4-e5f6-7890-abcd-ef1234567890
Secrettk_test_hx_4a7f2c9d8e1b3f6a5c2d9e8f7b4a1c3d
Callback URLhttp://localhost:8080/helix/callback

Important

Never use test credentials in production. Rotate your production secret regularly.


9

Security Considerations

Nonce invalidation

Clear req.session.helixNonce immediately after a successful callback to prevent replay attacks.

Secret management

Store HELIX_SECRET in environment variables or a secrets manager. Never commit it to source control.

Query normalization

Always normalize req.query to a flat Record before calling verifyCallback to avoid array injection.

HTTPS only

The callback endpoint must be served over HTTPS in production to protect the HMAC signature in transit.

Timestamp window

The SDK rejects callbacks older than a configured time window. Keep server clocks synchronized (NTP).

Licensed under MIT. For support, visit the Helix documentation portal.