diff --git a/index.ts b/index.ts index 589c130..103e470 100644 --- a/index.ts +++ b/index.ts @@ -4,6 +4,6 @@ export { Environments } from './src/configuration'; export { AccountTypes } from './src/resources/Account'; export { ElementTypes } from './src/resources/Element'; export { EntityTypes, EntityStatuses } from './src/resources/Entity'; -export { PaymentFundStatuses, PaymentStatuses } from './src/resources/Payment'; +export { PaymentDirectionStatuses, PaymentFundStatuses, PaymentStatuses } from './src/resources/Payment'; export { ReportTypes, ReportStatuses } from './src/resources/Report'; export { WebhookTypes } from './src/resources/Webhook'; diff --git a/package-lock.json b/package-lock.json index 8246e09..1d9c151 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "method-node", - "version": "3.0.0", + "version": "3.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "method-node", - "version": "3.0.0", + "version": "3.1.0", "license": "ISC", "dependencies": { "axios": "^1.7.4", diff --git a/package.json b/package.json index fe080e8..fb469bc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "method-node", - "version": "3.0.0", + "version": "3.1.0", "description": "Node.js library for the Method API", "main": "dist/index.ts", "module": "dist/index.mjs", diff --git a/src/resources/Account/Attributes.ts b/src/resources/Account/Attributes.ts index 1e69cab..c73d9c0 100644 --- a/src/resources/Account/Attributes.ts +++ b/src/resources/Account/Attributes.ts @@ -1,6 +1,6 @@ import Resource, { IResourceListOpts } from '../../resource'; import Configuration, { IResponse } from '../../configuration'; -import type { IAccountAttributes } from './types'; +import type { IAccountAttributes, IAccountAttributesCreateOpts } from './types'; export default class AccountAttributes extends Resource { constructor(config: Configuration) { @@ -37,7 +37,7 @@ export default class AccountAttributes extends Resource { * @returns Returns an Account’s Attributes object. */ - async create() { - return super._create, {}>({}); + async create(opts: IAccountAttributesCreateOpts = {}) { + return super._create, IAccountAttributesCreateOpts>(opts); } }; diff --git a/src/resources/Account/Subscriptions.ts b/src/resources/Account/Subscriptions.ts index 84e14ed..5db72f8 100644 --- a/src/resources/Account/Subscriptions.ts +++ b/src/resources/Account/Subscriptions.ts @@ -41,14 +41,13 @@ export default class AccountSubscriptions extends Resource { * * Note: Subscription requests are processed individually, meaning the success or failure of one subscription does not affect others. The response object will detail any errors encountered. * - * @param data IAccountSubscriptionCreateOpts * @returns Returns a map of Subscription name to Subscription object. */ - async create(sub_name: TAccountSubscriptionTypes) { - return super._create, IAccountSubscriptionCreateOpts>( - { enroll: sub_name }, - ); + async create(opts: IAccountSubscriptionCreateOpts | TAccountSubscriptionTypes) { + const data = (typeof opts === 'string' ? { enroll: opts } : opts) as IAccountSubscriptionCreateOpts; + + return super._create, IAccountSubscriptionCreateOpts>(data); } /** diff --git a/src/resources/Account/types.ts b/src/resources/Account/types.ts index 7fbd922..97fc9e3 100644 --- a/src/resources/Account/types.ts +++ b/src/resources/Account/types.ts @@ -77,19 +77,24 @@ export interface IAccountProductListResponse { export const AccountSubscriptionTypes = { card_brand: 'card_brand', - payment_instrument: 'payment_instrument', 'payment_instrument.card': 'payment_instrument.card', 'payment_instrument.network_token': 'payment_instrument.network_token', transaction: 'transaction', update: 'update', update_snapshot: 'update.snapshot', attribute: 'attribute', - connect: 'connect', - credit_score: 'credit_score', } as const; export type TAccountSubscriptionTypes = typeof AccountSubscriptionTypes[keyof typeof AccountSubscriptionTypes]; +export const DeprecatedAccountSubscriptionTypes = { + payment_instrument: 'payment_instrument', +} as const; + +export type TDeprecatedAccountSubscriptionTypes = typeof DeprecatedAccountSubscriptionTypes[keyof typeof DeprecatedAccountSubscriptionTypes]; + +export type TAccountSubscriptionNames = TAccountSubscriptionTypes | TDeprecatedAccountSubscriptionTypes; + export const AccountOwnership = { primary: 'primary', authorized: 'authorized', @@ -211,6 +216,7 @@ export interface IAccountLiabilityBase { next_payment_due_date: string | null; next_payment_minimum_amount: number | null; opened_at?: string | null; + past_due_status?: boolean | null; }; export interface IAccountLiabilityLoanBase extends IAccountLiabilityBase { @@ -289,6 +295,7 @@ export interface IAccountLiability { type: TAccountLiabilityTypes | null; sub_type: TAccountLiabilitySubTypes | null; name: string | null; + network: string | null; }; export interface IAccountACH { @@ -312,25 +319,68 @@ export interface IAccountCardBrand { account_id: string; brands: IAccountCardBrandInfo[]; source: 'method' | 'network' | null; - issuer?: string | null; - last4?: string | null; - network?: string | null; - status: 'completed' | 'in_progress' | 'failed'; + status: 'completed' | 'pending' | 'in_progress' | 'failed'; shared: boolean; error: IResourceError | null; created_at: string; updated_at: string; } +export interface IAccountCardBrandRewardCategory { + category: string | null; + category_presentable: string | null; + rate: number | null; + unit: string | null; + cap: string | null; +} + +export interface IAccountCardBrandRewards { + type: string | null; + program: string | null; + categories: IAccountCardBrandRewardCategory[]; +} + +export interface IAccountCardBrandQualifyingPeriod { + value: number; + unit: string; + relative_to: string; +} + +export interface IAccountCardBrandPromotion { + type: string | null; + title: string | null; + description: string | null; + value: number | null; + unit: string | null; + spend_requirement: number | null; + qualifying_period: IAccountCardBrandQualifyingPeriod | null; + expiration: string | null; +} + +export interface IAccountCardBrandDetails { + card_category: string | null; + purchase_apr_min: number | null; + purchase_apr_max: number | null; + cash_advance_apr_min: number | null; + cash_advance_apr_max: number | null; + annual_fee: number | null; + late_payment_fee: number | null; + rewards: IAccountCardBrandRewards; + promotions: IAccountCardBrandPromotion[]; + data_as_of: string | null; +} + export interface IAccountCardBrandInfo { id: string; - card_product_id: string; - description: string; + card_product_id?: string | null; + description?: string; name: string; - issuer: string; + issuer?: string | null; network: string; - type: 'specific' | 'generic' | 'in_review'; + network_tier?: string; + type?: string | null; url: string; + details: IAccountCardBrandDetails | null; } export interface IAccountPayoff { @@ -397,9 +447,9 @@ export type TAccountSubscriptionStatuses = keyof typeof AccountSubscriptionStatu export interface IAccountSubscription { id: string; - name: TAccountSubscriptionTypes; + name: TAccountSubscriptionNames; status: TAccountSubscriptionStatuses; - payload: any | null; + payload: IAccountSubscriptionPayload | null; latest_request_id: string | null; created_at: string; updated_at: string; @@ -414,14 +464,21 @@ export interface IAccountSubscriptionsResponse { 'payment_instrument.card'?: IAccountSubscription; 'payment_instrument.network_token'?: IAccountSubscription; attribute?: IAccountSubscription; - connect?: IAccountSubscription; - credit_score?: IAccountSubscription; }; -export interface IAccountSubscriptionCreateOpts { - enroll: TAccountSubscriptionTypes; +export interface IAccountSubscriptionPayload { + attributes?: TAccountAttributeRequestScope; }; +export type IAccountSubscriptionCreateOpts = + | { + enroll: typeof AccountSubscriptionTypes.attribute; + payload?: IAccountSubscriptionPayload; + } + | { + enroll: Exclude; + }; + export interface IAccountUpdate { id: string; status: TResourceStatus; @@ -660,8 +717,31 @@ export interface IAccountWithdrawConsentOpts { reason: 'holder_withdrew_consent' | null; }; -export const AccountAttributeNames = { +export const AccountAttributeBundles = { + wallet_intelligence: 'wallet_intelligence', + statement: 'statement', +} as const; + +export type TAccountAttributeBundles = typeof AccountAttributeBundles[keyof typeof AccountAttributeBundles]; + +export const StaticAccountAttributeNames = { type: 'type', +} as const; + +export type TStaticAccountAttributeNames = typeof StaticAccountAttributeNames[keyof typeof StaticAccountAttributeNames]; + +export const LegacyAccountAttributeNames = { + debt_settlement: 'debt_settlement', + interest_estimate_min: 'interest_estimate_min', + interest_estimate_max: 'interest_estimate_max', + account_standing: 'account_standing', + delinquent_period: 'delinquent_period', + delinquent_amount: 'delinquent_amount', +} as const; + +export type TLegacyAccountAttributeNames = typeof LegacyAccountAttributeNames[keyof typeof LegacyAccountAttributeNames]; + +export const AccountAttributeNames = { usage_pattern: 'usage_pattern', delinquency_flag: 'delinquency_flag', utilization: 'utilization', @@ -671,28 +751,116 @@ export const AccountAttributeNames = { utilization_delta_60d: 'utilization_delta_60d', utilization_delta_90d: 'utilization_delta_90d', monthly_installments_estimate: 'monthly_installments_estimate', + heloc_utilization: 'heloc_utilization', + available_credit_limit: 'available_credit_limit', + available_loan_amount: 'available_loan_amount', + any_delinquent_flag: 'any_delinquent_flag', + serious_delinquent_flag: 'serious_delinquent_flag', + delinquency_recently_cured_flag: 'delinquency_recently_cured_flag', + delinquency_worst_dpd_bucket: 'delinquency_worst_dpd_bucket', + delinquency_progression_flag: 'delinquency_progression_flag', + delinquent_outcome: 'delinquent_outcome', + next_payment_due_date: 'next_payment_due_date', + next_payment_minimum_amount: 'next_payment_minimum_amount', + estimated_apr: 'estimated_apr', + utilization_bucket: 'utilization_bucket', + purchasing_power: 'purchasing_power', + account_age: 'account_age', + utilization_velocity_4_week: 'utilization_velocity_4_week', + utilization_velocity_8_week: 'utilization_velocity_8_week', + utilization_velocity_12_week: 'utilization_velocity_12_week', + weeks_since_last_activity: 'weeks_since_last_activity', + recent_balance_spike_flag: 'recent_balance_spike_flag', + spend_concentration_4_week: 'spend_concentration_4_week', + spend_concentration_8_week: 'spend_concentration_8_week', + spend_concentration_12_week: 'spend_concentration_12_week', + current_wallet_rank: 'current_wallet_rank', + brand_category: 'brand_category', + brand_tier: 'brand_tier', + enrolled_in_direct_pay_previously: 'enrolled_in_direct_pay_previously', + last_direct_pay_date: 'last_direct_pay_date', + last_direct_pay_amount: 'last_direct_pay_amount', + number_of_direct_pay_in_12_months: 'number_of_direct_pay_in_12_months', + ...LegacyAccountAttributeNames, + ...StaticAccountAttributeNames, } as const; -export type TAccountAttributeNames = keyof typeof AccountAttributeNames; +export type TAccountAttributeNames = typeof AccountAttributeNames[keyof typeof AccountAttributeNames]; +export type TAccountRequestableAttributeNames = Exclude< + TAccountAttributeNames, + TStaticAccountAttributeNames | TLegacyAccountAttributeNames +>; export interface IAccountAttribute { value: T | null; - error: IResourceError | null; + error?: IResourceError | null; + metadata?: Record | null; } export interface IAccountAttributesType { type?: IAccountAttribute; usage_pattern?: IAccountAttribute; - delinquency_flag?: IAccountAttribute; + delinquency_flag?: IAccountAttribute; utilization?: IAccountAttribute; - utilization_trend_30d?: IAccountAttribute; - utilization_trend_90d?: IAccountAttribute; + utilization_trend_30d?: IAccountAttribute; + utilization_trend_90d?: IAccountAttribute; utilization_delta_30d?: IAccountAttribute; utilization_delta_60d?: IAccountAttribute; utilization_delta_90d?: IAccountAttribute; monthly_installments_estimate?: IAccountAttribute; + heloc_utilization?: IAccountAttribute; + available_credit_limit?: IAccountAttribute; + available_loan_amount?: IAccountAttribute; + any_delinquent_flag?: IAccountAttribute; + serious_delinquent_flag?: IAccountAttribute; + delinquency_recently_cured_flag?: IAccountAttribute; + delinquency_worst_dpd_bucket?: IAccountAttribute; + delinquency_progression_flag?: IAccountAttribute; + delinquent_outcome?: IAccountAttribute; + next_payment_due_date?: IAccountAttribute; + next_payment_minimum_amount?: IAccountAttribute; + estimated_apr?: IAccountAttribute; + utilization_bucket?: IAccountAttribute; + purchasing_power?: IAccountAttribute; + account_age?: IAccountAttribute; + utilization_velocity_4_week?: IAccountAttribute; + utilization_velocity_8_week?: IAccountAttribute; + utilization_velocity_12_week?: IAccountAttribute; + weeks_since_last_activity?: IAccountAttribute; + recent_balance_spike_flag?: IAccountAttribute; + spend_concentration_4_week?: IAccountAttribute; + spend_concentration_8_week?: IAccountAttribute; + spend_concentration_12_week?: IAccountAttribute; + current_wallet_rank?: IAccountAttribute; + brand_category?: IAccountAttribute; + brand_tier?: IAccountAttribute; + enrolled_in_direct_pay_previously?: IAccountAttribute; + last_direct_pay_date?: IAccountAttribute; + last_direct_pay_amount?: IAccountAttribute; + number_of_direct_pay_in_12_months?: IAccountAttribute; + debt_settlement?: IAccountAttribute; + interest_estimate_min?: IAccountAttribute; + interest_estimate_max?: IAccountAttribute; + account_standing?: IAccountAttribute; + delinquent_period?: IAccountAttribute; + delinquent_amount?: IAccountAttribute; } +export interface IAccountAttributesCreateOpts { + requested_attributes?: TAccountRequestableAttributeNames[]; + bundles?: TAccountAttributeBundles[]; +} + +export type TAccountAttributeRequestScope = + | { + requested_attributes: TAccountRequestableAttributeNames[]; + bundles?: TAccountAttributeBundles[]; + } + | { + requested_attributes?: TAccountRequestableAttributeNames[]; + bundles: TAccountAttributeBundles[]; + }; + export interface IAccountAttributes { id: string; account_id: string; @@ -772,9 +940,9 @@ export interface IAccount { liability?: IAccountLiability | null; products: TAccountProducts[]; restricted_products: TAccountProducts[]; - subscriptions?: TAccountSubscriptionTypes[]; - available_subscriptions?: TAccountSubscriptionTypes[]; - restricted_subscriptions?: TAccountSubscriptionTypes[]; + subscriptions?: TAccountSubscriptionNames[]; + available_subscriptions?: TAccountSubscriptionNames[]; + restricted_subscriptions?: TAccountSubscriptionNames[]; sensitive?: string | IAccountSensitive | null; balance?: string | IAccountBalance | null; card_brand?: string | IAccountCardBrand | null; diff --git a/src/resources/Entity/Attributes.ts b/src/resources/Entity/Attributes.ts index c814cdd..c612aa0 100644 --- a/src/resources/Entity/Attributes.ts +++ b/src/resources/Entity/Attributes.ts @@ -37,7 +37,7 @@ export default class EntityAttributes extends Resource { * @returns Returns an Entity’s Attributes object. */ - async create(opts: IEntityAttributesCreateOpts) { + async create(opts: IEntityAttributesCreateOpts = {}) { return super._create, IEntityAttributesCreateOpts>(opts); } }; diff --git a/src/resources/Entity/Connect.ts b/src/resources/Entity/Connect.ts index 99acfce..a412967 100644 --- a/src/resources/Entity/Connect.ts +++ b/src/resources/Entity/Connect.ts @@ -1,6 +1,6 @@ import Resource, { IResourceListOpts, IRequestConfig } from '../../resource'; import Configuration, { IResponse } from '../../configuration'; -import type { IEntityConnect } from './types'; +import type { IEntityConnect, TEntityConnectArtifactTypes, TEntityConnectFileBureaus } from './types'; export const AccountExpandableFields = { sensitive: 'sensitive', @@ -24,6 +24,8 @@ export interface IExpandableOpts { export interface IConnectListOpts extends IResourceListOpts, IExpandableOpts {} +export type IConnectRetrieveOpts = IExpandableOpts; + export const AccountProductsEligibleForAutomaticExecution = [ 'attribute', 'balance', @@ -42,11 +44,21 @@ export const AccountSubscriptionsEligibleForAutomaticExecution = [ export type AccountProduct = typeof AccountProductsEligibleForAutomaticExecution[number]; export type AccountSubscription = typeof AccountSubscriptionsEligibleForAutomaticExecution[number]; -export interface IConnectCreateOpts { +interface IConnectCreateOptsBase { products?: AccountProduct[]; subscriptions?: AccountSubscription[]; } +export type IConnectCreateOpts = + | (IConnectCreateOptsBase & { + artifacts: TEntityConnectArtifactTypes[]; + bureau: TEntityConnectFileBureaus; + }) + | (IConnectCreateOptsBase & { + artifacts?: never; + bureau?: TEntityConnectFileBureaus; + }); + export default class EntityConnect extends Resource { constructor(config: Configuration) { @@ -61,7 +73,7 @@ export default class EntityConnect extends Resource { * @returns Returns a Connect object. */ - async retrieve(cxn_id: string, opts: IExpandableOpts = {}) { + async retrieve(cxn_id: string, opts: IConnectRetrieveOpts = {}) { return super._getWithSubPathAndParams>(cxn_id, opts); } diff --git a/src/resources/Entity/types.ts b/src/resources/Entity/types.ts index f96b13f..cd6179e 100644 --- a/src/resources/Entity/types.ts +++ b/src/resources/Entity/types.ts @@ -3,7 +3,7 @@ import type { TResourceStatus, IResourceListOpts, } from '../../resource'; -import { TAccountProducts, TAccountSubscriptionTypes } from '../Account'; +import type { IAccount, TAccountProducts, TAccountSubscriptionTypes } from '../Account'; export const CreditReportBureaus = { experian: 'experian', @@ -115,13 +115,36 @@ export interface IEntityVerification { phone?: IEntityVerificationPhone; }; +export const EntityConnectArtifactTypes = { + raw_credit_report: 'raw_credit_report', + credit_report_pdf: 'credit_report_pdf', +} as const; + +export type TEntityConnectArtifactTypes = typeof EntityConnectArtifactTypes[keyof typeof EntityConnectArtifactTypes]; + +export const EntityConnectFileBureaus = { + equifax: 'equifax', + transunion: 'transunion', +} as const; + +export type TEntityConnectFileBureaus = typeof EntityConnectFileBureaus[keyof typeof EntityConnectFileBureaus]; + +export interface IEntityConnectFile { + id: string; + type: TEntityConnectArtifactTypes; + bureau: TEntityConnectFileBureaus; + mime_type: string; +}; + export interface IEntityConnect { id: string; entity_id: string; status: TResourceStatus; - accounts: string[] | null; + accounts: (string | IAccount)[] | null; requested_products: TAccountProducts[]; requested_subscriptions: TAccountSubscriptionTypes[]; + files: IEntityConnectFile[]; + credit_reports?: Record | null; error: IResourceError | null; created_at: string; updated_at: string; @@ -160,35 +183,62 @@ export interface IEntityCreditScores { export interface IEntityAttribute { value: T | null; error: IResourceError | null; + metadata: Record | null; +} + +export interface ICreditHealthAttribute { + value: T | null; + rating: string; + metadata?: Record | null; } export interface IEntityAttributesType { revolving_credit_card_balance_total?: IEntityAttribute; credit_limit_total?: IEntityAttribute; credit_card_utilization?: IEntityAttribute; + available_credit_limit_total?: IEntityAttribute; + available_credit_total?: IEntityAttribute; weighted_average_apr_credit_card?: IEntityAttribute; usage_pattern?: IEntityAttribute; + utilization?: IEntityAttribute; + purchasing_power?: IEntityAttribute; + healthy_cards_count?: IEntityAttribute; + dormant_cards_count?: IEntityAttribute; + delinquent_cards_count?: IEntityAttribute; + net_active_cards_count?: IEntityAttribute; + utilization_velocity_4_week?: IEntityAttribute; + utilization_velocity_8_week?: IEntityAttribute; + utilization_velocity_12_week?: IEntityAttribute; next_payment_minimum_total_credit_cards?: IEntityAttribute; payment_to_minimum_ratio_avg_credit_cards?: IEntityAttribute; revolving_credit_card_balance_change_30d?: IEntityAttribute; revolving_credit_card_balance_change_60d?: IEntityAttribute; revolving_credit_card_balance_change_90d?: IEntityAttribute; - revolving_credit_card_utilization_trend_30d?: IEntityAttribute; - revolving_credit_card_utilization_trend_90d?: IEntityAttribute; + revolving_credit_card_utilization_trend_30d?: IEntityAttribute; + revolving_credit_card_utilization_trend_90d?: IEntityAttribute; revolving_credit_card_utilization_delta_30d?: IEntityAttribute; revolving_credit_card_utilization_delta_60d?: IEntityAttribute; revolving_credit_card_utilization_delta_90d?: IEntityAttribute; - delinquency_flag_credit_cards?: IEntityAttribute; + delinquency_flag_credit_cards?: IEntityAttribute; + any_delinquent_flag?: IEntityAttribute; + serious_delinquent_flag?: IEntityAttribute; + delinquency_recently_cured_flag?: IEntityAttribute; + delinquency_worst_dpd_bucket?: IEntityAttribute; + delinquency_accounts_count?: IEntityAttribute; + delinquent_balance_total?: IEntityAttribute; + delinquency_progression_flag?: IEntityAttribute; + delinquent_outcome?: IEntityAttribute; personal_loan_balance_total?: IEntityAttribute; personal_loan_amount_total?: IEntityAttribute; + available_loan_amount_personal_loans?: IEntityAttribute; personal_loan_monthly_installments_estimate?: IEntityAttribute; personal_loan_utilization?: IEntityAttribute; weighted_average_apr_personal_loan?: IEntityAttribute; personal_loan_balance_change_30d?: IEntityAttribute; personal_loan_balance_change_60d?: IEntityAttribute; personal_loan_balance_change_90d?: IEntityAttribute; - personal_loan_utilization_trend_30d?: IEntityAttribute; - personal_loan_utilization_trend_90d?: IEntityAttribute; + personal_loan_utilization_trend_30d?: IEntityAttribute; + personal_loan_utilization_trend_90d?: IEntityAttribute; personal_loan_utilization_delta_30d?: IEntityAttribute; personal_loan_utilization_delta_60d?: IEntityAttribute; personal_loan_utilization_delta_90d?: IEntityAttribute; @@ -198,15 +248,17 @@ export interface IEntityAttributesType { mortgage_balance_change_30d?: IEntityAttribute; mortgage_balance_change_60d?: IEntityAttribute; mortgage_balance_change_90d?: IEntityAttribute; - mortgage_utilization_trend_30d?: IEntityAttribute; - mortgage_utilization_trend_90d?: IEntityAttribute; + mortgage_utilization_trend_30d?: IEntityAttribute; + mortgage_utilization_trend_90d?: IEntityAttribute; mortgage_utilization_delta_30d?: IEntityAttribute; mortgage_utilization_delta_60d?: IEntityAttribute; mortgage_utilization_delta_90d?: IEntityAttribute; + heloc_balance_total?: IEntityAttribute; + heloc_utilization?: IEntityAttribute; overall_loan_amount_total?: IEntityAttribute; overall_utilization?: IEntityAttribute; - overall_utilization_trend_30d?: IEntityAttribute; - overall_utilization_trend_90d?: IEntityAttribute; + overall_utilization_trend_30d?: IEntityAttribute; + overall_utilization_trend_90d?: IEntityAttribute; overall_utilization_delta_30d?: IEntityAttribute; overall_utilization_delta_60d?: IEntityAttribute; overall_utilization_delta_90d?: IEntityAttribute; @@ -218,23 +270,52 @@ export interface IEntityAttributesType { other_balance_change_30d?: IEntityAttribute; other_balance_change_60d?: IEntityAttribute; other_balance_change_90d?: IEntityAttribute; - credit_health_credit_card_usage?: IEntityAttribute; - credit_health_derogatory_marks?: IEntityAttribute; - credit_health_hard_inquiries?: IEntityAttribute; - credit_health_soft_inquiries?: IEntityAttribute; - credit_health_total_accounts?: IEntityAttribute; - credit_health_credit_age?: IEntityAttribute; - credit_health_payment_history?: IEntityAttribute; - credit_health_open_accounts?: IEntityAttribute; - credit_health_entity_delinquent?: IEntityAttribute; + enrolled_in_direct_pay_previously?: IEntityAttribute; + last_direct_pay_date?: IEntityAttribute; + last_direct_pay_amount?: IEntityAttribute; + number_of_direct_pay_in_12_months?: IEntityAttribute; + credit_health_credit_card_usage?: ICreditHealthAttribute; + credit_health_derogatory_marks?: ICreditHealthAttribute; + credit_health_hard_inquiries?: ICreditHealthAttribute; + credit_health_soft_inquiries?: ICreditHealthAttribute; + credit_health_total_accounts?: ICreditHealthAttribute; + credit_health_credit_age?: ICreditHealthAttribute; + credit_health_payment_history?: ICreditHealthAttribute; + credit_health_open_accounts?: ICreditHealthAttribute; + credit_health_entity_delinquent?: ICreditHealthAttribute; } +export const LegacyEntityAttributeNames = { + credit_health_credit_card_usage: 'credit_health_credit_card_usage', + credit_health_derogatory_marks: 'credit_health_derogatory_marks', + credit_health_hard_inquiries: 'credit_health_hard_inquiries', + credit_health_soft_inquiries: 'credit_health_soft_inquiries', + credit_health_total_accounts: 'credit_health_total_accounts', + credit_health_credit_age: 'credit_health_credit_age', + credit_health_payment_history: 'credit_health_payment_history', + credit_health_open_accounts: 'credit_health_open_accounts', + credit_health_entity_delinquent: 'credit_health_entity_delinquent', +} as const; + +export type TLegacyEntityAttributeNames = typeof LegacyEntityAttributeNames[keyof typeof LegacyEntityAttributeNames]; + export const EntityAttributeNames = { revolving_credit_card_balance_total: 'revolving_credit_card_balance_total', credit_limit_total: 'credit_limit_total', credit_card_utilization: 'credit_card_utilization', + available_credit_limit_total: 'available_credit_limit_total', + available_credit_total: 'available_credit_total', weighted_average_apr_credit_card: 'weighted_average_apr_credit_card', usage_pattern: 'usage_pattern', + utilization: 'utilization', + purchasing_power: 'purchasing_power', + healthy_cards_count: 'healthy_cards_count', + dormant_cards_count: 'dormant_cards_count', + delinquent_cards_count: 'delinquent_cards_count', + net_active_cards_count: 'net_active_cards_count', + utilization_velocity_4_week: 'utilization_velocity_4_week', + utilization_velocity_8_week: 'utilization_velocity_8_week', + utilization_velocity_12_week: 'utilization_velocity_12_week', next_payment_minimum_total_credit_cards: 'next_payment_minimum_total_credit_cards', payment_to_minimum_ratio_avg_credit_cards: 'payment_to_minimum_ratio_avg_credit_cards', revolving_credit_card_balance_change_30d: 'revolving_credit_card_balance_change_30d', @@ -246,8 +327,17 @@ export const EntityAttributeNames = { revolving_credit_card_utilization_delta_60d: 'revolving_credit_card_utilization_delta_60d', revolving_credit_card_utilization_delta_90d: 'revolving_credit_card_utilization_delta_90d', delinquency_flag_credit_cards: 'delinquency_flag_credit_cards', + any_delinquent_flag: 'any_delinquent_flag', + serious_delinquent_flag: 'serious_delinquent_flag', + delinquency_recently_cured_flag: 'delinquency_recently_cured_flag', + delinquency_worst_dpd_bucket: 'delinquency_worst_dpd_bucket', + delinquency_accounts_count: 'delinquency_accounts_count', + delinquent_balance_total: 'delinquent_balance_total', + delinquency_progression_flag: 'delinquency_progression_flag', + delinquent_outcome: 'delinquent_outcome', personal_loan_balance_total: 'personal_loan_balance_total', personal_loan_amount_total: 'personal_loan_amount_total', + available_loan_amount_personal_loans: 'available_loan_amount_personal_loans', personal_loan_monthly_installments_estimate: 'personal_loan_monthly_installments_estimate', personal_loan_utilization: 'personal_loan_utilization', weighted_average_apr_personal_loan: 'weighted_average_apr_personal_loan', @@ -270,6 +360,8 @@ export const EntityAttributeNames = { mortgage_utilization_delta_30d: 'mortgage_utilization_delta_30d', mortgage_utilization_delta_60d: 'mortgage_utilization_delta_60d', mortgage_utilization_delta_90d: 'mortgage_utilization_delta_90d', + heloc_balance_total: 'heloc_balance_total', + heloc_utilization: 'heloc_utilization', overall_loan_amount_total: 'overall_loan_amount_total', overall_utilization: 'overall_utilization', overall_utilization_trend_30d: 'overall_utilization_trend_30d', @@ -285,21 +377,26 @@ export const EntityAttributeNames = { other_balance_change_30d: 'other_balance_change_30d', other_balance_change_60d: 'other_balance_change_60d', other_balance_change_90d: 'other_balance_change_90d', - credit_health_credit_card_usage: 'credit_health_credit_card_usage', - credit_health_derogatory_marks: 'credit_health_derogatory_marks', - credit_health_hard_inquiries: 'credit_health_hard_inquiries', - credit_health_soft_inquiries: 'credit_health_soft_inquiries', - credit_health_total_accounts: 'credit_health_total_accounts', - credit_health_credit_age: 'credit_health_credit_age', - credit_health_payment_history: 'credit_health_payment_history', - credit_health_open_accounts: 'credit_health_open_accounts', - credit_health_entity_delinquent: 'credit_health_entity_delinquent', + enrolled_in_direct_pay_previously: 'enrolled_in_direct_pay_previously', + last_direct_pay_date: 'last_direct_pay_date', + last_direct_pay_amount: 'last_direct_pay_amount', + number_of_direct_pay_in_12_months: 'number_of_direct_pay_in_12_months', + ...LegacyEntityAttributeNames, +} as const; + +export type TEntityAttributeNames = typeof EntityAttributeNames[keyof typeof EntityAttributeNames]; +export type TEntityRequestableAttributeNames = Exclude; + +export const EntityAttributeBundles = { + portfolio_intelligence: 'portfolio_intelligence', + wallet_intelligence: 'wallet_intelligence', } as const; -export type TEntityAttributeNames = keyof typeof EntityAttributeNames; +export type TEntityAttributeBundles = typeof EntityAttributeBundles[keyof typeof EntityAttributeBundles]; export interface IEntityAttributesCreateOpts { - attributes: TEntityAttributeNames[]; + requested_attributes?: TEntityRequestableAttributeNames[]; + bundles?: TEntityAttributeBundles[]; } export interface IEntityAttributes { @@ -398,11 +495,26 @@ export type TEntitySubscriptionStatuses = keyof typeof EntitySubscriptionStatuse export interface IEntitySubscriptionPayload { attributes?: { - requested_attributes: TEntityAttributeNames[]; - version?: string; + requested_attributes?: TEntityAttributeNames[]; + bundles?: TEntityAttributeBundles[]; + version?: 'v1' | 'v2'; } | null; }; +export type TEntityAttributeRequestScope = + | { + requested_attributes: TEntityRequestableAttributeNames[]; + bundles?: TEntityAttributeBundles[]; + } + | { + requested_attributes?: TEntityRequestableAttributeNames[]; + bundles: TEntityAttributeBundles[]; + }; + +export interface IEntitySubscriptionCreatePayload { + attributes?: TEntityAttributeRequestScope; +}; + export interface IEntitySubscription { id: string; name: TEntitySubscriptionNames; @@ -421,7 +533,7 @@ export interface IEntitySubscriptionResponse { export interface IEntitySubscriptionCreateOpts { enroll: TEntitySubscriptionNames; - payload?: IEntitySubscriptionPayload; + payload?: IEntitySubscriptionCreatePayload; }; export const EntityVerificationSessionStatuses = { diff --git a/src/resources/Payment/types.ts b/src/resources/Payment/types.ts index 010b13e..2e3a9a2 100644 --- a/src/resources/Payment/types.ts +++ b/src/resources/Payment/types.ts @@ -11,13 +11,23 @@ export const PaymentStatuses = { reversal_required: 'reversal_required', reversal_processing: 'reversal_processing', settled: 'settled', - cashed: 'cashed', } as const; export type TPaymentStatuses = keyof typeof PaymentStatuses; +export const PaymentDirectionStatuses = { + pending: 'pending', + canceled: 'canceled', + processing: 'processing', + sent: 'sent', + posted: 'posted', + cashed: 'cashed', + returned: 'returned', +} as const; + +export type TPaymentDirectionStatuses = keyof typeof PaymentDirectionStatuses; + export const PaymentFundStatuses = { - hold: 'hold', pending: 'pending', requested: 'requested', clearing: 'clearing', @@ -38,7 +48,6 @@ export type TPaymentTypes = keyof typeof PaymentTypes; export const PaymentFeeTypes = { total: 'total', - markup: 'markup', } as const; export type TPaymentFeeTypes = keyof typeof PaymentFeeTypes; @@ -63,7 +72,7 @@ export interface IPayment { source: string; destination: string; amount: number; - description: string; + description: string | null; status: TPaymentStatuses; fund_status?: TPaymentFundStatuses; error: IResourceError | null; @@ -71,13 +80,14 @@ export interface IPayment { estimated_completion_date: string | null; source_settlement_date: string | null; destination_settlement_date: string | null; - source_status: TPaymentStatuses; - destination_status: TPaymentStatuses; - destination_payment_method?: TPaymentDestinationPaymentMethods | null; + destination_posted_date: string | null; + source_status: TPaymentDirectionStatuses | null; + destination_status: TPaymentDirectionStatuses | null; + destination_payment_method?: TPaymentDestinationPaymentMethods; fee: IPaymentFee | null; - idempotency_key?: string | null; - payment_instrument?: string | null; - reversal_account?: string | null; + idempotency_key: string | null; + payment_instrument: string | null; + reversal_account: string | null; type: TPaymentTypes; created_at: string; updated_at: string; diff --git a/test/resources/Account.tests.ts b/test/resources/Account.tests.ts index d18dcec..4d38f43 100644 --- a/test/resources/Account.tests.ts +++ b/test/resources/Account.tests.ts @@ -4,6 +4,8 @@ import { client } from '../config'; import { awaitResults } from '../utils'; import type { IEntity, IEntityConnect } from '../../src/resources/Entity'; import { + AccountAttributeNames, + LegacyAccountAttributeNames, type IAccount, type IAccountBalance, type IAccountCardBrand, @@ -24,6 +26,23 @@ import { IResponse } from '../../src/configuration'; should(); +describe('Account public attribute names', () => { + it('should expose legacy response-only attribute names', () => { + Object.keys(LegacyAccountAttributeNames).sort().should.be.eql([ + 'account_standing', + 'debt_settlement', + 'delinquent_amount', + 'delinquent_period', + 'interest_estimate_max', + 'interest_estimate_min', + ].sort()); + + Object.values(LegacyAccountAttributeNames).forEach((name) => { + AccountAttributeNames.should.have.property(name, name); + }); + }); +}); + describe('Accounts - core methods tests', () => { let holder_1_response: IResponse; let holder_connect_response: IResponse; @@ -148,13 +167,15 @@ describe('Accounts - core methods tests', () => { ownership: 'unknown', type: 'credit_card', sub_type: 'flexible_spending', - name: accounts_create_liability_response.liability?.name || null + name: accounts_create_liability_response.liability?.name || null, + network: null, }, latest_verification_session: accounts_create_liability_response.latest_verification_session, balance: null, attribute: null, update: accounts_create_liability_response.update, card_brand: null, + payment_instrument: null, payoff: null, products: accounts_create_liability_response.products, restricted_products: accounts_create_liability_response.restricted_products, @@ -304,9 +325,6 @@ describe('Accounts - core methods tests', () => { status: 'in_progress', shared: false, source: null, - issuer: card_create_response.issuer, - last4: card_create_response.last4, - network: card_create_response.network, error: null, created_at: card_create_response.created_at, updated_at: card_create_response.updated_at @@ -343,8 +361,10 @@ describe('Accounts - core methods tests', () => { expect(brand.name).to.equal('Chase Sapphire Reserve'); expect(brand.issuer).to.equal('Chase'); expect(brand.network).to.equal('visa'); + expect(brand.network_tier).to.equal('infinite'); expect(brand.type).to.equal('specific'); expect(brand.url).to.equal('https://static.methodfi.com/card_brands/1b7ccaba6535cb837f802d968add4700.png'); + expect(brand).to.have.property('details'); }); it('should successfully list card brands for an account.', async () => { @@ -371,8 +391,10 @@ describe('Accounts - core methods tests', () => { expect(brand.name).to.equal('Chase Sapphire Reserve'); expect(brand.issuer).to.equal('Chase'); expect(brand.network).to.equal('visa'); + expect(brand.network_tier).to.equal('infinite'); expect(brand.type).to.equal('specific'); expect(brand.url).to.equal('https://static.methodfi.com/card_brands/1b7ccaba6535cb837f802d968add4700.png'); + expect(brand).to.have.property('details'); }); }); @@ -920,6 +942,7 @@ describe('Accounts - core methods tests', () => { interest_rate_percentage_min: null, available_credit: null, credit_limit: null, + past_due_status: null, usage_pattern: null }, data_as_of: null, @@ -962,6 +985,7 @@ describe('Accounts - core methods tests', () => { interest_rate_percentage_min: 20.5, available_credit: 930000, credit_limit: 2800000, + past_due_status: retrieve_updates_response.credit_card?.past_due_status ?? null, usage_pattern: null }, data_as_of: retrieve_updates_response.data_as_of, @@ -1100,7 +1124,7 @@ describe('Accounts - core methods tests', () => { status_error: null, latest_request_id: accounts_retrieve_product_list_response.attribute?.latest_request_id || null, latest_successful_request_id: accounts_retrieve_product_list_response.attribute?.latest_successful_request_id || null, - is_subscribable: false, + is_subscribable: true, created_at: accounts_retrieve_product_list_response.attribute?.created_at || '', updated_at: accounts_retrieve_product_list_response.attribute?.updated_at || '' }, diff --git a/test/resources/Entity.tests.ts b/test/resources/Entity.tests.ts index b405ad4..c3bd0b0 100644 --- a/test/resources/Entity.tests.ts +++ b/test/resources/Entity.tests.ts @@ -491,6 +491,7 @@ describe('Entities - core methods tests', () => { accounts: entities_account_ids, requested_products: [], requested_subscriptions: [], + files: [], error: null, created_at: entities_connect_create_response.created_at, updated_at: entities_connect_create_response.updated_at, @@ -513,6 +514,7 @@ describe('Entities - core methods tests', () => { accounts: entities_account_ids, requested_products: [], requested_subscriptions: [], + files: [], error: null, created_at: entities_connect_create_response.created_at, updated_at: entities_connect_create_response.updated_at, @@ -535,6 +537,7 @@ describe('Entities - core methods tests', () => { accounts: entities_account_ids, requested_products: [], requested_subscriptions: [], + files: [], error: null, created_at: entities_connect_create_response.created_at, updated_at: entities_connect_create_response.updated_at, @@ -562,6 +565,7 @@ describe('Entities - core methods tests', () => { accounts: null, requested_products: ['card_brand'], requested_subscriptions: ['update'], + files: [], error: null, created_at: entities_connect_create_response_async.created_at, updated_at: entities_connect_create_response_async.updated_at, @@ -589,6 +593,7 @@ describe('Entities - core methods tests', () => { accounts: entities_connect_results_response_async.accounts, requested_products: ['card_brand'], requested_subscriptions: ['update'], + files: [], error: null, created_at: entities_connect_results_response_async.created_at, updated_at: entities_connect_results_response_async.updated_at, @@ -744,7 +749,7 @@ describe('Entities - core methods tests', () => { entities_create_attribute_response = await client .entities(entities_create_response.id) .attributes.create({ - attributes: [EntityAttributeNames.credit_health_credit_card_usage] + requested_attributes: [EntityAttributeNames.credit_card_utilization] }); const expect_results: IEntityAttributes = { diff --git a/test/resources/Event.tests.ts b/test/resources/Event.tests.ts index 9d8013c..d8c4ae3 100644 --- a/test/resources/Event.tests.ts +++ b/test/resources/Event.tests.ts @@ -54,7 +54,7 @@ describe('Events - core methods tests', () => { }); attribute_response = await client.entities(entity_response.id).attributes.create({ - attributes: [EntityAttributeNames.credit_health_credit_card_usage], + requested_attributes: [EntityAttributeNames.credit_card_utilization], }); credit_score_response = await client.entities(entity_response.id).creditScores.create(); diff --git a/test/resources/Payment.tests.ts b/test/resources/Payment.tests.ts index a075dd1..7ab2e61 100644 --- a/test/resources/Payment.tests.ts +++ b/test/resources/Payment.tests.ts @@ -3,11 +3,56 @@ import { describe } from 'mocha'; import { client } from '../config'; import type { IEntity } from '../../src/resources/Entity'; import type { IAccount } from '../../src/resources/Account'; +import { + PaymentDirectionStatuses, + PaymentFundStatuses, + PaymentStatuses, +} from '../../src/resources/Payment'; import type { IPayment } from '../../src/resources/Payment'; import { IResponse } from '../../src/configuration'; +import { PaymentDirectionStatuses as RootPaymentDirectionStatuses } from '../../index'; should(); +describe('Payment public response statuses', () => { + it('should expose only statuses serialized by Octo for each public field', () => { + RootPaymentDirectionStatuses.should.equal(PaymentDirectionStatuses); + + Object.keys(PaymentStatuses).sort().should.be.eql([ + 'canceled', + 'failed', + 'pending', + 'posted', + 'processing', + 'reversal_processing', + 'reversal_required', + 'reversed', + 'sent', + 'settled', + ].sort()); + + Object.keys(PaymentDirectionStatuses).sort().should.be.eql([ + 'canceled', + 'cashed', + 'pending', + 'posted', + 'processing', + 'returned', + 'sent', + ].sort()); + + Object.keys(PaymentFundStatuses).sort().should.be.eql([ + 'clearing', + 'failed', + 'pending', + 'posted', + 'requested', + 'sent', + 'unknown', + ].sort()); + }); +}); + describe('Payments - core methods tests', () => { let holder_1_response: IResponse; let source_1_response: IResponse; @@ -84,7 +129,9 @@ describe('Payments - core methods tests', () => { source_status: 'pending', destination_trace_id: null, destination_settlement_date: payments_create_response.destination_settlement_date, + destination_posted_date: null, destination_status: 'pending', + destination_payment_method: 'electronic', reversal_id: null, fee: null, idempotency_key: payments_create_response.idempotency_key, @@ -118,7 +165,9 @@ describe('Payments - core methods tests', () => { source_status: 'pending', destination_trace_id: null, destination_settlement_date: payments_create_response.destination_settlement_date, + destination_posted_date: null, destination_status: 'pending', + destination_payment_method: 'electronic', reversal_id: null, fee: null, idempotency_key: payments_retrieve_response.idempotency_key, @@ -162,7 +211,9 @@ describe('Payments - core methods tests', () => { source_status: 'canceled', destination_trace_id: null, destination_settlement_date: payments_create_response.destination_settlement_date, + destination_posted_date: null, destination_status: 'canceled', + destination_payment_method: 'electronic', reversal_id: null, fee: null, idempotency_key: payments_delete_response.idempotency_key,