Developer guide
Australian sanctions API in Node.js: onboarding with DFAT data
Add Australian sanctions API checks to Node.js onboarding. Select the DFAT list and retain its record references when aliases produce a possible match.
On this page
Screen Australian onboarding parties in Node.js
Keep the Australian Consolidated List source selection in the persisted operation and use the legal subject established by your onboarding process. A business name, an individual representative and an identifier issued to an organization can describe different subjects. Preserve the scheme and provenance of any identifier used.
In a synthetic business onboarding, the applicant provides a storefront name before the registered entity is known. Complete the identification step rather than treating the display name as a verified organization. When corrected details arrive, create a traceable new screening operation.
Prepare the synthetic exercise
Start with the invented sandbox person, then add a local fixture where an applicant supplies only a storefront name. Keep the identity-preparation step visible: the store, registered company and individual representative are different possible subjects, not interchangeable labels for one check.
| Requirement | Value or action |
|---|---|
| Runtime | Use Node.js 22 or later on a trusted server or CLI. This implementation uses the built-in fetch client and Node standard-library modules, so no SDK or npm dependency is required. |
| Client file | Save the client as screen.mjs. |
| Screening endpoint | POST /api/v1/screenings |
| SANCTIONSKIT_API_KEY | Sandbox key; screenings:write and results:read scopes |
| SCREENING_OPERATION_ID | Persist one operation ID; reuse only with the identical request body |
| request.json | Mira Calder: invented subject; sandbox@1: synthetic records |
{
"subject": {
"name": "Mira Calder",
"entityType": "person",
"birthDate": "1984"
},
"package": "sandbox@1",
"retention": "standard"
}Implement the Node.js request boundary
The Node.js client discovers au-consolidated and checks compatibility with the submitted entity type. Preserve that check when moving fetch into an onboarding service. An available source for one subject type does not establish support for every type your form accepts.
// Node.js 22+. Run on your trusted backend; no npm dependencies.
import { readFileSync } from 'node:fs';
const base = 'https://www.sanctionskit.com/api/v1';
async function main() {
const key = process.env.SANCTIONSKIT_API_KEY;
const operation = process.env.SCREENING_OPERATION_ID;
if (!key || !operation) throw new Error('Set your key and operation ID.');
const request = JSON.parse(readFileSync(process.argv[2] ?? 'request.json', 'utf8'));
const sandbox = request.package === 'sandbox@1';
const sourceIds = sandbox ? ['sandbox-synthetic'] : request.sources;
if (!Array.isArray(sourceIds) || !sourceIds.length) throw new Error('Select your sources.');
async function api(path, body) {
const response = await fetch(base + path, {
method: body ? 'POST' : 'GET', redirect: 'error', signal: AbortSignal.timeout(25000),
headers: { Authorization: 'Bearer ' + key,
...(body ? { 'Content-Type': 'application/json', 'Idempotency-Key': operation } : {}) },
...(body ? { body: JSON.stringify(body) } : {}),
});
const envelope = await response.json();
if (!response.ok) {
const code = /^[a-z0-9_]{1,80}$/.test(envelope?.error?.code ?? '') ? envelope.error.code : 'unknown';
throw new Error('API HTTP ' + response.status + ': ' + code);
}
return envelope?.data;
}
if (!sandbox) {
const sources = await api('/sources');
if (!Array.isArray(sources)) throw new Error('Invalid discovery response.');
for (const id of sourceIds) {
const found = sources.filter(source => source?.id === id);
const source = found[0];
if (found.length !== 1 || source.availability !== 'available' || source.fresh !== true ||
!Array.isArray(source.capabilities) || !source.capabilities.includes(request.subject.entityType)) throw new Error('Required source unavailable or incompatible.');
}
}
const result = await api('/screenings', request);
if (typeof result?.id !== 'string' || !result.id || result.environment !== (sandbox ? 'sandbox' : 'production') ||
!['potential_match', 'no_match'].includes(result.status) ||
!Array.isArray(result.matches) || (result.status === 'no_match') !== (result.matches.length === 0) ||
!Array.isArray(result.coverage) || result.coverage.length !== sourceIds.length ||
sourceIds.some(id => result.coverage.filter(item => item.sourceId === id && item.fresh === true).length !== 1)) {
throw new Error('Incomplete screening result.');
}
// Store result.id with your customer reference; use results:read to retrieve the evidence.
console.log(JSON.stringify({ id: result.id, status: result.status,
candidateCount: result.matches.length, sources: result.coverage.map(item => item.sourceId) }));
}
await main().catch(error => {
console.error((/^API HTTP [0-9]{3}: [a-z0-9_]{1,80}$/.test(error.message) ||
error.message === 'Required source unavailable or incompatible.')
? error.message : 'Screening incomplete. Check credentials, request and source coverage.');
process.exitCode = 1;
});Run the client
node screen.mjs request.jsonConfirm Australian sanctions scope before production
au-consolidated selects the Australian DFAT Consolidated List. A comparison against it does not answer every question about Australian transaction restrictions. Keep the established legal subject and selected list in the operation rather than treating the applicant’s display name as a verified identity.
| Check | Required evidence |
|---|---|
| GET /api/v1/sources | Production key with sources:read; response data array |
| id | au-consolidated |
| availability / fresh | available / true |
| capabilities | Contains the requested subject.entityType |
| currentVersion | Active version; retrieved_at and last_checked_at are not publication dates |
| lastImport | May describe an import that is not the active version |
| Missing or ineligible source | Inspect disabledReason; required coverage stays incomplete |
| Displayed client | Performs production discovery before screening |
curl --fail-with-body --max-time 25 --header "Authorization: Bearer $SANCTIONSKIT_API_KEY" "https://www.sanctionskit.com/api/v1/sources"Select au-consolidated in the production request
| Setting | Production request |
|---|---|
| Key | Separate production credential with screenings:write |
| Coverage | sources: ["au-consolidated"]; omit package |
| Operation ID | New ID for the changed body and environment |
| Usage | Production access and screening allowance apply |
| Subject | Only lawfully held, known identifying facts; no invented date precision |
{
"subject": {
"name": "Mira Calder",
"entityType": "person",
"birthDate": "1984"
},
"sources": [
"au-consolidated"
],
"retention": "standard"
}Interpret Australian sanctions evidence in this workflow
Connect data.id and data.coverage to the identified onboarding party. Group candidate aliases under their returned record identity instead of creating a separate customer for each name. An alias is evidence for review, not an independent confirmation that the applicant is listed.
| Fields in data.matches[] | Review use |
|---|---|
| record.id and record.names | Retain the DFAT source reference with the primary name and aliases; one listed identity may have several names. |
| record.designations | Display the available designation, program, legal-reference and effective-date context. |
| record.birthDates, identifiers and addresses | Compare the known identity details and retain uncertain dates at the precision supplied. |
- data.id; data.coverage; data.versions; supplied disclaimer
- data.matches[]: record, assessment, evidence, conflicts
- GET /api/v1/results/{id}: results:read scope
- Retained evidence and case review
Verify the application behavior
| Condition | Next action |
|---|---|
| 401 / 403 | Correct credentials or scopes before retrying |
| coverage_unavailable / stale_coverage | Keep required coverage incomplete; no silent source substitution |
| Timeout after submission | Recover with the original Idempotency-Key and identical body |
| 409 | Investigate an operation-key conflict |
| 429 / 503 | Follow the specific error and Retry-After; an allowance cap may require a plan or usage change |
Contract and safe diagnostic references
| Reference | Use |
|---|---|
| error.code / error.requestId | Safe recovery diagnostics; never log the submitted subject, key or full candidate response |
| potential_match / no_match | Completed comparison outcomes; neither is an automatic business approval |
- Reject an incompatible subject type in mocked source discovery.
- Keep a storefront label distinct from a registered-company subject.
- Display multiple DFAT aliases under their source record reference.
Sources and references
Authority and technical sources
SanctionsKit documentation
Frequently asked questions
What entity-type check does Node.js make before DFAT screening?
The production path checks whether the discovered source capabilities contain the request’s subject type. Preserve that guard in your backend, because source availability alone does not establish compatibility with every form input.
Does one Australian business account always correspond to one screening subject?
Not necessarily. A legal organization and its individual representative can require separate identity checks under your policy. Establish the subject before submitting it instead of treating the account’s display name as verified identity.
Should multiple DFAT aliases become separate customer records in Node.js?
No. Keep the returned source record identity with its names and aliases. Several names may describe one listed identity. Your application should show that evidence to a reviewer rather than treating every alias as a different customer or confirmed match.
How should Node.js present several aliases from one DFAT record?
Keep them attached to the returned source record. Multiple aliases describe evidence within the candidate and should not create duplicate customers or be counted as separate confirmations of identity.
