import {z} from 'zod' export type GetApiDataExtractsUserDataArgs = {fromDate: string, loginName: string, toDate: string}; export type GetApiDataExtractsUserDataOptions = {baseUrl: string, fetch?: typeof fetch | undefined}; export const money = z.object({amount: z.number(), currency: z.enum(["AUD", "BRL", "CAD", "EUR", "GBP", "HKD", "IDR", "INR", "JPY", "NZD", "SGD", "USD", "ZAR", "CNY", "VND", "MYR", "CHF"])}); export const dataExtractsHolding = z.object({symbol: z.string().optional(), exercisedQuantity: z.number().optional(), cusipNumber: z.string().optional(), vestedQuantity: z.number().optional(), description: z.string().optional(), unvestedValue: money.optional(), securityStyle: z.string().optional(), vestedValue: money.optional(), optionType: z.enum(["put", "call", "unknown", "other"]).optional(), lastUpdated: z.string().optional(), matchStatus: z.string().optional(), holdingType: z.enum(["stock", "mutualFund", "bond", "CD", "option", "moneyMarketFund", "other", "remic", "future", "commodity", "currency", "unitInvestmentTrust", "employeeStockOption", "insuranceAnnuity", "unknown", "preferredStock", "ETF", "warrants", "ETN"]).optional(), maturityDate: z.string().optional(), price: money.optional(), term: z.string().optional(), contractQuantity: z.number().optional(), id: z.number().int().optional(), isShort: z.boolean().optional(), value: money.optional(), expirationDate: z.string().optional(), interestRate: z.number().optional(), quantity: z.number().optional(), accruedInterest: money.optional(), grantDate: z.string().optional(), sedol: z.string().optional(), vestedSharesExercisable: z.number().optional(), spread: money.optional(), accountId: z.number().int().optional(), enrichedDescription: z.string().optional(), couponRate: z.number().optional(), createdDate: z.string().optional(), accruedIncome: money.optional(), securityType: z.string().optional(), providerAccountId: z.number().int().optional(), unvestedQuantity: z.number().optional(), costBasis: money.optional(), vestingDate: z.string().optional(), isin: z.string().optional(), strikePrice: money.optional()}); export const dataExtractsUser = z.object({loginName: z.string().optional()}); export const accountAddress = z.object({zip: z.string().optional(), country: z.string().optional(), address3: z.string().optional(), address2: z.string().optional(), city: z.string().optional(), sourceType: z.string().optional(), address1: z.string().optional(), street: z.string().optional(), state: z.string().optional(), type: z.enum(["HOME", "BUSINESS", "POBOX", "RETAIL", "OFFICE", "SMALL_BUSINESS", "COMMUNICATION", "PERMANENT", "STATEMENT_ADDRESS", "PAYMENT", "PAYOFF", "UNKNOWN"]).optional()}); export const accountDataset = z.object({lastUpdated: z.string().optional(), updateEligibility: z.enum(["ALLOW_UPDATE", "ALLOW_UPDATE_WITH_CREDENTIALS", "DISALLOW_UPDATE"]).optional(), additionalStatus: z.enum(["LOGIN_IN_PROGRESS", "DATA_RETRIEVAL_IN_PROGRESS", "ACCT_SUMMARY_RECEIVED", "AVAILABLE_DATA_RETRIEVED", "PARTIAL_DATA_RETRIEVED", "DATA_RETRIEVAL_FAILED", "DATA_NOT_AVAILABLE", "ACCOUNT_LOCKED", "ADDL_AUTHENTICATION_REQUIRED", "BETA_SITE_DEV_IN_PROGRESS", "CREDENTIALS_UPDATE_NEEDED", "INCORRECT_CREDENTIALS", "PROPERTY_VALUE_NOT_AVAILABLE", "INVALID_ADDL_INFO_PROVIDED", "REQUEST_TIME_OUT", "SITE_BLOCKING_ERROR", "UNEXPECTED_SITE_ERROR", "SITE_NOT_SUPPORTED", "SITE_UNAVAILABLE", "TECH_ERROR", "USER_ACTION_NEEDED_AT_SITE", "SITE_SESSION_INVALIDATED", "NEW_AUTHENTICATION_REQUIRED", "DATASET_NOT_SUPPORTED", "ENROLLMENT_REQUIRED_FOR_DATASET", "CONSENT_REQUIRED", "CONSENT_EXPIRED", "CONSENT_REVOKED", "INCORRECT_OAUTH_TOKEN", "MIGRATION_IN_PROGRESS"]).optional(), nextUpdateScheduled: z.string().optional(), name: z.enum(["BASIC_AGG_DATA", "ADVANCE_AGG_DATA", "ACCT_PROFILE", "DOCUMENT"]).optional(), lastUpdateAttempt: z.string().optional()}); export const rewardBalance = z.object({expiryDate: z.string().optional(), balanceToReward: z.string().optional(), balanceType: z.enum(["EXPIRING_BALANCE", "BALANCE_TO_LEVEL", "BALANCE_TO_REWARD", "BALANCE", "TOTAL_BALANCE"]).optional(), balance: z.number().optional(), description: z.string().optional(), balanceToLevel: z.string().optional(), units: z.string().optional()}); export const bankTransferCode = z.object({id: z.string().optional(), type: z.enum(["BSB", "IFSC", "ROUTING_NUMBER", "SORT_CODE"]).optional()}); export const coverageAmount = z.object({cover: money.optional(), unitType: z.enum(["PER_FAMILY", "PER_MEMBER"]).optional(), type: z.enum(["DEDUCTIBLE", "OUT_OF_POCKET", "ANNUAL_BENEFIT", "MAX_BENEFIT", "COVERAGE_AMOUNT", "MONTHLY_BENEFIT", "OTHER"]).optional(), limitType: z.enum(["IN_NETWORK", "OUT_NETWORK"]).optional(), met: money.optional()}); export const coverage = z.object({amount: z.array(coverageAmount).optional(), planType: z.enum(["PPO", "HMO", "UNKNOWN"]).optional(), endDate: z.string().optional(), type: z.enum(["VISION", "DENTAL", "MEDICAL", "HEALTH", "DEATH_COVER", "TOTAL_PERMANENT_DISABILITY", "ACCIDENTAL_DEATH_COVER", "INCOME_PROTECTION", "DEATH_TOTAL_PERMANENT_DISABILITY", "OTHER"]).optional(), startDate: z.string().optional()}); export const loanPayoffDetails = z.object({payByDate: z.string().optional(), payoffAmount: money.optional(), outstandingBalance: money.optional()}); export const dataExtractsAccount = z.object({availableCash: money.optional(), includeInNetWorth: z.boolean().optional(), moneyMarketBalance: money.optional(), enrollmentDate: z.string().optional(), estimatedDate: z.string().optional(), memo: z.string().optional(), guarantor: z.string().optional(), interestPaidLastYear: money.optional(), lastUpdated: z.string().optional(), balance: money.optional(), homeInsuranceType: z.enum(["HOME_OWNER", "RENTAL", "RENTER", "UNKNOWN", "OTHER"]).optional(), id: z.number().int().optional(), cash: money.optional(), totalCreditLine: money.optional(), providerName: z.string().optional(), valuationType: z.enum(["SYSTEM", "MANUAL"]).optional(), marginBalance: money.optional(), apr: z.number().optional(), availableCredit: money.optional(), currentBalance: money.optional(), isManual: z.boolean().optional(), escrowBalance: money.optional(), nextLevel: z.string().optional(), classification: z.enum(["OTHER", "PERSONAL", "CORPORATE", "SMALL_BUSINESS", "TRUST", "ADD_ON_CARD", "VIRTUAL_CARD"]).optional(), loanPayoffAmount: money.optional(), interestRateType: z.enum(["FIXED", "VARIABLE", "UNKNOWN", "OTHER"]).optional(), loanPayByDate: z.string().optional(), faceAmount: money.optional(), policyFromDate: z.string().optional(), premiumPaymentTerm: z.string().optional(), policyTerm: z.string().optional(), repaymentPlanType: z.enum(["STANDARD", "GRADUATED", "EXTENDED", "INCOME_BASED", "INCOME_CONTINGENT", "INCOME_SENSITIVE", "PAY_AS_YOU_EARN", "REVISED_PAY_AS_YOU_EARN"]).optional(), availableBalance: money.optional(), accountStatus: z.enum(["ACTIVE", "INACTIVE", "TO_BE_CLOSED", "CLOSED", "DELETED"]).optional(), lifeInsuranceType: z.enum(["OTHER", "TERM_LIFE_INSURANCE", "UNIVERSAL_LIFE_INSURANCE", "WHOLE_LIFE_INSURANCE", "VARIABLE_LIFE_INSURANCE", "ULIP", "ENDOWMENT"]).optional(), premium: money.optional(), aggregationSource: z.enum(["SYSTEM", "USER"]).optional(), isDeleted: z.boolean().optional(), overDraftLimit: money.optional(), nickname: z.string().optional(), term: z.string().optional(), interestRate: z.number().optional(), deathBenefit: money.optional(), address: accountAddress.optional(), cashValue: money.optional(), "401kLoan": money.optional(), homeValue: money.optional(), accountNumber: z.string().optional(), createdDate: z.string().optional(), interestPaidYTD: money.optional(), providerAccountId: z.number().int().optional(), collateral: z.string().optional(), dataset: z.array(accountDataset).optional(), runningBalance: money.optional(), sourceId: z.string().optional(), dueDate: z.string().optional(), frequency: z.enum(["DAILY", "ONE_TIME", "WEEKLY", "EVERY_2_WEEKS", "SEMI_MONTHLY", "MONTHLY", "QUARTERLY", "SEMI_ANNUALLY", "ANNUALLY", "EVERY_2_MONTHS", "EBILL", "FIRST_DAY_MONTHLY", "LAST_DAY_MONTHLY", "EVERY_4_WEEKS", "UNKNOWN", "OTHER"]).optional(), maturityAmount: money.optional(), associatedProviderAccountId: z.array(z.number().int()).optional(), isAsset: z.boolean().optional(), principalBalance: money.optional(), totalCashLimit: money.optional(), maturityDate: z.string().optional(), minimumAmountDue: money.optional(), annualPercentageYield: z.number().optional(), accountType: z.string().optional(), originationDate: z.string().optional(), totalVestedBalance: money.optional(), rewardBalance: z.array(rewardBalance).optional(), sourceAccountStatus: z.enum(["IN_REPAYMENT", "DEFAULTED", "IN_SCHOOL", "IN_GRACE_PERIOD", "DELINQUENCY", "DEFERMENT", "FORBEARANCE"]).optional(), derivedApr: z.number().optional(), policyEffectiveDate: z.string().optional(), totalUnvestedBalance: money.optional(), annuityBalance: money.optional(), accountName: z.string().optional(), totalCreditLimit: money.optional(), policyStatus: z.enum(["ACTIVE", "INACTIVE", "OTHER"]).optional(), shortBalance: money.optional(), lender: z.string().optional(), lastEmployeeContributionAmount: money.optional(), providerId: z.string().optional(), lastPaymentDate: z.string().optional(), primaryRewardUnit: z.string().optional(), lastPaymentAmount: money.optional(), remainingBalance: money.optional(), userClassification: z.enum(["BUSINESS", "PERSONAL"]).optional(), bankTransferCode: z.array(bankTransferCode).optional(), expirationDate: z.string().optional(), coverage: z.array(coverage).optional(), cashApr: z.number().optional(), oauthMigrationStatus: z.enum(["IN_PROGRESS", "TO_BE_MIGRATED", "COMPLETED"]).optional(), displayedName: z.string().optional(), amountDue: money.optional(), currentLevel: z.string().optional(), originalLoanAmount: money.optional(), policyToDate: z.string().optional(), loanPayoffDetails: loanPayoffDetails.optional(), CONTAINER: z.enum(["bank", "creditCard", "investment", "insurance", "loan", "reward", "realEstate", "otherAssets", "otherLiabilities"]).optional(), lastEmployeeContributionDate: z.string().optional(), lastPayment: money.optional(), recurringPayment: money.optional()}); export const description = z.object({security: z.string().optional(), original: z.string().optional(), simple: z.string().optional(), consumer: z.string().optional()}); export const contact = z.object({phone: z.string().optional(), email: z.string().optional()}); export const coordinates = z.object({latitude: z.number().optional(), longitude: z.number().optional()}); export const merchant = z.object({website: z.string().optional(), address: accountAddress.optional(), contact: contact.optional(), categoryLabel: z.array(z.string()).optional(), coordinates: coordinates.optional(), name: z.string().optional(), id: z.string().optional(), source: z.enum(["YODLEE", "FACTUAL"]).optional()}); export const dataExtractsTransaction = z.object({date: z.string().optional(), sourceId: z.string().optional(), symbol: z.string().optional(), cusipNumber: z.string().optional(), highLevelCategoryId: z.number().int().optional(), detailCategoryId: z.number().int().optional(), description: description.optional(), memo: z.string().optional(), settleDate: z.string().optional(), type: z.string().optional(), baseType: z.enum(["CREDIT", "DEBIT"]).optional(), categorySource: z.enum(["SYSTEM", "USER"]).optional(), principal: money.optional(), lastUpdated: z.string().optional(), isDeleted: z.boolean().optional(), interest: money.optional(), price: money.optional(), commission: money.optional(), id: z.number().int().optional(), amount: money.optional(), checkNumber: z.string().optional(), quantity: z.number().optional(), valoren: z.string().optional(), isManual: z.boolean().optional(), merchant: merchant.optional(), sedol: z.string().optional(), transactionDate: z.string().optional(), categoryType: z.enum(["TRANSFER", "DEFERRED_COMPENSATION", "UNCATEGORIZE", "INCOME", "EXPENSE"]).optional(), accountId: z.number().int().optional(), createdDate: z.string().optional(), sourceType: z.enum(["AGGREGATED", "MANUAL"]).optional(), CONTAINER: z.enum(["bank", "creditCard", "investment", "insurance", "loan", "reward", "realEstate", "otherAssets", "otherLiabilities"]).optional(), postDate: z.string().optional(), parentCategoryId: z.number().int().optional(), subType: z.enum(["AUTH_HOLD", "AUTH_REQUEST", "OVERDRAFT_CHARGE", "CREDIT_ADJUSTMENT", "PIN_DEBIT", "BANK_DIRECT_DEPOSIT", "DIVIDEND_DEPOSIT", "INTEREST_SAVINGS", "INTEREST_ADJUSTMENT", "ONLINE_PURCHASE", "PURCHASED_WITH_CHECK", "RECURRING_BILLING", "TAX_PAYMENT", "PAYMENT_BY_CHECK", "PAYMENT_PLAN", "FEE_REFUND", "WIRE_TRANSFER_CHARGE", "ACCOUNT_TO_ACCOUNT_TRANSFER", "BANK_TO_BANK_TRANSACTION", "BANK_TO_NON_BANK_ACCOUNT_TRANSFER", "CASH_WITHDRAWAL_AT_FI", "ATM_CASH_WITHDRAWAL", "AUTH_PROCESSING", "AUTH_RELEASE", "PRE_AUTH", "AUTH_COMPLETE", "AUTH_VOID", "BALANCE_ENQUIRY", "ACCOUNT_VERIFICATION", "PRE_AUTH_COMPLETION", "SERVICE_CHARGE", "SERVICE_CHARGE_FEE_REFUND", "RETURNED_CHECK_CHARGE", "RETURNED_CHECK_REIMBURSEMENT", "CASH_ADVANCE", "BILL_PAY_CHARGE", "CHECK_IMAGE_SERVICE_CHARGE", "OVERDRAFT_PROTECTION_CHARGE", "STOP_PAYMENT_CHARGE", "CHECKS_ORDERING_CHARGE", "MONTHLY_MAINTENANCE_CHARGE", "DEBIT_CARD_FEE", "CONVENIENCE_FEE", "PERSONAL_LOAN_CREDIT", "CREDIT_CARD_CREDIT", "AUTO_LOAN", "HOME_LOAN_MORTGAGE", "SHORT_TERM_CREDIT", "SIGNATURE_DEBIT", "CONTACT_LESS_DEBIT", "DEFERRED_DEPOSIT", "DEFERRED_BILL_PAY", "INSTALLMENT_PAYMENT", "RECURRING_SUBSCRIPTION_PAYMENT", "HOLD_CHECK_PAYMENT", "CAPITAL_GAINS_DISTIBUTION", "CG_LONG_TERM_DEPOSIT", "OPEN_SALE_DEPOSIT", "INTEREST__CHECK", "PURCHASE_VOID", "PURCHASE_WITH_CREDIT_CARD", "PURCHASE_WITH_DEBIT_CARD", "CHARGE_A_REPEAT_CUSTOMER", "DOWN_PAYMENT_OR_ANNUITY_PAYMENT_OR_DIRECT_PAYMENT", "FEE_PAYMENT", "FINANCE_CHARGE_REFUND", "TRANSACTION_VOID", "FEE_VOID", "DEBIT_CARD_WITHDRAWAL_AT_STORE", "ELECTRONIC_PAYMENT", "ACH_DEBIT", "ATM_TELLER_DEPOSIT", "POS_DEBIT", "BANK_ADJUSTMENT", "CHARGES_FEES", "INTEREST", "DEPOSITS_CREDITS", "PAYMENT", "PURCHASE", "REFUND", "TRANSFER", "WITHDRAWAL", "OTHER_DEPOSITS", "OTHER_WITHDRAWALS", "ADJUSTMENT", "FINANCE_CHARGE", "OTHER_CHARGES_FEES", "ANNUAL_FEE", "DEPOSIT", "DIRECT_DEPOSIT_SALARY", "INVESTMENT_INCOME_CASH", "SSA", "REWARDS", "CHECK_DEPOSIT", "MOBILE_REMOTE_DEPOSIT", "TELLER_DEPOSIT", "TAX_REFUND", "CREDIT_CARD_PAYMENT", "INSURANCE_PAYMENT", "UTILITIES_PAYMENT", "CHILD_SUPPORT", "LOAN", "PERSONAL_LOAN", "STUDENT_LOAN", "SALES_TAX", "REIMBURSEMENT", "BALANCE_TRANSFER", "WIRE_TRANSFER", "OVERDRAFT_PROTECTION", "DEBIT", "CREDIT", "NSF_FEES"]).optional(), category: z.string().optional(), runningBalance: money.optional(), categoryId: z.number().int().optional(), holdingDescription: z.string().optional(), isin: z.string().optional(), status: z.enum(["POSTED", "PENDING", "SCHEDULED", "FAILED", "CLEARED"]).optional()}); export const dataExtractsProviderAccount = z.object({lastUpdated: z.string().optional(), createdDate: z.string().optional(), aggregationSource: z.enum(["SYSTEM", "USER"]).optional(), isDeleted: z.boolean().optional(), oauthMigrationStatus: z.enum(["IN_PROGRESS", "TO_BE_MIGRATED", "COMPLETED"]).optional(), providerId: z.number().int().optional(), requestId: z.string().optional(), isManual: z.boolean().optional(), id: z.number().int().optional(), dataset: z.array(accountDataset).optional(), status: z.enum(["LOGIN_IN_PROGRESS", "USER_INPUT_REQUIRED", "IN_PROGRESS", "PARTIAL_SUCCESS", "SUCCESS", "FAILED", "MIGRATION_IN_PROGRESS"]).optional()}); export const dataExtractsUserData = z.object({holding: z.array(dataExtractsHolding).optional(), totalTransactionsCount: z.number().int().optional(), user: dataExtractsUser.optional(), account: z.array(dataExtractsAccount).optional(), transaction: z.array(dataExtractsTransaction).optional(), providerAccount: z.array(dataExtractsProviderAccount).optional()}); export const dataExtractsUserDataResponse = z.object({userData: z.array(dataExtractsUserData).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 userData * * GET /dataExtracts/userData */ export const getApiDataExtractsUserData = async (args: GetApiDataExtractsUserDataArgs, options: GetApiDataExtractsUserDataOptions) => { const {baseUrl, fetch: fetchFn = fetch} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json;charset=UTF-8") if (args.fromDate != null) query.append("fromDate", String(args.fromDate)) if (args.loginName != null) query.append("loginName", String(args.loginName)) if (args.toDate != null) query.append("toDate", String(args.toDate)) const url = `${baseUrl.replace(/\/+$/, '')}/dataExtracts/userData${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(dataExtractsUserDataResponse, await res.json()) };