import {z} from 'zod' export type GetApiPlatformV2CustomersIdArgs = {id: string}; export type GetApiPlatformV2CustomersIdOptions = {baseUrl?: string | undefined, BearerAuth?: string | undefined, fetch?: typeof fetch | undefined}; export const v2AuthenticatedLinkResponse = z.object({link: z.string().optional(), expiresAt: z.string().optional()}); export const v2RequiredActionTargetAgreement = z.object({kind: z.literal("AGREEMENT").optional(), assignedAgreementId: z.string().optional(), urn: z.string().optional(), version: z.string().optional(), title: z.string().optional(), locale: z.string().optional()}); export const v2RequiredActionTargetDocument = z.object({kind: z.literal("DOCUMENT").optional(), docSetType: z.string().optional(), types: z.array(z.string()).optional(), subTypes: z.array(z.string()).optional(), associateId: z.string().optional()}); export const v2RequiredActionTargetField = z.object({kind: z.literal("FIELD").optional(), path: z.string().optional(), associateId: z.string().optional()}); export const v2RequiredAction = z.object({type: z.enum(["DATA", "USER_ROLE", "BLOCKER"]).optional(), code: z.string().optional(), category: z.string().optional(), description: z.string().optional(), status: z.enum(["REQUIRED", "PROCESSING"]).optional(), target: z.discriminatedUnion("kind", [v2RequiredActionTargetAgreement, v2RequiredActionTargetDocument, v2RequiredActionTargetField]).optional()}); export const v2RegulatorInformation = z.object({regulatorName: z.string().optional(), regulatorJurisdiction: z.string().optional(), regulatorRegisterNumber: z.string().optional()}); export const v2PublicInformation = z.object({listedExchange: z.string().optional(), tickerSymbol: z.string().optional()}); export const v2AssociatePerson = z.object({firstName: z.string(), lastName: z.string(), dateOfBirth: z.string(), nationality: z.string().min(2).max(2).optional(), secondNationality: z.string().min(2).max(2).optional(), birthCountryCode: z.string().min(2).max(2).optional(), address: z.object({addressLine1: z.string().max(255), addressLine2: z.string().max(255).optional(), city: z.string().max(255), postalCode: z.string().max(255), stateCode: z.string().min(2).max(2).optional(), countryCode: z.string().min(2).max(2)}), contactInfo: z.object({emailAddress: z.string().optional(), phoneNumber: z.string().optional()}).optional(), taxIdentification: z.object({number: z.string().max(255), taxResidenceCountryCode: z.string().min(2).max(2)}), position: z.string().max(255).optional(), estimatedYearlyIncome: z.enum(["INCOME_0_TO_50K", "INCOME_50K_TO_100K", "INCOME_100K_TO_250K", "INCOME_250K_TO_500K", "INCOME_500K_TO_750K", "INCOME_750K_TO_1M", "INCOME_ABOVE_1M"]).optional(), controlOptions: z.object({canAppointDirectors: z.boolean(), hasSignificantControl: z.boolean(), controlsManagement: z.boolean(), controlsCorporateBody: z.boolean()}).optional(), reliance: z.object({identityDocumentMetadata: z.object({type: z.enum(["PASSPORT", "ID_CARD", "DRIVERS", "RESIDENCE_PERMIT", "OTHER"]), number: z.string(), issueDate: z.string().optional(), expiryDate: z.string().optional(), issuingCountryCode: z.string().min(2).max(2), kycTimestamp: z.string()}).optional(), biometricLiveness: z.object({livenessTimestamp: z.string()}).optional(), addressVerification: z.object({type: z.enum(["DOC", "NON_DOC"])}), attestation: z.object({riskScore: z.enum(["LOW", "MEDIUM", "HIGH"]), eddCompleted: z.boolean()})}).optional()}); export const v2CorporateCustomerAssociate = z.object({id: z.string().optional(), person: v2AssociatePerson, titles: z.array(z.enum(["UBO", "BUSINESS_OWNER", "CONTROL_PERSON", "SIGNATORY", "DIRECTOR", "ACCOUNT_REPRESENTATIVE"])), ownership: z.object({percentage: z.string(), type: z.enum(["DIRECT", "INDIRECT"])}).optional()}); export const v2CompanyCustomerDueDiligence = z.object({intendedUseOfAccount: z.enum(["SUPPLIER_VENDOR_PAYMENTS", "INTERCOMPANY_TRANSFERS", "PAYROLL", "CUSTOMER_PAYMENTS_RECEIVED", "CUSTOMER_PAYOUTS_REFUNDS_SETTLEMENTS", "OPERATING_EXPENSES", "DIVIDEND_PROFIT_DISTRIBUTIONS", "LOAN_REPAYMENT_FINANCIAL_ACTIVITIES"]).optional(), pepStatus: z.enum(["NOT_PEP", "FORMER_PEP_2_YEARS", "FORMER_PEP_OLDER", "DOMESTIC_PEP", "FOREIGN_PEP", "CLOSE_ASSOCIATES", "FAMILY_MEMBERS", "STATE_OWNED"]).optional(), expectedMonthlyVolume: z.object({amount: z.number().gte(0), currency: z.enum(["USD", "EUR"]).optional()}).optional()}); export const v2CompanyRelianceMetadata = z.object({attestation: z.object({riskScore: z.enum(["LOW", "MEDIUM", "HIGH"]), eddCompleted: z.boolean()})}); export const v2CreateCompanyRequest = z.object({name: z.string().max(255), entityType: z.enum(["CORPORATION", "LIMITED_LIABILITY_COMPANY", "PUBLICLY_LISTED_COMPANY", "SOLE_PROPRIETOR", "PARTNERSHIP", "TRUST"]), taxIdentification: z.object({number: z.string().max(255), taxResidenceCountryCode: z.string().min(2).max(2)}).optional(), registrationNumber: z.string().min(5).max(20), businessProfile: z.object({description: z.string().max(255).optional(), naicsCode: z.string().min(2).max(36), monthlyExpectedVolumes: z.enum(["FROM_0_TO_10K", "FROM_10K_TO_50K", "FROM_50K_TO_100K", "FROM_100K_TO_1M", "FROM_1M_TO_10M", "ABOVE_10M"]), website: z.string().max(255).optional(), websiteExplanation: z.string().min(10).max(500).optional(), isRegulated: z.boolean().optional(), regulatorInformation: v2RegulatorInformation.optional(), isPubliclyListed: z.boolean().optional(), publicInformation: v2PublicInformation.optional(), sourceOfFunds: z.enum(["COMMERCIAL_ACTIVITIES", "SHAREHOLDER_CAPITAL", "VENTURE_CAPITAL", "SALE_OF_ASSETS", "CRYPTO_FUNDRAISING", "CRYPTO_TRADING_REVENUE", "CORPORATE_LOANS", "SALARY", "PENSION", "SAVINGS", "SELF_EMPLOYMENT", "GAMBLING", "REAL_ESTATE", "OTHER"]).optional(), intendedUseOfAccount: z.enum(["SUPPLIER_VENDOR_PAYMENTS", "INTERCOMPANY_TRANSFERS", "PAYROLL", "CUSTOMER_PAYMENTS_RECEIVED", "CUSTOMER_PAYOUTS_REFUNDS_SETTLEMENTS", "OPERATING_EXPENSES", "DIVIDEND_PROFIT_DISTRIBUTIONS", "LOAN_REPAYMENT_FINANCIAL_ACTIVITIES"]).optional()}), address: z.object({addressLine1: z.string().max(255), addressLine2: z.string().max(255).optional(), city: z.string().max(255), postalCode: z.string().max(255), stateCode: z.string().min(2).max(2).optional(), countryCode: z.string().min(2).max(2)}), isOperationalAddressDifferent: z.boolean().optional(), operationalAddress: z.object({addressLine1: z.string().max(255).optional(), addressLine2: z.string().max(255).optional(), city: z.string().max(255).optional(), postalCode: z.string().max(255).optional(), stateCode: z.string().min(2).max(2).optional(), countryCode: z.string().min(2).max(2).optional()}).optional(), incorporationDate: z.string(), associates: z.array(v2CorporateCustomerAssociate).optional(), cdd: v2CompanyCustomerDueDiligence.optional(), reliance: v2CompanyRelianceMetadata.optional()}); export const v2IndividualDocumentInfo = z.object({number: z.string().max(255).optional(), type: z.enum(["PASSPORT", "ID_CARD", "DRIVERS", "RESIDENCE_PERMIT", "OTHER"]).optional(), issuingCountryCode: z.string().min(2).max(2).optional()}); export const v2PersonRelianceMetadata = z.object({identityDocumentMetadata: z.object({type: z.enum(["PASSPORT", "ID_CARD", "DRIVERS", "RESIDENCE_PERMIT", "OTHER"]), number: z.string(), issueDate: z.string().optional(), expiryDate: z.string().optional(), issuingCountryCode: z.string().min(2).max(2), kycTimestamp: z.string()}).optional(), biometricLiveness: z.object({livenessTimestamp: z.string()}).optional(), addressVerification: z.object({type: z.enum(["DOC", "NON_DOC"])}), attestation: z.object({riskScore: z.enum(["LOW", "MEDIUM", "HIGH"]), eddCompleted: z.boolean()})}); export const v2CreateIndividualRequest = z.object({firstName: z.string().max(255), lastName: z.string().max(255), emailAddress: z.string().max(255), phoneNumber: z.string().max(255).optional(), description: z.string().max(255).optional(), dateOfBirth: z.string(), placeOfBirth: z.string().max(255).optional(), birthCountryCode: z.string().min(2).max(2).optional(), nationality: z.string().min(2).max(2).optional(), documentNumber: z.string().min(5).max(20).optional(), documentInfo: v2IndividualDocumentInfo.optional(), address: z.object({addressLine1: z.string().max(255), addressLine2: z.string().max(255).optional(), city: z.string().max(255), postalCode: z.string().max(255), stateCode: z.string().min(2).max(2).optional(), countryCode: z.string().min(2).max(2)}), taxIdentification: z.object({number: z.string().max(255), taxResidenceCountryCode: z.string().min(2).max(2)}), cdd: z.object({employmentStatus: z.enum(["SALARIED", "SELF_EMPLOYED", "UNEMPLOYED", "RETIRED", "STUDENT", "NOT_PROVIDED"]).optional(), sourceOfFunds: z.enum(["SALARY", "PENSION", "SAVINGS", "SELF_EMPLOYMENT", "CRYPTO_TRADING", "GAMBLING", "REAL_ESTATE", "GIFT", "STUDENT_LOAN_GRANT"]).optional(), pepStatus: z.enum(["NOT_PEP", "FORMER_PEP_2_YEARS", "FORMER_PEP_OLDER", "DOMESTIC_PEP", "FOREIGN_PEP", "CLOSE_ASSOCIATES", "FAMILY_MEMBERS", "STATE_OWNED"]).optional(), intendedUseOfAccount: z.enum(["TRANSFERS_OWN_WALLET", "TRANSFERS_FAMILY_FRIENDS", "INVESTMENTS", "GOODS_SERVICES", "DONATIONS"]).optional(), expectedMonthlyVolume: z.object({amount: z.number().gte(0), currency: z.enum(["USD", "EUR"]).optional()}).optional(), estimatedYearlyIncome: z.enum(["INCOME_0_TO_50K", "INCOME_50K_TO_100K", "INCOME_100K_TO_250K", "INCOME_250K_TO_500K", "INCOME_500K_TO_750K", "INCOME_750K_TO_1M", "INCOME_ABOVE_1M"]).optional(), employmentIndustrySector: z.enum(["INVESTMENT", "HEDGE_FUND", "MONEY_SERVICE_BUSINESS", "STO_ISSUER", "PRECIOUS_METALS", "NON_PROFIT", "REGISTERED_INVESTMENT_ADVISOR", "AGRICULTURE_FORESTRY_FISHING_HUNTING", "MINING", "UTILITIES", "CONSTRUCTION", "MANUFACTURING", "WHOLESALE_TRADE", "RETAIL_TRADE", "TRANSPORTATION_WAREHOUSING", "INFORMATION", "FINANCE_INSURANCE", "REAL_ESTATE_RENTAL_LEASING", "PROFESSIONAL_SCIENTIFIC_TECHNICAL_SERVICES", "MANAGEMENT_OF_COMPANIES_ENTERPRISES", "ADMINISTRATIVE_SUPPORT_WASTE_MANAGEMENT_REMEDIATION_SERVICES", "EDUCATIONAL_SERVICES", "HEALTH_CARE_SOCIAL_ASSISTANCE", "ARTS_ENTERTAINMENT_RECREATION", "ACCOMMODATION_FOOD_SERVICES", "OTHER_SERVICES", "PUBLIC_ADMINISTRATION", "NOT_CLASSIFIED", "ADULT_ENTERTAINMENT", "AUCTIONS", "AUTOMOBILES", "BLOCKCHAIN", "CRYPTO", "DRUGS", "EXPORT_IMPORT", "E_COMMERCE", "FINANCIAL_INSTITUTION", "GAMBLING", "INSURANCE", "MARKET_MAKER", "SHELL_BANK", "TRAVEL_TRANSPORT", "WEAPONS"]).optional()}).optional(), reliance: v2PersonRelianceMetadata.optional()}); export const v2CustomerDetailResponse = z.object({id: z.string().optional(), reference: z.string().optional(), status: z.enum(["AGREEMENTS_PENDING", "INFO_REQUIRED", "PENDING", "ACTIONS_REQUIRED", "VERIFIED", "REJECTED", "TERMINATED"]).optional(), type: z.enum(["COMPANY", "INDIVIDUAL"]).optional(), model: z.enum(["EMBEDDED", "RELIANCE"]).optional(), useCase: z.enum(["FIAT", "CRYPTO", "STABLECOIN_PAYOUTS", "EMBEDDED_STABLECOIN_WALLETS", "EMBEDDED_FIAT_ACCOUNTS"]).optional(), name: z.string().optional(), createdAt: z.string().optional(), updatedAt: z.string().optional(), authenticatedLink: v2AuthenticatedLinkResponse.optional(), verificationLink: z.string().optional(), requiredActions: z.array(v2RequiredAction).optional(), company: v2CreateCompanyRequest.optional(), individual: v2CreateIndividualRequest.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 }; /** * Get customer * * GET /platform/v2/customers/{id} */ export const getApiPlatformV2CustomersId = async (args: GetApiPlatformV2CustomersIdArgs, options?: GetApiPlatformV2CustomersIdOptions) => { const {baseUrl = "https://api.sandbox.bvnk.com", fetch: fetchFn = fetch, BearerAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (BearerAuth !== undefined) headers.set('authorization', `Bearer ${BearerAuth}`) const url = `${baseUrl.replace(/\/+$/, '')}/platform/v2/customers/${encodeURIComponent(String(args.id))}${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(v2CustomerDetailResponse, await res.json()) };