npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dossier-wiki/cloud-sdk

v0.8.3

Published

Type-safe TypeScript SDK for the Dossiers API

Readme

@dossier-wiki/cloud-sdk

The official TypeScript SDK for the Dossiers API.

Covers AML screening, KYC session management, AI-powered document processing, form templates, and webhook verification — all with full TypeScript types and optional Zod runtime validation.

Table of Contents


Installation

npm install @dossier-wiki/cloud-sdk
# or
pnpm add @dossier-wiki/cloud-sdk

Requires Node.js 18+ (or any runtime with a global fetch and crypto.subtle).


Quick Start

import { DossiersAPIService } from '@dossier-wiki/cloud-sdk';

const service = new DossiersAPIService({
  apiKey: process.env.DOSSIERS_API_KEY!,
});

// AML — search sanctions
const { totalHits, documents } = await service.aml.searchSanctions({
  fullName: 'John Doe',
});

// KYC — create a session
const { sessionUrl } = await service.kyc.sessions.create({
  customer: { name: 'Alice Brown', email: '[email protected]' },
  workflowId: 'wf_abc123',
});

// Document processing
const instance = await service.documents.initiate({
  processorId: 'INVOICE',
  files: [{ url: 'https://example.com/invoice.pdf', mimeType: 'application/pdf' }],
});

Migrating from the flat API (v0.1)

Version 0.1 exposed every operation as a method directly on the service (service.searchSanctions(), service.createKycSession(), ...). That top-level surface grew too large to navigate, so operations are now grouped into resource namespaces.

The old flat methods still work — they are thin, deprecated wrappers that forward to the new resource methods, so existing code keeps running unchanged. Your editor will show them struck through; migrate at your own pace. They will be removed in a future major version.

| Deprecated flat method | Use instead | |------------------------|-------------| | service.searchSanctions(input) | service.aml.searchSanctions(input) | | service.searchDossiers(input) | service.aml.searchDossiers(input) | | service.createScreeningRequest(input) | service.aml.createScreeningRequest(input) | | service.createKycSession(input) | service.kyc.sessions.create(input) | | service.listKycSessions(filters?) | service.kyc.sessions.list(filters?) | | service.getKycSession(id) | service.kyc.sessions.get(id) | | service.deleteKycSession(id) | service.kyc.sessions.delete(id) | | service.initiateDocumentProcessing(input) | service.documents.initiate(input) | | service.listDocumentProcessingInstances(query?) | service.documents.list(query?) | | service.listDocumentProcessors() | service.documents.listProcessors() | | service.getDocumentProcessingInstance(id) | service.documents.get(id) | | service.getDocumentProcessingStage(id, stageId) | service.documents.getStage(id, stageId) | | service.deleteDocumentProcessingInstance(id) | service.documents.delete(id) | | service.streamDocumentProcessingEvents(id, init?) | service.documents.stream(id, init?) |

New capabilities added since v0.1 — KYC workflows (service.kyc.workflows), form templates (service.formTemplates), media access (service.media), and KYC session webhook events — are only available on the resource API.


Authentication

All requests are authenticated with your API key as a Bearer token. Set it once on the service instance — never include it in client-side code.

const service = new DossiersAPIService({
  apiKey: process.env.DOSSIERS_API_KEY!,

  // Optional: override the base URL (e.g. for local development)
  baseUrl: 'http://localhost:4000',

  // Optional: inject a custom fetch (useful for testing or proxying)
  fetch: myCustomFetch,
});

App Info, API Versions & Contract Notices

Every request carries the Cloud API version this SDK build speaks — a dated contract, exported as DOSSIERS_API_VERSION (2026-10-01) — in the Dossiers-Api-Version header. The API only ever changes behaviour on that version; within a version, changes are additive, so ignore response fields you don't know.

Tell Dossiers what is calling with appInfo. It is recorded against the API key (shown in the Developer Console) and never changes how the API behaves:

const service = new DossiersAPIService({
  apiKey: process.env.DOSSIERS_API_KEY!,
  appInfo: {
    name: 'dossiers-os',
    version: '1.5.0',
    commit: process.env.GIT_SHA,          // optional, first 8 chars are sent
    installationId: process.env.INSTALL_ID, // optional, sent as Dossiers-Installation-Id
  },

  // Called when the API says this SDK's API version is deprecated, has a
  // sunset date, or is no longer accepted (426).
  onContractNotice: (notice) => {
    // { apiVersion, status, deprecation?, sunset?, link?, message?, minimumApiVersion? }
    logger.warn('Dossiers API contract notice', notice);
  },
});

Requests then carry:

User-Agent: dossiers-os/1.5.0 (17bbc509) cloud-sdk/0.8.0 node/22.19.0
Dossiers-Api-Version: 2026-10-01
Dossiers-Installation-Id: 6f1c…

User-Agent is never set in browsers (they forbid it); the other headers always are.

Calling the API with fetch directly? Use the same helpers:

import { buildDossiersRequestHeaders, readContractNotice } from '@dossier-wiki/cloud-sdk';

const res = await fetch(url, {
  headers: { ...buildDossiersRequestHeaders(appInfo), Authorization: `Bearer ${key}` },
});
const notice = readContractNotice(res); // null unless Deprecation/Sunset or 426

CLOUD_SDK_VERSION exports the SDK's own version.


Error Handling

All SDK methods throw a DossiersAPIError on non-2xx responses.

import { DossiersAPIService, DossiersAPIError } from '@dossier-wiki/cloud-sdk';

try {
  const session = await service.kyc.sessions.get('ses_nonexistent');
} catch (err) {
  if (err instanceof DossiersAPIError) {
    console.error(err.status);  // e.g. 404
    console.error(err.message); // human-readable message from the API
    console.error(err.body);    // raw parsed response body
  }
}

A 426 Upgrade Required — the API no longer accepts this SDK's API version — throws DossiersUpgradeRequiredError (a DossiersAPIError subclass) with minimumApiVersion. Upgrade the SDK to a release that speaks it.


AML Screening

Sanctions Search

Search global sanctions lists (OFAC, UN, FCDO, DFAT, CASL, INTERPOL) for individuals or entities.

const results = await service.aml.searchSanctions({
  fullName: 'Jane Smith',

  // Optional: narrow to specific lists
  sources: ['ofac', 'un'],

  // Optional: filter by country
  countries: ['US', 'GB'],

  // Optional: match against document numbers
  idNumbers: ['P123456789'],
});

console.log(results.totalHits);
for (const sanction of results.documents) {
  console.log(sanction.name, sanction.source, sanction.sanctionsProgramme);
}

PEP & Adverse Media (Dossiers)

Search PEP registries and adverse media databases. Returns individual dossiers with risk scores, positions held, and associates.

const dossiers = await service.aml.searchDossiers({
  fullName: 'Robert Jones',
  onlyShowHighRiskProfiles: true,
  noCache: false, // use cached results (default)
});

for (const dossier of dossiers) {
  const score = dossier.riskScorecard?.overallRiskScore ?? 0;
  console.log(dossier.fullName, score, dossier.riskScorecard?.riskCategory);
}

Ongoing Screening Requests

Submit individuals for continuous monitoring. Webhook events fire when screening completes or when new alerts are triggered.

const { requestId } = await service.aml.createScreeningRequest({
  fullName: 'Alice Brown',
  externalId: 'cust_123',        // your internal reference ID
  dateOfBirth: '1985-06-15',
  country: 'GB',
  identificationDocument: {
    type: 'passport',
    number: 'AB123456',
    country: 'GB',
  },
});

KYC Sessions

A KYC session is a single customer verification journey. The customer receives a link (sessionUrl) they visit to complete the configured workflow steps.

// Create a session
const { session, sessionUrl, token } = await service.kyc.sessions.create({
  customer: {
    name: 'Nimal Perera',
    email: '[email protected]',
    externalId: 'cust_001',  // your internal reference
  },
  workflowId: 'wf_standard_kyc',
  expiresInMs: 86_400_000,   // 24 hours (default: 1 hour)
});

// Send the sessionUrl to your customer
await sendInvitationEmail(session.customer.email, sessionUrl);

// List sessions
const { sessions, totalCount } = await service.kyc.sessions.list({
  isComplete: true,
  sortBy: 'completedAt',
  sortOrder: 'desc',
  limit: 50,
  offset: 0,
});

// Get a specific session (includes full step history & media)
const fullSession = await service.kyc.sessions.get(session.id);
console.log(fullSession.status); // 'complete' | 'in-progress' | 'approved' | ...

// Delete a session
await service.kyc.sessions.delete(session.id);

KYC Workflows

A workflow defines the ordered steps a customer goes through during a session (e.g. identity verification → liveness → form collection).

Building a Workflow

Use stepDefaults() to get pre-built configurations for each step type, then assemble them into a workflow.

import type { WorkflowRules } from '@dossier-wiki/cloud-sdk';

// Fetch defaults for all step types
const defaults = await service.kyc.workflows.stepDefaults();
const idStep = defaults.find(d => d.type === 'id_verification')!;
const livenessStep = defaults.find(d => d.type === 'liveness')!;

// Create the workflow
const workflow = await service.kyc.workflows.create({
  name: 'Standard KYC',
  description: 'Identity check + liveness verification',
  steps: [
    {
      stepId: idStep.defaultStepId,
      type: 'id_verification',
      input: idStep.defaultInput as { config?: Record<string, unknown> },
      output: { schema: idStep.schema },
      rules: idStep.defaultRules as WorkflowRules,
      locales: idStep.defaultLocales,
      skippable: idStep.skippable,
    },
    {
      stepId: livenessStep.defaultStepId,
      type: 'liveness',
      input: livenessStep.defaultInput as { config?: Record<string, unknown> },
      output: { schema: livenessStep.schema },
      rules: livenessStep.defaultRules as WorkflowRules,
      locales: livenessStep.defaultLocales,
      skippable: livenessStep.skippable,
    },
  ],
});

// Use the workflow when creating sessions
const { sessionUrl } = await service.kyc.sessions.create({
  customer: { name: 'Bob Lee' },
  workflowId: workflow.id,
});

Zod Validation

The SDK exports Zod schemas for the step discriminated union, so you can validate workflow input at runtime before sending it to the API.

import { schemas } from '@dossier-wiki/cloud-sdk';

// Validates the full workflow creation input including per-step type constraints
const validated = schemas.CreateWorkflowSchema.parse(rawInput);
const workflow = await service.kyc.workflows.create(validated);

// Validate a single step
const step = schemas.WorkflowStepSchema.parse({
  stepId: 'step_liveness',
  type: 'liveness',
  input: { config: { challengeType: 'selfie', timeLimitSeconds: 30 } },
  output: {},
  rules: { onSuccess: 'COMPLETE_SESSION', onFailure: 'FAIL_SESSION' },
});

Available step types and their config constraints:

| Type | Config fields | |------|--------------| | id_verification | strategy, allowedDocuments, maxSubmissions, allowUpload | | document_collection | allowedDocuments, allowUpload, maxSubmissions | | liveness | challengeType, timeLimitSeconds, minFaceLuminance, minFaceDetectionConfidence | | form_collection | templateId, fields | | esignature | signatureTypesAllowed | | action | actionType |

Other workflow operations:

// List all workflows
const workflows = await service.kyc.workflows.list();

// Get a specific workflow
const wf = await service.kyc.workflows.get('wf_abc123');

// Update (creates a new version; existing sessions are unaffected)
const updated = await service.kyc.workflows.update('wf_abc123', {
  name: 'Standard KYC v2',
});

// Delete
await service.kyc.workflows.delete('wf_old123');

Document Processing

Initiate AI extraction jobs on uploaded documents. The pipeline validates the document, extracts structured data, and runs post-processing checks.

Available processor IDs:

| processorId | Document | |---------------|---------| | INVOICE | Invoice / bill | | SRI_LANKA_ID | Sri Lanka National Identity Card | | SRI_LANKA_FORM1_COMPANY_REGISTRATION | Company Registration Form 1 | | SRI_LANKA_FORM15_ANNUAL_RETURN | Annual Return Form 15 |

Initiate a Job

const instance = await service.documents.initiate({
  processorId: 'INVOICE',
  files: [
    { url: 'https://example.com/invoice.pdf', mimeType: 'application/pdf' },
  ],

  // Optional: arbitrary metadata stored on the instance
  metadata: { orderId: 'ord_456' },

  // Default: true — runs asynchronously; false waits for completion
  backgroundProcessing: true,
});

console.log(instance.instanceId); // use this to poll or stream

Poll for Results

let instance = await service.documents.get(instanceId);

while (instance.status === 'pending' || instance.status === 'running') {
  await new Promise(r => setTimeout(r, 2000));
  instance = await service.documents.get(instanceId);
}

if (instance.status === 'completed') {
  console.log(instance.result?.validation.passed);
  console.log(instance.result?.normalizedData);
}

Real-Time Progress (SSE)

const res = await service.documents.stream(instanceId);
const reader = res.body!.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  const text = decoder.decode(value, { stream: true });
  // Each SSE line is a DocumentProcessingEvent JSON payload
  console.log(text);
}

Typed Extraction Schemas

Use the generic parameter to type the result.schema field for a specific processor:

import type {
  DocumentProcessingExtractedField,
  DocumentProcessingTransliteratedField,
} from '@dossier-wiki/cloud-sdk';

type SriLankaIdSchema = {
  name: DocumentProcessingTransliteratedField;
  idNumber: DocumentProcessingExtractedField<string>;
  dateOfBirth: DocumentProcessingExtractedField<string>;
  address: DocumentProcessingTransliteratedField;
  gender: DocumentProcessingExtractedField<string>;
};

const instance = await service.documents.initiate<SriLankaIdSchema>({
  processorId: 'SRI_LANKA_ID',
  files: [{ base64Data: '...', mimeType: 'image/jpeg' }],
});

// result.schema is now typed as SriLankaIdSchema
const name = instance.result?.schema.name.enTransliterations[0].transliteratedText;

Other document processing operations:

// List instances
const { instances, count } = await service.documents.list({
  processorId: 'INVOICE',
  status: 'completed',
  limit: 20,
});

// Get a specific stage result
const stage = await service.documents.getStage(instanceId, 'post_validation');
console.log(stage.data.validation.passed);

// List available processors
const processors = await service.documents.listProcessors();

// Delete an instance
await service.documents.delete(instanceId);

Form Templates

Form templates define reusable sets of fields for the form_collection KYC workflow step.

// Create a template
const template = await service.formTemplates.create({
  name: 'Employment Details',
  fields: [
    {
      id: 'employer',
      type: 'text',
      label: 'Employer Name',
      required: true,
    },
    {
      id: 'salary',
      type: 'currency',
      label: 'Annual Salary (LKR)',
      required: true,
      validation: { min: 0 },
    },
    {
      id: 'employment_type',
      type: 'select',
      label: 'Employment Type',
      required: true,
      options: [
        { value: 'full_time', label: 'Full Time' },
        { value: 'part_time', label: 'Part Time' },
        { value: 'self_employed', label: 'Self Employed' },
      ],
    },
  ],
});

// Reference the template in a form_collection step config
const workflowStep = {
  type: 'form_collection' as const,
  input: { config: { templateId: template.id } },
  // ...
};

// List, get, update, delete
const { templates } = await service.formTemplates.list({ searchQuery: 'employment' });
const full = await service.formTemplates.get(template.id);
await service.formTemplates.update(template.id, { name: 'Employment Details v2' });
await service.formTemplates.delete(template.id);

Available field types: text, long_text, number, currency, country, language, email, phone, date, select, multi_select, dropdown, toggle, boolean, file, heading, paragraph, description, divider.


Media

Fetch binary files (images, videos, PDF signatures) from session results and document processing instances using signed storage tokens.

// Tokens appear in session result media arrays and processing instance files
const token = session.result.steps[0].summary?.media[0]?.key;

if (token) {
  const res = await service.media.get(token);

  // Browser — convert to object URL for display
  const blob = await res.blob();
  const objectUrl = URL.createObjectURL(blob);
  imageElement.src = objectUrl;

  // Node.js — pipe to disk
  const { createWriteStream } = await import('fs');
  const { Readable } = await import('stream');
  Readable.fromWeb(res.body!).pipe(createWriteStream('./capture.jpg'));
}

Webhooks

Use DossiersWebhookRouter to handle incoming webhook events with HMAC-SHA256 signature verification.

import { DossiersWebhookRouter, DossiersWebhookEventTypes } from '@dossier-wiki/cloud-sdk';

const router = new DossiersWebhookRouter(process.env.DOSSIERS_WEBHOOK_SECRET!);

router
  .on(DossiersWebhookEventTypes.DOCUMENT_VERIFICATION_INSTANCE_COMPLETED, async (event, ctx) => {
    const { documentProcessorInstanceId } = event.data;
    const instance = await service.documents.get(documentProcessorInstanceId);
    await saveResult(instance);
  })
  .on(DossiersWebhookEventTypes.KYC_SESSION_COMPLETED, async (event, ctx) => {
    // Payloads carry no PII — fetch the full session on demand.
    const { kycSessionId, outcome } = event.data;
    const session = await service.kyc.sessions.get(kycSessionId);
    await recordVerification(session, outcome); // outcome: 'complete' | 'failed'
  })
  .on(DossiersWebhookEventTypes.AML_SCREENING_ALERT_TRIGGERED, async (event, ctx) => {
    console.log('Alert triggered for screening request', event.data);
  });

// Express
app.post('/webhooks/dossiers', async (req, res) => {
  // Reconstruct a Web API Request from the Express request
  const body = await getRawBody(req);
  const webReq = new Request('https://your-server/webhooks/dossiers', {
    method: 'POST',
    headers: req.headers as HeadersInit,
    body,
  });
  const response = await router.handle(webReq);
  res.status(response.status).send(await response.text());
});

// Next.js App Router
export async function POST(req: Request) {
  return router.handle(req, { waitUntil: (p) => context.waitUntil(p) });
}

Webhook events are acknowledged immediately (200 OK) before the handler runs — a slow handler will not cause the platform to retry. If your handler throws, the error is logged but no retry occurs. Implement your own retry logic inside the handler if needed.

Event types this SDK build doesn't know — Dossiers adds them without a new API version — are acknowledged with 200 and ignored, as are events you registered no handler for.

Every event delivered to a handler has the shape:

{
  id: string;              // e.g. "evt_1712345678_ab12cd34"
  type: DossiersWebhookEventTypes;
  organizationId: string;
  apiVersion: string;       // the destination's Cloud API version, e.g. "2026-10-01"
  eventTriggeredAt: string; // ISO 8601
  data: /* typed per event — see below */;
}

Registering a Destination

service.webhooks.destinations.upsert() creates your destination for a URL, or updates the existing one — safe to call on every start. It needs an API key with the Webhooks permission (WEBHOOKS_MANAGE); without it the call throws a DossiersAPIError with status 403.

const { id, secret, created } = await service.webhooks.destinations.upsert({
  url: 'https://your-app.example.com/webhooks/dossiers',
  events: [
    DossiersWebhookEventTypes.KYC_SESSION_COMPLETED,
    DossiersWebhookEventTypes.KYC_SESSION_REVIEWED,
  ],
  name: 'My app',            // optional; defaults to the URL's host
  // apiVersion defaults to DOSSIERS_API_VERSION, and installationId to the
  // Dossiers-Installation-Id header the SDK sends from appInfo.
});

const router = new DossiersWebhookRouter(secret);

The signing secret is generated on create and kept (and returned again) on update. Fields you leave out are left as they are, and a destination disabled in the Developer Console stays disabled (isActive: false).

The data field is fully typed by the event type you pass to .on(). Import DossiersWebhookPayload for the discriminated union of all event shapes.

Available Event Types

Document processing

| Enum value | Event string | data type | |------------|-------------|-------------| | DOCUMENT_VERIFICATION_INSTANCE_CREATED | documentVerification.instance.created | DocumentVerificationInstanceCreatedData | | DOCUMENT_VERIFICATION_INSTANCE_UPDATED | documentVerification.instance.updated | DocumentVerificationInstanceUpdatedData | | DOCUMENT_VERIFICATION_INSTANCE_COMPLETED | documentVerification.instance.completed | DocumentVerificationInstanceCompletedData | | DOCUMENT_VERIFICATION_INSTANCE_DELETED | documentVerification.instance.deleted | DocumentVerificationInstanceDeletedData |

KYC sessions

| Enum value | Event string | data type | |------------|-------------|-------------| | KYC_SESSION_CREATED | kycSessions.session.created | KycSessionEventData | | KYC_SESSION_UPDATED | kycSessions.session.updated | KycSessionEventData | | KYC_SESSION_COMPLETED | kycSessions.session.completed | KycSessionEventData (with outcome) | | KYC_SESSION_REVIEWED | kycSessions.session.reviewed | KycSessionEventData (with review) | | KYC_SESSION_DELETED | kycSessions.session.deleted | KycSessionDeletedData | | KYC_STEP_COMPLETED | kycSessions.step.completed | KycStepEventData | | KYC_STEP_FAILED | kycSessions.step.failed | KycStepEventData | | KYC_SESSION_COMMENT_ADDED | kycSessions.session.commentAdded | KycSessionCommentAddedData | | KYC_SESSION_COMMENT_UPDATED | kycSessions.session.commentUpdated | KycSessionCommentUpdatedData | | KYC_SESSION_COMMENT_DELETED | kycSessions.session.commentDeleted | KycSessionCommentDeletedData |

KYC payloads carry no PII (no customer name/email, no step outputs). They reference a kycSessionId — fetch the detail you need with service.kyc.sessions.get(kycSessionId).

AML screening

| Enum value | Event string | |------------|-------------| | AML_SCREENING_REQUEST_CREATED | amlScreening.screeningRequest.created | | AML_SCREENING_REQUEST_COMPLETED | amlScreening.screeningRequest.completed | | AML_SCREENING_ALERT_TRIGGERED | amlScreening.screeningAlert.triggered | | AML_SCREENING_ALERT_STATUS_CHANGED | amlScreening.screeningAlert.statusChanged | | AML_SCREENING_ALERT_COMMENT_ADDED | amlScreening.screeningAlert.commentAdded | | AML_SCREENING_ALERT_COMMENT_UPDATED | amlScreening.screeningAlert.commentUpdated | | AML_SCREENING_ALERT_COMMENT_DELETED | amlScreening.screeningAlert.commentDeleted | | AML_SCREENING_ALERT_DELETED | amlScreening.screeningAlert.deleted |

System

| Enum value | Event string | |------------|-------------| | SYSTEM_TEST_EVENT | system.testEvent | | SYSTEM_PRODUCT_ACCESS_GRANTED | system.product.accessGranted | | SYSTEM_PRODUCT_ACCESS_REVOKED | system.product.accessRevoked | | SYSTEM_API_KEY_CREATED | system.apiKey.created | | SYSTEM_API_KEY_INVALIDATED | system.apiKey.invalidated | | SYSTEM_USAGE_LIMIT_REACHED | system.usage.limitReached | | SYSTEM_USAGE_LIMIT_WARNING | system.usage.limitWarning |


TypeScript

All API request and response shapes are exported as TypeScript interfaces. Import them as needed:

import type {
  // AML
  SanctionSearchInput,
  SanctionSearchResponse,
  Sanction,
  DossierSearchInput,
  IndividualDossier,
  CreateScreeningRequestDto,

  // KYC Sessions
  CreateKycSessionDTO,
  KycSessionOutputDTO,
  KycSessionFiltersDTO,
  PaginatedKycSessionsDTO,

  // KYC Workflows
  CreateKycWorkflowInput,
  KycWorkflow,
  KycWorkflowStep,
  KycWorkflowStepType,
  WorkflowRules,
  WorkflowStepDefault,

  // Document Processing
  InitiateDocumentProcessingInput,
  DocumentProcessingInstance,
  DocumentProcessingResult,
  DocumentProcessingExtractedField,
  DocumentProcessingTransliteratedField,
  DocumentProcessorId,

  // Form Templates
  CreateFormTemplateInput,
  FormTemplate,
  FormField,
  FormFieldType,

  // Webhooks
  DossiersWebhookPayload,
  DossiersWebhookEvent,
  UpsertWebhookDestinationInput,
  UpsertWebhookDestinationResult,

  // Client identity & API version contract
  DossiersAppInfo,
  DossiersContractNotice,
  KycSessionEventData,
  KycSessionDeletedData,
  KycStepEventData,
  KycSessionCommentAddedData,
  KycSessionCommentUpdatedData,
  KycSessionCommentDeletedData,
} from '@dossier-wiki/cloud-sdk';