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

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.cts CHANGED
@@ -16,12 +16,14 @@ type SessionStatus = "created" | "in_progress" | "review_pending" | "completed"
16
16
  type SessionOutcome = "approved" | "review" | "rejected";
17
17
  /**
18
18
  * How the person proves their identity on an optional-document app: type the
19
- * national number, or photograph the document.
19
+ * national number, or photograph the document (`document_chip`: native NFC clients only).
20
+ * `national_eid`: the country's national eID (e.g. Houwiyeti for Mauritania),
21
+ * offered when the app's profile turns the national eID on.
20
22
  * @public
21
23
  */
22
- type IdentityMethod = "national_number" | "document_photo";
24
+ type IdentityMethod = "national_number" | "document_photo" | "document_chip" | "national_eid";
23
25
  /** The verification checks a flow may contain. @public */
24
- type CheckType = "liveness" | "face_match" | "doc_ocr" | "population_registry" | "phone_otp";
26
+ type CheckType = "liveness" | "face_match" | "doc_ocr" | "population_registry" | "phone_otp" | "nfc_chip" | "email_otp" | "portrait_icao" | "eid_auth";
25
27
  /** Per-check execution state within a session. @public */
26
28
  type CheckState = "pending" | "input_required" | "processing" | "passed" | "failed" | "review" | "skipped";
27
29
  /**
@@ -79,6 +81,14 @@ type PolicyFailureReason = SessionFailureReason | EligibilityReason | "document_
79
81
  * @public
80
82
  */
81
83
  type MatchReason = "name_mismatch" | "birth_date_mismatch" | "nationality_mismatch" | "document_number_mismatch";
84
+ /**
85
+ * Face-match probe-binding reason a `face_match` {@link SessionStep.reason} may
86
+ * carry (SDK spec §4.10): `probe_not_from_liveness` — the face image isn't the
87
+ * person in the liveness clip. Retryable within the step's attempts (the
88
+ * person re-takes the liveness capture); billed.
89
+ * @public
90
+ */
91
+ type ProbeBindingReason = "probe_not_from_liveness";
82
92
  /** Hosted-flow languages. @public */
83
93
  type Locale = "ar" | "fr" | "en";
84
94
  /** The environment a webhook was emitted from. @public */
@@ -97,6 +107,57 @@ interface SessionStep {
97
107
  calibratedScore?: number;
98
108
  /** The check failed after using all of its attempts. */
99
109
  attemptsExhausted?: boolean;
110
+ /**
111
+ * `portrait_icao` only (ID mode): the per-criterion ICAO report of the last
112
+ * attempt — numbers and enums only, never the image.
113
+ */
114
+ report?: PortraitReportEntry[];
115
+ /**
116
+ * `face_match` only: the probe-quality measurement of the selfie that was
117
+ * matched (occlusion, head pose, eye openness, sharpness). Recorded for
118
+ * information only: it never changes the step's state or reason.
119
+ */
120
+ probeQuality?: ProbeQuality;
121
+ }
122
+ /**
123
+ * The probe-quality measurement on a `face_match` step. Numbers only; `null`
124
+ * means the value could not be measured. Informational: no threshold applies.
125
+ * @public
126
+ */
127
+ interface ProbeQuality {
128
+ /** Share of the inner face that is covered (a hand, a mask, a phone), in [0, 1]. */
129
+ occlusion: number | null;
130
+ /** Head pose in degrees. */
131
+ pose: {
132
+ yaw: number | null;
133
+ pitch: number | null;
134
+ roll: number | null;
135
+ };
136
+ /** Openness of the less-open eye, in [0, 1]. */
137
+ eyesOpen: number | null;
138
+ /** Sharpness of the face region (higher is sharper; no fixed scale). */
139
+ sharpness: number | null;
140
+ }
141
+ /**
142
+ * One row of the `portrait_icao` report (ID mode): the server's measurement of
143
+ * one ICAO criterion and the threshold that applied.
144
+ * @public
145
+ */
146
+ interface PortraitReportEntry {
147
+ criterion: "pose" | "eyes" | "mouth" | "occlusion" | "glare" | "lighting" | "background" | "resolution";
148
+ value: number | null;
149
+ threshold: number | string | null;
150
+ pass: boolean;
151
+ }
152
+ /**
153
+ * A short-lived link to a session's ICAO portrait (480×640 JPEG), from
154
+ * {@link SessionsApi.portrait}. Download it before `expiresAt`; never store the URL.
155
+ * @public
156
+ */
157
+ interface SessionPortraitLink {
158
+ url: string;
159
+ /** ISO 8601 (about 5 minutes after the call). */
160
+ expiresAt: string;
100
161
  }
101
162
  /**
102
163
  * Out-of-band delivery of the session's hosted link, sent by Sekyro AI after the
@@ -134,9 +195,36 @@ interface SessionSubjectInput {
134
195
  * its webhooks, and searchable on the subjects API.
135
196
  */
136
197
  externalRef?: string;
198
+ /**
199
+ * Returning user (profile v2 step 5): verify this already-verified subject
200
+ * again with liveness + face match only, against the reference photo stored
201
+ * on the subject. Name exactly one target. Errors at create:
202
+ * `404 subject_not_found`, `409 subject_revoked`, `409 subject_no_reference`,
203
+ * `409 subject_stale` (older than the app's `reuse.maxAgeMonths`) and
204
+ * `400` / `409 reuse_target_ambiguous`.
205
+ */
206
+ reuse?: SubjectReuseTarget;
137
207
  }
138
- /** A document type the backend reads (kyc-docs-v2 vocabulary). @public */
139
- type ProfileDocumentType = "carte_identite" | "passport";
208
+ /**
209
+ * Which subject a returning-user session re-verifies — exactly ONE of the
210
+ * subject id, your own `externalRef` (must match a single subject) or the NNI.
211
+ * @public
212
+ */
213
+ type SubjectReuseTarget = {
214
+ subjectId: string;
215
+ externalRef?: never;
216
+ nni?: never;
217
+ } | {
218
+ externalRef: string;
219
+ subjectId?: never;
220
+ nni?: never;
221
+ } | {
222
+ nni: string;
223
+ subjectId?: never;
224
+ externalRef?: never;
225
+ };
226
+ /** A document type the backend reads (kyc-docs-v2 vocabulary; `carte_identite` = identity card of any issuer). @public */
227
+ type ProfileDocumentType = "carte_identite" | "passport" | "residence_permit";
140
228
  /**
141
229
  * The settings of an app's eKYC profile that a session may override — a
142
230
  * mirror of the backend profile (schema version 2) without `schemaVersion`,
@@ -146,10 +234,32 @@ type ProfileDocumentType = "carte_identite" | "passport";
146
234
  * @public
147
235
  */
148
236
  interface EkycProfileSettings {
149
- /** Phone OTP step: off, or on with where the number comes from. */
237
+ /**
238
+ * Phone OTP step: off, or on with where the number comes from. The person
239
+ * chooses WhatsApp or SMS from the channels left after the org's settings
240
+ * and `channels`.
241
+ */
150
242
  phone: "off" | {
243
+ /** Where the number comes from: your `subject.phone` / `input.phone`, the person, or either. */
151
244
  numberSource: "prefilled" | "user_entered" | "prefilled_or_entered";
245
+ /**
246
+ * Narrow the channels the person may choose from (absent = every
247
+ * channel the org has on). A channel the org turned off answers
248
+ * `400 phone_channels_disabled_for_org`; an empty or duplicated list
249
+ * `400 phone_channels_invalid`.
250
+ */
251
+ channels?: Array<"whatsapp" | "sms">;
252
+ /**
253
+ * Which countries codes may be sent to: the profile's allowed
254
+ * `locations` (default), `any`, or a list of ISO 3166-1 alpha-2 codes.
255
+ * Invalid values answer `400 phone_destinations_invalid`.
256
+ */
257
+ destinations?: "locations" | "any" | {
258
+ countries: string[];
259
+ };
152
260
  };
261
+ /** Email OTP step (absent = off): a one-time code sent to the person's email address. */
262
+ email?: "off" | ProfileEmail;
153
263
  document: {
154
264
  mode: "off" | "optional" | "mandatory";
155
265
  /** Accepted document types: `'*'` (all) or a list, optionally per issuing country. */
@@ -185,6 +295,8 @@ interface EkycProfileSettings {
185
295
  /** Per-step attempt limits. */
186
296
  attempts?: {
187
297
  phone: number;
298
+ /** Email OTP attempts (1–5); absent = the platform default. */
299
+ email?: number;
188
300
  document: number;
189
301
  registry: number;
190
302
  liveness: number;
@@ -227,6 +339,32 @@ interface EkycProfileSettings {
227
339
  action: "signal" | "block";
228
340
  };
229
341
  };
342
+ /**
343
+ * The live photo. `purpose: "id_document"` also takes an ICAO 480×640 portrait you
344
+ * download for printing on an ID document. `icao` makes a verification selfie meet
345
+ * the ICAO photo rules: `"reject"` asks the person to retake a non-compliant photo
346
+ * (after the last attempt the session fails, or goes to review in review mode);
347
+ * `"alert"` lets the person continue and adds the risk signal `icao_non_compliant`.
348
+ * Both need liveness on; `"alert"` with `"id_document"` answers
349
+ * `400 portrait_icao_policy_id_document`. Absent = a verification selfie, no ICAO check.
350
+ */
351
+ portrait?: {
352
+ purpose?: "verification" | "id_document";
353
+ icao?: {
354
+ policy: "alert" | "reject";
355
+ };
356
+ };
357
+ }
358
+ /**
359
+ * The email OTP step of a profile. When the email check is not available on
360
+ * the platform yet, saving it answers `400 email_otp_not_available`.
361
+ * @public
362
+ */
363
+ interface ProfileEmail {
364
+ /** Where the address comes from: your `input.email`, the person, or either. */
365
+ emailSource: "prefilled" | "user_entered" | "prefilled_or_entered";
366
+ /** Disposable (temporary) addresses: allowed, flagged as a risk signal (default), or refused. */
367
+ disposable?: "allow" | "signal" | "block";
230
368
  }
231
369
  /**
232
370
  * `T` with every property optional, recursively. Arrays are replaced as a
@@ -296,11 +434,59 @@ interface CreateSessionInput {
296
434
  nni?: string;
297
435
  /** E.164 phone number, e.g. `+22236123456`. */
298
436
  phone?: string;
437
+ /** Email address for the email OTP step (`emailSource` `prefilled` / `prefilled_or_entered`). */
438
+ email?: string;
299
439
  fullName?: string;
300
440
  /** ISO 8601 date (`YYYY-MM-DD`). */
301
441
  birthDate?: string;
442
+ /**
443
+ * Partner-supplied identity data (`supplied` mode only): the person's
444
+ * biographic record and photo as YOUR system holds them — for example
445
+ * from your own ANRPTS answer, converted with {@link registryFromAnrpts}.
446
+ * Sekyro AI stores it as data you vouch for, makes no registry call, and
447
+ * never receives or stores any registry key. `nni` must be set too and
448
+ * equal `suppliedIdentity.nni`. Refused unless Sekyro AI enabled the mode
449
+ * for the environment (`403 supplied_identity_not_entitled`); required in
450
+ * that mode when the app verifies identity (`422 supplied_identity_required`).
451
+ */
452
+ suppliedIdentity?: SuppliedIdentityRecord;
302
453
  } & Record<string, unknown>;
303
454
  }
455
+ /**
456
+ * Partner-supplied identity data (`sessions.create` `input.suppliedIdentity`):
457
+ * the person's biographic record and photo, as your organization holds them.
458
+ * Sekyro AI treats it as identity data supplied by your organization, not as
459
+ * a registry lookup. Refusals at create: `400 supplied_identity_nni_mismatch`,
460
+ * `422 supplied_identity_stale` (`fetchedAt` older than 24 h),
461
+ * `422 supplied_identity_photo_unusable` (not a JPEG/PNG of at most 1 MB within the
462
+ * size bounds). In a `supplied` environment whose app verifies identity, a create
463
+ * without `input.suppliedIdentity` is `422 supplied_identity_required`. The face on
464
+ * the photo is checked after consent, at the face match (`no_face_reference`).
465
+ * @public
466
+ */
467
+ interface SuppliedIdentityRecord {
468
+ /** 10-digit NNI, as a string. */
469
+ nni: string;
470
+ firstNameFr: string;
471
+ lastNameFr: string;
472
+ fatherNameFr?: string;
473
+ firstNameAr: string;
474
+ lastNameAr: string;
475
+ fatherNameAr?: string;
476
+ /** ISO 8601 date (`YYYY-MM-DD`). */
477
+ birthDate: string;
478
+ birthPlaceFr?: string;
479
+ birthPlaceAr?: string;
480
+ sex?: "M" | "F";
481
+ /** Nationality text as your source holds it (e.g. `Mauritanienne`). */
482
+ nationalities?: string[];
483
+ /** Base64 JPEG or PNG (at most 1 MB decoded). */
484
+ photo: string;
485
+ /** ISO 8601 date (`YYYY-MM-DD`) of the registry photo. */
486
+ photoDate?: string;
487
+ /** ISO 8601 date-time at which your system obtained this record. */
488
+ fetchedAt: string;
489
+ }
304
490
  /** Per-request options. @public */
305
491
  interface RequestOptions {
306
492
  /**
@@ -382,6 +568,43 @@ interface SessionDevice {
382
568
  deviceKeys: string[];
383
569
  signals: SessionDeviceSignal[];
384
570
  }
571
+ /**
572
+ * The national eID that verified the session's identity (the `eid_auth` check
573
+ * passed): the provider id (`{country}.{provider}`, e.g. `MR.houwiyeti`), its
574
+ * ISO 3166-1 alpha-2 country and when. A passed eID ends the session.
575
+ * @public
576
+ */
577
+ interface EidResult {
578
+ provider: string;
579
+ country: string;
580
+ verifiedAt: string;
581
+ }
582
+ /**
583
+ * The full phone number and email address the person verified in a session
584
+ * (an OTP check that passed) — sent ONLY to you (the session view and your
585
+ * webhooks), never to the person's browser, and removed when the session's
586
+ * personal data is purged. You are the controller of these values. A
587
+ * prefilled value that was not verified is never listed.
588
+ * @public
589
+ */
590
+ interface VerifiedContacts {
591
+ /** From a passed `phone_otp` check. */
592
+ phone?: {
593
+ /** E.164, e.g. `+22236123456`. */
594
+ number: string;
595
+ /** The channel the code was delivered on. */
596
+ channel: "whatsapp" | "sms";
597
+ /** ISO 8601. */
598
+ verifiedAt: string;
599
+ };
600
+ /** From a passed `email_otp` check. */
601
+ email?: {
602
+ /** The verified address (domain lowercased). */
603
+ address: string;
604
+ /** ISO 8601. */
605
+ verifiedAt: string;
606
+ };
607
+ }
385
608
  /**
386
609
  * The whitelisted session view returned by {@link SessionsApi.get}. Never
387
610
  * contains the client token.
@@ -424,9 +647,27 @@ interface Session {
424
647
  overriddenFields?: string[];
425
648
  /**
426
649
  * Risk signals recorded on the session (e.g. `device_velocity`,
427
- * `timezone_mismatch`) — signals only, never a verdict by themselves.
650
+ * `timezone_mismatch`, `icao_non_compliant` when an `alert` ICAO policy flagged
651
+ * the selfie) — signals only, never a verdict by themselves.
428
652
  */
429
653
  riskSignals?: string[];
654
+ /**
655
+ * `true` for a returning-user session (created with
656
+ * {@link SessionSubjectInput.reuse}): liveness + face match against the
657
+ * subject's stored reference photo only.
658
+ */
659
+ returning?: true;
660
+ /** On a returning-user session: the subject (person) it re-verifies. */
661
+ reuseOf?: string;
662
+ /** The contacts verified in this session (passed OTP checks only); absent when none. */
663
+ verifiedContacts?: VerifiedContacts;
664
+ /** The national eID that verified this session (the `eid_auth` check passed); absent otherwise. */
665
+ eid?: EidResult;
666
+ /**
667
+ * ID mode (`portrait.purpose = id_document`) only: the ICAO portrait can be
668
+ * fetched with {@link SessionsApi.portrait}.
669
+ */
670
+ portraitAvailable?: boolean;
430
671
  }
431
672
  /**
432
673
  * `data` of the terminal / review-pending session lifecycle events
@@ -463,6 +704,10 @@ interface SessionLifecycleEventData {
463
704
  * different subject than `subjectId` — the subjects are never merged.
464
705
  */
465
706
  subjectConflict?: boolean;
707
+ /** `true` on a returning-user session (liveness + face match against the stored photo). */
708
+ returning?: true;
709
+ /** On a returning-user session: the subject (person) it re-verifies. */
710
+ reuseOf?: string;
466
711
  /**
467
712
  * On `session.failed` with `failureReason: 'device_cooldown'`: ISO time
468
713
  * from which the device may start a new verification.
@@ -470,18 +715,129 @@ interface SessionLifecycleEventData {
470
715
  retryAfter?: string;
471
716
  /** Dotted profile paths the session's create-time override changed. */
472
717
  overriddenFields?: string[];
718
+ /** On `completed` / `failed`: the contacts verified in this session (passed OTP checks only). */
719
+ verifiedContacts?: VerifiedContacts;
720
+ /** On `completed` / `failed`: the national eID that verified this session, when one did. */
721
+ eid?: EidResult;
722
+ /**
723
+ * ID mode only, on `completed` / `failed`: the ICAO portrait can be fetched
724
+ * with {@link SessionsApi.portrait} (the event never carries the image).
725
+ */
726
+ portraitAvailable?: boolean;
473
727
  }
474
728
  /**
475
- * `data` of `subject.updated` — a session linked to the subject reached a
476
- * terminal state. Ids and enums only.
729
+ * `data` of `subject.updated` — either a session linked to the subject reached
730
+ * a terminal state (`sessionId`, session `status`, `outcome`), or the subject
731
+ * was revoked (`status: 'revoked'`, no session). Ids and enums only.
477
732
  * @public
478
733
  */
479
734
  interface SubjectUpdatedEventData {
480
735
  subjectId: string;
736
+ /** The session that reached a terminal state; absent on a revocation. */
737
+ sessionId?: string;
738
+ status: SessionStatus | "revoked";
739
+ /** The session outcome; absent on a revocation. */
740
+ outcome?: SessionOutcome | null;
741
+ }
742
+ /**
743
+ * `data` of `subject.enrolled` — the subject's first reference photo was
744
+ * stored (it can now be used for returning-user sessions). Ids and enums only.
745
+ * @public
746
+ */
747
+ interface SubjectEnrolledEventData {
748
+ subjectId: string;
749
+ /** The approved session the reference photo came from. */
481
750
  sessionId: string;
751
+ assurance: SubjectAssurance;
752
+ }
753
+ /**
754
+ * `data` of `subject.deleted`. A delete through the subjects API carries
755
+ * `subjectId`; a right-to-erasure request carries the tokenized `subjectRef`
756
+ * (with `orgId` / `env`) instead — never the national number.
757
+ * @public
758
+ */
759
+ interface SubjectDeletedEventData {
760
+ subjectId?: string;
761
+ subjectRef?: string;
762
+ orgId?: string;
763
+ env?: SekyroEnvironment;
764
+ }
765
+ /** Subject lifecycle: a revoked subject cannot be reused. @public */
766
+ type SubjectStatus = "active" | "revoked";
767
+ /**
768
+ * How strongly a subject's identity was established: the reference photo
769
+ * came from the national registry, the document's chip (`chip_biometric`, a
770
+ * passed chip read plus a face match) or the document, and a face match passed
771
+ * (`*_biometric`) or the session had no face match (`*_only`). `supplied_*`:
772
+ * partner-supplied identity data (`input.suppliedIdentity`), with
773
+ * (`supplied_biometric`) or without (`supplied_only`) a face match against its photo.
774
+ * @public
775
+ */
776
+ type SubjectAssurance = "registry_biometric" | "chip_biometric" | "document_biometric" | "registry_only" | "document_only" | "supplied_biometric" | "supplied_only";
777
+ /**
778
+ * Origin of a subject's stored reference photo, best first (`chip`: the document chip's portrait;
779
+ * `org_supplied`: the photo of your partner-supplied identity data).
780
+ * @public
781
+ */
782
+ type SubjectReferenceSource = "registry" | "doc_registry" | "chip" | "org_supplied" | "document";
783
+ /** One session linked to a subject. @public */
784
+ interface SubjectSession {
785
+ sessionId: string;
786
+ appId: string | null;
787
+ /** ISO 8601 — when the session was linked. */
788
+ at: string;
482
789
  status: SessionStatus;
483
790
  outcome: SessionOutcome | null;
484
791
  }
792
+ /**
793
+ * A subject (the same person across your apps), as `GET /subjects/:id`
794
+ * returns it. Never contains photo keys or URLs.
795
+ * @public
796
+ */
797
+ interface Subject {
798
+ id: string;
799
+ status: SubjectStatus;
800
+ /** ISO 8601 — present only when revoked. */
801
+ revokedAt?: string;
802
+ sessions: SubjectSession[];
803
+ externalRefs: string[];
804
+ /** ISO 8601. */
805
+ firstSeenAt: string;
806
+ /** ISO 8601. */
807
+ lastSeenAt: string;
808
+ /** ISO 8601, or `null` before the first approved session. */
809
+ lastPassedAt: string | null;
810
+ /** ISO 8601 of the last approved full or returning session, or `null`. */
811
+ lastVerifiedAt: string | null;
812
+ /** The stored reference photo's origin and date — `null` until one is stored. */
813
+ reference: {
814
+ source: SubjectReferenceSource;
815
+ capturedAt: string;
816
+ } | null;
817
+ assurance: SubjectAssurance | null;
818
+ /**
819
+ * A returning-user session can be created now: active, a reference photo is
820
+ * stored, and the last FULL verification (returning-user sessions do not
821
+ * reset it) is within your app's
822
+ * `reuse.maxAgeMonths` (when set).
823
+ */
824
+ returningReady: boolean;
825
+ /** The verified name / birth date of the latest approved session. */
826
+ display?: {
827
+ name?: string;
828
+ birthDate?: string;
829
+ };
830
+ }
831
+ /** Result of {@link SubjectsApi.delete}. @public */
832
+ interface DeletedSubject {
833
+ id: string;
834
+ deleted: true;
835
+ }
836
+ /** Options of {@link SubjectsApi.revoke}. @public */
837
+ interface RevokeSubjectInput {
838
+ /** Kept on the audit trail only (≤ 500 characters). Do not put personal data here. */
839
+ reason?: string;
840
+ }
485
841
  /**
486
842
  * `data` of `subject.suspicious_activity` — a device already linked to
487
843
  * ANOTHER subject was used for a session of this subject. `count` is the
@@ -510,6 +866,12 @@ interface SessionStepCompletedEventData {
510
866
  * different subject than `subjectId` — the subjects are never merged.
511
867
  */
512
868
  subjectConflict?: boolean;
869
+ /** `true` on a returning-user session (liveness + face match against the stored photo). */
870
+ returning?: true;
871
+ /** On a returning-user session: the subject (person) it re-verifies. */
872
+ reuseOf?: string;
873
+ /** When the passed check is `phone_otp` / `email_otp`: that one verified contact. */
874
+ verifiedContacts?: VerifiedContacts;
513
875
  }
514
876
  /**
515
877
  * `data` of `session.review_decided` — a human (or the review-timeout sweep)
@@ -531,6 +893,12 @@ interface SessionReviewDecidedEventData {
531
893
  * different subject than `subjectId` — the subjects are never merged.
532
894
  */
533
895
  subjectConflict?: boolean;
896
+ /** `true` on a returning-user session (liveness + face match against the stored photo). */
897
+ returning?: true;
898
+ /** On a returning-user session: the subject (person) it re-verifies. */
899
+ reuseOf?: string;
900
+ /** ID mode only: the ICAO portrait can be fetched with {@link SessionsApi.portrait}. */
901
+ portraitAvailable?: boolean;
534
902
  }
535
903
  /**
536
904
  * Event type → the shape of its `data`. Session events are typed; the
@@ -547,10 +915,10 @@ interface WebhookEventDataMap {
547
915
  "session.rejected": SessionLifecycleEventData;
548
916
  "session.expired": SessionLifecycleEventData;
549
917
  "session.failed": SessionLifecycleEventData;
550
- "subject.enrolled": Record<string, unknown>;
918
+ "subject.enrolled": SubjectEnrolledEventData;
551
919
  "subject.updated": SubjectUpdatedEventData;
552
920
  "subject.suspicious_activity": SubjectSuspiciousActivityEventData;
553
- "subject.deleted": Record<string, unknown>;
921
+ "subject.deleted": SubjectDeletedEventData;
554
922
  "aml.match_flagged": Record<string, unknown>;
555
923
  "payment.received": Record<string, unknown>;
556
924
  "invoice.generated": Record<string, unknown>;
@@ -638,7 +1006,7 @@ declare class SessionsApi {
638
1006
  * surface on purpose (only its bound `call` crosses this boundary).
639
1007
  * @internal
640
1008
  */
641
- constructor(call: <T>(method: "GET" | "POST", path: string, body?: unknown, idempotencyKey?: string) => Promise<T>);
1009
+ constructor(call: <T>(method: "GET" | "POST" | "DELETE", path: string, body?: unknown, idempotencyKey?: string) => Promise<T>);
642
1010
  /**
643
1011
  * `POST /sessions`. Returns the one-time `clientToken` — hand it to the
644
1012
  * browser, never persist it. Pass an `idempotencyKey` so a retried call
@@ -654,6 +1022,47 @@ declare class SessionsApi {
654
1022
  selectMethod(id: string, method: IdentityMethod): Promise<Session>;
655
1023
  /** `GET /sessions/:id` — the whitelisted view (no client token). */
656
1024
  get(id: string): Promise<Session>;
1025
+ /**
1026
+ * `GET /sessions/:id/portrait?format=url` — ID mode: a 5-minute presigned
1027
+ * link to the 480×640 ICAO portrait (JPEG). Needs the `portrait:read` scope
1028
+ * (keys minted from the dashboard carry it). `404 portrait_not_available`
1029
+ * until the session's `portrait_icao` check has passed (`portraitAvailable`).
1030
+ */
1031
+ portrait(id: string): Promise<SessionPortraitLink>;
1032
+ }
1033
+ /**
1034
+ * `sekyro.subjects` — read and manage subjects (the same person across your
1035
+ * apps). Reads need the `subjects:read` scope, `revoke` / `delete` the
1036
+ * `subjects:write` scope (keys minted from the dashboard carry both; an older
1037
+ * key answers `403 insufficient_scope`). A foreign or unknown id answers
1038
+ * `404 subject_not_found`.
1039
+ *
1040
+ * Type-only export, like {@link SessionsApi}: obtained through
1041
+ * {@link Sekyro.subjects}.
1042
+ * @public
1043
+ */
1044
+ declare class SubjectsApi {
1045
+ private readonly call;
1046
+ /** @internal */
1047
+ constructor(call: <T>(method: "GET" | "POST" | "DELETE", path: string, body?: unknown, idempotencyKey?: string) => Promise<T>);
1048
+ /** `GET /subjects/:id` — the subject, its sessions and its returning-user readiness. */
1049
+ get(id: string): Promise<Subject>;
1050
+ /** `GET /subjects?externalRef=…` — the subjects carrying your own id (newest first, at most 50). */
1051
+ list(query: {
1052
+ externalRef: string;
1053
+ }): Promise<Subject[]>;
1054
+ /**
1055
+ * `POST /subjects/:id/revoke` — the subject can no longer be used for
1056
+ * returning-user sessions. Idempotent: revoking again returns the same view.
1057
+ * Emits `subject.updated` with `status: 'revoked'`.
1058
+ */
1059
+ revoke(id: string, input?: RevokeSubjectInput, opts?: RequestOptions): Promise<Subject>;
1060
+ /**
1061
+ * `DELETE /subjects/:id` — deletes the subject's stored photos, face
1062
+ * templates and identifiers, and unlinks its sessions. Emits
1063
+ * `subject.deleted`. Cannot be undone; a second call answers `404`.
1064
+ */
1065
+ delete(id: string): Promise<DeletedSubject>;
657
1066
  }
658
1067
  /**
659
1068
  * Sekyro AI partner API client. Server-side only: it carries your API key.
@@ -671,6 +1080,7 @@ declare class SessionsApi {
671
1080
  */
672
1081
  declare class Sekyro {
673
1082
  readonly sessions: SessionsApi;
1083
+ readonly subjects: SubjectsApi;
674
1084
  constructor(opts: SekyroOptions);
675
1085
  }
676
1086
 
@@ -687,7 +1097,7 @@ declare class SekyroWebhookError extends Error {
687
1097
  constructor(code: SekyroWebhookErrorCode, message?: string);
688
1098
  }
689
1099
  /** Why the {@link Sekyro} constructor rejected its options. @public */
690
- type SekyroConfigErrorCode = "missing_api_key" | "invalid_base_url";
1100
+ type SekyroConfigErrorCode = "missing_api_key" | "invalid_base_url" | "invalid_registry_record";
691
1101
  /**
692
1102
  * Thrown synchronously by `new Sekyro(...)` for an unusable configuration —
693
1103
  * before any request is made. Extends `TypeError` so existing
@@ -731,6 +1141,61 @@ declare class SekyroApiError extends Error {
731
1141
  constructor(init: SekyroApiErrorInit);
732
1142
  }
733
1143
 
1144
+ /**
1145
+ * The raw ANRPTS `getPersonne` answer your server received with your own
1146
+ * access: `{ personne, photo }`, where `photo` is a base64 JPEG (optionally
1147
+ * data-URL prefixed). Only the fields the mapping reads are typed.
1148
+ * @public
1149
+ */
1150
+ interface AnrptsPersonneResponse {
1151
+ personne?: {
1152
+ nni?: string | undefined;
1153
+ prenomFr?: string | undefined;
1154
+ patronymeFr?: string | undefined;
1155
+ perePrenomFr?: string | undefined;
1156
+ prenomAr?: string | undefined;
1157
+ patronymeAr?: string | undefined;
1158
+ perePrenomAr?: string | undefined;
1159
+ /** ISO date or date-time (`1990-01-01T00:00:00.000Z`), or `DD/MM/YYYY`. */
1160
+ dateNaissance?: string | undefined;
1161
+ lieuNaissanceFr?: string | undefined;
1162
+ lieuNaissanceAr?: string | undefined;
1163
+ sexeCode?: string | undefined;
1164
+ nationalities?: string[] | undefined;
1165
+ [key: string]: unknown;
1166
+ };
1167
+ photo?: string | undefined;
1168
+ datePhoto?: string | undefined;
1169
+ [key: string]: unknown;
1170
+ }
1171
+ /** Options of {@link registryFromAnrpts}. @public */
1172
+ interface RegistryFromAnrptsOptions {
1173
+ /**
1174
+ * When YOUR system received this ANRPTS answer (not "now" when you map a cached
1175
+ * answer). Required: records older than 24 h are refused at session create.
1176
+ */
1177
+ fetchedAt: Date | string;
1178
+ }
1179
+ /**
1180
+ * Convert an ANRPTS `getPersonne` answer that YOUR server already received,
1181
+ * with your own access, into the `input.suppliedIdentity` record of
1182
+ * `sessions.create` (partner-supplied identity data). A pure, local mapping:
1183
+ * it makes no network call, and Sekyro AI never sees, receives or stores any
1184
+ * ANRPTS key — only the record and photo you pass.
1185
+ *
1186
+ * ```ts
1187
+ * const anrpts = await myAnrptsClient.getPersonne(nni); // your call, your key
1188
+ * const suppliedIdentity = registryFromAnrpts(anrpts, { fetchedAt: receivedAt });
1189
+ * await sekyro.sessions.create({ input: { nni, suppliedIdentity } });
1190
+ * ```
1191
+ *
1192
+ * Throws {@link SekyroConfigError} (`invalid_registry_record`) when a required
1193
+ * field (NNI, French and Arabic first and last names, birth date, photo) is
1194
+ * missing. The message names the field, never its value.
1195
+ * @public
1196
+ */
1197
+ declare function registryFromAnrpts(response: AnrptsPersonneResponse, options: RegistryFromAnrptsOptions): SuppliedIdentityRecord;
1198
+
734
1199
  /**
735
1200
  * The HTTP header carrying the webhook signature:
736
1201
  * `t=<unix seconds>,v1=<hex>[,v1=<hex>]`.
@@ -787,4 +1252,4 @@ interface VerifyWebhookOptions {
787
1252
  */
788
1253
  declare function verifyWebhook(rawBody: string, header: string | null | undefined, secret: string, opts?: VerifyWebhookOptions): WebhookEnvelope;
789
1254
 
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 };
1255
+ export { type AnrptsPersonneResponse, type CheckState, type CheckType, type CreateSessionInput, type CreatedSession, DEFAULT_BASE_URL, DEFAULT_TIMEOUT_MS, type DecisionReason, type DeepPartial, type DeletedSubject, type DeliverOptions, type EidResult, type EkycProfileOverride, type EkycProfileSettings, type EligibilityReason, type FetchLike, type IdentityMethod, LEGACY_SIGNATURE_HEADER, type Locale, type MatchReason, type PolicyFailureReason, type PortraitReportEntry, type ProbeBindingReason, type ProbeQuality, type ProfileDocumentType, type ProfileEmail, type RegistryFromAnrptsOptions, type RequestOptions, type RevokeSubjectInput, 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 SessionPortraitLink, type SessionReviewDecidedEventData, type SessionStatus, type SessionStep, type SessionStepCompletedEventData, type SessionSubjectInput, SessionsApi, type Subject, type SubjectAssurance, type SubjectDeletedEventData, type SubjectEnrolledEventData, type SubjectReferenceSource, type SubjectReuseTarget, type SubjectSession, type SubjectStatus, type SubjectSuspiciousActivityEventData, type SubjectUpdatedEventData, SubjectsApi, type SuppliedIdentityRecord, type VerifiedContacts, type VerifyWebhookOptions, type WebhookEnvelope, type WebhookEnvelopeOf, type WebhookEventDataMap, type WebhookEventType, registryFromAnrpts, signatureFromHeaders, verifyWebhook };