SDKs & LibrariesNode.js
SDK v1.4Enterprise DX
Node.js
Official xaqiiji-sdk npm package and REST guides aligned with the live Xaqiiji API.
Overview
Server-side Node.js 18+ integration for Express, Fastify, NestJS, and background workers.
Install
npm
npm install xaqiiji-sdkConfigure client
setup
import { Xaqiiji } from "xaqiiji-sdk";const client = new Xaqiiji({ apiKey: process.env.XAQIIJI_API_KEY!, environment: "test", // use "live" with xq_live_* keys});// Optional: override API host (defaults to https://xaqiiji-api.ahmed-dalab.com)const client = new Xaqiiji({ apiKey: process.env.XAQIIJI_API_KEY!, environment: process.env.XAQIIJI_API_KEY?.startsWith("xq_test_") ? "test" : "live", baseUrl: process.env.XAQIIJI_BASE_URL,});Environment variables
.env
XAQIIJI_API_KEY=xq_test_xxxxxxxxxxxxxx# Optional — defaults to https://xaqiiji-api.ahmed-dalab.comXAQIIJI_BASE_URL=https://xaqiiji-api.ahmed-dalab.comQuick start
example
import { Xaqiiji } from "xaqiiji-sdk";const client = new Xaqiiji({ apiKey: process.env.XAQIIJI_API_KEY!, environment: "test", // use "live" with xq_live_* keys});const result = await client.verify.citizen( { nationalId: "12345678901", purpose: "pre_employment", }, { idempotencyKey: "verify-2026-06-02-001" },);console.log(result.result); // verified | not_found | expired | ...console.log(result.reference); // certificate reference numberconsole.log(result.isCached); // true when replayed within idempotency windowconsole.log(result.citizen?.fullName);Verify citizen
verify.citizen()
const result = await client.verify.citizen( { nationalId: "12345678901", purpose: "pre_employment", }, { idempotencyKey: "verify-2026-06-02-001" },);console.log(result.result); // verified | not_found | expired | ...console.log(result.reference); // certificate reference numberconsole.log(result.isCached); // true when replayed within idempotency windowconsole.log(result.citizen?.fullName);Error handling
try/catch
import { XaqiijiAuthError, XaqiijiInsufficientCreditsError, XaqiijiInvalidFormatError, XaqiijiRateLimitError,} from "xaqiiji-sdk";try { await client.verify.citizen({ nationalId: "12345678901", purpose: "pre_employment", });} catch (err) { if (err instanceof XaqiijiInsufficientCreditsError) { // Top up credits in the business portal } else if (err instanceof XaqiijiInvalidFormatError) { // National ID must be exactly 11 digits } else if (err instanceof XaqiijiAuthError) { // Missing, invalid, or revoked API key } else if (err instanceof XaqiijiRateLimitError) { // Back off using err.retryAfter (seconds) } else { throw err; }}Retries & idempotency
best practice
// The SDK retries HTTP 503 automatically (default: 2 attempts).// Pass an idempotency key when calling verify.citizen() for safe retries:await client.verify.citizen( { nationalId: "12345678901", purpose: "pre_employment" }, { idempotencyKey: "verify-2026-06-02-001" },);Production checklist
Before going live
Keep all API calls on trusted backend services — never expose API keys in browsers or mobile apps.
Store API keys in encrypted environment variables or a secret manager.
Use xq_test_* keys for development and xq_live_* keys only after business approval.
Verify webhook signatures before processing events.
Log reference and verification IDs, but never log API keys or raw national IDs.
Use idempotency keys on verify.citizen() and handle XaqiijiRateLimitError with backoff.
Troubleshooting
Common issues
401 — API key missing, revoked, or wrong environment (test vs live prefix).
402 — insufficient credits; top up in the business portal.
400 — validation failed; national ID must be exactly 11 digits and purpose must be a supported enum value.
429 — rate limited; use err.retryAfter from XaqiijiRateLimitError.
503 — identity registry temporarily unavailable (mock offline or live adapter not configured); SDK retries automatically, then throws XaqiijiServiceUnavailableError.
XaqiijiPortalSessionError — keys.* and billing.createStripeCheckout() always throw; use the business portal.
Edit this page
Was this page helpful?