Skip to content
Docs/SDK/TypeScript
Edit on GitHub

TypeScript SDK

The TypeScript client provides typed clients for APIGuard, NIS2 Compass, and CITADEL, plus a webhook router with HMAC-SHA256 signature verification. It requires Node.js 18+ or a modern browser, and has zero external runtime dependencies. See SDK & Contracts for the full integration contract reference.

Installation

Install the package from npm:

Bash
npm install @opensecstack/sdk

Client construction

Each platform client takes a configuration object with baseURL and apiKey. Optional parameters control request timeouts, retry count, and exponential back-off base. All client methods return Promises and are designed to be used with async/await.

clients.ts
TypeScript
import { APIGuardClient, NIS2CompassClient, CITADELClient } from "@opensecstack/sdk";

class=class="str">"cm">// APIGuard
const apiguard = new APIGuardClient({
  baseURL: "https:class=class="str">"cm">//apiguard.internal",
  apiKey: "ag_key_...",
  timeout: 30_000,    class=class="str">"cm">// ms, optional — default 30 s
  maxRetries: 3,      class=class="str">"cm">// optional
  retryWaitBase: 500, class=class="str">"cm">// ms, optional
});

class=class="str">"cm">// NIS2 Compass
const nis2 = new NIS2CompassClient({
  baseURL: "https:class=class="str">"cm">//nis2compass.internal",
  apiKey: "nis2_key_...",
});

class=class="str">"cm">// CITADEL(HMAC-SHA256 signed)
const citadel = new CITADELClient({
  baseURL: "https:class=class="str">"cm">//citadel.internal",
  keyID: "key-001",
  sharedSecret: "hmac-secret-...",
});

Running a scan

Start an APIGuard scan, wait for it to complete, then retrieve and triage findings. Use createScanFull to specify custom modules, target URL, or authentication.

scan.ts
TypeScript
class=class="str">"cm">// Simple scan from spec URL
const scan = await apiguard.createScan("https:class=class="str">"cm">//example.com/openapi.json");
console.log(class="str">`Scan ID: ${scan.id}, status: ${scan.status}`);

class=class="str">"cm">// Full options — modules, target, bearer auth
const scan2 = await apiguard.createScanFull({
  spec_url: "https:class=class="str">"cm">//example.com/openapi.json",
  target: "https:class=class="str">"cm">//api.example.com",
  modules: ["auth", "injection"],
  auth_type: "bearer",
  auth_token: "tok_...",
});

class=class="str">"cm">// Poll until complete
const completed = await apiguard.getScan(scan.id);

class=class="str">"cm">// Retrieve critical findings(paginated)
const findings = await apiguard.getFindings(scan.id, {
  severity: "critical",
  page: 1,
  per_page: 50,
});

class=class="str">"cm">// Triage a finding
await apiguard.patchFinding(findings[0].id, {
  status: "false_positive",
  note: "Not applicable in our deployment",
});

class=class="str">"cm">// Download a SARIF report
const report = await apiguard.getReport(scan.id, "sarif");

NIS2 Compass client

Create an organisation and assessment, update a NIS2 Article 21 control, and upload evidence artifacts. Controls are addressed by their measure_ref (letters a through j per Article 21(2)).

nis2.ts
TypeScript
class=class="str">"cm">// Create organisation
const org = await nis2.createOrganisation({
  name: "Acme Corp",
  industry: "energy",
  country: "DE",
});

class=class="str">"cm">// Create assessment
const assessment = await nis2.createAssessment(org.id, {
  title: "Q1 2026 NIS2 Assessment",
  framework_version: "2.0",
});

class=class="str">"cm">// List controls that have not been started yet
const controls = await nis2.listControls(assessment.id, {
  status: "not_started",
});

class=class="str">"cm">// Mark control class=class="str">"str">'a' as implemented with notes
await nis2.patchControl(assessment.id, controls[0].measure_ref, {
  status: "implemented",
  notes: "Deployed firewall rules per NIS2 Article 21(2)(a)",
  risk_score: 2.5,
});

class=class="str">"cm">// Upload evidence artifact
const artifact = await nis2.uploadArtifact(
  assessment.id,
  file,
  "evidence",
  { control_id: controls[0].measure_ref, description: "Firewall config evidence", filename: "evidence.pdf" },
);

class=class="str">"cm">// Generate PDF compliance report
const pdf = await nis2.generateReport(assessment.id);

CITADEL client

Send security events to the WORM audit chain and verify chain integrity locally. The CITADEL client also exposes AUGUR advisories for threat intelligence lookups.

citadel.ts
TypeScript
class=class="str">"cm">// Send an event(fire-and-forget)
citadel.sendEvent({
  event_type: "apiguard.scan.completed",
  source: "apiguard",
  actor_id: "system",
  actor_type: "system",
  resource_type: "scan",
  resource_id: scan.id,
  severity: "info",
  payload: { findings_count: 5 },
});

class=class="str">"cm">// Query events from the WORM chain
const events = await citadel.getEvents({
  source: "apiguard",
  since: "2026-03-01T00:00:00Z",
  limit: 100,
});

class=class="str">"cm">// Verify TripleHash chain integrity(throws if chain is broken)
citadel.verifyChain(events);

class=class="str">"cm">// Fetch active AUGUR advisories
const active = await citadel.getActiveAdvisories();

Webhook router

The WebhookRouter verifies incoming HMAC-SHA256 signatures, enforces the ±5-minute replay window, and dispatches typed events to registered handlers. It integrates with any Node.js HTTP server.

webhook.ts
TypeScript
import { WebhookRouter, EventAPIScanCompleted } from "@opensecstack/sdk";
import http from "node:http";

const router = new WebhookRouter("my-shared-secret");

router
  .on(EventAPIScanCompleted, (event) => {
    console.log("Scan completed:", event.id, event.payload);
  })
  .on("*", (event) => {
    console.log("Unhandled event:", event.event_type);
  });

class=class="str">"cm">// Mount on a plain Node.js HTTP server
http.createServer((req, res) => router.handleHttp(req, res)).listen(3000);

For standalone signature verification (useful in Express / Koa middleware):

verify.ts
TypeScript
import { verifySignature, InvalidSignatureError } from "@opensecstack/sdk";

try {
  verifySignature(rawBody, req.headers["x-citadel-signature"] as string, secret);
} catch(err) {
  if (err instanceof InvalidSignatureError) {
    res.status(400).send("Bad signature");
  }
}

Error handling

All client methods throw instances of OpenSecStackError or its subclasses. Catch RateLimitError to implement back-off; its retryAfter property gives the wait time in seconds.

errors.ts
TypeScript
import { OpenSecStackError, RateLimitError } from "@opensecstack/sdk";

try {
  await apiguard.getScan("nonexistent-id");
} catch(err) {
  if (err instanceof RateLimitError) {
    console.log(class="str">`Rate limited — retry after ${err.retryAfter}s`);
  } else if (err instanceof OpenSecStackError) {
    console.log(class="str">`API error ${err.statusCode}: ${err.message}`);
    if (err.code) console.log(class="str">`Error code: ${err.code}`);
  }
}

Full documentation

Other SDK language clients: Go SDK, Python SDK, Rust SDK.

The complete TypeScript client reference — including all method signatures, option types, and configuration defaults — is available in the SDK repository:

https://github.com/opensecstack/opensecstack/tree/main/sdk

SIN — Security Intelligence Network — Open-source cybersecurity & compliance for the EU Digital Decade.

Apache-2.0 & AGPL-3.0 · GitHub · Contribute