@kyvshield/rest-sdk 1.0.0
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 +372 -0
- package/dist/index.d.ts +163 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +309 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +208 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
# @kyvshield/rest-sdk
|
|
2
|
+
|
|
3
|
+
Fully typed Node.js / TypeScript SDK for the [KyvShield](https://kyvshield.com) KYC REST API.
|
|
4
|
+
|
|
5
|
+
Requires **Node.js 18+** (uses native `fetch` and `crypto`).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @kyvshield/rest-sdk
|
|
13
|
+
# or
|
|
14
|
+
yarn add @kyvshield/rest-sdk
|
|
15
|
+
# or
|
|
16
|
+
pnpm add @kyvshield/rest-sdk
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Quick start
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { KyvShield } from '@kyvshield/rest-sdk';
|
|
25
|
+
|
|
26
|
+
const kyv = new KyvShield('your-api-key');
|
|
27
|
+
|
|
28
|
+
const result = await kyv.verify({
|
|
29
|
+
steps: ['selfie', 'recto', 'verso'],
|
|
30
|
+
target: 'SN-CIN',
|
|
31
|
+
language: 'fr',
|
|
32
|
+
challengeMode: 'standard',
|
|
33
|
+
requireFaceMatch: true,
|
|
34
|
+
images: {
|
|
35
|
+
// key = {step}_{challenge}
|
|
36
|
+
selfie_center_face: './images/selfie.jpg',
|
|
37
|
+
selfie_close_eyes: './images/selfie_eyes_closed.jpg',
|
|
38
|
+
recto_center_document: './images/recto.jpg',
|
|
39
|
+
recto_tilt_left: './images/recto_tilt_left.jpg',
|
|
40
|
+
verso_center_document: './images/verso.jpg',
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (result.overall_status === 'pass') {
|
|
45
|
+
console.log('KYC passed!', result.session_id);
|
|
46
|
+
} else {
|
|
47
|
+
console.warn('KYC rejected:', result.steps.map(s => s.user_messages).flat());
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## API Reference
|
|
54
|
+
|
|
55
|
+
### `new KyvShield(apiKey, baseUrl?)`
|
|
56
|
+
|
|
57
|
+
| Parameter | Type | Default | Description |
|
|
58
|
+
|-----------|----------|-------------------------------------------------|--------------------------------|
|
|
59
|
+
| `apiKey` | `string` | — | Your KyvShield API key |
|
|
60
|
+
| `baseUrl` | `string` | `https://kyvshield-naruto.innolinkcloud.com` | Override for staging/local use |
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
// Production (default)
|
|
64
|
+
const kyv = new KyvShield('your-api-key');
|
|
65
|
+
|
|
66
|
+
// Local development
|
|
67
|
+
const kyv = new KyvShield('your-api-key', 'http://localhost:8080');
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
### `kyv.getChallenges()`
|
|
73
|
+
|
|
74
|
+
Returns the available challenge names grouped by type (`document` / `selfie`) and mode (`minimal` / `standard` / `strict`).
|
|
75
|
+
|
|
76
|
+
Use this to discover which image keys you need to provide for a given `challengeMode`.
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
const { challenges } = await kyv.getChallenges();
|
|
80
|
+
|
|
81
|
+
// challenges.document.standard => ['center_document', 'tilt_left', 'tilt_right']
|
|
82
|
+
// challenges.selfie.minimal => ['center_face', 'close_eyes']
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Return type:** [`ChallengesResponse`](#challengesresponse)
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
### `kyv.verify(options)`
|
|
90
|
+
|
|
91
|
+
Submit a KYC verification request. Reads image files from disk and sends them as multipart form data.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
const result = await kyv.verify({
|
|
95
|
+
steps: ['selfie', 'recto'],
|
|
96
|
+
target: 'SN-CIN',
|
|
97
|
+
language: 'en',
|
|
98
|
+
challengeMode: 'minimal',
|
|
99
|
+
requireFaceMatch: true,
|
|
100
|
+
kycIdentifier: 'user-ref-42',
|
|
101
|
+
images: {
|
|
102
|
+
selfie_center_face: './selfie.jpg',
|
|
103
|
+
recto_center_document: './recto.jpg',
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Options:** [`VerifyOptions`](#verifyoptions)
|
|
109
|
+
|
|
110
|
+
**Return type:** [`KycResponse`](#kycresponse)
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
### `KyvShield.verifyWebhookSignature(payload, apiKey, signatureHeader)`
|
|
115
|
+
|
|
116
|
+
Static method. Validates an incoming KyvShield webhook using HMAC-SHA256.
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
// Express example
|
|
120
|
+
import express from 'express';
|
|
121
|
+
import { KyvShield } from '@kyvshield/rest-sdk';
|
|
122
|
+
|
|
123
|
+
const app = express();
|
|
124
|
+
|
|
125
|
+
app.post('/webhook', express.raw({ type: '*/*' }), (req, res) => {
|
|
126
|
+
const valid = KyvShield.verifyWebhookSignature(
|
|
127
|
+
req.body, // Buffer
|
|
128
|
+
process.env.KYVSHIELD_API_KEY!,
|
|
129
|
+
req.headers['x-kyvshield-signature'] as string,
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
if (!valid) return res.status(401).send('Invalid signature');
|
|
133
|
+
|
|
134
|
+
const event = JSON.parse(req.body.toString());
|
|
135
|
+
console.log('Webhook event:', event);
|
|
136
|
+
res.sendStatus(200);
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
| Parameter | Type | Description |
|
|
141
|
+
|---------------------|----------|-------------------------------------------------------|
|
|
142
|
+
| `payload` | `Buffer` | Raw request body |
|
|
143
|
+
| `apiKey` | `string` | Your KyvShield API key |
|
|
144
|
+
| `signatureHeader` | `string` | Value of `X-KyvShield-Signature` from the HTTP header |
|
|
145
|
+
|
|
146
|
+
Returns `true` if the signature is valid, `false` otherwise.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Types Reference
|
|
151
|
+
|
|
152
|
+
### `VerifyOptions`
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
interface VerifyOptions {
|
|
156
|
+
/** Steps to execute in order. */
|
|
157
|
+
steps: Step[]; // e.g. ['selfie', 'recto', 'verso']
|
|
158
|
+
|
|
159
|
+
/** Document type. */
|
|
160
|
+
target: DocumentTarget; // e.g. 'SN-CIN'
|
|
161
|
+
|
|
162
|
+
/** Response language. Default: 'fr' */
|
|
163
|
+
language?: Language; // 'fr' | 'en' | 'wo'
|
|
164
|
+
|
|
165
|
+
/** Global challenge intensity. Default: 'standard' */
|
|
166
|
+
challengeMode?: ChallengeMode; // 'minimal' | 'standard' | 'strict'
|
|
167
|
+
|
|
168
|
+
/** Per-step overrides */
|
|
169
|
+
selfieChallengeMode?: ChallengeMode;
|
|
170
|
+
rectoChallengeMode?: ChallengeMode;
|
|
171
|
+
versoChallengeMode?: ChallengeMode;
|
|
172
|
+
|
|
173
|
+
/** Whether to match selfie face against document photo. Default: false */
|
|
174
|
+
requireFaceMatch?: boolean;
|
|
175
|
+
|
|
176
|
+
/** Your internal reference ID, echoed back in the response. */
|
|
177
|
+
kycIdentifier?: string;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Map of images to submit.
|
|
181
|
+
* Key format: `{step}_{challenge}`, e.g. 'recto_center_document'
|
|
182
|
+
* Value: path to the image file on disk.
|
|
183
|
+
*/
|
|
184
|
+
images: Record<string, string>;
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### `KycResponse`
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
interface KycResponse {
|
|
192
|
+
success: boolean;
|
|
193
|
+
session_id: string;
|
|
194
|
+
overall_status: 'pass' | 'reject';
|
|
195
|
+
overall_confidence: number; // 0–1
|
|
196
|
+
processing_time_ms: number;
|
|
197
|
+
face_verification?: FaceVerification;
|
|
198
|
+
steps: StepResult[];
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### `StepResult`
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
interface StepResult {
|
|
206
|
+
step_index: number;
|
|
207
|
+
step_type: 'selfie' | 'recto' | 'verso';
|
|
208
|
+
success: boolean;
|
|
209
|
+
processing_time_ms: number;
|
|
210
|
+
|
|
211
|
+
liveness: {
|
|
212
|
+
is_live: boolean;
|
|
213
|
+
score: number; // 0–1
|
|
214
|
+
confidence: 'HIGH' | 'MEDIUM' | 'LOW';
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
verification: {
|
|
218
|
+
is_authentic: boolean;
|
|
219
|
+
confidence: number; // 0–1
|
|
220
|
+
checks_passed: string[];
|
|
221
|
+
fraud_indicators: string[];
|
|
222
|
+
warnings: string[];
|
|
223
|
+
issues: string[];
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
user_messages: string[];
|
|
227
|
+
|
|
228
|
+
// Document steps (recto / verso) only:
|
|
229
|
+
aligned_document?: string; // base64 JPEG
|
|
230
|
+
extraction?: ExtractionField[];
|
|
231
|
+
extracted_photos?: ExtractedPhoto[];
|
|
232
|
+
|
|
233
|
+
// Selfie step only:
|
|
234
|
+
captured_image?: string; // base64 JPEG
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### `ExtractionField`
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
interface ExtractionField {
|
|
242
|
+
key: string;
|
|
243
|
+
document_key: string;
|
|
244
|
+
label: string;
|
|
245
|
+
value: string;
|
|
246
|
+
display_priority: number;
|
|
247
|
+
icon?: string;
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### `ExtractedPhoto`
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
interface ExtractedPhoto {
|
|
255
|
+
image: string; // base64 JPEG
|
|
256
|
+
confidence: number; // 0–1
|
|
257
|
+
bbox: number[]; // [x, y, width, height]
|
|
258
|
+
area: number;
|
|
259
|
+
width: number;
|
|
260
|
+
height: number;
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### `FaceVerification`
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
interface FaceVerification {
|
|
268
|
+
is_match: boolean;
|
|
269
|
+
similarity_score: number; // 0–100
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### `ChallengesResponse`
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
interface ChallengesResponse {
|
|
277
|
+
challenges: {
|
|
278
|
+
document: { minimal: string[]; standard: string[]; strict: string[] };
|
|
279
|
+
selfie: { minimal: string[]; standard: string[]; strict: string[] };
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Error handling
|
|
287
|
+
|
|
288
|
+
All API errors throw a `KyvShieldError`:
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
import { KyvShield, KyvShieldError } from '@kyvshield/rest-sdk';
|
|
292
|
+
|
|
293
|
+
try {
|
|
294
|
+
const result = await kyv.verify({ ... });
|
|
295
|
+
} catch (e) {
|
|
296
|
+
if (e instanceof KyvShieldError) {
|
|
297
|
+
console.error('Status code:', e.statusCode); // e.g. 401, 422, 500
|
|
298
|
+
console.error('Body:', e.body); // parsed JSON body when available
|
|
299
|
+
console.error('Message:', e.message);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
The SDK also throws `KyvShieldError` (without a `statusCode`) for:
|
|
305
|
+
- Empty API key in the constructor
|
|
306
|
+
- Empty `steps` array
|
|
307
|
+
- Empty `target` string
|
|
308
|
+
- Empty `images` map
|
|
309
|
+
- Image file path that does not exist on disk
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## Building
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
npm install
|
|
317
|
+
npm run build # outputs to ./dist
|
|
318
|
+
npm run lint # type-check only, no emit
|
|
319
|
+
npm run build:watch
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Running the test suite
|
|
325
|
+
|
|
326
|
+
Ensure the KyvShield backend is running locally on port 8080, then:
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
npx ts-node --esm test.ts
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
The test script covers:
|
|
333
|
+
- Constructor validation
|
|
334
|
+
- Webhook signature verification (HMAC-SHA256, timing-safe comparison)
|
|
335
|
+
- `VerifyOptions` validation (no network)
|
|
336
|
+
- `getChallenges()` (network)
|
|
337
|
+
- `verify()` with a single recto step (network)
|
|
338
|
+
- `verify()` with recto + verso steps (network)
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## Challenge modes
|
|
343
|
+
|
|
344
|
+
| Mode | Document challenges | Selfie challenges |
|
|
345
|
+
|------------|----------------------------------------------------------------------------|-----------------------------------------------------------------|
|
|
346
|
+
| `minimal` | `center_document` | `center_face`, `close_eyes` |
|
|
347
|
+
| `standard` | `center_document`, `tilt_left`, `tilt_right` | `center_face`, `close_eyes`, `turn_left`, `turn_right` |
|
|
348
|
+
| `strict` | `center_document`, `tilt_left`, `tilt_right`, `tilt_forward`, `tilt_back` | `center_face`, `close_eyes`, `turn_left`, `turn_right`, `smile`, `look_up`, `look_down` |
|
|
349
|
+
|
|
350
|
+
The image map key for each image is `{step}_{challenge}`, e.g.:
|
|
351
|
+
- `recto_center_document`
|
|
352
|
+
- `recto_tilt_left`
|
|
353
|
+
- `selfie_center_face`
|
|
354
|
+
- `selfie_turn_right`
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## Supported document targets
|
|
359
|
+
|
|
360
|
+
| Value | Document |
|
|
361
|
+
|-----------------------|---------------------------------|
|
|
362
|
+
| `SN-CIN` | Carte d'Identité Nationale (SN) |
|
|
363
|
+
| `SN-PASSPORT` | Passeport sénégalais |
|
|
364
|
+
| `SN-DRIVER-LICENCE` | Permis de conduire (SN) |
|
|
365
|
+
|
|
366
|
+
Custom target strings are also accepted.
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## License
|
|
371
|
+
|
|
372
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KyvShield REST SDK — Node.js / TypeScript
|
|
3
|
+
*
|
|
4
|
+
* A fully typed SDK for the KyvShield KYC REST API.
|
|
5
|
+
* Requires Node.js 18+ (uses native fetch and crypto).
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { KyvShield } from '@kyvshield/rest-sdk';
|
|
10
|
+
*
|
|
11
|
+
* const kyv = new KyvShield('your-api-key');
|
|
12
|
+
*
|
|
13
|
+
* const result = await kyv.verify({
|
|
14
|
+
* steps: ['selfie', 'recto', 'verso'],
|
|
15
|
+
* target: 'SN-CIN',
|
|
16
|
+
* language: 'fr',
|
|
17
|
+
* challengeMode: 'standard',
|
|
18
|
+
* requireFaceMatch: true,
|
|
19
|
+
* images: {
|
|
20
|
+
* selfie_center_face: './selfie.jpg',
|
|
21
|
+
* recto_center_document: './recto.jpg',
|
|
22
|
+
* verso_center_document: './verso.jpg',
|
|
23
|
+
* },
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* console.log(result.overall_status); // 'pass' | 'reject'
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
import type { ChallengesResponse, KycResponse, KyvShieldErrorDetails, VerifyOptions } from './types.js';
|
|
30
|
+
export * from './types.js';
|
|
31
|
+
/**
|
|
32
|
+
* Error thrown when the KyvShield API returns a non-2xx response
|
|
33
|
+
* or when a request cannot be completed.
|
|
34
|
+
*/
|
|
35
|
+
export declare class KyvShieldError extends Error {
|
|
36
|
+
readonly statusCode?: number;
|
|
37
|
+
readonly body?: unknown;
|
|
38
|
+
constructor(message: string, details?: KyvShieldErrorDetails);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* KyvShield SDK client.
|
|
42
|
+
*
|
|
43
|
+
* Instantiate once and reuse across your application.
|
|
44
|
+
*/
|
|
45
|
+
export declare class KyvShield {
|
|
46
|
+
private readonly apiKey;
|
|
47
|
+
private readonly baseUrl;
|
|
48
|
+
/**
|
|
49
|
+
* Create a new KyvShield client.
|
|
50
|
+
*
|
|
51
|
+
* @param apiKey - Your KyvShield API key (sent as the `X-API-Key` header).
|
|
52
|
+
* @param baseUrl - Optional base URL override. Defaults to the production endpoint.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* // Production
|
|
57
|
+
* const kyv = new KyvShield('your-api-key');
|
|
58
|
+
*
|
|
59
|
+
* // Local / staging
|
|
60
|
+
* const kyv = new KyvShield('your-api-key', 'http://localhost:8080');
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
constructor(apiKey: string, baseUrl?: string);
|
|
64
|
+
/**
|
|
65
|
+
* Retrieve the list of available challenges for each mode and step type.
|
|
66
|
+
*
|
|
67
|
+
* Useful for dynamically building the image map to pass to {@link verify}.
|
|
68
|
+
*
|
|
69
|
+
* @returns A {@link ChallengesResponse} object describing all available challenges.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* const { challenges } = await kyv.getChallenges();
|
|
74
|
+
* console.log(challenges.selfie.standard);
|
|
75
|
+
* // ['center_face', 'close_eyes', 'turn_left', 'turn_right']
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
getChallenges(): Promise<ChallengesResponse>;
|
|
79
|
+
/**
|
|
80
|
+
* Submit a KYC verification request.
|
|
81
|
+
*
|
|
82
|
+
* The SDK reads each image from disk, packages everything as a
|
|
83
|
+
* `multipart/form-data` request, and returns the fully typed response.
|
|
84
|
+
*
|
|
85
|
+
* @param options - Verification options. See {@link VerifyOptions} for full documentation.
|
|
86
|
+
* @returns A {@link KycResponse} with per-step results and an overall decision.
|
|
87
|
+
*
|
|
88
|
+
* @throws {@link KyvShieldError} on HTTP errors or missing image files.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* const result = await kyv.verify({
|
|
93
|
+
* steps: ['selfie', 'recto'],
|
|
94
|
+
* target: 'SN-CIN',
|
|
95
|
+
* language: 'en',
|
|
96
|
+
* challengeMode: 'minimal',
|
|
97
|
+
* requireFaceMatch: true,
|
|
98
|
+
* images: {
|
|
99
|
+
* selfie_center_face: './selfie.jpg',
|
|
100
|
+
* recto_center_document: './recto.jpg',
|
|
101
|
+
* },
|
|
102
|
+
* });
|
|
103
|
+
*
|
|
104
|
+
* if (result.overall_status === 'pass') {
|
|
105
|
+
* console.log('Verification passed!', result.session_id);
|
|
106
|
+
* } else {
|
|
107
|
+
* console.warn('Verification rejected', result.steps.map(s => s.user_messages));
|
|
108
|
+
* }
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
verify(options: VerifyOptions): Promise<KycResponse>;
|
|
112
|
+
/**
|
|
113
|
+
* Verify an incoming webhook signature.
|
|
114
|
+
*
|
|
115
|
+
* KyvShield signs webhook payloads with HMAC-SHA256 using your API key.
|
|
116
|
+
* Call this before processing any webhook to confirm it came from KyvShield.
|
|
117
|
+
*
|
|
118
|
+
* @param payload - Raw request body as a `Buffer`.
|
|
119
|
+
* @param apiKey - Your KyvShield API key (same one used to create the client).
|
|
120
|
+
* @param signatureHeader - Value of the `X-KyvShield-Signature` header sent with the webhook.
|
|
121
|
+
* @returns `true` if the signature is valid, `false` otherwise.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```ts
|
|
125
|
+
* // Express example
|
|
126
|
+
* app.post('/webhook', express.raw({ type: '*\/*' }), (req, res) => {
|
|
127
|
+
* const valid = KyvShield.verifyWebhookSignature(
|
|
128
|
+
* req.body,
|
|
129
|
+
* process.env.KYVSHIELD_API_KEY!,
|
|
130
|
+
* req.headers['x-kyvshield-signature'] as string,
|
|
131
|
+
* );
|
|
132
|
+
*
|
|
133
|
+
* if (!valid) return res.status(401).send('Invalid signature');
|
|
134
|
+
*
|
|
135
|
+
* // process webhook ...
|
|
136
|
+
* res.sendStatus(200);
|
|
137
|
+
* });
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
static verifyWebhookSignature(payload: Buffer, apiKey: string, signatureHeader: string): boolean;
|
|
141
|
+
/** Build the common headers used by all non-multipart requests. */
|
|
142
|
+
private buildHeaders;
|
|
143
|
+
/**
|
|
144
|
+
* Validate required fields in {@link VerifyOptions} before sending.
|
|
145
|
+
* Throws a descriptive {@link KyvShieldError} on the first problem found.
|
|
146
|
+
*/
|
|
147
|
+
private validateVerifyOptions;
|
|
148
|
+
/**
|
|
149
|
+
* Build the `multipart/form-data` body from {@link VerifyOptions}.
|
|
150
|
+
*
|
|
151
|
+
* Text fields are appended first, followed by binary image fields.
|
|
152
|
+
*/
|
|
153
|
+
private buildFormData;
|
|
154
|
+
/**
|
|
155
|
+
* Throw a {@link KyvShieldError} when the HTTP response is not successful (2xx).
|
|
156
|
+
* Tries to parse JSON error details from the body when available.
|
|
157
|
+
*/
|
|
158
|
+
private assertOk;
|
|
159
|
+
/** Return a MIME type based on file extension. Defaults to `image/jpeg`. */
|
|
160
|
+
private guessMimeType;
|
|
161
|
+
}
|
|
162
|
+
export default KyvShield;
|
|
163
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAOH,OAAO,KAAK,EACV,kBAAkB,EAClB,WAAW,EACX,qBAAqB,EACrB,aAAa,EACd,MAAM,YAAY,CAAC;AAEpB,cAAc,YAAY,CAAC;AAS3B;;;GAGG;AACH,qBAAa,cAAe,SAAQ,KAAK;IACvC,SAAgB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpC,SAAgB,IAAI,CAAC,EAAE,OAAO,CAAC;gBAEnB,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB;CAM7D;AAID;;;;GAIG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC;;;;;;;;;;;;;;OAcG;gBACS,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,MAAyB;IAW9D;;;;;;;;;;;;;OAaG;IACG,aAAa,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAYlD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACG,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC;IAwB1D;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,MAAM,CAAC,sBAAsB,CAC3B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,MAAM,GACtB,OAAO;IA0BV,mEAAmE;IACnE,OAAO,CAAC,YAAY;IAOpB;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAsB7B;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAkDrB;;;OAGG;YACW,QAAQ;IAgBtB,4EAA4E;IAC5E,OAAO,CAAC,aAAa;CAWtB;AAED,eAAe,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KyvShield REST SDK — Node.js / TypeScript
|
|
3
|
+
*
|
|
4
|
+
* A fully typed SDK for the KyvShield KYC REST API.
|
|
5
|
+
* Requires Node.js 18+ (uses native fetch and crypto).
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { KyvShield } from '@kyvshield/rest-sdk';
|
|
10
|
+
*
|
|
11
|
+
* const kyv = new KyvShield('your-api-key');
|
|
12
|
+
*
|
|
13
|
+
* const result = await kyv.verify({
|
|
14
|
+
* steps: ['selfie', 'recto', 'verso'],
|
|
15
|
+
* target: 'SN-CIN',
|
|
16
|
+
* language: 'fr',
|
|
17
|
+
* challengeMode: 'standard',
|
|
18
|
+
* requireFaceMatch: true,
|
|
19
|
+
* images: {
|
|
20
|
+
* selfie_center_face: './selfie.jpg',
|
|
21
|
+
* recto_center_document: './recto.jpg',
|
|
22
|
+
* verso_center_document: './verso.jpg',
|
|
23
|
+
* },
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* console.log(result.overall_status); // 'pass' | 'reject'
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
import * as fs from 'node:fs';
|
|
30
|
+
import * as path from 'node:path';
|
|
31
|
+
import * as crypto from 'node:crypto';
|
|
32
|
+
import FormData from 'form-data';
|
|
33
|
+
export * from './types.js';
|
|
34
|
+
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
35
|
+
const DEFAULT_BASE_URL = 'https://kyvshield-naruto.innolinkcloud.com';
|
|
36
|
+
const API_VERSION = '/api/v1';
|
|
37
|
+
// ─── Error class ─────────────────────────────────────────────────────────────
|
|
38
|
+
/**
|
|
39
|
+
* Error thrown when the KyvShield API returns a non-2xx response
|
|
40
|
+
* or when a request cannot be completed.
|
|
41
|
+
*/
|
|
42
|
+
export class KyvShieldError extends Error {
|
|
43
|
+
statusCode;
|
|
44
|
+
body;
|
|
45
|
+
constructor(message, details) {
|
|
46
|
+
super(message);
|
|
47
|
+
this.name = 'KyvShieldError';
|
|
48
|
+
this.statusCode = details?.statusCode;
|
|
49
|
+
this.body = details?.body;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// ─── SDK Class ────────────────────────────────────────────────────────────────
|
|
53
|
+
/**
|
|
54
|
+
* KyvShield SDK client.
|
|
55
|
+
*
|
|
56
|
+
* Instantiate once and reuse across your application.
|
|
57
|
+
*/
|
|
58
|
+
export class KyvShield {
|
|
59
|
+
apiKey;
|
|
60
|
+
baseUrl;
|
|
61
|
+
/**
|
|
62
|
+
* Create a new KyvShield client.
|
|
63
|
+
*
|
|
64
|
+
* @param apiKey - Your KyvShield API key (sent as the `X-API-Key` header).
|
|
65
|
+
* @param baseUrl - Optional base URL override. Defaults to the production endpoint.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* // Production
|
|
70
|
+
* const kyv = new KyvShield('your-api-key');
|
|
71
|
+
*
|
|
72
|
+
* // Local / staging
|
|
73
|
+
* const kyv = new KyvShield('your-api-key', 'http://localhost:8080');
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
constructor(apiKey, baseUrl = DEFAULT_BASE_URL) {
|
|
77
|
+
if (!apiKey || apiKey.trim() === '') {
|
|
78
|
+
throw new KyvShieldError('apiKey must be a non-empty string');
|
|
79
|
+
}
|
|
80
|
+
this.apiKey = apiKey;
|
|
81
|
+
// Normalise: remove trailing slash so we can always append '/api/v1/...'
|
|
82
|
+
this.baseUrl = baseUrl.replace(/\/+$/, '');
|
|
83
|
+
}
|
|
84
|
+
// ── Public methods ──────────────────────────────────────────────────────────
|
|
85
|
+
/**
|
|
86
|
+
* Retrieve the list of available challenges for each mode and step type.
|
|
87
|
+
*
|
|
88
|
+
* Useful for dynamically building the image map to pass to {@link verify}.
|
|
89
|
+
*
|
|
90
|
+
* @returns A {@link ChallengesResponse} object describing all available challenges.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* const { challenges } = await kyv.getChallenges();
|
|
95
|
+
* console.log(challenges.selfie.standard);
|
|
96
|
+
* // ['center_face', 'close_eyes', 'turn_left', 'turn_right']
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
async getChallenges() {
|
|
100
|
+
const url = `${this.baseUrl}${API_VERSION}/challenges`;
|
|
101
|
+
const response = await fetch(url, {
|
|
102
|
+
method: 'GET',
|
|
103
|
+
headers: this.buildHeaders(),
|
|
104
|
+
});
|
|
105
|
+
await this.assertOk(response);
|
|
106
|
+
return response.json();
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Submit a KYC verification request.
|
|
110
|
+
*
|
|
111
|
+
* The SDK reads each image from disk, packages everything as a
|
|
112
|
+
* `multipart/form-data` request, and returns the fully typed response.
|
|
113
|
+
*
|
|
114
|
+
* @param options - Verification options. See {@link VerifyOptions} for full documentation.
|
|
115
|
+
* @returns A {@link KycResponse} with per-step results and an overall decision.
|
|
116
|
+
*
|
|
117
|
+
* @throws {@link KyvShieldError} on HTTP errors or missing image files.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```ts
|
|
121
|
+
* const result = await kyv.verify({
|
|
122
|
+
* steps: ['selfie', 'recto'],
|
|
123
|
+
* target: 'SN-CIN',
|
|
124
|
+
* language: 'en',
|
|
125
|
+
* challengeMode: 'minimal',
|
|
126
|
+
* requireFaceMatch: true,
|
|
127
|
+
* images: {
|
|
128
|
+
* selfie_center_face: './selfie.jpg',
|
|
129
|
+
* recto_center_document: './recto.jpg',
|
|
130
|
+
* },
|
|
131
|
+
* });
|
|
132
|
+
*
|
|
133
|
+
* if (result.overall_status === 'pass') {
|
|
134
|
+
* console.log('Verification passed!', result.session_id);
|
|
135
|
+
* } else {
|
|
136
|
+
* console.warn('Verification rejected', result.steps.map(s => s.user_messages));
|
|
137
|
+
* }
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
async verify(options) {
|
|
141
|
+
this.validateVerifyOptions(options);
|
|
142
|
+
const form = this.buildFormData(options);
|
|
143
|
+
const url = `${this.baseUrl}${API_VERSION}/kyc/verify`;
|
|
144
|
+
// form-data provides its own headers (with boundary); merge with our auth header
|
|
145
|
+
const headers = {
|
|
146
|
+
'X-API-Key': this.apiKey,
|
|
147
|
+
...form.getHeaders(),
|
|
148
|
+
};
|
|
149
|
+
const response = await fetch(url, {
|
|
150
|
+
method: 'POST',
|
|
151
|
+
headers,
|
|
152
|
+
// form.getBuffer() returns a Buffer; Node 18 native fetch accepts it.
|
|
153
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
154
|
+
body: form.getBuffer(),
|
|
155
|
+
});
|
|
156
|
+
await this.assertOk(response);
|
|
157
|
+
return response.json();
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Verify an incoming webhook signature.
|
|
161
|
+
*
|
|
162
|
+
* KyvShield signs webhook payloads with HMAC-SHA256 using your API key.
|
|
163
|
+
* Call this before processing any webhook to confirm it came from KyvShield.
|
|
164
|
+
*
|
|
165
|
+
* @param payload - Raw request body as a `Buffer`.
|
|
166
|
+
* @param apiKey - Your KyvShield API key (same one used to create the client).
|
|
167
|
+
* @param signatureHeader - Value of the `X-KyvShield-Signature` header sent with the webhook.
|
|
168
|
+
* @returns `true` if the signature is valid, `false` otherwise.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```ts
|
|
172
|
+
* // Express example
|
|
173
|
+
* app.post('/webhook', express.raw({ type: '*\/*' }), (req, res) => {
|
|
174
|
+
* const valid = KyvShield.verifyWebhookSignature(
|
|
175
|
+
* req.body,
|
|
176
|
+
* process.env.KYVSHIELD_API_KEY!,
|
|
177
|
+
* req.headers['x-kyvshield-signature'] as string,
|
|
178
|
+
* );
|
|
179
|
+
*
|
|
180
|
+
* if (!valid) return res.status(401).send('Invalid signature');
|
|
181
|
+
*
|
|
182
|
+
* // process webhook ...
|
|
183
|
+
* res.sendStatus(200);
|
|
184
|
+
* });
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
static verifyWebhookSignature(payload, apiKey, signatureHeader) {
|
|
188
|
+
if (!payload || !apiKey || !signatureHeader)
|
|
189
|
+
return false;
|
|
190
|
+
const expected = crypto
|
|
191
|
+
.createHmac('sha256', apiKey)
|
|
192
|
+
.update(payload)
|
|
193
|
+
.digest('hex');
|
|
194
|
+
// Use timingSafeEqual to prevent timing attacks
|
|
195
|
+
try {
|
|
196
|
+
const expectedBuf = Buffer.from(expected, 'hex');
|
|
197
|
+
// Strip an optional 'sha256=' prefix the server might prepend
|
|
198
|
+
const incomingSig = signatureHeader.startsWith('sha256=')
|
|
199
|
+
? signatureHeader.slice(7)
|
|
200
|
+
: signatureHeader;
|
|
201
|
+
const incomingBuf = Buffer.from(incomingSig, 'hex');
|
|
202
|
+
if (expectedBuf.length !== incomingBuf.length)
|
|
203
|
+
return false;
|
|
204
|
+
return crypto.timingSafeEqual(expectedBuf, incomingBuf);
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// ── Private helpers ─────────────────────────────────────────────────────────
|
|
211
|
+
/** Build the common headers used by all non-multipart requests. */
|
|
212
|
+
buildHeaders() {
|
|
213
|
+
return {
|
|
214
|
+
'X-API-Key': this.apiKey,
|
|
215
|
+
Accept: 'application/json',
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Validate required fields in {@link VerifyOptions} before sending.
|
|
220
|
+
* Throws a descriptive {@link KyvShieldError} on the first problem found.
|
|
221
|
+
*/
|
|
222
|
+
validateVerifyOptions(options) {
|
|
223
|
+
if (!options.steps || options.steps.length === 0) {
|
|
224
|
+
throw new KyvShieldError('VerifyOptions.steps must contain at least one step');
|
|
225
|
+
}
|
|
226
|
+
if (!options.target || options.target.trim() === '') {
|
|
227
|
+
throw new KyvShieldError('VerifyOptions.target must be a non-empty string');
|
|
228
|
+
}
|
|
229
|
+
if (!options.images || Object.keys(options.images).length === 0) {
|
|
230
|
+
throw new KyvShieldError('VerifyOptions.images must contain at least one entry');
|
|
231
|
+
}
|
|
232
|
+
// Validate that all image files exist on disk
|
|
233
|
+
for (const [key, filePath] of Object.entries(options.images)) {
|
|
234
|
+
const resolved = path.resolve(filePath);
|
|
235
|
+
if (!fs.existsSync(resolved)) {
|
|
236
|
+
throw new KyvShieldError(`Image file for "${key}" not found: ${resolved}`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Build the `multipart/form-data` body from {@link VerifyOptions}.
|
|
242
|
+
*
|
|
243
|
+
* Text fields are appended first, followed by binary image fields.
|
|
244
|
+
*/
|
|
245
|
+
buildFormData(options) {
|
|
246
|
+
const form = new FormData();
|
|
247
|
+
// ── Text fields ─────────────────────────────────────────────────────────
|
|
248
|
+
// steps is a JSON array string, e.g. '["selfie","recto","verso"]'
|
|
249
|
+
form.append('steps', JSON.stringify(options.steps));
|
|
250
|
+
form.append('target', options.target);
|
|
251
|
+
form.append('language', options.language ?? 'fr');
|
|
252
|
+
form.append('challenge_mode', options.challengeMode ?? 'standard');
|
|
253
|
+
if (options.selfieChallengeMode !== undefined) {
|
|
254
|
+
form.append('selfie_challenge_mode', options.selfieChallengeMode);
|
|
255
|
+
}
|
|
256
|
+
if (options.rectoChallengeMode !== undefined) {
|
|
257
|
+
form.append('recto_challenge_mode', options.rectoChallengeMode);
|
|
258
|
+
}
|
|
259
|
+
if (options.versoChallengeMode !== undefined) {
|
|
260
|
+
form.append('verso_challenge_mode', options.versoChallengeMode);
|
|
261
|
+
}
|
|
262
|
+
form.append('require_face_match', options.requireFaceMatch === true ? 'true' : 'false');
|
|
263
|
+
if (options.kycIdentifier !== undefined) {
|
|
264
|
+
form.append('kyc_identifier', options.kycIdentifier);
|
|
265
|
+
}
|
|
266
|
+
// ── Image files ─────────────────────────────────────────────────────────
|
|
267
|
+
for (const [key, filePath] of Object.entries(options.images)) {
|
|
268
|
+
const resolved = path.resolve(filePath);
|
|
269
|
+
const buffer = fs.readFileSync(resolved);
|
|
270
|
+
const filename = path.basename(resolved);
|
|
271
|
+
const mimeType = this.guessMimeType(filename);
|
|
272
|
+
form.append(key, buffer, {
|
|
273
|
+
filename,
|
|
274
|
+
contentType: mimeType,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
return form;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Throw a {@link KyvShieldError} when the HTTP response is not successful (2xx).
|
|
281
|
+
* Tries to parse JSON error details from the body when available.
|
|
282
|
+
*/
|
|
283
|
+
async assertOk(response) {
|
|
284
|
+
if (response.ok)
|
|
285
|
+
return;
|
|
286
|
+
let body;
|
|
287
|
+
try {
|
|
288
|
+
body = await response.json();
|
|
289
|
+
}
|
|
290
|
+
catch {
|
|
291
|
+
body = await response.text().catch(() => undefined);
|
|
292
|
+
}
|
|
293
|
+
throw new KyvShieldError(`KyvShield API error ${response.status}: ${response.statusText}`, { statusCode: response.status, body });
|
|
294
|
+
}
|
|
295
|
+
/** Return a MIME type based on file extension. Defaults to `image/jpeg`. */
|
|
296
|
+
guessMimeType(filename) {
|
|
297
|
+
const ext = path.extname(filename).toLowerCase();
|
|
298
|
+
const map = {
|
|
299
|
+
'.jpg': 'image/jpeg',
|
|
300
|
+
'.jpeg': 'image/jpeg',
|
|
301
|
+
'.png': 'image/png',
|
|
302
|
+
'.webp': 'image/webp',
|
|
303
|
+
'.gif': 'image/gif',
|
|
304
|
+
};
|
|
305
|
+
return map[ext] ?? 'image/jpeg';
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
export default KyvShield;
|
|
309
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KyvShield REST SDK - Type Definitions
|
|
3
|
+
* All TypeScript interfaces and types for the KyvShield KYC API.
|
|
4
|
+
*/
|
|
5
|
+
/** Challenge intensity mode */
|
|
6
|
+
export type ChallengeMode = 'minimal' | 'standard' | 'strict';
|
|
7
|
+
/** Verification step type */
|
|
8
|
+
export type Step = 'selfie' | 'recto' | 'verso';
|
|
9
|
+
/** Supported document target types */
|
|
10
|
+
export type DocumentTarget = 'SN-CIN' | 'SN-PASSPORT' | 'SN-DRIVER-LICENCE' | string;
|
|
11
|
+
/** Supported languages */
|
|
12
|
+
export type Language = 'fr' | 'en' | 'wo';
|
|
13
|
+
/** Overall verification outcome */
|
|
14
|
+
export type OverallStatus = 'pass' | 'reject';
|
|
15
|
+
/** Confidence level descriptor */
|
|
16
|
+
export type ConfidenceLevel = 'HIGH' | 'MEDIUM' | 'LOW';
|
|
17
|
+
/** Available challenges grouped by intensity for a single asset type */
|
|
18
|
+
export interface ChallengeModeMap {
|
|
19
|
+
minimal: string[];
|
|
20
|
+
standard: string[];
|
|
21
|
+
strict: string[];
|
|
22
|
+
}
|
|
23
|
+
/** Full challenges response from GET /api/v1/challenges */
|
|
24
|
+
export interface ChallengesResponse {
|
|
25
|
+
challenges: {
|
|
26
|
+
/** Challenges applicable to document steps (recto / verso) */
|
|
27
|
+
document: ChallengeModeMap;
|
|
28
|
+
/** Challenges applicable to selfie steps */
|
|
29
|
+
selfie: ChallengeModeMap;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/** A single extracted text field from a document */
|
|
33
|
+
export interface ExtractionField {
|
|
34
|
+
/** Machine-readable field key */
|
|
35
|
+
key: string;
|
|
36
|
+
/** Key as used in the document specification */
|
|
37
|
+
document_key: string;
|
|
38
|
+
/** Human-readable label */
|
|
39
|
+
label: string;
|
|
40
|
+
/** Extracted value */
|
|
41
|
+
value: string;
|
|
42
|
+
/** Display ordering hint (lower = higher priority) */
|
|
43
|
+
display_priority: number;
|
|
44
|
+
/** Optional icon identifier */
|
|
45
|
+
icon?: string;
|
|
46
|
+
}
|
|
47
|
+
/** A photo extracted from a document image */
|
|
48
|
+
export interface ExtractedPhoto {
|
|
49
|
+
/** Base-64-encoded JPEG image data */
|
|
50
|
+
image: string;
|
|
51
|
+
/** Model confidence for this extraction (0–1) */
|
|
52
|
+
confidence: number;
|
|
53
|
+
/** Bounding box [x, y, width, height] in pixels */
|
|
54
|
+
bbox: number[];
|
|
55
|
+
/** Area of the bounding box in pixels² */
|
|
56
|
+
area: number;
|
|
57
|
+
/** Width of the extracted region in pixels */
|
|
58
|
+
width: number;
|
|
59
|
+
/** Height of the extracted region in pixels */
|
|
60
|
+
height: number;
|
|
61
|
+
}
|
|
62
|
+
/** Liveness sub-result for a single step */
|
|
63
|
+
export interface LivenessResult {
|
|
64
|
+
/** Whether the subject / document is considered live / physical */
|
|
65
|
+
is_live: boolean;
|
|
66
|
+
/** Liveness score (0–1) */
|
|
67
|
+
score: number;
|
|
68
|
+
/** Qualitative confidence descriptor */
|
|
69
|
+
confidence: ConfidenceLevel;
|
|
70
|
+
}
|
|
71
|
+
/** Authenticity & fraud sub-result for a single step */
|
|
72
|
+
export interface VerificationResult {
|
|
73
|
+
/** Whether the document / selfie is considered authentic */
|
|
74
|
+
is_authentic: boolean;
|
|
75
|
+
/** Confidence of the authenticity decision (0–1) */
|
|
76
|
+
confidence: number;
|
|
77
|
+
/** List of checks that passed */
|
|
78
|
+
checks_passed: string[];
|
|
79
|
+
/** Detected fraud indicators */
|
|
80
|
+
fraud_indicators: string[];
|
|
81
|
+
/** Non-blocking warnings */
|
|
82
|
+
warnings: string[];
|
|
83
|
+
/** Blocking issues */
|
|
84
|
+
issues: string[];
|
|
85
|
+
}
|
|
86
|
+
/** Result for a single verification step */
|
|
87
|
+
export interface StepResult {
|
|
88
|
+
/** Zero-based index of this step within the submitted steps array */
|
|
89
|
+
step_index: number;
|
|
90
|
+
/** Type of this step */
|
|
91
|
+
step_type: Step;
|
|
92
|
+
/** Whether this step succeeded overall */
|
|
93
|
+
success: boolean;
|
|
94
|
+
/** Server-side processing time for this step in milliseconds */
|
|
95
|
+
processing_time_ms: number;
|
|
96
|
+
/** Liveness detection result */
|
|
97
|
+
liveness: LivenessResult;
|
|
98
|
+
/** Document / selfie authenticity result */
|
|
99
|
+
verification: VerificationResult;
|
|
100
|
+
/** Localised messages intended for display to the end-user */
|
|
101
|
+
user_messages: string[];
|
|
102
|
+
/** Base-64-encoded aligned/deskewed document image (document steps only) */
|
|
103
|
+
aligned_document?: string;
|
|
104
|
+
/** Extracted text fields (document steps only) */
|
|
105
|
+
extraction?: ExtractionField[];
|
|
106
|
+
/** Extracted photos from the document (document steps only) */
|
|
107
|
+
extracted_photos?: ExtractedPhoto[];
|
|
108
|
+
/** Base-64-encoded captured selfie image (selfie step only) */
|
|
109
|
+
captured_image?: string;
|
|
110
|
+
}
|
|
111
|
+
/** Cross-step face-match result */
|
|
112
|
+
export interface FaceVerification {
|
|
113
|
+
/** Whether the selfie face matches the document face */
|
|
114
|
+
is_match: boolean;
|
|
115
|
+
/** Cosine similarity score (0–100) */
|
|
116
|
+
similarity_score: number;
|
|
117
|
+
}
|
|
118
|
+
/** Top-level response from POST /api/v1/kyc/verify */
|
|
119
|
+
export interface KycResponse {
|
|
120
|
+
/** Whether the API call itself succeeded (HTTP-level success) */
|
|
121
|
+
success: boolean;
|
|
122
|
+
/** Unique session identifier for this verification run */
|
|
123
|
+
session_id: string;
|
|
124
|
+
/** Aggregated pass / reject decision across all steps */
|
|
125
|
+
overall_status: OverallStatus;
|
|
126
|
+
/** Aggregated confidence score (0–1) */
|
|
127
|
+
overall_confidence: number;
|
|
128
|
+
/** Total server-side processing time in milliseconds */
|
|
129
|
+
processing_time_ms: number;
|
|
130
|
+
/** Face-match result (present when require_face_match was true) */
|
|
131
|
+
face_verification?: FaceVerification;
|
|
132
|
+
/** Per-step results in submission order */
|
|
133
|
+
steps: StepResult[];
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Options for KyvShield.verify().
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```ts
|
|
140
|
+
* const options: VerifyOptions = {
|
|
141
|
+
* steps: ['selfie', 'recto', 'verso'],
|
|
142
|
+
* target: 'SN-CIN',
|
|
143
|
+
* language: 'fr',
|
|
144
|
+
* challengeMode: 'standard',
|
|
145
|
+
* requireFaceMatch: true,
|
|
146
|
+
* images: {
|
|
147
|
+
* selfie_center_face: '/path/to/selfie.jpg',
|
|
148
|
+
* recto_center_document: '/path/to/recto.jpg',
|
|
149
|
+
* verso_center_document: '/path/to/verso.jpg',
|
|
150
|
+
* },
|
|
151
|
+
* };
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
export interface VerifyOptions {
|
|
155
|
+
/**
|
|
156
|
+
* Ordered list of steps to execute.
|
|
157
|
+
* Example: `['selfie', 'recto', 'verso']`
|
|
158
|
+
*/
|
|
159
|
+
steps: Step[];
|
|
160
|
+
/**
|
|
161
|
+
* Document type to verify against.
|
|
162
|
+
* Example: `'SN-CIN'`
|
|
163
|
+
*/
|
|
164
|
+
target: DocumentTarget;
|
|
165
|
+
/**
|
|
166
|
+
* Language for user-facing messages in the response.
|
|
167
|
+
* @default 'fr'
|
|
168
|
+
*/
|
|
169
|
+
language?: Language;
|
|
170
|
+
/**
|
|
171
|
+
* Global fallback challenge mode applied to all steps unless overridden.
|
|
172
|
+
* @default 'standard'
|
|
173
|
+
*/
|
|
174
|
+
challengeMode?: ChallengeMode;
|
|
175
|
+
/** Per-step challenge mode override for the selfie step */
|
|
176
|
+
selfieChallengeMode?: ChallengeMode;
|
|
177
|
+
/** Per-step challenge mode override for the recto step */
|
|
178
|
+
rectoChallengeMode?: ChallengeMode;
|
|
179
|
+
/** Per-step challenge mode override for the verso step */
|
|
180
|
+
versoChallengeMode?: ChallengeMode;
|
|
181
|
+
/**
|
|
182
|
+
* Whether to perform a cross-step face match between selfie and document photo.
|
|
183
|
+
* @default false
|
|
184
|
+
*/
|
|
185
|
+
requireFaceMatch?: boolean;
|
|
186
|
+
/**
|
|
187
|
+
* Optional caller-provided identifier for correlating sessions in your system.
|
|
188
|
+
*/
|
|
189
|
+
kycIdentifier?: string;
|
|
190
|
+
/**
|
|
191
|
+
* Map of image files to submit.
|
|
192
|
+
* Keys follow the pattern `{step}_{challenge}`, e.g.:
|
|
193
|
+
* - `'selfie_center_face'`
|
|
194
|
+
* - `'recto_center_document'`
|
|
195
|
+
* - `'recto_tilt_left'`
|
|
196
|
+
*
|
|
197
|
+
* Values are absolute or relative file-system paths to JPEG/PNG images.
|
|
198
|
+
*/
|
|
199
|
+
images: Record<string, string>;
|
|
200
|
+
}
|
|
201
|
+
/** Structured error thrown by the SDK */
|
|
202
|
+
export interface KyvShieldErrorDetails {
|
|
203
|
+
/** HTTP status code, if the error originated from an HTTP response */
|
|
204
|
+
statusCode?: number;
|
|
205
|
+
/** Raw response body, if available */
|
|
206
|
+
body?: unknown;
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kyvshield/rest-sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Fully typed Node.js / TypeScript SDK for the KyvShield KYC REST API",
|
|
5
|
+
"author": "KyvShield",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs",
|
|
14
|
+
"types": "./dist/index.d.ts"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"build:watch": "tsc --watch",
|
|
24
|
+
"clean": "rm -rf dist",
|
|
25
|
+
"prebuild": "npm run clean",
|
|
26
|
+
"test": "npx ts-node --esm test.ts",
|
|
27
|
+
"lint": "tsc --noEmit"
|
|
28
|
+
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18.0.0"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"kyc",
|
|
34
|
+
"kyvshield",
|
|
35
|
+
"identity-verification",
|
|
36
|
+
"liveness",
|
|
37
|
+
"ocr",
|
|
38
|
+
"sdk"
|
|
39
|
+
],
|
|
40
|
+
"dependencies": {},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "^20.0.0",
|
|
43
|
+
"typescript": "^5.4.0"
|
|
44
|
+
}
|
|
45
|
+
}
|