import {z} from 'zod' export type IndividualName = {firstName: string, lastName: string, middleName?: string | undefined}; export type AssociatedPersonPersonalInfoAttestation = {type: 'associatedPersonPersonalInfo', name: IndividualName, birthDate: string, nationality: string, isPoliticallyExposed?: boolean | undefined, jobTitle: string, ownershipPercentage: number}; export type AssociatedPersonContactInfoAttestation = {type: 'associatedPersonContactInfo', email: string, phoneNumber: string}; export type PhysicalAddressVerification = {address1: string, address2?: string | undefined, city: string, country: string, postalCode: string, subDivision: string}; export type AssociatedPersonResidentialAddressAttestation = {type: 'associatedPersonResidentialAddress', address: PhysicalAddressVerification}; export type AssociatedPersonTaxInfoAttestation = {type: 'associatedPersonTaxInfo', taxIdentificationNumber: string, taxIdentificationNumberType: 'SSN' | 'ITIN' | 'CPF' | 'CURP' | 'CUIL' | 'NINO' | 'INE' | 'RFC' | 'NIF' | 'STEUER_ID' | 'TCKN' | 'TIN' | 'PAN' | 'ADOAZ' | 'AHV' | 'AOM' | 'BSN' | 'BVN' | 'CDI' | 'CNP' | 'CPR' | 'EGN' | 'EMIRATES_ID' | 'EMSO' | 'FIN' | 'FN' | 'FODSELSNR' | 'HETU' | 'HKID' | 'IDNP' | 'IIN' | 'IK' | 'ITR' | 'JMBG' | 'MN' | 'NIN' | 'NRIC' | 'NRN' | 'PERSONNUMMER' | 'PESEL' | 'PIN' | 'PINFL' | 'PPSN' | 'RICN' | 'RNOKPP' | 'RODNE_CISLO' | 'RP' | 'RRN' | 'SI' | 'SIN' | 'SPI' | 'TFN' | 'UCN' | 'UTR' | 'BIR' | 'BIN' | 'BP' | 'CF' | 'CN' | 'CRIB' | 'CUI' | 'CUIT' | 'ID' | 'ID_BROJ' | 'IDNO' | 'IF' | 'INN' | 'IRD' | 'MATRICULE' | 'MST' | 'NIT' | 'NPWP' | 'NRT' | 'NTN' | 'OIB' | 'PIB' | 'RC' | 'RIF' | 'RN' | 'RTN' | 'RUC' | 'RUT' | 'TRN' | 'UNP' | 'USC' | 'VAT' | 'VOEN'}; export type AssociatedPersonIdentityDocumentAttestation = {type: 'associatedPersonIdentityDocument', governmentId: {countryCode: string, passportDocumentId: string, passportNumber: string, type: 'passport'} | {countryCode: string, driverLicenseBackDocumentId: string, driverLicenseFrontDocumentId: string, driverLicenseNumber: string, type: 'driverLicense'} | {cnhBackDocumentId?: string | undefined, cnhFrontDocumentId: string, cnhNumber: string, type: 'cnh'} | {countryCode: string, nationalIdBackDocumentId: string, nationalIdFrontDocumentId: string, nationalIdNumber: string, type: 'nationalId'} | {countryCode: string, stateIdBackDocumentId: string, stateIdFrontDocumentId: string, stateIdNumber: string, type: 'stateId'} | {countryCode: string, passportCardBackDocumentId: string, passportCardFrontDocumentId: string, passportCardNumber: string, type: 'passportCard'} | {countryCode: string, permanentResidenceCardBackDocumentId: string, permanentResidenceCardFrontDocumentId: string, permanentResidenceCardNumber: string, type: 'permanentResidenceCard'} | {countryCode: string, type: 'visa', visaBackDocumentId: string, visaFrontDocumentId: string, visaNumber: string} | {countryCode: string, residencePermitBackDocumentId: string, residencePermitFrontDocumentId: string, residencePermitNumber: string, type: 'residencePermit'} | {citizenshipCertificateDocumentId: string, citizenshipCertificateNumber: string, countryCode: string, type: 'citizenshipCertificate'} | {consularIdBackDocumentId: string, consularIdFrontDocumentId: string, consularIdNumber: string, countryCode: string, type: 'consularId'} | {countryCode: string, foreignIdBackDocumentId: string, foreignIdFrontDocumentId: string, foreignIdNumber: string, type: 'foreignId'} | {countryCode: string, healthInsuranceCardBackDocumentId: string, healthInsuranceCardFrontDocumentId: string, healthInsuranceCardNumber: string, type: 'healthInsuranceCard'} | {countryCode: string, internalPassportDocumentId: string, internalPassportNumber: string, type: 'internalPassport'} | {countryCode: string, keypassIdBackDocumentId: string, keypassIdFrontDocumentId: string, keypassIdNumber: string, type: 'keypassId'} | {countryCode: string, longTermPassBackDocumentId: string, longTermPassFrontDocumentId: string, longTermPassNumber: string, type: 'longTermPass'} | {countryCode: string, municipalIdBackDocumentId: string, municipalIdFrontDocumentId: string, municipalIdNumber: string, type: 'municipalId'} | {countryCode: string, myNumberCardBackDocumentId: string, myNumberCardFrontDocumentId: string, myNumberCardNumber: string, type: 'myNumberCard'} | {countryCode: string, nbiClearanceDocumentId: string, nbiClearanceNumber: string, type: 'nbiClearance'} | {countryCode: string, ofwIdBackDocumentId: string, ofwIdFrontDocumentId: string, ofwIdNumber: string, type: 'ofwId'} | {countryCode: string, panCardDocumentId: string, panCardNumber: string, type: 'panCard'} | {countryCode: string, postalIdBackDocumentId: string, postalIdFrontDocumentId: string, postalIdNumber: string, type: 'postalId'} | {countryCode: string, sssIdBackDocumentId: string, sssIdFrontDocumentId: string, sssIdNumber: string, type: 'sssId'} | {countryCode: string, travelDocumentDocumentId: string, travelDocumentNumber: string, type: 'travelDocument'} | {countryCode: string, tribalIdBackDocumentId: string, tribalIdFrontDocumentId: string, tribalIdNumber: string, type: 'tribalId'} | {countryCode: string, type: 'umid', umidBackDocumentId: string, umidFrontDocumentId: string, umidNumber: string} | {countryCode: string, type: 'voterId', voterIdBackDocumentId: string, voterIdFrontDocumentId: string, voterIdNumber: string} | {countryCode: string, type: 'workPermit', workPermitBackDocumentId: string, workPermitFrontDocumentId: string, workPermitNumber: string}}; export type ProofOfAddressDocumentReference = {documentType: 'BANK_STATEMENT' | 'GOVERNMENT_ISSUED_LETTER' | 'UTILITY_BILL', documentId: string}; export type AssociatedPersonProofOfAddressAttestation = {type: 'associatedPersonProofOfAddress', proofOfAddressDocuments: Array}; export type AssociatedPersonEEAInfoAttestation = {type: 'associatedPersonEeaInfo', isDirector: boolean, placeOfBirthCountry: string, placeOfBirthCity: string}; export type SignatoryAuthorityDocumentReference = {documentType: 'LETTER_OF_AUTHORITY' | 'BOARD_RESOLUTION' | 'POWER_OF_ATTORNEY', documentId: string}; export type AssociatedPersonProofOfSignatoryAuthorityAttestation = {type: 'associatedPersonProofOfSignatoryAuthority', signatoryAuthorityDocuments: Array}; export type UploadAssociatedPersonAttestationsRequest = {attestations: Array}; export type UpdateApiApiComplianceOrganizationIdAssociatedPersonsAssociatedPersonIdAttestationsArgs = {organizationId: string, associatedPersonId: string, body: UploadAssociatedPersonAttestationsRequest}; export type UpdateApiApiComplianceOrganizationIdAssociatedPersonsAssociatedPersonIdAttestationsOptions = {baseUrl?: string | undefined, bearer?: string | undefined, fetch?: typeof fetch | undefined}; export const attestationValidationStatusPending = z.object({type: z.literal("pending")}); export const attestationValidationStatusApproved = z.object({type: z.literal("approved")}); export const addressNotFoundFailureInfo = z.object({type: z.literal("addressNotFound"), failureCode: z.literal("ADDRESS_NOT_FOUND"), description: z.string().optional()}); export const physicalAddressVerification = z.object({address1: z.string(), address2: z.string().optional(), city: z.string(), country: z.string(), postalCode: z.string(), subDivision: z.string()}); export const addressSuggestedCorrectionFailureInfo = z.object({type: z.literal("addressSuggestedCorrection"), failureCode: z.literal("ADDRESS_SUGGESTED_CORRECTION"), description: z.string().optional(), submittedAddress: physicalAddressVerification, suggestedAddress: physicalAddressVerification}); export const generalFailureInfo = z.object({type: z.literal("general"), failureCode: z.enum(["INCORRECT_DOCUMENT", "POOR_QUALITY", "MISSING_INFORMATION", "INCONSISTENT_DATA", "EXPIRED_DOCUMENT", "OTHER"]), description: z.string().optional()}); export const governmentIdFailureInfo = z.object({type: z.literal("governmentId"), governmentIdFailure: z.discriminatedUnion("type", [z.object({type: z.literal("minimumAgeNotMet"), description: z.string().optional()}), z.object({type: z.literal("documentAuthenticityCheckFailed"), description: z.string().optional()}), z.object({type: z.literal("documentCopyNotAccepted"), description: z.string().optional()}), z.object({type: z.literal("documentTypeNotAccepted"), description: z.string().optional(), selectedDocumentType: z.enum(["PASSPORT", "PASSPORT_CARD", "DRIVER_LICENSE", "STATE_ID", "PERMANENT_RESIDENCE_CARD", "VISA", "NATIONAL_ID", "RESIDENCE_PERMIT", "VOTER_ID", "CITIZENSHIP_CERTIFICATE", "HEALTH_INSURANCE_CARD", "WORK_PERMIT", "CONSULAR_ID", "FOREIGN_ID", "MY_NUMBER_CARD", "PAN_CARD", "LONG_TERM_PASS", "NBI_CLEARANCE", "OFW_ID", "POSTAL_ID", "SSS_ID", "UMID", "MUNICIPAL_ID", "TRAVEL_DOCUMENT", "INTERNAL_PASSPORT", "TRIBAL_ID", "KEYPASS_ID", "CNH"]).optional(), detectedDocumentType: z.enum(["PASSPORT", "PASSPORT_CARD", "DRIVER_LICENSE", "STATE_ID", "PERMANENT_RESIDENCE_CARD", "VISA", "NATIONAL_ID", "RESIDENCE_PERMIT", "VOTER_ID", "CITIZENSHIP_CERTIFICATE", "HEALTH_INSURANCE_CARD", "WORK_PERMIT", "CONSULAR_ID", "FOREIGN_ID", "MY_NUMBER_CARD", "PAN_CARD", "LONG_TERM_PASS", "NBI_CLEARANCE", "OFW_ID", "POSTAL_ID", "SSS_ID", "UMID", "MUNICIPAL_ID", "TRAVEL_DOCUMENT", "INTERNAL_PASSPORT", "TRIBAL_ID", "KEYPASS_ID", "CNH"]).optional(), detectedCountryCode: z.string().optional(), outOfCirculation: z.boolean().optional()}), z.object({type: z.literal("documentCountryNotAccepted"), description: z.string().optional(), detectedCountryCode: z.string().optional(), selectedCountryCode: z.string().optional()}), z.object({type: z.literal("documentExpiredOrDamaged"), description: z.string().optional(), expirationDate: z.string().optional()}), z.object({type: z.literal("documentDataMismatch"), description: z.string().optional()}), z.object({type: z.literal("documentSideMissing"), description: z.string().optional()}), z.object({type: z.literal("documentUnreadable"), description: z.string().optional()}), z.object({type: z.literal("documentVerificationFailed"), description: z.string().optional()})])}); export const proofOfAddressFailureInfo = z.object({type: z.literal("proofOfAddress"), documentId: z.string().optional(), proofOfAddressFailure: z.discriminatedUnion("type", [z.object({type: z.literal("proofOfAddressAuthenticityCheckFailed"), description: z.string().optional()}), z.object({type: z.literal("proofOfAddressTypeNotAccepted"), description: z.string().optional()}), z.object({type: z.literal("proofOfAddressExpiredOrDamaged"), description: z.string().optional()}), z.object({type: z.literal("proofOfAddressDataMismatch"), description: z.string().optional()}), z.object({type: z.literal("proofOfAddressUnreadable"), description: z.string().optional()}), z.object({type: z.literal("proofOfAddressVerificationFailed"), description: z.string().optional()})])}); export const sourceOfFundsFailureInfo = z.object({type: z.literal("sourceOfFunds"), documentId: z.string().optional(), sourceOfFundsFailure: z.discriminatedUnion("type", [z.object({type: z.literal("sourceOfFundsAuthenticityCheckFailed"), description: z.string().optional()}), z.object({type: z.literal("sourceOfFundsTypeNotAccepted"), description: z.string().optional()}), z.object({type: z.literal("sourceOfFundsExpiredOrDamaged"), description: z.string().optional()}), z.object({type: z.literal("sourceOfFundsDataMismatch"), description: z.string().optional()}), z.object({type: z.literal("sourceOfFundsUnreadable"), description: z.string().optional()}), z.object({type: z.literal("sourceOfFundsVerificationFailed"), description: z.string().optional()})])}); export const formationDocumentsFailureInfo = z.object({type: z.literal("formationDocuments"), documentId: z.string().optional(), formationDocumentsFailure: z.discriminatedUnion("type", [z.object({type: z.literal("formationDocumentsAuthenticityCheckFailed"), description: z.string().optional()}), z.object({type: z.literal("formationDocumentsTypeNotAccepted"), description: z.string().optional()}), z.object({type: z.literal("formationDocumentsExpiredOrDamaged"), description: z.string().optional()}), z.object({type: z.literal("formationDocumentsDataMismatch"), description: z.string().optional()}), z.object({type: z.literal("formationDocumentsUnreadable"), description: z.string().optional()}), z.object({type: z.literal("formationDocumentsVerificationFailed"), description: z.string().optional()})])}); export const uboOwnershipFailureInfo = z.object({type: z.literal("uboOwnership"), documentId: z.string().optional(), uboOwnershipFailure: z.discriminatedUnion("type", [z.object({type: z.literal("uboOwnershipAuthenticityCheckFailed"), description: z.string().optional()}), z.object({type: z.literal("uboOwnershipTypeNotAccepted"), description: z.string().optional()}), z.object({type: z.literal("uboOwnershipExpiredOrDamaged"), description: z.string().optional()}), z.object({type: z.literal("uboOwnershipDataMismatch"), description: z.string().optional()}), z.object({type: z.literal("uboOwnershipUnreadable"), description: z.string().optional()}), z.object({type: z.literal("uboOwnershipVerificationFailed"), description: z.string().optional()})])}); export const flowOfFundsFailureInfo = z.object({type: z.literal("flowOfFunds"), documentId: z.string().optional(), flowOfFundsFailure: z.discriminatedUnion("type", [z.object({type: z.literal("flowOfFundsAuthenticityCheckFailed"), description: z.string().optional()}), z.object({type: z.literal("flowOfFundsTypeNotAccepted"), description: z.string().optional()}), z.object({type: z.literal("flowOfFundsExpiredOrDamaged"), description: z.string().optional()}), z.object({type: z.literal("flowOfFundsDataMismatch"), description: z.string().optional()}), z.object({type: z.literal("flowOfFundsUnreadable"), description: z.string().optional()}), z.object({type: z.literal("flowOfFundsVerificationFailed"), description: z.string().optional()})])}); export const proofOfSignatoryAuthorityFailureInfo = z.object({type: z.literal("proofOfSignatoryAuthority"), documentId: z.string().optional(), proofOfSignatoryAuthorityFailure: z.discriminatedUnion("type", [z.object({type: z.literal("proofOfSignatoryAuthorityAuthenticityCheckFailed"), description: z.string().optional()}), z.object({type: z.literal("proofOfSignatoryAuthorityTypeNotAccepted"), description: z.string().optional()}), z.object({type: z.literal("proofOfSignatoryAuthorityExpiredOrDamaged"), description: z.string().optional()}), z.object({type: z.literal("proofOfSignatoryAuthorityDataMismatch"), description: z.string().optional()}), z.object({type: z.literal("proofOfSignatoryAuthorityUnreadable"), description: z.string().optional()}), z.object({type: z.literal("proofOfSignatoryAuthorityVerificationFailed"), description: z.string().optional()})])}); export const supplementalDocumentFailureInfo = z.object({type: z.literal("supplementalDocument"), documentId: z.string().optional(), supplementalDocumentFailure: z.discriminatedUnion("type", [z.object({type: z.literal("supplementalDocumentAuthenticityCheckFailed"), description: z.string().optional()}), z.object({type: z.literal("supplementalDocumentTypeNotAccepted"), description: z.string().optional()}), z.object({type: z.literal("supplementalDocumentExpiredOrDamaged"), description: z.string().optional()}), z.object({type: z.literal("supplementalDocumentDataMismatch"), description: z.string().optional()}), z.object({type: z.literal("supplementalDocumentUnreadable"), description: z.string().optional()}), z.object({type: z.literal("supplementalDocumentVerificationFailed"), description: z.string().optional()})])}); export const attestationValidationFailure = z.object({failureInfo: z.discriminatedUnion("type", [addressNotFoundFailureInfo, addressSuggestedCorrectionFailureInfo, generalFailureInfo, governmentIdFailureInfo, proofOfAddressFailureInfo, sourceOfFundsFailureInfo, formationDocumentsFailureInfo, uboOwnershipFailureInfo, flowOfFundsFailureInfo, proofOfSignatoryAuthorityFailureInfo, supplementalDocumentFailureInfo]), field: z.enum(["address", "residentialAddress", "registeredAddress", "operatingAddress"]).optional(), severity: z.enum(["BLOCKING", "WARNING"])}); export const attestationValidationStatusFailed = z.object({failures: z.array(attestationValidationFailure), type: z.literal("failed")}); export const associatedPersonAttestationResponse = z.object({attestationType: z.enum(["associatedPersonPersonalInfo", "associatedPersonContactInfo", "associatedPersonResidentialAddress", "associatedPersonTaxInfo", "associatedPersonIdentityDocument", "associatedPersonProofOfAddress", "associatedPersonEeaInfo", "associatedPersonProofOfSignatoryAuthority"]), createdAt: z.string(), id: z.string(), validationStatus: z.discriminatedUnion("type", [attestationValidationStatusPending, attestationValidationStatusApproved, attestationValidationStatusFailed])}); export const uploadAssociatedPersonAttestationsResponse = z.object({attestations: z.array(associatedPersonAttestationResponse)}); 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 }; /** * Upload attestations for an associated person * * PUT /api/compliance/{organizationId}/associated-persons/{associatedPersonId}/attestations */ export const updateApiApiComplianceOrganizationIdAssociatedPersonsAssociatedPersonIdAttestations = async (args: UpdateApiApiComplianceOrganizationIdAssociatedPersonsAssociatedPersonIdAttestationsArgs, options?: UpdateApiApiComplianceOrganizationIdAssociatedPersonsAssociatedPersonIdAttestationsOptions) => { const {baseUrl = "https://api.muralpay.com", fetch: fetchFn = fetch, bearer} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (bearer !== undefined) headers.set('authorization', `Bearer ${bearer}`) const url = `${baseUrl.replace(/\/+$/, '')}/api/compliance/${encodeURIComponent(String(args.organizationId))}/associated-persons/${encodeURIComponent(String(args.associatedPersonId))}/attestations${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "PUT", 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(uploadAssociatedPersonAttestationsResponse, await res.json()) };