valyd-verify-sdk
v0.1.0
Published
Official Node.js SDK for Valyd Verify — hosted identity verification, standalone checks (KYC, liveness, face match, license) and signed webhooks.
Maintainers
Readme
valyd-verify-sdk
Official Node.js SDK for Valyd Verify — hosted identity verification, standalone checks (KYC, liveness, face match, professional-license) and signed webhooks.
- Zero runtime dependencies (native
fetch, Node 18+) - Typed requests/responses, typed errors (
ValydVerifyError) - Stripe-style webhook verification
- Server-side only — your API key never touches the browser
npm i valyd-verify-sdkQuickstart
import { VerifyClient } from "valyd-verify-sdk";
const verify = new VerifyClient({
apiKey: process.env.VALYD_API_KEY!, // Valyd console → Apps
webhookSecret: process.env.VALYD_WEBHOOK_SECRET, // optional, for webhooks
});| Option | Default | |
|---|---|---|
| apiKey | — | required — sent as X-API-Key |
| baseUrl | https://verify.pollus.tech | API base |
| webhookSecret | — | lets webhooks.constructEvent skip the secret arg |
| timeoutMs | 15000 | per-request timeout |
| fetch | global | custom fetch impl |
Hosted verification
Redirect the user to a Valyd-hosted page that captures everything; receive the result via a signed webhook + the decision API. Two products, same code — only the workflowId differs:
- License Verification — workflow features
[credential] - KYC + License —
[id_verification, liveness, face_match, credential](the license is checked against the name read from the verified ID)
// 1. Create a session and redirect the user to session.url
const session = await verify.sessions.create({
workflowId: process.env.VALYD_WORKFLOW_ID!,
redirectUrl: "https://app.com/verify/done",
callback: "https://app.com/api/valyd/webhook",
vendorData: user.id,
});
res.redirect(session.url);// 2. Webhook endpoint — pass the RAW request body
const event = verify.webhooks.constructEvent(rawBody, req.headers);
if (["APPROVED", "DECLINED", "IN_REVIEW"].includes(event.status)) {
const decision = await verify.sessions.decision(event.sessionId);
// decision.checks → act on the outcome
}The decision endpoint is the source of truth; the ?status= on your redirectUrl is only a hint. See examples/express-hosted.ts.
Sessions API
verify.sessions.create(params) // → Session (has .url, .sessionId)
verify.sessions.retrieve(id) // → SessionSummary
verify.sessions.list({ status, vendorData, limit })
verify.sessions.decision(id) // → Decision (with checks[])
verify.sessions.updateStatus(id, "APPROVED" | "DECLINED")Standalone checks (server-to-server)
Build your own UI and call the engines directly. Images accept a Buffer, Uint8Array, base64/data-URL string, or use readImage("./path.jpg").
import { readImage } from "valyd-verify-sdk";
await verify.standalone.idVerification({ frontImage: readImage("./id.jpg"), backImage });
await verify.standalone.liveness({ image: selfie });
await verify.standalone.faceMatch({ idImage, selfie });
await verify.standalone.ageVerification({ dob: "1998-05-01", bands: ["is_18_plus"] });
await verify.standalone.credentialVerification({ providerCode, licenseState: "CA", licenseNumber, firstName, lastName });
// Combined: ID + liveness + face match, then license checked vs the OCR'd name
const r = await verify.standalone.kycCredential({ frontImage, selfie, licenseState: "CA", licenseNumber, providerCode });
r.identity; // { name, dob } r.checks; // [{ type, status, ... }]Credential discovery (build state / license-type pickers)
const states = await verify.credentials.states(); // [{ stateName, stateCode }]
const providers = await verify.credentials.providers("CA"); // [{ providerCode, credentialName, requiredFields }]Workflows
await verify.workflows.create({ name: "KYC + License", features: ["id_verification","liveness","face_match","credential"] });
await verify.workflows.list();
await verify.workflows.update(id, { isActive: false });
await verify.workflows.remove(id);Webhooks
Signature = hmac_sha256(${timestamp}.${rawBody}, secret) over headers X-Valyd-Timestamp / X-Valyd-Signature. Always verify against the raw body.
import { constructEvent } from "valyd-verify-sdk"; // or verify.webhooks.constructEvent
const event = constructEvent(rawBody, req.headers, process.env.VALYD_WEBHOOK_SECRET!, { toleranceSeconds: 300 });Throws ValydVerifyError (code: "invalid_signature") on mismatch or a stale timestamp. A boolean verify(...) variant is also exported.
Errors
Every failure throws ValydVerifyError with a machine-readable code (from the API, e.g. API_KEY_INVALID, or the SDK, e.g. network_error, timeout, invalid_signature), an optional HTTP status, and any data the API attached.
import { ValydVerifyError } from "valyd-verify-sdk";
try { await verify.sessions.create({ workflowId }); }
catch (e) { if (e instanceof ValydVerifyError) console.error(e.code, e.status, e.message); }Statuses
Session: NOT_STARTED → IN_PROGRESS → (IN_REVIEW) → APPROVED | DECLINED, plus ABANDONED, EXPIRED. Check: pending | running | passed | failed | review.
License
MIT
