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
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.
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.
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.
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:
| Layer | Verdict surfaces as | What it means |
|---|---|---|
| Bot Management (first line of defense) | failed | Request 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) | verifiedfailed | Specific 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.
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:
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.
# .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.
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.
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.
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.
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;
}
});API Reference
Generates a signed redirect URL and a cryptographic nonce.
| Option | Type | Required | Description |
|---|---|---|---|
spaceId | string | Yes | Your Space ID (UUID) from the Helix admin panel. |
state | string | Yes | Opaque base64 payload echoed back in the callback. |
baseUrl | string | No | Override Helix portal URL. Defaults to https://capsule.helix.id when omitted. |
Returns { url: string, nonce: string } — store nonce in the user session.
Verifies the HMAC-signed callback payload and returns the parsed result.
| Option | Type | Required | Description |
|---|---|---|---|
nonce | string | Yes | Nonce returned by createAuthUrl, stored in the session. |
secret | string | Yes | Shared secret from the Helix admin panel. |
Returns { status, statusCode, logId, state }
Throws InvalidSignatureError, NonceMismatchError, ExpiredTimestampError, MalformedCallbackError.
Status Codes
The callback result includes a statusCode and a high-level status field.
| status_code | status | description |
|---|---|---|
voice_verified | verified | Voice matched the enrolled profile successfully. |
voice_enrolled | verified | First-time user — voice profile created during this session. |
challenge_mismatch | failed | Spoken digits did not match the displayed challenge. |
synthetic_voice_detected | failed | Audio was flagged as AI-generated or spoofed (Bot Management). |
voice_mismatch | failed | Voice biometrics did not match the enrolled profile. |
Error Handling
Handle each error class specifically to return appropriate HTTP responses:
| Error Class | HTTP | Cause |
|---|---|---|
InvalidSignatureError | 401 | HMAC does not match — possible tampering or wrong secret. |
NonceMismatchError | 401 | Nonce in callback does not match the session nonce. |
ExpiredTimestampError | 401 | Callback timestamp is outside the accepted time window. |
MalformedCallbackError | 400 | Required callback fields are missing or unparseable. |
Testing & Credentials
Use the built-in test credentials for local development. Import them from the @helix-id/voice-auth/testing sub-path.
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",
});| Credential | Value |
|---|---|
| Space ID | a1b2c3d4-e5f6-7890-abcd-ef1234567890 |
| Secret | tk_test_hx_4a7f2c9d8e1b3f6a5c2d9e8f7b4a1c3d |
| Callback URL | http://localhost:8080/helix/callback |
Important
Never use test credentials in production. Rotate your production secret regularly.
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.