Legichain node SDK v2
Official SDK for the existing Legichain API. KYC v2 integration and migration contains the current wire contract, check flags, asynchronous evidence and submission behavior. Version: 2.0.0; publication status is tracked separately.
import { Legichain } from "legichain";
const client = new Legichain({ apiKey: process.env.LEGICHAIN_API_KEY! });
const flow = await client.kyc.start({ subject_external_id: "customer-42" }, { idem: "customer-42-application" });
const receipt = await flow.evidence("documents", body, "customer-42-front-capture-1");
await flow.wait(receipt.operation_id);
// Upload remaining configured evidence, then:
const submission = await flow.submit();
Legichain Node.js / TypeScript SDK
Official client for the Legichain AML, KYC and Travel Rule API.
npm install legichain
# or
pnpm add legichain
# or
yarn add legichain
- TypeScript-first with full types for every response
- Native
fetch(Node 18+) — zero runtime dependencies - Dual ESM + CommonJS build
- HMAC webhook verification helper
Get an API key
Sign up at https://legichain.com — the Free plan ships with 1 RPS and 300 monthly credits, no card required. Once signed in:
panel.legichain.com → Settings → API Keys → New key
Keys look like lc_live_<22>.sk_live_<44> (production) or
lc_test_<22>.sk_test_<44> (test mode, never spends credits). Store
them in your secret manager — the secret half is shown once and can't
be recovered. See the full API guide
for plans, rate limits and reference docs.
Quick start
import { Legichain } from "legichain";
const lc = new Legichain({
apiKey: process.env.LEGICHAIN_API_KEY!,
// baseUrl: "https://api.legichain.com", // override for staging
});
// Screen a person — every response carries summary.recommendation
// so banks can branch in one line.
const r = await lc.screen.person({
name: "Vladimir Putin",
country: "RU",
dob: "1952-10-07",
});
if (r.summary.recommendation === "block") {
await denyOnboarding(customerId);
} else if (r.summary.recommendation === "review") {
await queueForCompliance(customerId, r.screening_id);
} else {
await approveOnboarding(customerId);
}
console.log(`${r.cost_credits} credits spent; ${r.credits_remaining} remaining`);
Company + crypto wallet
const company = await lc.screen.company({
name: "Rosneft Oil Company",
country: "RU",
});
const wallet = await lc.screen.crypto({
address: "0x098B716B8Aaf21512996dC57EB0615e2383E2f96",
});
Batch (sync + async)
// Up to 200 items synchronously
const out = await lc.screen.batch([
{ name: "Acme Trading GmbH" },
{ address: "TVj7RNVH…", chain: "tron" },
{ name: "Maria Lopez", country: "ES" },
]);
// Async batch → result delivered to your webhook
const job = await lc.screen.batchAsync(items);
console.log(job.job_id); // 01HXYZ…
// later …
console.log(await lc.screen.job(job.job_id));
PDF reports
import { writeFile } from "node:fs/promises";
const pdf = await lc.reports.wallet({
address: "0x6c0bD2BB04Fda9CBfeBb8DC1208Db32a0F8a4Edd",
chain: "eth",
});
await writeFile("wallet.pdf", pdf); // Uint8Array
await writeFile(
"putin.pdf",
await lc.reports.person({ name: "Vladimir Putin", country: "RU" }),
);
Idempotency
await lc.screen.person(
{ name: "Maria Lopez" },
{ idem: "onboarding-2026-05-20-7f3c" },
);
// Re-running with the same `idem` within 24 h returns the cached
// response and the `Idempotent-Replay: true` header.
Error handling
import { LegichainError } from "legichain";
try {
await lc.screen.person({ name: "x" });
} catch (err) {
if (err instanceof LegichainError) {
console.log(err.status, err.code, err.detail);
// err.errors[] for field-level validation problems
} else {
throw err;
}
}
LegichainError.code enumerates everything in the API guide
(AUTH_002_INVALID_TOKEN, BIL_001_INSUFFICIENT_CREDITS,
RL_001_RATE_LIMITED, …).
Webhook verification
import express from "express";
import { verifyWebhookSignature } from "legichain/webhooks";
const app = express();
app.post(
"/webhooks/legichain",
express.raw({ type: "application/json" }),
(req, res) => {
const ok = verifyWebhookSignature({
body: req.body,
signature: String(req.headers["legichain-signature"] ?? ""),
secret: process.env.LEGICHAIN_WEBHOOK_SECRET!,
});
if (!ok) return res.status(401).end();
const evt = JSON.parse(req.body.toString("utf8"));
if (evt.event === "screen.batch.completed") {
// …
}
res.json({ ok: true });
},
);
TypeScript types
Every public response is fully typed — start with ScreeningResponse:
import type {
Legichain, ScreeningResponse, Hit, HitFlags, ScreeningSummary,
Recommendation, RiskLevel, ProblemDetails,
} from "legichain";
hit.flags.is_sanctioned, summary.recommendation,
summary.top_risk_level, hits[].risk_score — typed everywhere.
Reference
| Method | Endpoint |
|---|---|
lc.screen.person(q) |
POST /v1/screen/person |
lc.screen.company(q) |
POST /v1/screen/company |
lc.screen.crypto(q) |
POST /v1/screen/crypto |
lc.screen.batch(items) |
POST /v1/screen/batch |
lc.screen.batchAsync(items) |
POST /v1/screen/batch/async |
lc.screen.job(jobId) |
GET /v1/screen/jobs/{id} |
lc.reports.wallet(q) |
POST /v1/reports/wallet (PDF) |
lc.reports.person(q) |
POST /v1/reports/person (PDF) |
lc.reports.company(q) |
POST /v1/reports/company (PDF) |
lc.status() |
GET /v1/status |
Versioning & support
- Tracks API
v1. Breaking changes ship on/v2/with ≥ 6 months overlap. - Status: https://legichain.com/status
- Email:
contact@legichain.com - GitHub: https://github.com/legichain/legichain-node