@dossier-wiki/cloud-sdk 0.1.0 → 0.2.0-staging.3dda5e6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +697 -46
- package/dist/cjs/api.js +34 -0
- package/dist/cjs/api.js.map +1 -0
- package/dist/cjs/error.js +29 -0
- package/dist/cjs/error.js.map +1 -0
- package/dist/cjs/http.js +75 -0
- package/dist/cjs/http.js.map +1 -0
- package/dist/cjs/index.js +48 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/resources/aml.js +88 -0
- package/dist/cjs/resources/aml.js.map +1 -0
- package/dist/cjs/resources/documents.js +170 -0
- package/dist/cjs/resources/documents.js.map +1 -0
- package/dist/cjs/resources/form-templates.js +117 -0
- package/dist/cjs/resources/form-templates.js.map +1 -0
- package/dist/cjs/resources/kyc/index.js +32 -0
- package/dist/cjs/resources/kyc/index.js.map +1 -0
- package/dist/cjs/resources/kyc/sessions.js +103 -0
- package/dist/cjs/resources/kyc/sessions.js.map +1 -0
- package/dist/cjs/resources/kyc/workflows.js +150 -0
- package/dist/cjs/resources/kyc/workflows.js.map +1 -0
- package/dist/cjs/resources/media.js +62 -0
- package/dist/cjs/resources/media.js.map +1 -0
- package/dist/cjs/schemas/index.js +9 -0
- package/dist/cjs/schemas/index.js.map +1 -0
- package/dist/cjs/schemas/kyc/workflow-steps.js +145 -0
- package/dist/cjs/schemas/kyc/workflow-steps.js.map +1 -0
- package/dist/cjs/service.js +132 -0
- package/dist/cjs/service.js.map +1 -0
- package/dist/cjs/session.js +379 -0
- package/dist/cjs/session.js.map +1 -0
- package/dist/cjs/types.js +36 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/webhooks.js +93 -0
- package/dist/cjs/webhooks.js.map +1 -0
- package/dist/esm/api.js +33 -0
- package/dist/esm/api.js.map +1 -0
- package/dist/esm/error.js +25 -0
- package/dist/esm/error.js.map +1 -0
- package/dist/esm/http.js +71 -0
- package/dist/esm/http.js.map +1 -0
- package/dist/esm/index.js +19 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/resources/aml.js +84 -0
- package/dist/esm/resources/aml.js.map +1 -0
- package/dist/esm/resources/documents.js +166 -0
- package/dist/esm/resources/documents.js.map +1 -0
- package/dist/esm/resources/form-templates.js +113 -0
- package/dist/esm/resources/form-templates.js.map +1 -0
- package/dist/esm/resources/kyc/index.js +26 -0
- package/dist/esm/resources/kyc/index.js.map +1 -0
- package/dist/esm/resources/kyc/sessions.js +99 -0
- package/dist/esm/resources/kyc/sessions.js.map +1 -0
- package/dist/esm/resources/kyc/workflows.js +146 -0
- package/dist/esm/resources/kyc/workflows.js.map +1 -0
- package/dist/esm/resources/media.js +58 -0
- package/dist/esm/resources/media.js.map +1 -0
- package/dist/esm/schemas/index.js +2 -0
- package/dist/esm/schemas/index.js.map +1 -0
- package/dist/esm/schemas/kyc/workflow-steps.js +142 -0
- package/dist/esm/schemas/kyc/workflow-steps.js.map +1 -0
- package/dist/esm/service.js +127 -0
- package/dist/esm/service.js.map +1 -0
- package/dist/esm/session.js +375 -0
- package/dist/esm/session.js.map +1 -0
- package/dist/{types.js → esm/types.js} +11 -27
- package/dist/esm/types.js.map +1 -0
- package/dist/{webhooks.js → esm/webhooks.js} +10 -11
- package/dist/esm/webhooks.js.map +1 -0
- package/dist/{api.d.ts → types/api.d.ts} +297 -166
- package/dist/types/api.d.ts.map +1 -0
- package/dist/types/error.d.ts +24 -0
- package/dist/types/error.d.ts.map +1 -0
- package/dist/types/http.d.ts +17 -0
- package/dist/types/http.d.ts.map +1 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/resources/aml.d.ts +79 -0
- package/dist/types/resources/aml.d.ts.map +1 -0
- package/dist/types/resources/documents.d.ts +153 -0
- package/dist/types/resources/documents.d.ts.map +1 -0
- package/dist/types/resources/form-templates.d.ts +104 -0
- package/dist/types/resources/form-templates.d.ts.map +1 -0
- package/dist/types/resources/kyc/index.d.ts +34 -0
- package/dist/types/resources/kyc/index.d.ts.map +1 -0
- package/dist/types/resources/kyc/sessions.d.ts +92 -0
- package/dist/types/resources/kyc/sessions.d.ts.map +1 -0
- package/dist/types/resources/kyc/workflows.d.ts +135 -0
- package/dist/types/resources/kyc/workflows.d.ts.map +1 -0
- package/dist/types/resources/media.d.ts +56 -0
- package/dist/types/resources/media.d.ts.map +1 -0
- package/dist/types/schemas/index.d.ts +3 -0
- package/dist/types/schemas/index.d.ts.map +1 -0
- package/dist/types/schemas/kyc/workflow-steps.d.ts +5113 -0
- package/dist/types/schemas/kyc/workflow-steps.d.ts.map +1 -0
- package/dist/types/service.d.ts +143 -0
- package/dist/types/service.d.ts.map +1 -0
- package/dist/types/session.d.ts +176 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/{types.d.ts → types/types.d.ts} +100 -2
- package/dist/types/types.d.ts.map +1 -0
- package/dist/{webhooks.d.ts → types/webhooks.d.ts} +5 -5
- package/dist/types/webhooks.d.ts.map +1 -0
- package/package.json +26 -32
- package/dist/api.d.ts.map +0 -1
- package/dist/api.js +0 -22
- package/dist/api.js.map +0 -1
- package/dist/index.d.ts +0 -6
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -5
- package/dist/index.js.map +0 -1
- package/dist/service.d.ts +0 -39
- package/dist/service.d.ts.map +0 -1
- package/dist/service.js +0 -150
- package/dist/service.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/webhooks.d.ts.map +0 -1
- package/dist/webhooks.js.map +0 -1
- package/docs/REFERENCE.md +0 -114
package/README.md
CHANGED
|
@@ -1,88 +1,739 @@
|
|
|
1
1
|
# @dossier-wiki/cloud-sdk
|
|
2
2
|
|
|
3
|
-
TypeScript SDK for the
|
|
3
|
+
The official TypeScript SDK for the Dossiers API.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Covers AML screening, KYC session management, AI-powered document processing,
|
|
6
|
+
form templates, and webhook verification — all with full TypeScript types and
|
|
7
|
+
optional Zod runtime validation.
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
- [Installation](#installation)
|
|
12
|
+
- [Quick Start](#quick-start)
|
|
13
|
+
- [Migrating from the flat API (v0.1)](#migrating-from-the-flat-api-v01)
|
|
14
|
+
- [Authentication](#authentication)
|
|
15
|
+
- [Error Handling](#error-handling)
|
|
16
|
+
- [AML Screening](#aml-screening)
|
|
17
|
+
- [Sanctions Search](#sanctions-search)
|
|
18
|
+
- [PEP & Adverse Media (Dossiers)](#pep--adverse-media-dossiers)
|
|
19
|
+
- [Ongoing Screening Requests](#ongoing-screening-requests)
|
|
20
|
+
- [KYC Sessions](#kyc-sessions)
|
|
21
|
+
- [KYC Workflows](#kyc-workflows)
|
|
22
|
+
- [Building a Workflow](#building-a-workflow)
|
|
23
|
+
- [Zod Validation](#zod-validation)
|
|
24
|
+
- [Document Processing](#document-processing)
|
|
25
|
+
- [Initiate a Job](#initiate-a-job)
|
|
26
|
+
- [Poll for Results](#poll-for-results)
|
|
27
|
+
- [Real-Time Progress (SSE)](#real-time-progress-sse)
|
|
28
|
+
- [Typed Extraction Schemas](#typed-extraction-schemas)
|
|
29
|
+
- [Form Templates](#form-templates)
|
|
30
|
+
- [Media](#media)
|
|
31
|
+
- [Webhooks](#webhooks)
|
|
32
|
+
- [TypeScript](#typescript)
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
8
39
|
npm install @dossier-wiki/cloud-sdk
|
|
9
40
|
# or
|
|
10
|
-
|
|
41
|
+
pnpm add @dossier-wiki/cloud-sdk
|
|
11
42
|
```
|
|
12
43
|
|
|
13
|
-
|
|
44
|
+
Requires Node.js 18+ (or any runtime with a global `fetch` and `crypto.subtle`).
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Quick Start
|
|
14
49
|
|
|
15
50
|
```ts
|
|
16
51
|
import { DossiersAPIService } from '@dossier-wiki/cloud-sdk';
|
|
17
52
|
|
|
18
|
-
const
|
|
19
|
-
|
|
53
|
+
const service = new DossiersAPIService({
|
|
54
|
+
apiKey: process.env.DOSSIERS_API_KEY!,
|
|
20
55
|
});
|
|
21
56
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
57
|
+
// AML — search sanctions
|
|
58
|
+
const { totalHits, documents } = await service.aml.searchSanctions({
|
|
59
|
+
fullName: 'John Doe',
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// KYC — create a session
|
|
63
|
+
const { sessionUrl } = await service.kyc.sessions.create({
|
|
64
|
+
customer: { name: 'Alice Brown', email: 'alice@example.com' },
|
|
65
|
+
workflowId: 'wf_abc123',
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Document processing
|
|
69
|
+
const instance = await service.documents.initiate({
|
|
70
|
+
processorId: 'INVOICE',
|
|
71
|
+
files: [{ url: 'https://example.com/invoice.pdf', mimeType: 'application/pdf' }],
|
|
25
72
|
});
|
|
26
73
|
```
|
|
27
74
|
|
|
28
|
-
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Migrating from the flat API (v0.1)
|
|
78
|
+
|
|
79
|
+
Version 0.1 exposed every operation as a method directly on the service
|
|
80
|
+
(`service.searchSanctions()`, `service.createKycSession()`, ...). That top-level
|
|
81
|
+
surface grew too large to navigate, so operations are now grouped into resource
|
|
82
|
+
namespaces.
|
|
83
|
+
|
|
84
|
+
**The old flat methods still work** — they are thin, deprecated wrappers that
|
|
85
|
+
forward to the new resource methods, so existing code keeps running unchanged.
|
|
86
|
+
Your editor will show them struck through; migrate at your own pace. They will
|
|
87
|
+
be removed in a future major version.
|
|
88
|
+
|
|
89
|
+
| Deprecated flat method | Use instead |
|
|
90
|
+
|------------------------|-------------|
|
|
91
|
+
| `service.searchSanctions(input)` | `service.aml.searchSanctions(input)` |
|
|
92
|
+
| `service.searchDossiers(input)` | `service.aml.searchDossiers(input)` |
|
|
93
|
+
| `service.createScreeningRequest(input)` | `service.aml.createScreeningRequest(input)` |
|
|
94
|
+
| `service.createKycSession(input)` | `service.kyc.sessions.create(input)` |
|
|
95
|
+
| `service.listKycSessions(filters?)` | `service.kyc.sessions.list(filters?)` |
|
|
96
|
+
| `service.getKycSession(id)` | `service.kyc.sessions.get(id)` |
|
|
97
|
+
| `service.deleteKycSession(id)` | `service.kyc.sessions.delete(id)` |
|
|
98
|
+
| `service.initiateDocumentProcessing(input)` | `service.documents.initiate(input)` |
|
|
99
|
+
| `service.listDocumentProcessingInstances(query?)` | `service.documents.list(query?)` |
|
|
100
|
+
| `service.listDocumentProcessors()` | `service.documents.listProcessors()` |
|
|
101
|
+
| `service.getDocumentProcessingInstance(id)` | `service.documents.get(id)` |
|
|
102
|
+
| `service.getDocumentProcessingStage(id, stageId)` | `service.documents.getStage(id, stageId)` |
|
|
103
|
+
| `service.deleteDocumentProcessingInstance(id)` | `service.documents.delete(id)` |
|
|
104
|
+
| `service.streamDocumentProcessingEvents(id, init?)` | `service.documents.stream(id, init?)` |
|
|
105
|
+
|
|
106
|
+
New capabilities added since v0.1 — KYC workflows (`service.kyc.workflows`),
|
|
107
|
+
form templates (`service.formTemplates`), media access (`service.media`), and
|
|
108
|
+
KYC session webhook events — are only available on the resource API.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Authentication
|
|
113
|
+
|
|
114
|
+
All requests are authenticated with your API key as a Bearer token. Set it
|
|
115
|
+
once on the service instance — never include it in client-side code.
|
|
29
116
|
|
|
30
117
|
```ts
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
DossiersWebhookEventTypes,
|
|
34
|
-
} from '@dossier-wiki/cloud-sdk';
|
|
118
|
+
const service = new DossiersAPIService({
|
|
119
|
+
apiKey: process.env.DOSSIERS_API_KEY!,
|
|
35
120
|
|
|
36
|
-
|
|
121
|
+
// Optional: override the base URL (e.g. for local development)
|
|
122
|
+
baseUrl: 'http://localhost:4000',
|
|
123
|
+
|
|
124
|
+
// Optional: inject a custom fetch (useful for testing or proxying)
|
|
125
|
+
fetch: myCustomFetch,
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Error Handling
|
|
37
132
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
133
|
+
All SDK methods throw a `DossiersAPIError` on non-2xx responses.
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
import { DossiersAPIService, DossiersAPIError } from '@dossier-wiki/cloud-sdk';
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
const session = await service.kyc.sessions.get('ses_nonexistent');
|
|
140
|
+
} catch (err) {
|
|
141
|
+
if (err instanceof DossiersAPIError) {
|
|
142
|
+
console.error(err.status); // e.g. 404
|
|
143
|
+
console.error(err.message); // human-readable message from the API
|
|
144
|
+
console.error(err.body); // raw parsed response body
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## AML Screening
|
|
152
|
+
|
|
153
|
+
### Sanctions Search
|
|
154
|
+
|
|
155
|
+
Search global sanctions lists (OFAC, UN, FCDO, DFAT, CASL, INTERPOL) for
|
|
156
|
+
individuals or entities.
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
const results = await service.aml.searchSanctions({
|
|
160
|
+
fullName: 'Jane Smith',
|
|
161
|
+
|
|
162
|
+
// Optional: narrow to specific lists
|
|
163
|
+
sources: ['ofac', 'un'],
|
|
164
|
+
|
|
165
|
+
// Optional: filter by country
|
|
166
|
+
countries: ['US', 'GB'],
|
|
167
|
+
|
|
168
|
+
// Optional: match against document numbers
|
|
169
|
+
idNumbers: ['P123456789'],
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
console.log(results.totalHits);
|
|
173
|
+
for (const sanction of results.documents) {
|
|
174
|
+
console.log(sanction.name, sanction.source, sanction.sanctionsProgramme);
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### PEP & Adverse Media (Dossiers)
|
|
179
|
+
|
|
180
|
+
Search PEP registries and adverse media databases. Returns individual dossiers
|
|
181
|
+
with risk scores, positions held, and associates.
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
const dossiers = await service.aml.searchDossiers({
|
|
185
|
+
fullName: 'Robert Jones',
|
|
186
|
+
onlyShowHighRiskProfiles: true,
|
|
187
|
+
noCache: false, // use cached results (default)
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
for (const dossier of dossiers) {
|
|
191
|
+
const score = dossier.riskScorecard?.overallRiskScore ?? 0;
|
|
192
|
+
console.log(dossier.fullName, score, dossier.riskScorecard?.riskCategory);
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Ongoing Screening Requests
|
|
197
|
+
|
|
198
|
+
Submit individuals for continuous monitoring. Webhook events fire when
|
|
199
|
+
screening completes or when new alerts are triggered.
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
const { requestId } = await service.aml.createScreeningRequest({
|
|
203
|
+
fullName: 'Alice Brown',
|
|
204
|
+
externalId: 'cust_123', // your internal reference ID
|
|
205
|
+
dateOfBirth: '1985-06-15',
|
|
206
|
+
country: 'GB',
|
|
207
|
+
identificationDocument: {
|
|
208
|
+
type: 'passport',
|
|
209
|
+
number: 'AB123456',
|
|
210
|
+
country: 'GB',
|
|
211
|
+
},
|
|
212
|
+
});
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## KYC Sessions
|
|
218
|
+
|
|
219
|
+
A KYC session is a single customer verification journey. The customer receives
|
|
220
|
+
a link (`sessionUrl`) they visit to complete the configured workflow steps.
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
// Create a session
|
|
224
|
+
const { session, sessionUrl, token } = await service.kyc.sessions.create({
|
|
225
|
+
customer: {
|
|
226
|
+
name: 'Nimal Perera',
|
|
227
|
+
email: 'nimal@example.com',
|
|
228
|
+
externalId: 'cust_001', // your internal reference
|
|
229
|
+
},
|
|
230
|
+
workflowId: 'wf_standard_kyc',
|
|
231
|
+
expiresInMs: 86_400_000, // 24 hours (default: 1 hour)
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// Send the sessionUrl to your customer
|
|
235
|
+
await sendInvitationEmail(session.customer.email, sessionUrl);
|
|
236
|
+
|
|
237
|
+
// List sessions
|
|
238
|
+
const { sessions, totalCount } = await service.kyc.sessions.list({
|
|
239
|
+
isComplete: true,
|
|
240
|
+
sortBy: 'completedAt',
|
|
241
|
+
sortOrder: 'desc',
|
|
242
|
+
limit: 50,
|
|
243
|
+
offset: 0,
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
// Get a specific session (includes full step history & media)
|
|
247
|
+
const fullSession = await service.kyc.sessions.get(session.id);
|
|
248
|
+
console.log(fullSession.status); // 'complete' | 'in-progress' | 'approved' | ...
|
|
249
|
+
|
|
250
|
+
// Delete a session
|
|
251
|
+
await service.kyc.sessions.delete(session.id);
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## KYC Workflows
|
|
257
|
+
|
|
258
|
+
A workflow defines the ordered steps a customer goes through during a session
|
|
259
|
+
(e.g. identity verification → liveness → form collection).
|
|
260
|
+
|
|
261
|
+
### Building a Workflow
|
|
262
|
+
|
|
263
|
+
Use `stepDefaults()` to get pre-built configurations for each step type, then
|
|
264
|
+
assemble them into a workflow.
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
import type { WorkflowRules } from '@dossier-wiki/cloud-sdk';
|
|
268
|
+
|
|
269
|
+
// Fetch defaults for all step types
|
|
270
|
+
const defaults = await service.kyc.workflows.stepDefaults();
|
|
271
|
+
const idStep = defaults.find(d => d.type === 'id_verification')!;
|
|
272
|
+
const livenessStep = defaults.find(d => d.type === 'liveness')!;
|
|
273
|
+
|
|
274
|
+
// Create the workflow
|
|
275
|
+
const workflow = await service.kyc.workflows.create({
|
|
276
|
+
name: 'Standard KYC',
|
|
277
|
+
description: 'Identity check + liveness verification',
|
|
278
|
+
steps: [
|
|
279
|
+
{
|
|
280
|
+
stepId: idStep.defaultStepId,
|
|
281
|
+
type: 'id_verification',
|
|
282
|
+
input: idStep.defaultInput as { config?: Record<string, unknown> },
|
|
283
|
+
output: { schema: idStep.schema },
|
|
284
|
+
rules: idStep.defaultRules as WorkflowRules,
|
|
285
|
+
locales: idStep.defaultLocales,
|
|
286
|
+
skippable: idStep.skippable,
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
stepId: livenessStep.defaultStepId,
|
|
290
|
+
type: 'liveness',
|
|
291
|
+
input: livenessStep.defaultInput as { config?: Record<string, unknown> },
|
|
292
|
+
output: { schema: livenessStep.schema },
|
|
293
|
+
rules: livenessStep.defaultRules as WorkflowRules,
|
|
294
|
+
locales: livenessStep.defaultLocales,
|
|
295
|
+
skippable: livenessStep.skippable,
|
|
44
296
|
},
|
|
45
|
-
|
|
297
|
+
],
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// Use the workflow when creating sessions
|
|
301
|
+
const { sessionUrl } = await service.kyc.sessions.create({
|
|
302
|
+
customer: { name: 'Bob Lee' },
|
|
303
|
+
workflowId: workflow.id,
|
|
304
|
+
});
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Zod Validation
|
|
308
|
+
|
|
309
|
+
The SDK exports Zod schemas for the step discriminated union, so you can
|
|
310
|
+
validate workflow input at runtime before sending it to the API.
|
|
311
|
+
|
|
312
|
+
```ts
|
|
313
|
+
import { schemas } from '@dossier-wiki/cloud-sdk';
|
|
314
|
+
|
|
315
|
+
// Validates the full workflow creation input including per-step type constraints
|
|
316
|
+
const validated = schemas.CreateWorkflowSchema.parse(rawInput);
|
|
317
|
+
const workflow = await service.kyc.workflows.create(validated);
|
|
318
|
+
|
|
319
|
+
// Validate a single step
|
|
320
|
+
const step = schemas.WorkflowStepSchema.parse({
|
|
321
|
+
stepId: 'step_liveness',
|
|
322
|
+
type: 'liveness',
|
|
323
|
+
input: { config: { challengeType: 'selfie', timeLimitSeconds: 30 } },
|
|
324
|
+
output: {},
|
|
325
|
+
rules: { onSuccess: 'COMPLETE_SESSION', onFailure: 'FAIL_SESSION' },
|
|
326
|
+
});
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Available step types and their config constraints:
|
|
330
|
+
|
|
331
|
+
| Type | Config fields |
|
|
332
|
+
|------|--------------|
|
|
333
|
+
| `id_verification` | `strategy`, `allowedDocuments`, `maxSubmissions`, `allowUpload` |
|
|
334
|
+
| `document_collection` | `allowedDocuments`, `allowUpload`, `maxSubmissions` |
|
|
335
|
+
| `liveness` | `challengeType`, `timeLimitSeconds`, `minFaceLuminance`, `minFaceDetectionConfidence` |
|
|
336
|
+
| `form_collection` | `templateId`, `fields` |
|
|
337
|
+
| `esignature` | `signatureTypesAllowed` |
|
|
338
|
+
| `action` | `actionType` |
|
|
339
|
+
|
|
340
|
+
Other workflow operations:
|
|
341
|
+
|
|
342
|
+
```ts
|
|
343
|
+
// List all workflows
|
|
344
|
+
const workflows = await service.kyc.workflows.list();
|
|
345
|
+
|
|
346
|
+
// Get a specific workflow
|
|
347
|
+
const wf = await service.kyc.workflows.get('wf_abc123');
|
|
46
348
|
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
-
|
|
349
|
+
// Update (creates a new version; existing sessions are unaffected)
|
|
350
|
+
const updated = await service.kyc.workflows.update('wf_abc123', {
|
|
351
|
+
name: 'Standard KYC v2',
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
// Delete
|
|
355
|
+
await service.kyc.workflows.delete('wf_old123');
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## Document Processing
|
|
361
|
+
|
|
362
|
+
Initiate AI extraction jobs on uploaded documents. The pipeline validates the
|
|
363
|
+
document, extracts structured data, and runs post-processing checks.
|
|
364
|
+
|
|
365
|
+
Available processor IDs:
|
|
366
|
+
|
|
367
|
+
| `processorId` | Document |
|
|
368
|
+
|---------------|---------|
|
|
369
|
+
| `INVOICE` | Invoice / bill |
|
|
370
|
+
| `SRI_LANKA_ID` | Sri Lanka National Identity Card |
|
|
371
|
+
| `SRI_LANKA_FORM1_COMPANY_REGISTRATION` | Company Registration Form 1 |
|
|
372
|
+
| `SRI_LANKA_FORM15_ANNUAL_RETURN` | Annual Return Form 15 |
|
|
373
|
+
|
|
374
|
+
### Initiate a Job
|
|
375
|
+
|
|
376
|
+
```ts
|
|
377
|
+
const instance = await service.documents.initiate({
|
|
378
|
+
processorId: 'INVOICE',
|
|
379
|
+
files: [
|
|
380
|
+
{ url: 'https://example.com/invoice.pdf', mimeType: 'application/pdf' },
|
|
381
|
+
],
|
|
382
|
+
|
|
383
|
+
// Optional: cross-check context for the AI
|
|
384
|
+
inputData: {
|
|
385
|
+
expectedVendor: 'ACME Corp',
|
|
386
|
+
expectedAmount: '1500.00',
|
|
387
|
+
},
|
|
388
|
+
|
|
389
|
+
// Optional: arbitrary metadata stored on the instance
|
|
390
|
+
metadata: { orderId: 'ord_456' },
|
|
391
|
+
|
|
392
|
+
// Default: true — runs asynchronously; false waits for completion
|
|
393
|
+
backgroundProcessing: true,
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
console.log(instance.instanceId); // use this to poll or stream
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### Poll for Results
|
|
400
|
+
|
|
401
|
+
```ts
|
|
402
|
+
let instance = await service.documents.get(instanceId);
|
|
403
|
+
|
|
404
|
+
while (instance.status === 'pending' || instance.status === 'running') {
|
|
405
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
406
|
+
instance = await service.documents.get(instanceId);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (instance.status === 'completed') {
|
|
410
|
+
console.log(instance.result?.validation.passed);
|
|
411
|
+
console.log(instance.result?.normalizedData);
|
|
412
|
+
}
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### Real-Time Progress (SSE)
|
|
416
|
+
|
|
417
|
+
```ts
|
|
418
|
+
const res = await service.documents.stream(instanceId);
|
|
419
|
+
const reader = res.body!.getReader();
|
|
420
|
+
const decoder = new TextDecoder();
|
|
421
|
+
|
|
422
|
+
while (true) {
|
|
423
|
+
const { done, value } = await reader.read();
|
|
424
|
+
if (done) break;
|
|
425
|
+
const text = decoder.decode(value, { stream: true });
|
|
426
|
+
// Each SSE line is a DocumentProcessingEvent JSON payload
|
|
427
|
+
console.log(text);
|
|
428
|
+
}
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
### Typed Extraction Schemas
|
|
432
|
+
|
|
433
|
+
Use the generic parameter to type the `result.schema` field for a specific processor:
|
|
434
|
+
|
|
435
|
+
```ts
|
|
436
|
+
import type {
|
|
437
|
+
DocumentProcessingExtractedField,
|
|
438
|
+
DocumentProcessingTransliteratedField,
|
|
439
|
+
} from '@dossier-wiki/cloud-sdk';
|
|
440
|
+
|
|
441
|
+
type SriLankaIdSchema = {
|
|
442
|
+
name: DocumentProcessingTransliteratedField;
|
|
443
|
+
idNumber: DocumentProcessingExtractedField<string>;
|
|
444
|
+
dateOfBirth: DocumentProcessingExtractedField<string>;
|
|
445
|
+
address: DocumentProcessingTransliteratedField;
|
|
446
|
+
gender: DocumentProcessingExtractedField<string>;
|
|
50
447
|
};
|
|
448
|
+
|
|
449
|
+
const instance = await service.documents.initiate<SriLankaIdSchema>({
|
|
450
|
+
processorId: 'SRI_LANKA_ID',
|
|
451
|
+
files: [{ base64Data: '...', mimeType: 'image/jpeg' }],
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
// result.schema is now typed as SriLankaIdSchema
|
|
455
|
+
const name = instance.result?.schema.name.enTransliterations[0].transliteratedText;
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
Other document processing operations:
|
|
459
|
+
|
|
460
|
+
```ts
|
|
461
|
+
// List instances
|
|
462
|
+
const { instances, count } = await service.documents.list({
|
|
463
|
+
processorId: 'INVOICE',
|
|
464
|
+
status: 'completed',
|
|
465
|
+
limit: 20,
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
// Get a specific stage result
|
|
469
|
+
const stage = await service.documents.getStage(instanceId, 'post_validation');
|
|
470
|
+
console.log(stage.data.validation.passed);
|
|
471
|
+
|
|
472
|
+
// List available processors
|
|
473
|
+
const processors = await service.documents.listProcessors();
|
|
474
|
+
|
|
475
|
+
// Delete an instance
|
|
476
|
+
await service.documents.delete(instanceId);
|
|
51
477
|
```
|
|
52
478
|
|
|
53
|
-
|
|
479
|
+
---
|
|
480
|
+
|
|
481
|
+
## Form Templates
|
|
54
482
|
|
|
55
|
-
|
|
483
|
+
Form templates define reusable sets of fields for the `form_collection` KYC
|
|
484
|
+
workflow step.
|
|
56
485
|
|
|
57
486
|
```ts
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
487
|
+
// Create a template
|
|
488
|
+
const template = await service.formTemplates.create({
|
|
489
|
+
name: 'Employment Details',
|
|
490
|
+
fields: [
|
|
491
|
+
{
|
|
492
|
+
id: 'employer',
|
|
493
|
+
type: 'text',
|
|
494
|
+
label: 'Employer Name',
|
|
495
|
+
required: true,
|
|
496
|
+
},
|
|
497
|
+
{
|
|
498
|
+
id: 'salary',
|
|
499
|
+
type: 'currency',
|
|
500
|
+
label: 'Annual Salary (LKR)',
|
|
501
|
+
required: true,
|
|
502
|
+
validation: { min: 0 },
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
id: 'employment_type',
|
|
506
|
+
type: 'select',
|
|
507
|
+
label: 'Employment Type',
|
|
508
|
+
required: true,
|
|
509
|
+
options: [
|
|
510
|
+
{ value: 'full_time', label: 'Full Time' },
|
|
511
|
+
{ value: 'part_time', label: 'Part Time' },
|
|
512
|
+
{ value: 'self_employed', label: 'Self Employed' },
|
|
513
|
+
],
|
|
514
|
+
},
|
|
515
|
+
],
|
|
62
516
|
});
|
|
517
|
+
|
|
518
|
+
// Reference the template in a form_collection step config
|
|
519
|
+
const workflowStep = {
|
|
520
|
+
type: 'form_collection' as const,
|
|
521
|
+
input: { config: { templateId: template.id } },
|
|
522
|
+
// ...
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
// List, get, update, delete
|
|
526
|
+
const { templates } = await service.formTemplates.list({ searchQuery: 'employment' });
|
|
527
|
+
const full = await service.formTemplates.get(template.id);
|
|
528
|
+
await service.formTemplates.update(template.id, { name: 'Employment Details v2' });
|
|
529
|
+
await service.formTemplates.delete(template.id);
|
|
63
530
|
```
|
|
64
531
|
|
|
65
|
-
|
|
532
|
+
Available field types: `text`, `long_text`, `number`, `currency`, `country`,
|
|
533
|
+
`language`, `email`, `phone`, `date`, `select`, `multi_select`, `dropdown`,
|
|
534
|
+
`toggle`, `boolean`, `file`, `heading`, `paragraph`, `description`, `divider`.
|
|
535
|
+
|
|
536
|
+
---
|
|
537
|
+
|
|
538
|
+
## Media
|
|
66
539
|
|
|
67
|
-
|
|
540
|
+
Fetch binary files (images, videos, PDF signatures) from session results and
|
|
541
|
+
document processing instances using signed storage tokens.
|
|
68
542
|
|
|
69
543
|
```ts
|
|
70
|
-
|
|
544
|
+
// Tokens appear in session result media arrays and processing instance files
|
|
545
|
+
const token = session.result.steps[0].summary?.media[0]?.key;
|
|
71
546
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
547
|
+
if (token) {
|
|
548
|
+
const res = await service.media.get(token);
|
|
549
|
+
|
|
550
|
+
// Browser — convert to object URL for display
|
|
551
|
+
const blob = await res.blob();
|
|
552
|
+
const objectUrl = URL.createObjectURL(blob);
|
|
553
|
+
imageElement.src = objectUrl;
|
|
554
|
+
|
|
555
|
+
// Node.js — pipe to disk
|
|
556
|
+
const { createWriteStream } = await import('fs');
|
|
557
|
+
const { Readable } = await import('stream');
|
|
558
|
+
Readable.fromWeb(res.body!).pipe(createWriteStream('./capture.jpg'));
|
|
79
559
|
}
|
|
80
560
|
```
|
|
81
561
|
|
|
82
|
-
|
|
562
|
+
---
|
|
563
|
+
|
|
564
|
+
## Webhooks
|
|
83
565
|
|
|
84
|
-
|
|
566
|
+
Use `DossiersWebhookRouter` to handle incoming webhook events with HMAC-SHA256
|
|
567
|
+
signature verification.
|
|
85
568
|
|
|
86
|
-
|
|
569
|
+
```ts
|
|
570
|
+
import { DossiersWebhookRouter, DossiersWebhookEventTypes } from '@dossier-wiki/cloud-sdk';
|
|
87
571
|
|
|
88
|
-
|
|
572
|
+
const router = new DossiersWebhookRouter(process.env.DOSSIERS_WEBHOOK_SECRET!);
|
|
573
|
+
|
|
574
|
+
router
|
|
575
|
+
.on(DossiersWebhookEventTypes.DOCUMENT_VERIFICATION_INSTANCE_COMPLETED, async (event, ctx) => {
|
|
576
|
+
const { documentProcessorInstanceId } = event.data;
|
|
577
|
+
const instance = await service.documents.get(documentProcessorInstanceId);
|
|
578
|
+
await saveResult(instance);
|
|
579
|
+
})
|
|
580
|
+
.on(DossiersWebhookEventTypes.KYC_SESSION_COMPLETED, async (event, ctx) => {
|
|
581
|
+
// Payloads carry no PII — fetch the full session on demand.
|
|
582
|
+
const { kycSessionId, outcome } = event.data;
|
|
583
|
+
const session = await service.kyc.sessions.get(kycSessionId);
|
|
584
|
+
await recordVerification(session, outcome); // outcome: 'complete' | 'failed'
|
|
585
|
+
})
|
|
586
|
+
.on(DossiersWebhookEventTypes.AML_SCREENING_ALERT_TRIGGERED, async (event, ctx) => {
|
|
587
|
+
console.log('Alert triggered for screening request', event.data);
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
// Express
|
|
591
|
+
app.post('/webhooks/dossiers', async (req, res) => {
|
|
592
|
+
// Reconstruct a Web API Request from the Express request
|
|
593
|
+
const body = await getRawBody(req);
|
|
594
|
+
const webReq = new Request('https://your-server/webhooks/dossiers', {
|
|
595
|
+
method: 'POST',
|
|
596
|
+
headers: req.headers as HeadersInit,
|
|
597
|
+
body,
|
|
598
|
+
});
|
|
599
|
+
const response = await router.handle(webReq);
|
|
600
|
+
res.status(response.status).send(await response.text());
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
// Next.js App Router
|
|
604
|
+
export async function POST(req: Request) {
|
|
605
|
+
return router.handle(req, { waitUntil: (p) => context.waitUntil(p) });
|
|
606
|
+
}
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
Webhook events are acknowledged immediately (200 OK) before the handler runs —
|
|
610
|
+
a slow handler will not cause the platform to retry. If your handler throws,
|
|
611
|
+
the error is logged but no retry occurs. Implement your own retry logic inside
|
|
612
|
+
the handler if needed.
|
|
613
|
+
|
|
614
|
+
Every event delivered to a handler has the shape:
|
|
615
|
+
|
|
616
|
+
```ts
|
|
617
|
+
{
|
|
618
|
+
id: string; // e.g. "evt_1712345678_ab12cd34"
|
|
619
|
+
type: DossiersWebhookEventTypes;
|
|
620
|
+
organizationId: string;
|
|
621
|
+
eventTriggeredAt: string; // ISO 8601
|
|
622
|
+
data: /* typed per event — see below */;
|
|
623
|
+
}
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
The `data` field is fully typed by the event `type` you pass to `.on()`. Import
|
|
627
|
+
`DossiersWebhookPayload` for the discriminated union of all event shapes.
|
|
628
|
+
|
|
629
|
+
### Available Event Types
|
|
630
|
+
|
|
631
|
+
**Document processing**
|
|
632
|
+
|
|
633
|
+
| Enum value | Event string | `data` type |
|
|
634
|
+
|------------|-------------|-------------|
|
|
635
|
+
| `DOCUMENT_VERIFICATION_INSTANCE_CREATED` | `documentVerification.instance.created` | `DocumentVerificationInstanceCreatedData` |
|
|
636
|
+
| `DOCUMENT_VERIFICATION_INSTANCE_UPDATED` | `documentVerification.instance.updated` | `DocumentVerificationInstanceUpdatedData` |
|
|
637
|
+
| `DOCUMENT_VERIFICATION_INSTANCE_COMPLETED` | `documentVerification.instance.completed` | `DocumentVerificationInstanceCompletedData` |
|
|
638
|
+
| `DOCUMENT_VERIFICATION_INSTANCE_DELETED` | `documentVerification.instance.deleted` | `DocumentVerificationInstanceDeletedData` |
|
|
639
|
+
|
|
640
|
+
**KYC sessions**
|
|
641
|
+
|
|
642
|
+
| Enum value | Event string | `data` type |
|
|
643
|
+
|------------|-------------|-------------|
|
|
644
|
+
| `KYC_SESSION_CREATED` | `kycSessions.session.created` | `KycSessionEventData` |
|
|
645
|
+
| `KYC_SESSION_UPDATED` | `kycSessions.session.updated` | `KycSessionEventData` |
|
|
646
|
+
| `KYC_SESSION_COMPLETED` | `kycSessions.session.completed` | `KycSessionEventData` (with `outcome`) |
|
|
647
|
+
| `KYC_SESSION_REVIEWED` | `kycSessions.session.reviewed` | `KycSessionEventData` (with `review`) |
|
|
648
|
+
| `KYC_SESSION_DELETED` | `kycSessions.session.deleted` | `KycSessionDeletedData` |
|
|
649
|
+
| `KYC_STEP_COMPLETED` | `kycSessions.step.completed` | `KycStepEventData` |
|
|
650
|
+
| `KYC_STEP_FAILED` | `kycSessions.step.failed` | `KycStepEventData` |
|
|
651
|
+
| `KYC_SESSION_COMMENT_ADDED` | `kycSessions.session.commentAdded` | `KycSessionCommentAddedData` |
|
|
652
|
+
| `KYC_SESSION_COMMENT_UPDATED` | `kycSessions.session.commentUpdated` | `KycSessionCommentUpdatedData` |
|
|
653
|
+
| `KYC_SESSION_COMMENT_DELETED` | `kycSessions.session.commentDeleted` | `KycSessionCommentDeletedData` |
|
|
654
|
+
|
|
655
|
+
> KYC payloads carry **no PII** (no customer name/email, no step outputs). They
|
|
656
|
+
> reference a `kycSessionId` — fetch the detail you need with
|
|
657
|
+
> `service.kyc.sessions.get(kycSessionId)`.
|
|
658
|
+
|
|
659
|
+
**AML screening**
|
|
660
|
+
|
|
661
|
+
| Enum value | Event string |
|
|
662
|
+
|------------|-------------|
|
|
663
|
+
| `AML_SCREENING_REQUEST_CREATED` | `amlScreening.screeningRequest.created` |
|
|
664
|
+
| `AML_SCREENING_REQUEST_COMPLETED` | `amlScreening.screeningRequest.completed` |
|
|
665
|
+
| `AML_SCREENING_ALERT_TRIGGERED` | `amlScreening.screeningAlert.triggered` |
|
|
666
|
+
| `AML_SCREENING_ALERT_STATUS_CHANGED` | `amlScreening.screeningAlert.statusChanged` |
|
|
667
|
+
| `AML_SCREENING_ALERT_COMMENT_ADDED` | `amlScreening.screeningAlert.commentAdded` |
|
|
668
|
+
| `AML_SCREENING_ALERT_COMMENT_UPDATED` | `amlScreening.screeningAlert.commentUpdated` |
|
|
669
|
+
| `AML_SCREENING_ALERT_COMMENT_DELETED` | `amlScreening.screeningAlert.commentDeleted` |
|
|
670
|
+
| `AML_SCREENING_ALERT_DELETED` | `amlScreening.screeningAlert.deleted` |
|
|
671
|
+
|
|
672
|
+
**System**
|
|
673
|
+
|
|
674
|
+
| Enum value | Event string |
|
|
675
|
+
|------------|-------------|
|
|
676
|
+
| `SYSTEM_TEST_EVENT` | `system.testEvent` |
|
|
677
|
+
| `SYSTEM_PRODUCT_ACCESS_GRANTED` | `system.product.accessGranted` |
|
|
678
|
+
| `SYSTEM_PRODUCT_ACCESS_REVOKED` | `system.product.accessRevoked` |
|
|
679
|
+
| `SYSTEM_API_KEY_CREATED` | `system.apiKey.created` |
|
|
680
|
+
| `SYSTEM_API_KEY_INVALIDATED` | `system.apiKey.invalidated` |
|
|
681
|
+
| `SYSTEM_USAGE_LIMIT_REACHED` | `system.usage.limitReached` |
|
|
682
|
+
| `SYSTEM_USAGE_LIMIT_WARNING` | `system.usage.limitWarning` |
|
|
683
|
+
|
|
684
|
+
---
|
|
685
|
+
|
|
686
|
+
## TypeScript
|
|
687
|
+
|
|
688
|
+
All API request and response shapes are exported as TypeScript interfaces.
|
|
689
|
+
Import them as needed:
|
|
690
|
+
|
|
691
|
+
```ts
|
|
692
|
+
import type {
|
|
693
|
+
// AML
|
|
694
|
+
SanctionSearchInput,
|
|
695
|
+
SanctionSearchResponse,
|
|
696
|
+
Sanction,
|
|
697
|
+
DossierSearchInput,
|
|
698
|
+
IndividualDossier,
|
|
699
|
+
CreateScreeningRequestDto,
|
|
700
|
+
|
|
701
|
+
// KYC Sessions
|
|
702
|
+
CreateKycSessionDTO,
|
|
703
|
+
KycSessionOutputDTO,
|
|
704
|
+
KycSessionFiltersDTO,
|
|
705
|
+
PaginatedKycSessionsDTO,
|
|
706
|
+
|
|
707
|
+
// KYC Workflows
|
|
708
|
+
CreateKycWorkflowInput,
|
|
709
|
+
KycWorkflow,
|
|
710
|
+
KycWorkflowStep,
|
|
711
|
+
KycWorkflowStepType,
|
|
712
|
+
WorkflowRules,
|
|
713
|
+
WorkflowStepDefault,
|
|
714
|
+
|
|
715
|
+
// Document Processing
|
|
716
|
+
InitiateDocumentProcessingInput,
|
|
717
|
+
DocumentProcessingInstance,
|
|
718
|
+
DocumentProcessingResult,
|
|
719
|
+
DocumentProcessingExtractedField,
|
|
720
|
+
DocumentProcessingTransliteratedField,
|
|
721
|
+
DocumentProcessorId,
|
|
722
|
+
|
|
723
|
+
// Form Templates
|
|
724
|
+
CreateFormTemplateInput,
|
|
725
|
+
FormTemplate,
|
|
726
|
+
FormField,
|
|
727
|
+
FormFieldType,
|
|
728
|
+
|
|
729
|
+
// Webhooks
|
|
730
|
+
DossiersWebhookPayload,
|
|
731
|
+
DossiersWebhookEvent,
|
|
732
|
+
KycSessionEventData,
|
|
733
|
+
KycSessionDeletedData,
|
|
734
|
+
KycStepEventData,
|
|
735
|
+
KycSessionCommentAddedData,
|
|
736
|
+
KycSessionCommentUpdatedData,
|
|
737
|
+
KycSessionCommentDeletedData,
|
|
738
|
+
} from '@dossier-wiki/cloud-sdk';
|
|
739
|
+
```
|