import {z} from 'zod' export type CreateAssociatedPersonRequest = {relationships: Array<'BENEFICIAL_OWNER' | 'CONTROL_PERSON'>}; export type CreateApiApiComplianceOrganizationIdAssociatedPersonsArgs = {organizationId: string, body: CreateAssociatedPersonRequest}; export type CreateApiApiComplianceOrganizationIdAssociatedPersonsOptions = {baseUrl?: string | undefined, bearer?: string | undefined, fetch?: typeof fetch | undefined}; export const associatedPersonAttestationRequirement = z.object({attestationType: z.enum(["associatedPersonPersonalInfo", "associatedPersonContactInfo", "associatedPersonResidentialAddress", "associatedPersonTaxInfo", "associatedPersonIdentityDocument", "associatedPersonProofOfAddress", "associatedPersonEeaInfo", "associatedPersonProofOfSignatoryAuthority"])}); 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 associatedPersonAttestationSummary = z.object({attestationType: z.enum(["associatedPersonPersonalInfo", "associatedPersonContactInfo", "associatedPersonResidentialAddress", "associatedPersonTaxInfo", "associatedPersonIdentityDocument", "associatedPersonProofOfAddress", "associatedPersonEeaInfo", "associatedPersonProofOfSignatoryAuthority"]), id: z.string(), validationStatus: z.discriminatedUnion("type", [attestationValidationStatusPending, attestationValidationStatusApproved, attestationValidationStatusFailed])}); export const associatedPersonResource = z.object({associatedPersonId: z.string(), relationships: z.array(z.enum(["BENEFICIAL_OWNER", "CONTROL_PERSON"])), createdAt: z.string(), updatedAt: z.string(), requiredAttestations: z.array(associatedPersonAttestationRequirement).optional(), uploadedAttestations: z.array(associatedPersonAttestationSummary)}); 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 }; /** * Create an associated person * * POST /api/compliance/{organizationId}/associated-persons */ export const createApiApiComplianceOrganizationIdAssociatedPersons = async (args: CreateApiApiComplianceOrganizationIdAssociatedPersonsArgs, options?: CreateApiApiComplianceOrganizationIdAssociatedPersonsOptions) => { 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${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(associatedPersonResource, await res.json()) };