import {z} from 'zod' export type APIClientID = string; export type APISecret = string; export type NewUserID = string; export type ConsumerReportPermissiblePurpose = 'ACCOUNT_REVIEW_CREDIT' | 'ACCOUNT_REVIEW_NON_CREDIT' | 'EXTENSION_OF_CREDIT' | 'LEGITIMATE_BUSINESS_NEED_TENANT_SCREENING' | 'LEGITIMATE_BUSINESS_NEED_OTHER' | 'WRITTEN_INSTRUCTION_PREQUALIFICATION' | 'WRITTEN_INSTRUCTION_OTHER' | 'ELIGIBILITY_FOR_GOVT_BENEFITS' | 'INSURANCE_UNDERWRITING' | 'SECONDARY_INVESTOR'; export type CraCreditProfileReportType = 'QUALIFY'; export type CraCreditProfileInquiryType = 'SOFT_INQUIRY' | 'STANDARD_INQUIRY'; export type CraCreditProfileReportVersion = 'v1'; export type CraCreditProfileReportGetRequest = {client_id?: APIClientID | undefined, secret?: APISecret | undefined, user_id: NewUserID, consumer_report_permissible_purpose: ConsumerReportPermissiblePurpose, client_report_id: string, report_type: CraCreditProfileReportType, inquiry_type: CraCreditProfileInquiryType, version: CraCreditProfileReportVersion}; export type CreateApiCraCreditProfileReportGetArgs = {body: CraCreditProfileReportGetRequest}; export type CreateApiCraCreditProfileReportGetOptions = {baseUrl?: string | undefined, clientId?: string | undefined, secret?: string | undefined, plaidVersion?: string | undefined, fetch?: typeof fetch | undefined}; export const craCreditProfileInquiryType = z.enum(["SOFT_INQUIRY", "STANDARD_INQUIRY"]); export const craCreditProfileLendScore = z.object({score: z.number().int().nullable(), reason_codes: z.array(z.string()), variant: z.string(), error_reason: z.string().nullable()}).and(z.record(z.string(), z.unknown())).nullable(); export const craCreditProfileCashflowAttributesSchema = z.record(z.string(), z.unknown()).nullable(); export const craCreditProfileNetworkInsightsSchema = z.record(z.string(), z.unknown()).nullable(); export const craCreditProfileReportMetadata = z.object({item_count: z.number().int(), institution_ids: z.array(z.string()), account_count: z.number().int(), primary_account_count: z.number().int(), depository_account_type_count: z.number().int(), credit_account_type_count: z.number().int(), investment_account_type_count: z.number().int(), other_account_type_count: z.number().int(), multiple_owner_account_count: z.number().int(), generated_at: z.string(), oldest_transaction_date: z.string(), most_recent_transaction_date: z.string()}).and(z.record(z.string(), z.unknown())).nullable(); export const craCreditProfileReport = z.object({date_retrieved: z.string(), inquiry_type: craCreditProfileInquiryType, client_report_id: z.string(), lend_scores: z.array(craCreditProfileLendScore), cashflow_insights_attributes: craCreditProfileCashflowAttributesSchema, network_insights_attributes: craCreditProfileNetworkInsightsSchema, metadata: craCreditProfileReportMetadata}).and(z.record(z.string(), z.unknown())); export const requestID = z.string(); export const newUserID = z.string(); export const checkReportWarningCode = z.enum(["IDENTITY_UNAVAILABLE", "TRANSACTIONS_UNAVAILABLE", "USER_FRAUD_ALERT"]); export const plaidErrorType = z.enum(["INVALID_REQUEST", "INVALID_RESULT", "INVALID_INPUT", "INSTITUTION_ERROR", "RATE_LIMIT_EXCEEDED", "API_ERROR", "ITEM_ERROR", "ASSET_REPORT_ERROR", "BASE_REPORT_ERROR", "RECAPTCHA_ERROR", "OAUTH_ERROR", "PAYMENT_ERROR", "BANK_TRANSFER_ERROR", "INCOME_VERIFICATION_ERROR", "MICRODEPOSITS_ERROR", "SANDBOX_ERROR", "PARTNER_ERROR", "SIGNAL_ERROR", "TRANSACTIONS_ERROR", "TRANSACTION_ERROR", "TRANSFER_ERROR", "CHECK_REPORT_ERROR", "CONSUMER_REPORT_ERROR", "USER_ERROR", "IDEMPOTENCY_ERROR", "ASSETS_ERROR", "CRA_MONITORING_ERROR", "CREDIT_PROFILE_REPORT_ERROR", "ENCOMPASS_ERROR", "ENRICH_ERROR", "FRAUD_INSIGHTS_ERROR", "FREDDIE_MAC_ERROR", "LINK_DELIVERY_ERROR", "PROFILE_ERROR", "RECURRING_TRANSACTIONS_ERROR", "STATEMENTS_ERROR", "TRANSFER_RECURRING_ERROR", "TRANSFER_REFUND_ERROR", "CRA_REPORT_ERROR", "CRA_PARTNER_INSIGHTS_ERROR"]); export const itemId = z.string(); export const cause = z.object({error_type: plaidErrorType, error_code: z.string(), error_code_reason: z.string().nullable().optional(), error_message: z.string(), display_message: z.string().nullable(), request_id: z.string().optional(), causes: z.array(z.unknown()).optional(), status: z.number().int().nullable().optional(), documentation_url: z.string().optional(), suggested_action: z.string().nullable().optional(), required_account_subtypes: z.array(z.string()).optional(), provided_account_subtypes: z.array(z.string()).optional(), item_id: itemId}).and(z.record(z.string(), z.unknown())).nullable(); export const checkReportWarning = z.object({warning_type: z.string(), warning_code: checkReportWarningCode, cause: cause}).and(z.record(z.string(), z.unknown())); export const craCreditProfileReportGetResponse = z.object({report: craCreditProfileReport, request_id: requestID, user_id: newUserID.optional(), warnings: z.array(checkReportWarning)}).and(z.record(z.string(), z.unknown())); 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 }; /** * Retrieve the credit profile report for a user * * POST /cra/credit_profile/report/get */ export const createApiCraCreditProfileReportGet = async (args: CreateApiCraCreditProfileReportGetArgs, options?: CreateApiCraCreditProfileReportGetOptions) => { const {baseUrl = "https://production.plaid.com", fetch: fetchFn = fetch, clientId, secret, plaidVersion} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (clientId !== undefined) headers.set("PLAID-CLIENT-ID", clientId) if (secret !== undefined) headers.set("PLAID-SECRET", secret) if (plaidVersion !== undefined) headers.set("Plaid-Version", plaidVersion) const url = `${baseUrl.replace(/\/+$/, '')}/cra/credit_profile/report/get${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(craCreditProfileReportGetResponse, await res.json()) };