import {z} from 'zod' export type CreateApiApiV2TokenArgs = {body: {clientId: string, tokenType: 'IDENTIFICATION' | 'DOCUMENT', externalRef?: (string | null) | undefined, generateDigitString?: boolean | undefined, expiryTime?: number | undefined, locale?: (string | null) | undefined, country?: (string | null) | undefined, sessionLength?: number | undefined, documents?: (Array | null) | undefined, firstName?: (string | null) | undefined, lastName?: (string | null) | undefined, dateOfBirth?: (string | null) | undefined, nationality?: (string | null) | undefined, documentNumber?: (string | null) | undefined, personalNumber?: (string | null) | undefined, sex?: ('M' | 'F' | null) | undefined, dateOfExpiry?: (string | null) | undefined, dateOfIssue?: (string | null) | undefined, address?: (string | null) | undefined, successUrl?: (string | null) | undefined, errorUrl?: (string | null) | undefined, unverifiedUrl?: (string | null) | undefined, callbackUrl?: (string | null) | undefined, showInstructions?: boolean | undefined, reviewSuccessful?: boolean | undefined, reviewFailed?: boolean | undefined, questionnaire?: (string | null) | undefined, questionnaireRequired?: boolean | undefined, riskAssessmentProfile?: (string | null) | undefined, theme?: (string | null) | undefined, registryCentersCountries?: (Array | null) | undefined, verifyEmail?: boolean | undefined, verifyPhone?: boolean | undefined, verifyBank?: boolean | undefined, verifyBankAccounts?: boolean | undefined, verifyBankBalances?: boolean | undefined, verifyBankTransactions?: boolean | undefined, bankCardVerification?: boolean | undefined, bankCardPdfUpload?: boolean | undefined, verifyAddress?: boolean | undefined, checkAml?: boolean | undefined, checkCriminal?: boolean | undefined, checkLiveness?: boolean | undefined, checkFaceBlacklist?: boolean | undefined, checkDocFaceBlacklist?: boolean | undefined, checkPersonBlacklist?: boolean | undefined, checkDuplicateFaces?: boolean | undefined, checkDuplicateDocFaces?: boolean | undefined, checkDuplicatePersonalData?: boolean | undefined, checkDriverLicense?: boolean | undefined, checkLid?: boolean | undefined, checkIpProxy?: boolean | undefined, allowBsnMasking?: boolean | undefined, nfcRequired?: boolean | undefined, autoAmlMonitoring?: boolean | undefined, driverLicenseBack?: boolean | undefined, faceMatchingThresholdModifier?: number | undefined, additionalSteps?: Record | undefined, additionalData?: Record | undefined, utilityBill?: (boolean | null) | undefined, nfcOptional?: boolean | undefined, ageLimit?: number | undefined, ageMax?: number | undefined}}; export type CreateApiApiV2TokenOptions = {baseUrl?: string | undefined, apiKeyPair?: {username: string, password: string} | undefined, fetch?: typeof fetch | undefined}; export const createApiApiV2TokenResponse = z.object({message: z.string().optional(), authToken: z.string(), redirectUrl: z.string().nullable().optional(), scanRef: z.string(), clientId: z.string().nullable().optional(), personScanRef: z.string().nullable().optional(), firstName: z.string().nullable().optional(), lastName: z.string().nullable().optional(), successUrl: z.string().nullable().optional(), errorUrl: z.string().nullable().optional(), unverifiedUrl: z.string().nullable().optional(), callbackUrl: z.string().nullable().optional(), locale: z.string().nullable().optional(), country: z.string().nullable().optional(), expiryTime: z.number().int().optional(), sessionLength: z.number().int().optional(), documents: z.array(z.string()).optional(), allowedDocuments: z.record(z.string(), z.array(z.string())).optional(), dateOfBirth: z.string().nullable().optional(), dateOfExpiry: z.string().nullable().optional(), dateOfIssue: z.string().nullable().optional(), nationality: z.string().nullable().optional(), personalNumber: z.string().nullable().optional(), documentNumber: z.string().nullable().optional(), sex: z.string().nullable().optional(), address: z.string().nullable().optional(), showInstructions: z.boolean().optional(), tokenType: z.enum(["IDENTIFICATION", "DOCUMENT"]), utilityBill: z.unknown(), additionalSteps: z.object({}).optional(), additionalData: z.object({}).optional(), externalRef: z.string().nullable().optional(), questionnaire: z.string().nullable().optional(), registryCentersCountries: z.array(z.string()).optional(), riskAssessmentProfile: z.string().nullable().optional(), theme: z.string().nullable().optional(), allowBsnMasking: z.boolean().optional(), verifyBankTransactions: z.boolean().optional(), bankCardVerification: z.boolean().optional(), bankCardPdfUpload: z.boolean().optional(), checkLid: z.boolean().optional(), checkDriverLicense: z.boolean().optional(), verifyAddress: z.boolean().optional(), checkFaceBlacklist: z.boolean().optional(), verifyEmail: z.boolean().optional(), checkPersonBlacklist: z.boolean().optional(), checkDuplicateDocFaces: z.boolean().optional(), reviewSuccessful: z.boolean().optional(), reviewFailed: z.boolean().optional(), verifyBank: z.boolean().optional(), autoAmlMonitoring: z.boolean().optional(), verifyPhone: z.boolean().optional(), faceMatchingThresholdModifier: z.number().optional(), checkCriminal: z.boolean().optional(), checkAml: z.boolean().optional(), checkDuplicateFaces: z.boolean().optional(), driverLicenseBack: z.boolean().optional(), verifyBankAccounts: z.boolean().optional(), checkDuplicatePersonalData: z.boolean().optional(), verifyBankBalances: z.boolean().optional(), nfcRequired: z.boolean().optional(), checkIpProxy: z.boolean().optional(), checkDocFaceBlacklist: z.boolean().optional(), checkLiveness: z.boolean().optional(), digitString: z.string().nullable().optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Generate KYC token * * POST /api/v2/token */ export const createApiApiV2Token = async (args: CreateApiApiV2TokenArgs, options?: CreateApiApiV2TokenOptions) => { const {baseUrl = "https://ivs.idenfy.com", fetch: fetchFn = fetch, apiKeyPair} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (apiKeyPair !== undefined) headers.set('authorization', `Basic ${btoa(`${apiKeyPair.username}:${apiKeyPair.password}`)}`) const url = `${baseUrl.replace(/\/+$/, '')}/api/v2/token${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(createApiApiV2TokenResponse, await res.json()) };