import {z} from 'zod' export type APIClientID = string; export type APISecret = string; export type AccessTokenNullable = string | null; export type IncomeVerificationPaystubsGetRequest = {client_id?: APIClientID | undefined, secret?: APISecret | undefined, income_verification_id?: (string | null) | undefined, access_token?: AccessTokenNullable | undefined}; export type CreateApiIncomeVerificationPaystubsGetArgs = {body: IncomeVerificationPaystubsGetRequest}; export type CreateApiIncomeVerificationPaystubsGetOptions = {baseUrl?: string | undefined, clientId?: string | undefined, secret?: string | undefined, plaidVersion?: string | undefined, fetch?: typeof fetch | undefined}; export const docType = z.enum(["UNKNOWN", "DOCUMENT_TYPE_PAYSTUB", "DOCUMENT_TYPE_BANK_STATEMENT", "DOCUMENT_TYPE_US_TAX_W2", "DOCUMENT_TYPE_US_MILITARY_ERAS", "DOCUMENT_TYPE_US_MILITARY_LES", "DOCUMENT_TYPE_US_MILITARY_CLES", "DOCUMENT_TYPE_GIG", "DOCUMENT_TYPE_NONE", "DOCUMENT_TYPE_US_TAX_1099_MISC", "DOCUMENT_TYPE_US_TAX_1099_K", "DOCUMENT_TYPE_PLAID_GENERATED_PAYSTUB_PDF", "DOCUMENT_TYPE_US_STUDENT_I20"]); export const documentMetadata = z.object({name: z.string().optional(), status: z.string().nullable().optional(), doc_id: z.string().optional(), doc_type: docType.optional()}).and(z.record(z.string(), z.unknown())); export const totalCanonicalDescription = z.enum(["BONUS", "COMMISSION", "OVERTIME", "PAID TIME OFF", "REGULAR PAY", "VACATION", "EMPLOYEE MEDICARE", "FICA", "SOCIAL SECURITY EMPLOYEE TAX", "MEDICAL", "VISION", "DENTAL", "NET PAY", "TAXES", "NOT_FOUND", "OTHER", "null"]).nullable(); export const pay = z.object({amount: z.number().nullable().optional(), currency: z.string().nullable().optional()}).and(z.record(z.string(), z.unknown())); export const total = z.object({canonical_description: totalCanonicalDescription.optional(), description: z.string().nullable().optional(), current_pay: pay.optional(), ytd_pay: pay.optional()}).and(z.record(z.string(), z.unknown())); export const deductionsBreakdown = z.object({current_amount: z.number().nullable().optional(), description: z.string().nullable().optional(), iso_currency_code: z.string().nullable().optional(), unofficial_currency_code: z.string().nullable().optional(), ytd_amount: z.number().nullable().optional()}).and(z.record(z.string(), z.unknown())); export const deductionsTotal = z.object({current_amount: z.number().nullable().optional(), iso_currency_code: z.string().nullable().optional(), unofficial_currency_code: z.string().nullable().optional(), ytd_amount: z.number().nullable().optional()}).and(z.record(z.string(), z.unknown())); export const deductions = z.object({subtotals: z.array(total).optional(), breakdown: z.array(deductionsBreakdown), totals: z.array(total).optional(), total: deductionsTotal}).and(z.record(z.string(), z.unknown())); export const earningsTotal = z.object({current_amount: z.number().nullable().optional(), current_pay: pay.optional(), ytd_pay: pay.optional(), hours: z.number().nullable().optional(), iso_currency_code: z.string().nullable().optional(), unofficial_currency_code: z.string().nullable().optional(), ytd_amount: z.number().nullable().optional()}).and(z.record(z.string(), z.unknown())); export const earningsBreakdownCanonicalDescription = z.enum(["BONUS", "COMMISSION", "OVERTIME", "PAID TIME OFF", "REGULAR PAY", "VACATION", "BASIC ALLOWANCE HOUSING", "BASIC ALLOWANCE SUBSISTENCE", "OTHER", "null"]).nullable(); export const earningsBreakdown = z.object({canonical_description: earningsBreakdownCanonicalDescription.optional(), current_amount: z.number().nullable().optional(), description: z.string().nullable().optional(), hours: z.number().nullable().optional(), iso_currency_code: z.string().nullable().optional(), rate: z.number().nullable().optional(), unofficial_currency_code: z.string().nullable().optional(), ytd_amount: z.number().nullable().optional()}).and(z.record(z.string(), z.unknown())); export const earnings = z.object({subtotals: z.array(earningsTotal).optional(), totals: z.array(earningsTotal).optional(), breakdown: z.array(earningsBreakdown).optional(), total: earningsTotal.optional()}).and(z.record(z.string(), z.unknown())); export const paystubAddress = z.object({city: z.string().nullable().optional(), country: z.string().nullable().optional(), postal_code: z.string().nullable().optional(), region: z.string().nullable().optional(), street: z.string().nullable().optional(), line1: z.string().nullable().optional(), line2: z.string().nullable().optional(), state_code: z.string().nullable().optional()}).and(z.record(z.string(), z.unknown())); export const taxpayerID = z.object({id_type: z.string().nullable().optional(), id_mask: z.string().nullable().optional(), last_4_digits: z.string().min(4).max(4).nullable().optional()}).and(z.record(z.string(), z.unknown())); export const employee = z.object({address: paystubAddress, name: z.string().nullable(), marital_status: z.string().nullable().optional(), taxpayer_id: taxpayerID.optional()}).and(z.record(z.string(), z.unknown())); export const paystubEmployer = z.object({address: paystubAddress.optional(), name: z.string().nullable()}).and(z.record(z.string(), z.unknown())); export const employmentDetails = z.object({annual_salary: pay.optional(), hire_date: z.string().nullable().optional()}).and(z.record(z.string(), z.unknown())); export const netPay = z.object({current_amount: z.number().nullable().optional(), description: z.string().nullable().optional(), iso_currency_code: z.string().nullable().optional(), unofficial_currency_code: z.string().nullable().optional(), ytd_amount: z.number().nullable().optional(), total: total.optional()}).and(z.record(z.string(), z.unknown())); export const distributionBreakdown = z.object({account_name: z.string().nullable().optional(), bank_name: z.string().nullable().optional(), current_amount: z.number().nullable().optional(), iso_currency_code: z.string().nullable().optional(), mask: z.string().nullable().optional(), type: z.string().nullable().optional(), unofficial_currency_code: z.string().nullable().optional(), current_pay: pay.optional()}).and(z.record(z.string(), z.unknown())); export const payPeriodDetailsPayFrequency = z.enum(["PAY_FREQUENCY_UNKNOWN", "PAY_FREQUENCY_WEEKLY", "PAY_FREQUENCY_BIWEEKLY", "PAY_FREQUENCY_SEMIMONTHLY", "PAY_FREQUENCY_MONTHLY", "null"]).nullable(); export const payPeriodDetails = z.object({check_amount: z.number().nullable().optional(), distribution_breakdown: z.array(distributionBreakdown).optional(), end_date: z.string().nullable().optional(), gross_earnings: z.number().nullable().optional(), pay_date: z.string().nullable().optional(), pay_frequency: payPeriodDetailsPayFrequency.optional(), pay_day: z.string().nullable().optional(), start_date: z.string().nullable().optional()}).and(z.record(z.string(), z.unknown())); export const paystubPayFrequency = z.enum(["MONTHLY", "BI-WEEKLY", "WEEKLY", "SEMI-MONTHLY", "null"]).nullable(); export const paystubDetails = z.object({pay_period_start_date: z.string().nullable().optional(), pay_period_end_date: z.string().nullable().optional(), pay_date: z.string().nullable().optional(), paystub_provider: z.string().nullable().optional(), pay_frequency: paystubPayFrequency.optional()}).and(z.record(z.string(), z.unknown())); export const incomeBreakdownType = z.enum(["bonus", "overtime", "regular", "null"]).nullable(); export const incomeBreakdown = z.object({type: incomeBreakdownType, rate: z.number().nullable(), hours: z.number().nullable(), total: z.number().nullable()}).and(z.record(z.string(), z.unknown())); export const paystubYTDDetails = z.object({gross_earnings: z.number().nullable().optional(), net_earnings: z.number().nullable().optional()}).and(z.record(z.string(), z.unknown())); export const paystub = z.object({deductions: deductions, doc_id: z.string(), earnings: earnings, employee: employee, employer: paystubEmployer, employment_details: employmentDetails.optional(), net_pay: netPay, pay_period_details: payPeriodDetails, paystub_details: paystubDetails.optional(), income_breakdown: z.array(incomeBreakdown).optional(), ytd_earnings: paystubYTDDetails.optional()}).and(z.record(z.string(), z.unknown())); 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 plaidError = 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()}).and(z.record(z.string(), z.unknown())).nullable(); export const requestID = z.string(); export const incomeVerificationPaystubsGetResponse = z.object({document_metadata: z.array(documentMetadata).optional(), paystubs: z.array(paystub), error: plaidError.optional(), request_id: requestID}).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 }; /** * (Deprecated) Retrieve information from the paystubs used for income verification * * POST /income/verification/paystubs/get */ export const createApiIncomeVerificationPaystubsGet = async (args: CreateApiIncomeVerificationPaystubsGetArgs, options?: CreateApiIncomeVerificationPaystubsGetOptions) => { 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(/\/+$/, '')}/income/verification/paystubs/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(incomeVerificationPaystubsGetResponse, await res.json()) };