import {z} from 'zod' export type CustomerOnboardingAddress = {addressLine1: string, city: string, postalCode: string, countryCode: string, stateCode?: string | undefined}; export type CustomerOnboardingJurisdictionDistribution = {country: string, percentage: number}; export type CustomerOnboardingBusinessProfile = {description: string, naicsCode: string, monthlyExpectedVolumes: 'UNDER_100K' | 'FROM_100K_TO_1M' | 'FROM_1M_TO_10M' | 'FROM_10M_TO_100M' | 'OVER_100M', website: string, customerTypes: 'Both' | 'Individuals' | 'Businesses', prohibitedJurisdictionsExposure: boolean, annualIncomingTransactionValue: string, annualOutgoingTransactionValue: string, jurisdictionalPortfolioDistribution: Array, isRegulated: boolean, sourceOfFunds: 'COMMERCIAL_ACTIVITIES' | 'SHAREHOLDER_CAPITAL' | 'VENTURE_CAPITAL' | 'SALE_OF_ASSETS' | 'CRYPTO_FUNDRAISING' | 'CRYPTO_TRADING_REVENUE' | 'CORPORATE_LOANS' | 'OTHER', intendedUseOfAccount: 'SUPPLIER_VENDOR_PAYMENTS' | 'INTERCOMPANY_TRANSFER' | 'PAYROLL' | 'CUSTOMER_PAYMENTS_RECEIVED' | 'CUSTOMER_PAYOUTS_REFUNDS_SETTLEMENTS' | 'OPERATING_EXPENSES' | 'DIVIDEND_PROFIT_DISTRIBUTIONS' | 'LOAN_REPAYMENT_FINANCIAL_ACTIVITIES'}; export type CustomerOnboardingTaxIdentification = {number?: string | undefined, taxResidenceCountryCode?: string | undefined}; export type CustomerOnboardingAssociatePerson = {firstName: string, lastName: string, dateOfBirth: string, nationality?: string | undefined, birthCountryCode?: string | undefined, address: CustomerOnboardingAddress, contactInfo: {emailAddress: string}, taxIdentification?: CustomerOnboardingTaxIdentification | undefined, position: string}; export type CustomerOnboardingOwnership = {percentage?: number | undefined, type?: ('DIRECT' | 'INDIRECT') | undefined}; export type CustomerOnboardingAssociate = {person: CustomerOnboardingAssociatePerson, titles: Array<'BUSINESS_OWNER' | 'DIRECTOR' | 'SIGNATORY' | 'ACCOUNT_REPRESENTATIVE'>, ownership?: CustomerOnboardingOwnership | undefined}; export type CustomerOnboardingCompany = {name: string, entityType: 'CORPORATION' | 'LIMITED_LIABILITY_COMPANY' | 'PUBLICLY_LISTED_COMPANY' | 'SOLE_PROPRIETOR' | 'PARTNERSHIP' | 'TRUST' | 'PRIVATE_FOUNDATION' | 'CHARITY' | 'NON_PROFIT_ORGANIZATION' | 'PUBLIC_AGENCIES_OR_AUTHORITIES' | 'OTHER', taxNumber: string, registrationNumber: string, incorporationDate: string, address: CustomerOnboardingAddress, businessProfile: CustomerOnboardingBusinessProfile, associates: Array}; export type CreateCorporateRiskScore = 'LOW' | 'MEDIUM' | 'HIGH'; export type RelianceAttestation = {riskScore: CreateCorporateRiskScore, eddCompleted: boolean}; export type Reliance = {identityDocumentMetadata: {type: 'PASSPORT' | 'ID_CARD' | 'DRIVERS' | 'RESIDENCE_PERMIT' | 'OTHER', number: string, expiryDate?: string | undefined, issueDate?: string | undefined, issuingCountryCode: string, kycTimestamp: string}, biometricLiveness: {livenessTimestamp: string}, addressVerification: {type: 'DOC' | 'NON_DOC'}}; export type EmbeddedPartnerCustomerOnboardingPayload = {partnerAccountReference: string, company: CustomerOnboardingCompany, useCase: 'STABLECOIN_PAYOUTS' | 'EMBEDDED_STABLECOIN_WALLETS' | 'EMBEDDED_FIAT_ACCOUNTS', externalReference: string, attestation?: RelianceAttestation | undefined, reliance?: Reliance | undefined}; export type CreateBusinessCustomerOnboardingRequest = {onboardingType: 'EMBEDDED', embeddedPartnerCustomer: EmbeddedPartnerCustomerOnboardingPayload}; export type CreateApiOnboardingV1ApplicationsArgs = {body: CreateBusinessCustomerOnboardingRequest}; export type CreateApiOnboardingV1ApplicationsOptions = {baseUrl?: string | undefined, Hawk?: string | undefined, fetch?: typeof fetch | undefined}; export const createBusinessCustomerOnboardingResponse = z.object({id: z.string(), status: z.enum(["NOT_STARTED", "IN_PROGRESS", "SUBMITTED", "REQUIRED_ACTIONS", "APPROVED", "REJECTED", "SUSPENDED"])}); 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 business customer * * POST /onboarding/v1/applications */ export const createApiOnboardingV1Applications = async (args: CreateApiOnboardingV1ApplicationsArgs, options?: CreateApiOnboardingV1ApplicationsOptions) => { const {baseUrl = "https://api.sandbox.bvnk.com", fetch: fetchFn = fetch, Hawk} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (Hawk !== undefined) headers.set("Authorization", Hawk) const url = `${baseUrl.replace(/\/+$/, '')}/onboarding/v1/applications${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(createBusinessCustomerOnboardingResponse, await res.json()) };