Node.js SDK
Official typed Node.js / TypeScript wrapper for VerifyMX. Handles auth, retries, idempotency, webhook signatures and polling so you don't have to.
The official Node.js SDK is a thin, typed wrapper around the REST API. It
handles OAuth token caching + refresh, retries on rate-limit and 5xx,
idempotency-key generation, multipart uploads, HMAC webhook signature
verification, and a waitUntilTerminal() polling helper.
Status:
0.1.0-beta— API surface is stable, minor pre-1.0 changes still possible. See the changelog. Requires Node 18+ (uses nativefetchandFormData).
Install
npm install @verifymx/sdk-node
# or
pnpm add @verifymx/sdk-node
# or
yarn add @verifymx/sdk-node
First call
import { VerifyMXClient } from '@verifymx/sdk-node';
import { readFileSync } from 'node:fs';
const vmx = new VerifyMXClient({
clientId: process.env.VERIFYMX_CLIENT_ID!,
clientSecret: process.env.VERIFYMX_CLIENT_SECRET!,
});
// 1. Create a verification
const ver = await vmx.createVerification({ workflowId: 'wf_default' });
// 2. Upload the user's INE front photo
await vmx.uploadDocument(
ver.id,
readFileSync('./ine-front.jpg'),
'ine-front.jpg',
'front',
);
// 3. Wait for the verdict
const result = await vmx.waitUntilTerminal(ver.id);
// result.status: 'APPROVED' | 'REJECTED' | 'MANUAL_REVIEW' | 'EXPIRED'
That's the full happy path. ~5 lines replaces ~80 of raw fetch + auth +
retry + idempotency boilerplate.
Configuration
new VerifyMXClient({
clientId: '...', // required
clientSecret: '...', // required
apiUrl: 'https://api.verifymx.xyz', // default; override for staging
timeoutMs: 30_000, // per-request timeout
retries: {
max: 3, // max retries after the first try
baseDelayMs: 500, // doubles per attempt, capped at 16s
},
userAgent: 'my-app/1.4.2', // optional, appended to the SDK UA
});
Typed error handling
Every error thrown by the SDK extends VerifyMXError. HTTP-class subclasses
let you branch with instanceof:
import {
RateLimitedError,
UnauthorizedError,
ValidationError,
VerifyMXError,
} from '@verifymx/sdk-node';
try {
await vmx.createVerification({ workflowId: 'wf_default' });
} catch (err) {
if (err instanceof RateLimitedError) {
// SDK exhausted retries. Caller is over budget.
console.warn(`Wait ${err.retryAfter}s`);
} else if (err instanceof UnauthorizedError) {
console.error('Bad credentials.');
} else if (err instanceof ValidationError) {
console.error('Bad input:', err.details);
} else if (err instanceof VerifyMXError) {
console.error(`code=${err.code} requestId=${err.requestId}`);
} else {
throw err;
}
}
The code field on VerifyMXError mirrors the server's stable taxonomy
('WORKFLOW_INACTIVE', 'CURP_STATUS_ANNULLED', 'VALIDATION_ERROR', ...).
Branch on err.code for business-rule failures, on the instanceof
hierarchy for HTTP-class buckets.
Webhook signature verification
The SDK ships a constant-time HMAC verifier plus an Express/Fastify- compatible middleware:
import express from 'express';
import { webhookMiddleware } from '@verifymx/sdk-node';
const app = express();
app.post(
'/webhooks/verifymx',
express.raw({ type: 'application/json' }), // raw body required
webhookMiddleware(process.env.WEBHOOK_SECRET!),
(req, res) => {
const event = JSON.parse(req.body.toString('utf-8'));
// event.type === 'verification.approved' | ...
res.status(200).send('ok');
},
);
Important: always pass the raw request body to the verifier. If you pass parsed JSON re-serialised, the HMAC will mismatch on whitespace and key ordering. See the Webhooks page for the full signature scheme.
What the SDK takes care of for you
- OAuth client_credentials with a cached token and refresh 30 s before expiry.
- Retry with backoff on HTTP 429 (honors
Retry-After), 5xx, and transient network errors. Default: 3 retries, exponential backoff capped at 16 s. - Idempotency keys auto-generated on every
POSTso retries are safe. Override with{ idempotencyKey }when you need cross-process dedup. - Polling with timeout:
waitUntilTerminal(). - Per-request timeout via
AbortSignal.timeout(default 30 s). - Native
fetch+FormData— no third-party HTTP client.
Method reference
| Method | Endpoint |
|---|---|
createVerification(input) | POST /v1/verifications |
getVerification(id) | GET /v1/verifications/:id |
listVerifications(opts?) | GET /v1/verifications |
updateVerificationStatus(id, status, notes?) | PATCH /v1/verifications/:id/status |
uploadDocument(id, buf, filename, type) | POST /v1/verifications/:id/inputs |
waitUntilTerminal(id, opts?) | polling helper |
createWorkflow(data) / getWorkflow(id) / listWorkflows() / updateWorkflow(id, data) / deleteWorkflow(id) | /v1/workflows |
createWebhook(url, events) / listWebhooks() / deleteWebhook(id) | /v1/webhooks |
screenName(name, opts?) / getAmlLists() | /v1/aml |
sendOtp(...) / verifyOtp(...) | /v1/otp/{send,verify} |
Source
- npm:
@verifymx/sdk-node - GitHub:
Ivanull/verifymx - Issues: GitHub Issues
- License: Apache-2.0