Skip to main content

@zyphe-sdk/node

Install the package:

pnpm add @zyphe-sdk/node

1. Webhook Signature Verification

This package provides the core webhook signature verification logic for Zyphe. It enables secure verification of incoming webhook requests in Node.js using HMAC-SHA256 signatures.

Basic Usage

import { verifyWebhookSignatureHeader } from '@zyphe-sdk/node'

const secretHex = '<your-hex-encoded-secret>'
const rawBodyString = '...' // The raw request body as a string
const signatureHeader = 't=1234567890,v0=abcdef...' // The signature header from the webhook

const isValid = verifyWebhookSignatureHeader(secretHex, rawBodyString, signatureHeader)
if (isValid) {
// Signature is valid
} else {
// Signature is invalid
}
  • secretHex: The hex-encoded secret key used to sign the webhook.
  • rawBodyString: The raw request body as a string (must match exactly what was sent).
  • signatureHeader: The signature header string, e.g. t=1234567890,v0=abcdef....
  • Returns: true if the signature is valid, or false otherwise.

Advanced Utilities

  • parseSignatureHeader(signatureHeader) – Parse the signature header into timestamp and signature.
  • hexToBytes(hex) / bufferToHex(buffer) – Convert between hex and bytes.
  • timingSafeEqual(a, b) – Constant-time string comparison.
  • Error codes/messages for robust error handling.

2. Verification Session Management

You can programmatically create verification sessions and construct user-facing URLs for onboarding flows.

Create a Verification Session

import { createVerificationSession } from '@zyphe-sdk/node'

const response = await createVerificationSession(
{
email: 'user@example.com', // required
flowId: '<flowId>', // required
flowStepId: '<flowStepId>', // required
isSandbox: false, // required
customData: {
// optional
walletAddress: '0x123...',
// ...any extra data you want to pass
},
},
{
apiKey: '<your-api-key>',
environment: 'staging', // or "production", "local"
handoffBaseUrl: 'https://your-app.com', // optional
primaryColor: '#000000', // optional
secondaryColor: '#ffffff', // optional
isFullscreen: true, // optional
},
)
  • customData (optional): Pass any extra data you want to associate with the verification session. This will be available in the webhook payload and session data.
  • The function returns a Promise resolving to the API response. Handle errors as needed (e.g., try/catch or checking for error fields).

Construct a Verification Session URL

import { constructVerificationSessionUrl } from '@zyphe-sdk/node'

const url = constructVerificationSessionUrl({
flowParams: {
flowId: '...',
flowStepId: '...',
email: 'user@example.com',
product: 'kyc', // or "kyb" if supported
isSandbox: false,
customData: { walletAddress: '0x123...' }, // optional
},
verificationSession: response.data, // from createVerificationSession
opts: {
apiKey: '<your-api-key>',
environment: 'staging',
handoffBaseUrl: 'https://your-app.com', // optional
primaryColor: '#000000', // optional
secondaryColor: '#ffffff', // optional
isFullscreen: true, // optional
},
})
  • The constructed URL includes all relevant parameters and can be used to embed or redirect users to the verification flow.
  • Optional fields (like handoffBaseUrl, primaryColor, etc.) will be appended as query parameters if provided.

Types

  • InitializeZypheFlowParams: Parameters for initializing a verification flow.
  • SDKOptions: Configuration for the SDK.
  • SdkCreateVerificationRequestResponse: API response type for session creation.

Error Handling

  • If session creation fails, the function may throw or return an error object depending on usage context. Always check for errors and handle them appropriately.
  • Example:
try {
const response = await createVerificationSession(...);
if (response.error) {
// Handle error
console.error(response.error);
} else {
// Success
}
} catch (err) {
// Handle thrown errors (e.g., network issues)
console.error(err);
}

3. Complete Verification Steps

The Node SDK also includes helpers for completing document selection, document verification, and liveness steps from your backend.

Typical flow:

  1. Create a verification session with createVerificationSession.
  2. Check the current step with getNextStepDetails if you need to branch dynamically.
  3. Complete document selection with completeDocumentSelectionStep when the next step is document-selection.
  4. Upload document images with completeDvStep when the next step is a document verification step.
  5. Complete liveness with completeLivenessStep when the flow requires liveness.

Inspect the Next Step

import { getNextStepDetails, type SDKOptions } from '@zyphe-sdk/node'

const opts: SDKOptions = {
apiKey: '<your-secret-api-key>',
environment: 'staging',
}

const { error, data: nextStep } = await getNextStepDetails(
{
flowId: '<flow-id>',
email: 'user@example.com',
isSandbox: true,
},
opts,
)

if (error) {
console.error(error)
} else {
console.log('Next step:', nextStep)
}
  • Use getNextStepDetails to decide whether to ask for document selection, document images, liveness capture, or another step.
  • This helper calls the sdk_get_next_step endpoint documented in docs/openapi/sdk-get-next-step.api.mdx.

Complete Document Selection and Document Verification

import { completeDocumentSelectionStep, completeDvStep, createVerificationSession, DocumentType, type SDKOptions } from '@zyphe-sdk/node'
import { readFile } from 'node:fs/promises'

async function readBase64File(filePath: string) {
return (await readFile(filePath)).toString('base64')
}

const opts: SDKOptions = {
apiKey: '<your-secret-api-key>',
environment: 'staging',
}

const verificationSessionResponse = await createVerificationSession(
{
email: 'user@example.com',
flowId: '<flow-id>',
flowStepId: '<document-selection-step-id>',
isSandbox: true,
},
opts,
)

if (verificationSessionResponse.error || !verificationSessionResponse.data) {
throw new Error('Failed to create verification session')
}

await completeDocumentSelectionStep(
{
verificationSession: verificationSessionResponse.data,
payload: {
country: 'IT',
documentType: DocumentType.IDENTITY_CARD,
},
},
opts,
)

const dvResult = await completeDvStep(
{
verificationSession: verificationSessionResponse.data,
countryCode: 'IT',
images: {
type: 'DOUBLE_SIDED_DOCUMENT',
frontImage: await readBase64File('./front.jpg'),
backImage: await readBase64File('./back.jpg'),
},
},
opts,
)

console.log('DV step completed')
console.log(dvResult)
  • This example follows ../zyphe-sdk/examples/node-complete-step-dv/src/index.ts.
  • Use DocumentType.IDENTITY_CARD, DocumentType.DRIVING_LICENSE, or DocumentType.PASSPORT when selecting the document type.
  • completeDvStep accepts either:
    • type: 'DOUBLE_SIDED_DOCUMENT' with frontImage and backImage
    • type: 'SINGLE_SIDED_DOCUMENT' with a single image
  • Image values must be base64-encoded strings.
  • The SDK returns the API response for the submitted document job, including the verification request ID and job ID.

Complete a Liveness Step

import { completeLivenessStep, createVerificationSession, type SDKOptions } from '@zyphe-sdk/node'
import { readFile } from 'node:fs/promises'

async function readBinaryFile(filePath: string) {
return new Uint8Array(await readFile(filePath))
}

const opts: SDKOptions = {
apiKey: '<your-secret-api-key>',
environment: 'staging',
}

const verificationSessionResponse = await createVerificationSession(
{
email: 'user@example.com',
flowId: '<flow-id>',
flowStepId: '<liveness-step-id>',
isSandbox: true,
},
opts,
)

if (verificationSessionResponse.error || !verificationSessionResponse.data) {
throw new Error('Failed to create verification session')
}

const calibrationImage = await readBinaryFile('./calibration.jpg')
const video = await readBinaryFile('./liveness.mp4')
const movementImages = await Promise.all(['./movement-1.jpg', './movement-2.jpg'].map((filePath) => readBinaryFile(filePath)))

const livenessResult = await completeLivenessStep(
{
verificationSession: verificationSessionResponse.data,
frontImage: Buffer.from(calibrationImage),
video: Buffer.from(video),
movementImages: movementImages.map((image) => Buffer.from(image)),
},
opts,
)

console.log('Liveness step completed')
console.log(livenessResult)
  • This example follows ../zyphe-sdk/examples/node-complete-step-liveness/src/index.ts.
  • completeLivenessStep first fetches the challenge configuration, uploads the required assets to the provided presigned URLs, and then calls the final liveness processing endpoint.
  • For active liveness challenges, you must provide a video and the same number of movementImages requested by the challenge.
  • frontImage is the calibration image uploaded before the final liveness submission.

4. Flow Results

You can use the Node SDK to list flow results for a flow and fetch a single flow result by ID.

List Flow Results

import { listFlowResults, type SDKOptions } from '@zyphe-sdk/node'

const opts: SDKOptions = {
apiKey: '<your-secret-api-key>',
environment: 'staging',
}

const { error, data } = await listFlowResults(
{
organizationId: '<organization-id>',
flowSlug: '<flow-slug>',
isSandbox: true,
pagination: {
take: 10,
skip: 0,
},
},
opts,
)

if (error) {
console.error(error)
} else {
console.log('Total flow results:', data?.totalCount ?? 0)
console.log('Current page:', data?.page ?? [])
}
  • organizationId: The organization that owns the flow results.
  • flowSlug: The flow slug used to scope the results.
  • isSandbox: Set to true for sandbox data and false for production data.
  • pagination (optional): Use take, skip, sort, and filter to control paging.
  • locale (optional): Localize fields that support translated values.
  • Returns: A Promise resolving to a paginated response with totalCount and a page array of flow results.

Get a Flow Result

import { getFlowResult, type SDKOptions } from '@zyphe-sdk/node'

const opts: SDKOptions = {
apiKey: '<your-secret-api-key>',
environment: 'staging',
}

const { error, data: flowResult } = await getFlowResult(
{
organizationId: '<organization-id>',
flowResultId: '<flow-result-id>',
isSandbox: true,
},
opts,
)

if (error) {
console.error(error)
} else {
console.log('Flow result:', flowResult)
}
  • flowResultId: The ID of the specific flow result you want to retrieve.
  • Returns: A Promise resolving to the full flow result payload, including result collections such as dvResults, poaResults, and amlResults when available.

5. Types and Configuration

  • InitializeZypheFlowParams, SDKOptions, SdkCreateVerificationRequestResponse – for type-safe integration.
  • Environments, EnvironmentConfigs, API_KEY_HEADER – for environment and API configuration.