@sekyro/node 0.1.0-rc.1 → 0.1.0-rc.3

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/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Wire-level enums and shapes of the Sekyro partner API (`/api/v2`). These
2
+ * Wire-level enums and shapes of the Sekyro AI partner API (`/api/v2`). These
3
3
  * mirror the backend's frozen partner contract; they are plain string unions so
4
4
  * a newer API value never throws at runtime — it simply widens the type in the
5
5
  * next SDK release.
@@ -14,10 +14,71 @@ type SessionStatus = "created" | "in_progress" | "review_pending" | "completed"
14
14
  * @public
15
15
  */
16
16
  type SessionOutcome = "approved" | "review" | "rejected";
17
+ /**
18
+ * How the person proves their identity on an optional-document app: type the
19
+ * national number, or photograph the document.
20
+ * @public
21
+ */
22
+ type IdentityMethod = "national_number" | "document_photo";
17
23
  /** The verification checks a flow may contain. @public */
18
24
  type CheckType = "liveness" | "face_match" | "doc_ocr" | "population_registry" | "phone_otp";
19
25
  /** Per-check execution state within a session. @public */
20
26
  type CheckState = "pending" | "input_required" | "processing" | "passed" | "failed" | "review" | "skipped";
27
+ /**
28
+ * Why a session was stopped by a profile-v2 policy gate rather than by a
29
+ * failed check:
30
+ * - `location_not_allowed` — the end user's IP location is not allowed for the app;
31
+ * - `anonymizer_blocked` — an anonymizer (VPN / proxy / Tor) was detected while the app blocks them;
32
+ * - `capture_tampered` — the device reported a tampered capture (virtual
33
+ * camera, hooking, emulator…) while the app's `device.tamper` is `block`;
34
+ * - `device_velocity_exceeded` — the device already verified more different
35
+ * people than `device.velocity` allows, with `action: 'block'`;
36
+ * - `device_cooldown` — the device had too many rejected sessions
37
+ * (`cooldown` tiers); {@link Session.retryAfter} says when it may try again.
38
+ * Not billed.
39
+ * @public
40
+ */
41
+ type SessionFailureReason = "location_not_allowed" | "anonymizer_blocked" | "capture_tampered" | "device_velocity_exceeded" | "device_cooldown";
42
+ /**
43
+ * Profile-v2 decision-mode reasons a check's {@link SessionStep.reason} may
44
+ * carry when the app decides automatically (`decisions.mode: 'automatic'`)
45
+ * instead of routing to human review. All are retryable within the step's
46
+ * attempts: `liveness_inconclusive` (liveness middle band),
47
+ * `match_inconclusive` (face match middle band on every reference),
48
+ * `document_authenticity` (doc_ocr authenticity warning — retake the original)
49
+ * and `mobile_required` (liveness captured on a desktop — continue on a phone;
50
+ * not billed). Every inconclusive attempt is billed.
51
+ * @public
52
+ */
53
+ type DecisionReason = "liveness_inconclusive" | "match_inconclusive" | "document_authenticity" | "mobile_required";
54
+ /**
55
+ * Profile-v2 eligibility reasons a check's {@link SessionStep.reason} may carry:
56
+ * `document_type_not_accepted` (doc_ocr; the person may pick another
57
+ * document), `nationality_not_allowed` and `underage` (doc_ocr or
58
+ * population_registry; terminal), and `age_unverifiable` (the app sets a
59
+ * minimum age but the birth date could not be read — doc_ocr: retryable with
60
+ * a clearer photo; population_registry: terminal).
61
+ * @public
62
+ */
63
+ type EligibilityReason = "document_type_not_accepted" | "nationality_not_allowed" | "underage" | "age_unverifiable";
64
+ /**
65
+ * Why a profile-v2 policy ended a session: a session-level
66
+ * {@link SessionFailureReason} (location / anonymizer gate), or the failed
67
+ * check's policy reason — an {@link EligibilityReason} or
68
+ * `document_nni_mismatch` (the document belongs to someone other than the
69
+ * NNI the session was created for).
70
+ * @public
71
+ */
72
+ type PolicyFailureReason = SessionFailureReason | EligibilityReason | "document_nni_mismatch";
73
+ /**
74
+ * Profile-v2 matching reasons a check's {@link SessionStep.reason} may carry
75
+ * when the data you sent in {@link CreateSessionInput.subject} differs from the
76
+ * reference identity: `name_mismatch`, `birth_date_mismatch`,
77
+ * `nationality_mismatch` (doc_ocr or population_registry) and
78
+ * `document_number_mismatch` (doc_ocr). All are final.
79
+ * @public
80
+ */
81
+ type MatchReason = "name_mismatch" | "birth_date_mismatch" | "nationality_mismatch" | "document_number_mismatch";
21
82
  /** Hosted-flow languages. @public */
22
83
  type Locale = "ar" | "fr" | "en";
23
84
  /** The environment a webhook was emitted from. @public */
@@ -34,19 +95,196 @@ interface SessionStep {
34
95
  reason?: string;
35
96
  /** Calibrated model score in [0, 1] for scored checks (liveness, face match). */
36
97
  calibratedScore?: number;
98
+ /** The check failed after using all of its attempts. */
99
+ attemptsExhausted?: boolean;
100
+ }
101
+ /**
102
+ * Out-of-band delivery of the session's hosted link, sent by Sekyro AI after the
103
+ * session is created. Best effort: a failed send never fails the create.
104
+ * @public
105
+ */
106
+ interface DeliverOptions {
107
+ /** Delivery channel. */
108
+ channel: "sms" | "whatsapp";
109
+ /** E.164 phone number of the recipient, e.g. `+22236123456`. */
110
+ to: string;
111
+ }
112
+ /**
113
+ * What you already know about the person (`subject` at session create). A
114
+ * closed object: unknown keys are refused (`400`). Every field is optional;
115
+ * `null` or blank counts as absent. Identity fields are compared with the
116
+ * person's document or registry record when the app's profile turns name
117
+ * matching on; `nni` binds the session to that identity.
118
+ * @public
119
+ */
120
+ interface SessionSubjectInput {
121
+ /** 10-digit Mauritanian NNI, as a string. */
122
+ nni?: string;
123
+ /** E.164 phone number, e.g. `+22236123456`. */
124
+ phone?: string;
125
+ fullName?: string;
126
+ /** ISO 8601 date (`YYYY-MM-DD`). */
127
+ birthDate?: string;
128
+ /** ISO 3166-1 alpha-2, e.g. `MR`. */
129
+ nationality?: string;
130
+ /** Identity-document number (1–40 characters). */
131
+ documentNumber?: string;
132
+ /**
133
+ * Your own id for this person (1–128 characters). Echoed on the session and
134
+ * its webhooks, and searchable on the subjects API.
135
+ */
136
+ externalRef?: string;
137
+ }
138
+ /** A document type the backend reads (kyc-docs-v2 vocabulary). @public */
139
+ type ProfileDocumentType = "carte_identite" | "passport";
140
+ /**
141
+ * The settings of an app's eKYC profile that a session may override — a
142
+ * mirror of the backend profile (schema version 2) without `schemaVersion`,
143
+ * `link` (use {@link CreateSessionInput.ttlMinutes}) and `overrides` (the
144
+ * app's own permission). Country codes are ISO 3166-1 alpha-2 (`MR`).
145
+ * Used through {@link EkycProfileOverride}.
146
+ * @public
147
+ */
148
+ interface EkycProfileSettings {
149
+ /** Phone OTP step: off, or on with where the number comes from. */
150
+ phone: "off" | {
151
+ numberSource: "prefilled" | "user_entered" | "prefilled_or_entered";
152
+ };
153
+ document: {
154
+ mode: "off" | "optional" | "mandatory";
155
+ /** Accepted document types: `'*'` (all) or a list, optionally per issuing country. */
156
+ accepted: {
157
+ default: "*" | ProfileDocumentType[];
158
+ byIssuer?: Record<string, ProfileDocumentType[]>;
159
+ };
160
+ /** Expired documents: refused, allowed, or allowed for `graceDays` (1–365) after expiry. */
161
+ expired: "reject" | "allow" | {
162
+ graceDays: number;
163
+ };
164
+ authenticity: "standard" | "off";
165
+ };
166
+ registry: {
167
+ enabled: boolean;
168
+ sources: Array<"MR.anrpts">;
169
+ /** Which identity is the reference for face match and your data. */
170
+ reference?: "document" | "registry";
171
+ /** What happens when the registry has no record for the NNI. */
172
+ onNoRecord?: "fail" | "use_document";
173
+ };
174
+ liveness: {
175
+ enabled: boolean;
176
+ };
177
+ faceMatch: {
178
+ enabled: boolean;
179
+ };
180
+ /** Comparison of your `subject` data with the reference identity. */
181
+ nameMatch?: {
182
+ level: "strict" | "standard" | "lenient";
183
+ onMismatch: "fail" | "signal";
184
+ };
185
+ /** Per-step attempt limits. */
186
+ attempts?: {
187
+ phone: number;
188
+ document: number;
189
+ registry: number;
190
+ liveness: number;
191
+ faceMatch: number;
192
+ };
193
+ /** Where the end user may be (IP location). */
194
+ locations: {
195
+ mode: "all";
196
+ } | {
197
+ mode: "only" | "all_except";
198
+ countries: string[];
199
+ };
200
+ anonymizers: "allow" | "block";
201
+ /** Accepted nationalities: `'*'` or a list, optionally per IP location. */
202
+ nationalities: {
203
+ default: "*" | string[];
204
+ byLocation?: Record<string, "*" | string[]>;
205
+ };
206
+ /** Minimum age in years (1–120), or `null` for none. */
207
+ minAge: number | null;
208
+ /** Automatic decisions instead of human review (`retryConfidentRejects` lets confident rejects retry). */
209
+ decisions?: {
210
+ mode: "automatic" | "review";
211
+ retryConfidentRejects: boolean;
212
+ };
213
+ /** Device cooldown after repeated rejections (at most 5 tiers; `[]` = off). */
214
+ cooldown?: {
215
+ tiers: Array<{
216
+ rejectedSessions: number;
217
+ windowHours: number;
218
+ waitMinutes: number;
219
+ }>;
220
+ };
221
+ /** Device tamper and velocity actions. */
222
+ device?: {
223
+ tamper: "block" | "signal";
224
+ velocity: {
225
+ maxIdentitiesPerDevice: number;
226
+ windowDays: number;
227
+ action: "signal" | "block";
228
+ };
229
+ };
37
230
  }
38
231
  /**
39
- * Input of {@link SessionsApi.create}. Name the recipe by EITHER `flow` (the
40
- * flow slug) OR `templateId` — exactly one; the API rejects both or neither.
232
+ * `T` with every property optional, recursively. Arrays are replaced as a
233
+ * whole, never merged element by element.
234
+ * @public
235
+ */
236
+ type DeepPartial<T> = T extends readonly unknown[] ? T : T extends object ? {
237
+ [K in keyof T]?: DeepPartial<T[K]>;
238
+ } : T;
239
+ /**
240
+ * A per-session override of the app's eKYC profile
241
+ * ({@link CreateSessionInput.profile}): any subset of
242
+ * {@link EkycProfileSettings}, at any depth (every field optional). Objects
243
+ * are merged into the app's profile; arrays and scalar values replace it.
244
+ *
245
+ * The API validates the merged result like a profile save. Unknown keys are
246
+ * rejected server-side (`400`, also for keys this SDK version does not type).
247
+ * An override may only make the profile stricter unless the app allows
248
+ * widening (`overrides.allowWidening`); otherwise a widening change answers
249
+ * `403 override_widens_profile`. The changed paths are reported on
250
+ * {@link Session.overriddenFields}.
251
+ * @public
252
+ */
253
+ type EkycProfileOverride = DeepPartial<EkycProfileSettings>;
254
+ /**
255
+ * Input of {@link SessionsApi.create}. There is no recipe field: the API key
256
+ * belongs to an app, and that app's eKYC profile decides the steps.
41
257
  * @public
42
258
  */
43
259
  interface CreateSessionInput {
44
- /** Flow slug configured for your organisation. */
45
- flow?: string;
46
- /** Legacy template id (pre-flows path). Prefer `flow`. */
47
- templateId?: string;
48
260
  /** Pins the hosted-flow language. Omit to let the person's device decide. */
49
261
  locale?: Locale;
262
+ /**
263
+ * Pre-choose the identity method when the app's document step is optional
264
+ * (the hosted method screen is then skipped). Ignored for other apps.
265
+ */
266
+ identityMethod?: IdentityMethod;
267
+ /**
268
+ * Session lifetime in minutes. Must fall within the app profile's link
269
+ * range, otherwise the API answers `400 ttl_out_of_policy`. Omit to use the
270
+ * profile's default.
271
+ */
272
+ ttlMinutes?: number;
273
+ /** Also send the hosted link to the person by SMS or WhatsApp. */
274
+ deliver?: DeliverOptions;
275
+ /**
276
+ * What you already know about the person (preferred over `input` for
277
+ * identity data). A key sent in both `subject` and `input` with different
278
+ * values answers `400 subject_input_conflict`.
279
+ */
280
+ subject?: SessionSubjectInput;
281
+ /**
282
+ * Override the app's eKYC profile for this session only (profile v2): a
283
+ * deep-partial {@link EkycProfileOverride}. Unknown keys are rejected
284
+ * server-side; a change that makes the profile less strict answers
285
+ * `403 override_widens_profile` unless the app allows widening.
286
+ */
287
+ profile?: EkycProfileOverride;
50
288
  /**
51
289
  * Step inputs consumed server-side. The known anchors are typed (all
52
290
  * strings — an `nni` is a 10-digit string, never a number); further keys
@@ -87,6 +325,63 @@ interface CreatedSession {
87
325
  /** ISO 8601 — when the session (and its link) stop accepting input. */
88
326
  expiresAt: string;
89
327
  }
328
+ /**
329
+ * The end user's network at the start of the session (IP-derived, approximate).
330
+ * @public
331
+ */
332
+ interface SessionNetworkEvent {
333
+ /** ISO 8601. */
334
+ at: string;
335
+ /** ISO 3166-1 alpha-2. */
336
+ country?: string;
337
+ region?: string;
338
+ city?: string;
339
+ asn?: number;
340
+ operator?: string;
341
+ connectionType: "mobile" | "hosting" | "unknown";
342
+ anonymizer: {
343
+ vpn: boolean;
344
+ tor: boolean;
345
+ hosting: boolean;
346
+ };
347
+ /** IANA time zone reported by the end user's device. */
348
+ browserTimezone?: string;
349
+ /** True when the device time zone does not belong to the IP country. */
350
+ timezoneMismatch?: boolean;
351
+ }
352
+ /**
353
+ * End-user network context; absent when not recorded.
354
+ * @public
355
+ */
356
+ interface SessionNetwork {
357
+ /** The start event's IP address. Never sent in webhooks. */
358
+ ip?: string;
359
+ /** True when a later call came from a different country than the start. */
360
+ countryChanged: boolean;
361
+ start: SessionNetworkEvent;
362
+ }
363
+ /**
364
+ * Device signals detected on the end user's device.
365
+ * @public
366
+ */
367
+ type SessionDeviceSignal = "webdriver" | "headless" | "emulator" | "rooted" | "jailbroken" | "debugger" | "hooking" | "virtual_camera";
368
+ /**
369
+ * End-user device summary; absent when not recorded.
370
+ * @public
371
+ */
372
+ interface SessionDevice {
373
+ platform: "web" | "android" | "ios";
374
+ sdk?: string;
375
+ os?: string;
376
+ osVersion?: string;
377
+ browser?: string;
378
+ browserVersion?: string;
379
+ deviceClass: "mobile" | "tablet" | "desktop" | "unknown";
380
+ model?: string;
381
+ /** Device ids hashed with a key unique to your organization. */
382
+ deviceKeys: string[];
383
+ signals: SessionDeviceSignal[];
384
+ }
90
385
  /**
91
386
  * The whitelisted session view returned by {@link SessionsApi.get}. Never
92
387
  * contains the client token.
@@ -101,6 +396,37 @@ interface Session {
101
396
  expiresAt: string;
102
397
  /** ISO 8601. */
103
398
  createdAt: string;
399
+ /** End-user network context; absent when not recorded. */
400
+ network?: SessionNetwork;
401
+ /** End-user device; absent when not recorded. */
402
+ device?: SessionDevice;
403
+ /**
404
+ * Set when a profile-v2 policy ended the session: a session-level gate
405
+ * (location, anonymizer) or a failed check's policy reason (eligibility,
406
+ * `document_nni_mismatch`). Absent otherwise.
407
+ */
408
+ failureReason?: PolicyFailureReason;
409
+ /** The subject (person) this session is linked to, once an identifier is known. */
410
+ subjectId?: string;
411
+ /** Your own id for the person, from `subject.externalRef` at create. */
412
+ externalRef?: string;
413
+ /**
414
+ * `true` when an identifier this session read already belongs to a
415
+ * different subject than `subjectId` — the subjects are never merged.
416
+ */
417
+ subjectConflict?: boolean;
418
+ /**
419
+ * ISO 8601 — when the end user's device may verify again; set with
420
+ * `failureReason: 'device_cooldown'`.
421
+ */
422
+ retryAfter?: string;
423
+ /** Dotted profile paths this session's {@link CreateSessionInput.profile} changed (e.g. `decisions.mode`). */
424
+ overriddenFields?: string[];
425
+ /**
426
+ * Risk signals recorded on the session (e.g. `device_velocity`,
427
+ * `timezone_mismatch`) — signals only, never a verdict by themselves.
428
+ */
429
+ riskSignals?: string[];
104
430
  }
105
431
  /**
106
432
  * `data` of the terminal / review-pending session lifecycle events
@@ -118,6 +444,54 @@ interface SessionLifecycleEventData {
118
444
  steps?: Array<Pick<SessionStep, "checkType" | "state">>;
119
445
  /** Machine-readable reason, when the transition has one. */
120
446
  reason?: string;
447
+ /** End-user network context (no IP); on `completed` / `failed` when recorded. */
448
+ network?: Omit<SessionNetwork, "ip">;
449
+ /** End-user device; on `completed` / `failed` when recorded. */
450
+ device?: SessionDevice;
451
+ /**
452
+ * On `session.failed`: set when a profile-v2 policy ended the session — a
453
+ * session-level gate (location, anonymizer) or a failed check's policy
454
+ * reason (eligibility, `document_nni_mismatch`).
455
+ */
456
+ failureReason?: PolicyFailureReason;
457
+ /** The subject (person) the session is linked to, when known. */
458
+ subjectId?: string;
459
+ /** Your own id for the person, from `subject.externalRef` at create. */
460
+ externalRef?: string;
461
+ /**
462
+ * `true` when an identifier this session read already belongs to a
463
+ * different subject than `subjectId` — the subjects are never merged.
464
+ */
465
+ subjectConflict?: boolean;
466
+ /**
467
+ * On `session.failed` with `failureReason: 'device_cooldown'`: ISO time
468
+ * from which the device may start a new verification.
469
+ */
470
+ retryAfter?: string;
471
+ /** Dotted profile paths the session's create-time override changed. */
472
+ overriddenFields?: string[];
473
+ }
474
+ /**
475
+ * `data` of `subject.updated` — a session linked to the subject reached a
476
+ * terminal state. Ids and enums only.
477
+ * @public
478
+ */
479
+ interface SubjectUpdatedEventData {
480
+ subjectId: string;
481
+ sessionId: string;
482
+ status: SessionStatus;
483
+ outcome: SessionOutcome | null;
484
+ }
485
+ /**
486
+ * `data` of `subject.suspicious_activity` — a device already linked to
487
+ * ANOTHER subject was used for a session of this subject. `count` is the
488
+ * subject's running total of such events. Ids only.
489
+ * @public
490
+ */
491
+ interface SubjectSuspiciousActivityEventData {
492
+ subjectId: string;
493
+ sessionId: string;
494
+ count: number;
121
495
  }
122
496
  /**
123
497
  * `data` of `session.step.completed` — the check that just passed.
@@ -127,6 +501,15 @@ interface SessionStepCompletedEventData {
127
501
  sessionId: string;
128
502
  checkType: CheckType;
129
503
  state: CheckState;
504
+ /** The subject (person) the session is linked to, when known. */
505
+ subjectId?: string;
506
+ /** Your own id for the person, from `subject.externalRef` at create. */
507
+ externalRef?: string;
508
+ /**
509
+ * `true` when an identifier this session read already belongs to a
510
+ * different subject than `subjectId` — the subjects are never merged.
511
+ */
512
+ subjectConflict?: boolean;
130
513
  }
131
514
  /**
132
515
  * `data` of `session.review_decided` — a human (or the review-timeout sweep)
@@ -139,6 +522,15 @@ interface SessionReviewDecidedEventData {
139
522
  sessionId: string;
140
523
  outcome: "pass" | "fail";
141
524
  reason: string;
525
+ /** The subject (person) the session is linked to, when known. */
526
+ subjectId?: string;
527
+ /** Your own id for the person, from `subject.externalRef` at create. */
528
+ externalRef?: string;
529
+ /**
530
+ * `true` when an identifier this session read already belongs to a
531
+ * different subject than `subjectId` — the subjects are never merged.
532
+ */
533
+ subjectConflict?: boolean;
142
534
  }
143
535
  /**
144
536
  * Event type → the shape of its `data`. Session events are typed; the
@@ -156,6 +548,8 @@ interface WebhookEventDataMap {
156
548
  "session.expired": SessionLifecycleEventData;
157
549
  "session.failed": SessionLifecycleEventData;
158
550
  "subject.enrolled": Record<string, unknown>;
551
+ "subject.updated": SubjectUpdatedEventData;
552
+ "subject.suspicious_activity": SubjectSuspiciousActivityEventData;
159
553
  "subject.deleted": Record<string, unknown>;
160
554
  "aml.match_flagged": Record<string, unknown>;
161
555
  "payment.received": Record<string, unknown>;
@@ -250,12 +644,19 @@ declare class SessionsApi {
250
644
  * browser, never persist it. Pass an `idempotencyKey` so a retried call
251
645
  * cannot create a second session.
252
646
  */
253
- create(input: CreateSessionInput, opts?: RequestOptions): Promise<CreatedSession>;
647
+ create(input?: CreateSessionInput, opts?: RequestOptions): Promise<CreatedSession>;
648
+ /**
649
+ * `POST /sessions/:id/method` — choose the identity method of an
650
+ * optional-document session on the person's behalf (the hosted method
651
+ * screen is then skipped). `409 method_locked` once the choice can no
652
+ * longer change; `409 session_not_active` on a finished or expired session.
653
+ */
654
+ selectMethod(id: string, method: IdentityMethod): Promise<Session>;
254
655
  /** `GET /sessions/:id` — the whitelisted view (no client token). */
255
656
  get(id: string): Promise<Session>;
256
657
  }
257
658
  /**
258
- * Sekyro partner API client. Server-side only: it carries your API key.
659
+ * Sekyro AI partner API client. Server-side only: it carries your API key.
259
660
  *
260
661
  * Throws {@link SekyroConfigError} synchronously when `apiKey` is missing or
261
662
  * `baseUrl` is not `https:` (plain `http:` is accepted for `localhost`,
@@ -264,7 +665,7 @@ declare class SessionsApi {
264
665
  * @example
265
666
  * ```ts
266
667
  * const sekyro = new Sekyro({ apiKey: process.env.SEKYRO_API_KEY! });
267
- * const { id, clientToken } = await sekyro.sessions.create({ flow: "onboarding" });
668
+ * const { id, clientToken } = await sekyro.sessions.create({ input: { nni: "1357924632" } });
268
669
  * ```
269
670
  * @public
270
671
  */
@@ -277,7 +678,7 @@ declare class Sekyro {
277
678
  type SekyroWebhookErrorCode = "invalid_signature" | "stale" | "malformed";
278
679
  /**
279
680
  * Thrown by {@link verifyWebhook}. Respond with a 4xx and do not process the
280
- * body; Sekyro retries deliveries that do not receive a 2xx.
681
+ * body; Sekyro AI retries deliveries that do not receive a 2xx.
281
682
  * @public
282
683
  */
283
684
  declare class SekyroWebhookError extends Error {
@@ -337,7 +738,7 @@ declare class SekyroApiError extends Error {
337
738
  */
338
739
  declare const SEKYRO_SIGNATURE_HEADER = "x-sekyro-signature";
339
740
  /**
340
- * The pre-rebrand name of the signature header. Sekyro sends BOTH headers with
741
+ * The pre-rebrand name of the signature header. Sekyro AI sends BOTH headers with
341
742
  * the same value during the transition; prefer {@link SEKYRO_SIGNATURE_HEADER}
342
743
  * and use {@link signatureFromHeaders} to accept either.
343
744
  * @public
@@ -365,13 +766,13 @@ interface VerifyWebhookOptions {
365
766
  now?: () => number;
366
767
  }
367
768
  /**
368
- * Verify a Sekyro webhook delivery and return its parsed envelope, discriminated
769
+ * Verify a Sekyro AI webhook delivery and return its parsed envelope, discriminated
369
770
  * on `event` (narrow with a `switch` to type `data`).
370
771
  *
371
772
  * - `rawBody` MUST be the request body exactly as received (before any JSON
372
773
  * parsing / re-serialisation); the signature covers those bytes.
373
774
  * - Accepts the delivery when ANY `v1` in the header matches, which is what
374
- * makes secret rotation seamless (Sekyro signs with current + previous).
775
+ * makes secret rotation seamless (Sekyro AI signs with current + previous).
375
776
  * - Uses `node:crypto` only; the digest compare is constant-time.
376
777
  *
377
778
  * Checks run in this order: header/secret present → header well-formed →
@@ -386,4 +787,4 @@ interface VerifyWebhookOptions {
386
787
  */
387
788
  declare function verifyWebhook(rawBody: string, header: string | null | undefined, secret: string, opts?: VerifyWebhookOptions): WebhookEnvelope;
388
789
 
389
- export { type CheckState, type CheckType, type CreateSessionInput, type CreatedSession, DEFAULT_BASE_URL, DEFAULT_TIMEOUT_MS, type FetchLike, LEGACY_SIGNATURE_HEADER, type Locale, type RequestOptions, SEKYRO_SIGNATURE_HEADER, Sekyro, SekyroApiError, type SekyroApiErrorInit, type SekyroClientErrorCode, SekyroConfigError, type SekyroConfigErrorCode, type SekyroEnvironment, type SekyroOptions, SekyroWebhookError, type SekyroWebhookErrorCode, type Session, type SessionEventData, type SessionLifecycleEventData, type SessionOutcome, type SessionReviewDecidedEventData, type SessionStatus, type SessionStep, type SessionStepCompletedEventData, SessionsApi, type VerifyWebhookOptions, type WebhookEnvelope, type WebhookEnvelopeOf, type WebhookEventDataMap, type WebhookEventType, signatureFromHeaders, verifyWebhook };
790
+ export { type CheckState, type CheckType, type CreateSessionInput, type CreatedSession, DEFAULT_BASE_URL, DEFAULT_TIMEOUT_MS, type DecisionReason, type DeepPartial, type DeliverOptions, type EkycProfileOverride, type EkycProfileSettings, type EligibilityReason, type FetchLike, type IdentityMethod, LEGACY_SIGNATURE_HEADER, type Locale, type MatchReason, type PolicyFailureReason, type ProfileDocumentType, type RequestOptions, SEKYRO_SIGNATURE_HEADER, Sekyro, SekyroApiError, type SekyroApiErrorInit, type SekyroClientErrorCode, SekyroConfigError, type SekyroConfigErrorCode, type SekyroEnvironment, type SekyroOptions, SekyroWebhookError, type SekyroWebhookErrorCode, type Session, type SessionDevice, type SessionDeviceSignal, type SessionEventData, type SessionFailureReason, type SessionLifecycleEventData, type SessionNetwork, type SessionNetworkEvent, type SessionOutcome, type SessionReviewDecidedEventData, type SessionStatus, type SessionStep, type SessionStepCompletedEventData, type SessionSubjectInput, SessionsApi, type SubjectSuspiciousActivityEventData, type SubjectUpdatedEventData, type VerifyWebhookOptions, type WebhookEnvelope, type WebhookEnvelopeOf, type WebhookEventDataMap, type WebhookEventType, signatureFromHeaders, verifyWebhook };