Skip to content

Repository files navigation

SanctionsKit for JavaScript and TypeScript

The official Node.js SDK for the SanctionsKit API. Screen people and organizations against selected sanctions and watchlist sources, retrieve saved evidence, submit batches, and manage ongoing monitoring.

Documentation · API reference · Create an account · Get an API key

Install

npm install sanctionskit

Requires Node.js 22 or later. Includes TypeScript types, ESM and CommonJS exports, and no runtime dependencies. Use it on your server; API keys must stay out of browser bundles.

Your first screening

  1. Create a workspace and open API keys.
  2. Create a sandbox key with screenings:write and results:read scopes.
  3. Set the key in your server environment, then save this example as screen.mjs.
export SANCTIONSKIT_API_KEY='your-sandbox-api-key'
export REQUEST_KEY="$(node -p 'crypto.randomUUID()')"
import SanctionsKit from 'sanctionskit';

const client = new SanctionsKit({
  apiKey: process.env.SANCTIONSKIT_API_KEY,
});

const { data } = await client.screenings.create(
  {
    subject: {
      name: 'Alex Morgan',
      entityType: 'person',
      birthDate: '1984',
    },
    package: 'sandbox@1',
    reference: 'example-customer-001',
  },
  { idempotencyKey: process.env.REQUEST_KEY },
);

console.log(data.id, data.status);
node screen.mjs

Alex Morgan is an invented subject. sandbox@1 uses synthetic records and does not search live sanctions lists. Follow the quickstart for the full walkthrough.

potential_match means the candidates need review. no_match applies to the supplied information and selected coverage; it is not a clearance decision. Inspect data.matches, data.coverage, and data.versions before taking the next step. An error is an incomplete request, never a no-match result. See screening results.

For CommonJS:

const { SanctionsKit } = require('sanctionskit');

OFAC and sanctions screening

Use the SDK to screen customers and vendors against selected sanctions and watchlist sources. The OFAC SDN guide explains that list's scope, record details, and review limitations.

For production, create a production API key with screenings:write, or batches:write for batch sanctions screening. Add results:read to retrieve saved results and sources:read to call sources.list(). Check the returned availability and supported entity types before selecting a source; a catalog entry alone does not guarantee it can be screened.

When available in your environment, select OFAC SDN with sources: ['ofac-sdn'], or choose a versioned package that includes your required sources. Supply exactly one coverage selector. sandbox@1 contains synthetic records and does not screen live sanctions lists. See source discovery and screening requests for coverage selection and result handling.

The list screening example checks availability and person-screening support before making a request. It works with an explicit source ID:

List Source ID Guide
OFAC SDN ofac-sdn OFAC designations
UK Sanctions List uk-sanctions FCDO UK sanctions
U.S. Consolidated Screening List us-csl CSL scope and restrictions
BIS Denied Persons List us-bis-denied Denial orders and dates

These lists have different meanings. Review the relevant designation or order when interpreting a match. The API remains authoritative about the coverage currently usable by your key.

Retrieve results and evidence

const result = await client.results.retrieve('your-screening-id');
const evidence = await client.results.evidence(result.data.id);

The SDK preserves the API response shape. Most methods return { data }; results.evidence() returns the evidence object directly. Keep evidence in access-controlled storage. See results and evidence.

Methods

Method Purpose Key scope
sources.list() Discover available sources sources:read
policies.list(params?) List approved policies sources:read
policies.retrieve(id) Read a policy sources:read
screenings.create(body, options) Screen one subject screenings:write
results.list(params?) Page through screening history results:read
results.retrieve(id) Read a saved screening results:read
results.evidence(id) Read its evidence results:read
batches.create(body, options) Submit a batch batches:write
batches.list(params?) List batches results:read
batches.retrieve(id, params?) Read progress and row outcomes results:read
batches.cancel(id) Cancel a batch batches:write
usage.retrieve() Read usage and limits usage:read
monitors.create(body, options) Retain a subject for recurring checks monitors:write
monitors.list(params?) List compact monitor records results:read
monitors.retrieve(id) Read a compact monitor record results:read
monitors.update(id, body, options) Replace a monitor definition monitors:write
monitors.delete(id) Stop a monitor and clear its saved request monitors:write
monitoring.list(params?) Read monitor health and revisions results:read
monitoring.update(id, body, options) Pause, resume, change cadence, or queue a check monitors:write
monitoring.inbox.list(params?) List monitoring events results:read
monitoring.inbox.retrieve(id) Read one monitoring event results:read

This release covers these 21 operations. The API reference also documents webhook endpoint management, uploads, counterparties, and review workflows, which you can call with fetch.

List methods return one page per call. Use data.nextCursor for results, policies, and batch lists. Batch row pages use data.nextOffset with batches.retrieve(id, { offset }). Continue until the continuation value is null, even if a page is short. sources.list() returns its source array in data.

Automatic pagination

Use an iterator when you want to read every item without handling page tokens:

for await (const result of client.results.iterate({ summary: true, limit: 100 })) {
  console.log(result.id, result.status);
}

results.iterate(), policies.iterate(), and batches.iterate() accept the same filters and request options as their list methods. batches.iterateRows(id, params?, options?) yields individual batch rows. They fetch one page at a time and request the next only as the loop needs it. A break stops further requests. A supplied signal cancels iteration; timeoutMs applies to each request. Errors reject the loop without retrying.

Wait for a batch

const { data: batch } = await client.batches.waitForCompletion('your-batch-id', {
  timeoutMs: 300_000,
  pollIntervalMs: 5000,
});

console.log(batch.status, batch.completed, batch.failed);
for await (const row of client.batches.iterateRows(batch.id)) {
  console.log(row.row_number, row.status, row.screening_id);
}

The helper polls an existing batch until it is completed, failed, or cancelled. It does not submit work. The defaults are a five-minute total deadline and five seconds between polls. Pass signal to cancel waiting. Cancellation or expiry stops the wait while the batch continues on the service; use batches.cancel(id) if you intend to cancel pending work.

A completed batch can contain failed rows. Inspect each row and handle its error before treating the portfolio as processed. The helper returns the batch detail response with one row page; use iterateRows() for all rows. See the batch guide and complete example.

Ongoing monitoring

const { data: monitor } = await client.monitors.create(
  {
    name: 'Example customer monitoring',
    subject: { name: 'Alex Morgan', entityType: 'person', birthDate: '1984' },
    package: 'sandbox@1',
  },
  { idempotencyKey: process.env.REQUEST_KEY },
);

const { data } = await client.monitoring.list({ monitorId: monitor.id });
const current = data.items.find(({ id }) => id === monitor.id);
console.log(current?.health, current?.lastSuccessfulAt);

Create and update operations require a saved idempotency key. Monitor creation queues the first screening asynchronously. An active monitor has scheduling enabled; inspect health and the latest successful screening before interpreting an outcome. Each completed rescreen uses the applicable screening allowance.

To pause, read the current revision and call monitoring.update(id, { expectedRevision, status: 'paused' }, options); use status: 'active' to resume. The same method accepts intervalHours (6, 24, or 168) or runNow: true. monitors.update() replaces the full name, subject, and coverage definition and also requires expectedRevision. After a stale_revision error, reload the monitor and reconsider the change with a new operation key.

monitors preserves the compact API's snake_case fields. monitoring returns richer camelCase health records and an event inbox. API keys can read inbox events; human review acknowledgement stays in the dashboard. See monitoring for retention, cadence, and event handling.

Verify webhooks

import { verifyWebhook } from 'sanctionskit';

const rawBody = new Uint8Array(await request.arrayBuffer());
const valid = verifyWebhook(
  process.env.SANCTIONSKIT_WEBHOOK_SECRET,
  request.headers,
  rawBody,
);

Call the helper with the exact request bytes before parsing JSON. It checks the signature and a five-minute timestamp window with Node.js built-ins. Use the signing secret returned when registering the endpoint, not your API key. Headers and plain string header records are supported. The optional fourth argument accepts now in Unix seconds and toleranceSeconds; normal receivers should keep the defaults.

Invalid signatures return false. Invalid caller configuration throws a TypeError. Verification authenticates a delivery; your application must still validate the event and deduplicate its ID. The receiver example accepts a Web Request and a durable persistence callback, so it can be used in a Next.js Node route or another server adapter. See webhook setup and delivery handling.

Errors and retries

import { SanctionsKitError } from 'sanctionskit';

try {
  const { data } = await client.usage.retrieve();
  console.log(data);
} catch (error) {
  if (error instanceof SanctionsKitError) {
    console.error(error.status, error.code, error.requestId);
  }
  throw error;
}

API errors expose status, code, message, requestId, retryAfter, and optional details. retryAfter is the raw Retry-After header. Network failures and cancellations reject the request too.

The SDK makes one attempt per call. It does not retry automatically. Generate an idempotency key once for each new screening or batch and save it with the request. After a timeout, retry with the same key and body. A changed body needs a new key. In the quickstart, rerun the script without generating another REQUEST_KEY.

Read idempotency and errors and rate limits before adding retries. rate_limited and usage_cap_reached both use HTTP 429, but waiting alone does not fix an exhausted allowance.

Configuration

const client = new SanctionsKit({
  apiKey: process.env.SANCTIONSKIT_API_KEY,
  timeoutMs: 30_000,
});

const controller = new AbortController();
const result = await client.results.retrieve('your-screening-id', {
  signal: controller.signal,
  timeoutMs: 10_000,
});

Requests default to a 30-second timeout. You can supply fetch for testing and baseURL for a trusted API deployment. The default is https://www.sanctionskit.com/api/v1.

Your API key determines the environment. For production, create a production key, replace sandbox@1 with an available production package, or use sources instead of package. Supply exactly one coverage selector. Workspaces that require approved policies also need a policy ID and version. Review authentication, source availability, policies, and plans.

Examples and development

The examples directory contains short JavaScript and TypeScript scripts. For examples in other languages, see SanctionsKit API examples.

npm ci
npm run check

Tests use local fixtures and do not require API keys. See CONTRIBUTING.md for development and release steps.

License

MIT. The license covers this SDK; use of the hosted API is subject to SanctionsKit's terms.

About

Official JavaScript and TypeScript SDK for the SanctionsKit API. Screen people and organizations, retrieve evidence, and run batch screenings.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages