export class GetIdSdkError extends Error { code?: string; constructor(message: string, code?: string) { super(message); this.name = 'GetIdSdkError'; this.code = code; } } export class DocumentScanError extends GetIdSdkError { /** * @hidden */ constructor(message: string, code?: GeneralErrorCode) { super(message); this.name = 'DocumentScanError'; this.code = code; } } export class LivenessError extends GetIdSdkError { constructor(message: string, code?: LivenessErrorCode | GeneralErrorCode) { super(message); this.name = 'LivenessError'; this.code = code; } } export class SelfieError extends GetIdSdkError { constructor(message: string, code?: SelfieErrorCode | GeneralErrorCode) { super(message); this.name = 'SelfieError'; this.code = code; } } export interface Styles { 'success-color'?: string; 'error-color'?: string; 'mobile-camera-background-color'?: string; 'border-color'?: string; } /** * The properties to initialise the SDK with. * * If `sdkKey` is provided, the SDK will use it to authenticate with the backend (not recommended for production). Otherwise a `token` * needs to be provided that is created outside the app using the API token endpoint (`/sdk/v2/token`). */ export type InitialiseSdkProps = { /** * The flow to use for the identification process. * * Different flows requires different checks to be executed, e.g `doc-only` (document scan), `doc-selfie` (document scan and selfie), * `doc-selfie-liveness` (document scan, selfie and liveness check). Flows are configured in the backoffice admin. */ flow: string; /** The token created by the backend using the API token endpoint (`/sdk/v2/token`). This is a signed JWT that contains the sessionId. */ token?: string; /** * Instead of passing a token, the SDK can be initialised with the SDK key. This can be useful during development, but should not be used in a production build. */ sdkKey?: string; /** * The base URL of the API to use for the identification process. This can be found in * the backoffice admin panel or by contacting our [integration support](mailto:support@getid.ee?subject=[GitHub]%20Obtaining%20GetID%20credentials). */ apiUrl: string; /** * In case you don't want your users to complete verification more than once or for any other identification purposes you can pass a `customerId` * param when generating the jwt token, or include the `customerId` property directly into config if you prefer sdkKey authorization to JWT. */ customerId?: string; /** * An externalID that can be used to to know which user or session the verification belongs to when fetching the result or when the result is received via a webhook. * * The same `externalId` can be used in multiple verifications. For example, if a user failed the first verification, you can use the same `externalId` in the next one. */ externalId?: string; /** * List of acceptable documents and issuing countries. If provided, the SDK will only accept documents from the list. */ acceptableDocuments?: CountryDocumentTypes[] | CountryDocumentTypesFunction; /** * Allows you to cross-reference pre-collected user data with the data extracted from documents. */ profile?: ProfileType[]; /** * You can override the default styles of the SDK on initialization by providing a `styles` object. */ styles?: Theme; }; /** * The profile that should be used for the identification process. */ export type ProfileType = { category: string; value: string; fieldType?: string; contentType?: string; }; /** * The type of documents that should be accepted for a specific country. */ export type CountryDocumentTypes = { /** Three-letter country code (ISO 3166-1 alpha-3) */ country: string; /** List of document types that are acceptable for the country */ documentTypes?: DocumentType[]; /** List of document versions that are acceptable for the country */ excludedDocumentVersions?: string[]; }; export type CountryDocumentTypesFunction = ( acceptableDocuments: CountryDocumentTypes[] ) => CountryDocumentTypes[]; /** * The result of the `initialiseSDK` function. */ export type InitialiseSdkResult = { /** abort method that can be called to abort the identification process and fully reset the SDK state. */ abort: () => Promise; success?: boolean; }; /** * The different hints that can occur during the document scan process. */ export enum DocumentScanUserHint { NOTHING = '', POSITION_OK = 'position-ok', MOVE_LEFT = 'move-left', MOVE_RIGHT = 'move-right', MOVE_UP = 'move-up', MOVE_DOWN = 'move-down', MOVE_BACK = 'move-back', MOVE_FORWARD = 'move-forward', ROTATE = 'rotate', SKEWED = 'skewed', HOLD_STILL = 'hold-still', MANY_DOCUMENTS = 'many-documents', OUT_OF_CAMERA_FRAME = 'out-of-camera-frame', GLARE = 'glare', NO_DOCUMENT = 'no-document', } /** * Initialisation properties for the document scan. */ export type InitialiseDocumentScanProps = { /** Called when the document is sent to the server for validation, will be called after capture of image */ onDocumentScanServerValidationStarted: () => void; /** Called when the user hint changes */ onUserHintChange: (hint: DocumentScanUserHint) => void; /** Called when camera initialisation is ready */ onCameraReady?: () => void; /** * Automatically scan when a document is detected * * @default false * @remarks Not supported supported in phase 1 */ useAutoCapture?: boolean; /** * Enable debug mode to show debug information on the screen * * @default false */ debugMode?: boolean; }; /** * The result of the init that contains the component, results and the actionable functions for the specific screen */ export type InitialiseDocumentScanResult = { /** React Component to render the camera feed */ component: React.JSX.Element; /** * Function start the document scan process, i.e. Start finding the document and reporting hints with the ML algorithm. * * Resolves when the step is finished with a ScannedDocument * * rejects with: {@link DocumentScanError} if the step fails */ capture?: () => Promise; /** * Function to stop the document scan process, i.e. Stop finding the document in the viewport with the ML algorithm. * This is normally not needed, but may be used to lower cpu usage if a overlay or redirect is used for a longer time */ stopCapture: () => void; /** * Function to upload a document image from the photo library * * resolves when the step is finished * * rejects with: {@link DocumentScanError} if the step fails */ uploadDocument?: () => Promise; /** * Function to take a picture of the document when auto capture is disabled * */ takePicture?: () => Promise; }; /** * The different type of documents that can be scanned. */ export enum DocumentType { PASSPORT = 'passport', ID_CARD = 'id-card', DRIVING_LICENCE = 'driving-licence', RESIDENCE_PERMIT = 'residence-permit', VOTER_CARD = 'voter-card', TAX_CARD = 'tax-card', ADDRESS_CARD = 'address-card', DOMESTIC_PASSPORT = 'domestic-passport', } /** * The different conclusions that can be made during the document scan process. Based on these conclusions the identification * process can continue or be stopped. */ export enum DocumentConclusion { /** The document is considered valid and the identification process can continue. */ OK = 'ok', /** The user should be informed to also scan the back side of the document */ BACK_SIDE_MISSING = 'back-side-missing', FRONT_SIDE_MISSING = 'front-side-missing', /** The sides scanned comes from different documents */ DIFFERENT_DOCUMENTS = 'different-documents', /** The document is not known */ UNKNOWN_SIDES = 'unknown-sides', /** The document is issued in a country that is configured to be not allowed in the flow configuration */ UNACCEPTABLE_COUNTRY = 'unacceptable-country', /** The document type is set to not be allowed in the flow configuration */ UNACCEPTABLE_DOCUMENT_TYPE = 'unacceptable-document-type', /** The document is expired and the identification process should be stopped */ EXPIRED = 'expired', /** The document indicates that the user is too young compared with the age restrictions set in the flow configuration. */ TOO_YOUNG = 'too-young', /** The document indicates that the user is too old compared with the age restrictions set in the flow configuration. */ TOO_OLD = 'too-old', /** The document is missing required fields */ MISSING_REQUIRED_FIELDS = 'missing-required-fields', } /** * The different fields that can be required in a document. */ export type RequiredField = | 'first-name' | 'last-name' | 'date-of-expiry' | 'date-of-birth' | 'date-of-issue' | 'personal-number' | 'document-number' | 'nationality' | 'gender' | 'original-first-name' | 'original-last-name'; /** * The result of a document scan. */ export type ScannedDocument = { /** The country in which the document has been issued. (ISO 3166-1 alpha-3) */ issuingCountry: string; /** The type of document. */ documentType: DocumentType; /** DocumentConclusion of the document scan, e.g BACK_SIDE_MISSING, EXPIRED, UNACCEPTABLE_COUNTRY */ conclusion: DocumentConclusion; /** If the flow is configured with age restrictions and conclusion is either TOO_YOUNG or TOO_OLD, the restrictions can be found here */ ageRestrictions?: { min?: number; max?: number; }; missingRequiredFields?: RequiredField[]; }; /** * @hidden */ export type Theme = { 'success-color'?: string; 'error-color'?: string; 'mobile-camera-background-color'?: string; 'border-color'?: string; }; /** * @hidden */ export type SDKConfiguration = { name: string; flow: { component: 'document' | 'selfie' | 'liveness'; }[]; styles: { theme: Theme; }; }; /** * @hidden */ export type GetidSdkConfig = InitialiseSdkProps & { configuration?: SDKConfiguration; stepsConfigs: { [key: string]: any }; }; /** * @hidden */ export type DocumentScanHandle = Omit< InitialiseDocumentScanResult, 'component' >; /** * @hidden */ export type LivenessScanHandle = Omit< InitialiseLivenessScanResult, 'component' >; /** * @hidden */ export type SelfieScanHandle = Omit; /** * @hidden */ export type UploadDocFile = { type: 'front' | 'back'; uri: string; fileId: string; }; /** * @hidden */ export type UploadSelfieFile = { type: 'selfie'; uri: string; fileId: string; }; /** * @hidden */ export type PassiveLivenessInfo = { fileId: string; isAlive: boolean; livenessFeedback: string[]; success: boolean; signature: string; }; /** * @hidden */ export type UploadPassiveLivenessFile = { kind: 'liveness-passive'; fileId: string; signature: string; }; export enum SelfieUserHint { SELFIE_OK = 'selfie-ok', SELFIE_MULTIPLE_FACES = 'selfie-multiple-faces', SELFIE_NO_FACE = 'selfie-no-face', SELFIE_NOT_CENTERED = 'selfie-not-centered', SELFIE_TOO_BIG = 'selfie-too-big', SELFIE_TOO_SMALL = 'selfie-too-small', SELFIE_NOT_FACING_CAMERA = 'selfie-not-facing-camera', SELFIE_HOLD_STILL = 'selfie-hold-still', } export type InitialiseSelfieProps = { /** Called when the selfie is sent to the server for validation */ onServerValidationStarted: () => void; /** Called when the user hint changes */ onUserHintChange: (hint: SelfieUserHint) => void; /** Called when camera initialisation is ready */ onCameraReady?: () => void; /** * Automatically take picture of the user when correctly positioned in the frame * * @default false * @remarks Not supported supported in phase 1 */ useAutoCapture?: boolean; }; export type InitialiseSelfieScanResult = { /** React Component to render the camera feed */ component: React.JSX.Element; /** * Function start the selfie scan process and ML analysis * * resolves when the selfie is captured correctly * * rejects with: {@link SelfieError} if the step fails */ capture: () => Promise; /** * Stop sending or analyzing the viewport data with the ML algorithm. * This is normally not needed, but may be used to lower cpu usage if a overlay or redirect is used for a longer time * */ stopCapture: () => void; /** * Function to take a picture of the user when auto capture is disabled */ takePicture: () => Promise; }; /** * The different hints that can occur during the liveness check. It can either be an action that the user should * perform or a warning. */ export type LivenessUserHint = { type: 'action' | 'warning'; value: LivenessUserAction; }; /** * The different actions can be asked to perform during the liveness check. */ export enum LivenessUserAction { LOOK_STRAIGHT = 'look-straight', LOOK_UP = 'look-up', LOOK_DOWN = 'look-down', TURN_LEFT = 'turn-left', TURN_RIGHT = 'turn-right', CLOSE_EYES = 'close-eyes', SMILE = 'smile', /** * Hint that will be sent everytime a user has completed an action. This can be used * to give feedback when a user has completed an action. Next action will be sent * after 2 seconds. */ ACTION_COMPLETED = 'action-completed', } export type InitialiseLivenessScanProps = { /** Called when the stream to the backend liveness servers are started. For liveness this is at the start */ onServerValidationStarted: () => void; /** Called when the user hint changes */ onUserHintChange: (hint: LivenessUserHint) => void; /** Called when camera initialisation is ready */ onCameraReady?: () => void; }; export type InitialiseLivenessScanResult = { /** React Component to render the camera feed */ component: React.JSX.Element; /** * Function start the liveness scan process. * * The user can re-try the scan for the configured amount of times (normally 3). * * If the user fails more than the configured amount of times, the liveness will be stopped and the * InitialiseLivenessScanResult.capture will reject with a LivenessError * * resolves when the step is finished * * rejects with: {@link LivenessError} if the step fails */ capture: () => Promise; /** * Stop sending and analyzing the viewport data with the ML algorithm. * This is normally not needed, but may be used to lower cpu usage if a overlay or redirect is used for a longer time * */ stopCapture: () => void; }; /** * The different statuses that the final verification process can be in. */ export enum VerificationStatus { NOT_STARTED = 'not-started', PROCESSING = 'processing', APPROVED = 'approved', NEEDS_REVIEW = 'needs-review', DECLINED = 'declined', PENDING_VERIFICATION = 'pending-verification', } /** * This contains the result of the verification process. */ export type VerificationResult = { /** The unique ID of the verification */ id: string; /** The status of the verification */ status: VerificationStatus; // The API returns a lot of data, but we are only interested in the status for now }; export type SubmitForVerificationProps = { /** * Since the verification can take some time to be completed, it is possible to set a timeout of how long * the SDK should poll the backend before resolving the promise without a completed VerificationResult. * * Once the verification is completed, the result will be sent using a webhook or it can also be fetched * using the GetID API. */ timeoutInSeconds?: number; /** * Callback to listen to for when the processing is started and when the verification status changes. * * Initial status is `NOT_STARTED` */ onVerificationStatusChange: (status: VerificationStatus) => void; /** * Callback to listen to for when an application id is received. */ onApplicationIdChange: (applicationId: string) => void; }; /** * Possible errors that can occur during the document scan process. */ export enum GeneralErrorCode { NO_CAMERA_PERMISSION = 'no-camera-permission', NO_CAMERA_DEVICE = 'no-camera-device', INVALID_SDK_KEY = 'invalid-sdk-key', CUSTOMER_ID_EXISTS = 'customerid_exists', UNKNOWN_ERROR = 'unknown-error', } /** * Possible errors that can occur during the selfie process. */ export enum SelfieErrorCode { SELFIE_NO_FACE = 'selfie-no-face', SELFIE_MULTIPLE_FACES = 'selfie-multiple-faces', SELFIE_PASSIVE_LIVENESS_FAILED = 'selfie-passive-liveness-failed', } /** * If something goes wrong during the liveness scan, the fault will be one of these. * This indicates a failed liveness scan. */ export enum LivenessErrorCode { FACE_TOO_SMALL = 'face-too-small', /** User performs another action than the required */ WRONG_INSTRUCTION_ACTION = 'wrong-instruction-action', /** More than one face detected */ MULTIPLE_FACES = 'multiple-faces', /** User moves out of the frame */ NO_FACE = 'no-face', TIMEOUT = 'timeout', SESSION_ERROR = 'session-error', SLOW_CONNECTION = 'slow-connection', TOO_MANY_FRAMES = 'too-many-frames', SERVER_UNAVAILABLE = 'server-unavailable', }