compliancelayer
v1.0.1
Published
Official Node.js SDK for the ComplianceLayer security scanning API
Maintainers
Readme
ComplianceLayer Node.js SDK
Official Node.js/TypeScript SDK for the ComplianceLayer security scanning API. Run external security scans against any domain and get A-F graded reports covering SSL/TLS, DNS, headers, ports, breach detection, and more.
Installation
npm install compliancelayerRequires Node.js 18 or later. Zero runtime dependencies -- uses native fetch.
Quick Start
import { ComplianceLayer } from "compliancelayer";
const client = new ComplianceLayer({
apiKey: "cl_your_api_key",
});
// Submit a scan and wait for results
const job = await client.scanAndWait("example.com");
console.log(`${job.domain}: ${job.grade} (${job.score}/100)`);
// Get the full report
const report = await job.getReport();
for (const [category, result] of Object.entries(report.categories)) {
console.log(`${category}: ${result.status}`);
}Async Scanning
For more control over the scan lifecycle, submit and poll separately:
// Submit a scan (returns immediately)
const job = await client.scan("example.com");
console.log(`Job ${job.jobId} queued`);
// Poll for completion with custom interval
const completed = await client.waitForCompletion(job.jobId, {
pollInterval: 5000, // check every 5 seconds
pollTimeout: 180000, // give up after 3 minutes
});
// Or poll manually
await job.refresh();
if (job.isComplete) {
const report = await job.getReport();
}Batch Scanning
Scan up to 50 domains in a single request:
const batch = await client.batchScan([
"example.com",
"github.com",
"cloudflare.com",
]);
// Batch scans run synchronously and return a score summary per domain
console.log(`${batch.total} domains, average score ${batch.summary.avgScore}`);
for (const result of batch.results) {
console.log(`${result.domain}: ${result.overallGrade} (${result.overallScore})`);
}
// Or compare domains side by side
const comparison = await client.batchCompare([
"example.com",
"github.com",
]);Free Scan
Run a quick scan without authentication (rate limited to 5/hour per IP):
const result = await client.freeScan("example.com");
console.log(`Score: ${result.score}, Grade: ${result.grade}`);Webhooks
Receive notifications when scans complete:
// Create a webhook
// The signing secret is generated by the API and returned once, on create.
const webhook = await client.webhooks.create({
url: "https://your-server.com/hooks/compliance",
enabled_events: ["scan.completed", "scan.failed"],
description: "Production listener",
});
console.log(`Signing secret: ${webhook.secret}`);
// Test it
const test = await client.webhooks.test(webhook.id);
console.log(`Delivery ${test.success ? "succeeded" : "failed"}`);
// List all webhooks
const webhooks = await client.webhooks.list();
// Update
await client.webhooks.update(webhook.id, { is_active: false });
// Check delivery history
const deliveries = await client.webhooks.deliveries(webhook.id);
// Delete
await client.webhooks.delete(webhook.id);Domain Monitoring
Track domains and receive alerts:
// Add a domain
const domain = await client.domains.create({ domain: "example.com" });
// List monitored domains, plus how many of your quota are in use
const { domains, limitUsed, limitMax } = await client.domains.list();
console.log(`Monitoring ${limitUsed} of ${limitMax} domains`);
// Trigger a scan for a monitored domain
const job = await client.domains.scan(domain.id);
// Check alerts across all domains
const alerts = await client.domains.alerts();
// Remove a domain
await client.domains.delete(domain.id);Security Badges
Embed a security badge on your site:
// Get badge URLs (no API call needed)
const svgUrl = client.badgeSvgUrl("example.com");
// => "https://api.compliancelayer.net/v1/badge/example.com.svg"
// Fetch badge data as JSON
const badge = await client.getBadge("example.com");
console.log(`${badge.domain}: ${badge.grade}`);Use in HTML:
<img src="https://api.compliancelayer.net/v1/badge/example.com.svg" alt="Security Score" />Scan History
const history = await client.history({ limit: 20 });
for (const scan of history.scans) {
console.log(`${scan.domain}: ${scan.grade} (${scan.scannedAt})`);
}Account Info
const account = await client.me();
console.log(`Plan: ${account.plan}`);
console.log(`Scans: ${account.scansThisMonth}/${account.scanLimit}`);
console.log(`Remaining this month: ${account.scansRemaining}`);
// /v1/auth/me reports the domain quota but not how many are in use --
// read limitUsed from the domain list for that.
console.log(`Domain limit: ${account.domainLimit}`);Error Handling
The SDK throws typed errors for different failure modes:
import {
ComplianceLayer,
AuthenticationError,
QuotaExceededError,
RateLimitError,
ScanTimeoutError,
NotFoundError,
ValidationError,
} from "compliancelayer";
try {
const job = await client.scanAndWait("example.com");
} catch (error) {
if (error instanceof AuthenticationError) {
// Invalid API key (401)
} else if (error instanceof QuotaExceededError) {
// Plan scan limit reached (429, not retried)
} else if (error instanceof RateLimitError) {
// Rate limited after all retries exhausted (429)
} else if (error instanceof ScanTimeoutError) {
// Polling timed out; scan may still be running
console.log(`Timed out waiting for job ${error.jobId}`);
} else if (error instanceof NotFoundError) {
// Resource does not exist (404)
} else if (error instanceof ValidationError) {
// Invalid request (422)
}
}Error hierarchy:
| Error | HTTP Status | Retried? |
|-------|------------|----------|
| AuthenticationError | 401 | No |
| ForbiddenError | 403 | No |
| NotFoundError | 404 | No |
| ValidationError | 409, 422 | No |
| QuotaExceededError | 429 (quota) | No |
| RateLimitError | 429 (rate) | Yes |
| ScanError | 500 (scan failed) | No |
| APIError | 5xx | Yes |
| ScanTimeoutError | N/A | N/A |
Configuration
const client = new ComplianceLayer({
apiKey: "cl_your_key", // Required. Must start with "cl_".
baseUrl: "https://...", // Default: "https://api.compliancelayer.net"
timeout: 30000, // Request timeout in ms. Default: 30000.
pollInterval: 3000, // Scan polling interval in ms. Default: 3000.
pollTimeout: 120000, // Max time to wait for scan completion. Default: 120000.
maxRetries: 3, // Retries for 429/5xx errors. Default: 3.
fetch: customFetch, // Injectable fetch for testing or custom environments.
});TypeScript
All types are exported:
import type {
ScanJobResponse,
ScanReport,
ScanResult,
CategoryResult,
Finding,
Grade,
Webhook,
Domain,
DomainAlert,
AccountInfo,
BadgeJson,
} from "compliancelayer";License
MIT
