Integration tutorial

Sanctions screening API with Node.js and TypeScript

Run a complete TypeScript sanctions screening example using Node.js fetch, a sandbox API key, idempotent requests and explicit error handling.

Updated

Run the example
node screen.ts

Copy the complete code below into a new file.

Runtime
Node.js 24

Built-in fetch; keep your key on the server.

Failures
HTTP status + error code

Inspect status, code, and requestId.

1. Prepare Node.js and your sandbox key

Use Node.js 24, which runs this TypeScript example directly. You do not need npm dependencies or a SanctionsKit client package. Create a sandbox key with screenings:write and results:read in Dashboard → API keys. The authentication guide explains key scopes and rotation.

Set the following variables in a trusted terminal. Replace the placeholder with your own sandbox key. REQUEST_KEY identifies one operation: keep it and the request body unchanged when retrying that operation. Generate a new key only when starting a new screening. For a deployed application, keep the API secret in server-side environment configuration.

1. Prepare Node.js and your sandbox key
export SANCTIONSKIT_API_KEY='YOUR_SANDBOX_KEY'
export REQUEST_KEY="$(node -p 'crypto.randomUUID()')"

2. Copy the complete screening example

Save this as screen.ts. It submits Alex Morgan, an invented sandbox subject, using the sandbox@1 package. The code uses built-in fetch and a 15-second timeout. It sends the same key from your environment each time and performs no automatic retries.

The example checks the HTTP response and the result format before interpreting the outcome. It prints only the screening ID and status on success, or the HTTP status, error code and request ID on failure. Keep the full result in your authorized application workflow; do not log names, identifiers, API keys or full responses.

2. Copy the complete screening example
// Save as screen.ts. Run with Node.js 24: node screen.ts
type ApiResponse = {
  data?: { id: string; status: string; matches: unknown[] };
  error?: { code?: string; requestId?: string };
};

const apiKey = process.env.SANCTIONSKIT_API_KEY;
const requestKey = process.env.REQUEST_KEY;
if (!apiKey || !requestKey) {
  throw new Error('Set SANCTIONSKIT_API_KEY and REQUEST_KEY first.');
}

function safeField(value: unknown): string {
  return typeof value === 'string' && /^[a-zA-Z0-9_.:-]{1,128}$/.test(value)
    ? value : 'unknown';
}

try {
  const response = await fetch('https://www.sanctionskit.com/api/v1/screenings', {
    method: 'POST',
    headers: {
      Authorization: 'Bearer ' + apiKey,
      'Content-Type': 'application/json',
      'Idempotency-Key': requestKey,
    },
    body: JSON.stringify({
      subject: { name: 'Alex Morgan', entityType: 'person', birthDate: '1984' },
      package: 'sandbox@1',
    }),
    signal: AbortSignal.timeout(15000),
  });
  const payload: ApiResponse = await response.json().catch(() => ({}));
  if (!response.ok) {
    console.error('HTTP ' + response.status,
      'code=' + safeField(payload?.error?.code),
      'requestId=' + safeField(payload?.error?.requestId));
    process.exitCode = 1;
  } else {
    const result = payload?.data;
    if (!result || typeof result.id !== 'string' || !Array.isArray(result.matches)
        || !['potential_match', 'no_match'].includes(result.status)) {
      throw new Error('Unexpected response format.');
    }
    // Keep the full result in your authorized workflow, not application logs.
    console.log({ id: result.id, status: result.status });
    // potential_match: route to review. no_match: retain coverage and versions.
  }
} catch {
  console.error('The request did not complete. Keep the same REQUEST_KEY and body when retrying.');
  process.exitCode = 1;
}

export {};

3. Run it and inspect the result

Run the command below from the folder containing screen.ts. A successful response prints an object containing id and status. Open sandbox screening history to inspect the evidence. Potential matches belong in the review queue; no_match is limited to the coverage and matching policy used for that request.

A nonzero exit code means the example did not establish a completed screening outcome. Resolve authentication or validation errors before trying again. After a timeout, reuse the existing REQUEST_KEY and identical body to recover the original operation. Follow the idempotency reference and error guide when integrating this into a job or HTTP handler.

3. Run it and inspect the result
node screen.ts

4. Adapt it to your application

Replace the fixed invented subject with validated input supplied to your server. Preserve uncertain dates and original name structure. Keep the full response’s coverage and versions with the screening ID so a reviewer can understand the result later. See screening requests and evidence retrieval.

For production, use a production key and replace sandbox@1 with explicit available source IDs or a production package from source discovery. Do not send both sources and package. Add bounded retries for transient errors, reuse the operation’s idempotency key, and follow Retry-After when supplied. Use the webhook reference to verify signatures before accepting events.

KEEP BUILDING

Where to go next