Migration guide
Upgrade an existing Core Exchange integration to get the latest functionality
This guide covers every breaking change and major new capability added to Core Exchange from v4.6 through v6.4, in version order. Each item is tagged with the version that introduced it. For the full field-by-field history, see the Changelog.
Why migrate
v6.x is the current Core Exchange specification, aligned with FDX 6.x, and each version since v4.6 has added capabilities that aren't available on earlier ones — see New capabilities by version below.
New capabilities by version
- v5.0 — An
AUTHORIZED_USERaccount holder relationship type. - v5.1 — Digital asset holdings and securities (
DIGITALASSET), and theUS_RTPreal-time payment network. - v5.2 —
GET /accounts/{accountId}/statementsandGET /accounts/{accountId}/statements/{statementId}, for retrieving account statements. Business customer support (BusinessCustomer), so/customers/currentcan represent a business rather than only an individual. Canadian retirement and tax-advantaged investment account types. - v5.3 — A dedicated
CommercialAccountType(see Commercial account types moved to their own schema). - v6.0 —
GET /accounts/{accountId}/asset-transfer-networks, which returns the identifiers needed to submit an inter-institution investment account transfer (ACATS, DTC, or ATON). See New endpoint: asset transfer networks. - v6.2 — Digital wallet accounts (
DIGITAL_WALLETcategory), theZWGcurrency code, and aPREPAIDinvestment account type. - v6.3 —
pageKey-based pagination on list endpoints, new savings account types, expanded contact fields (authorized signers, phone number type/network/primary), student loan details (currentSchool,loanProviderName), masked card numbers on transactions, and date-range filtering on statements and transactions. - v6.4 — Interest-rate reporting on deposit, investment, loan, and line-of-credit accounts; overdraft fields on deposit accounts; scheduled payments and bills on line-of-credit accounts; loan APR; and a
productIdon account descriptors.
Breaking changes
Some date-time fields converted to date only (v5.0 and later)
Certain fields that were inappropriately treated as date-time but actually represent dates were changed to date fields. Impacted fields are: LoanAccount.originatingDate, nextPaymentDate, lastPaymentDate, and maturityDate; LineOfCreditAccount.nextPaymentDate, lastPaymentDate, and lastStmtDate; and Holding.currentUnitPriceDate and TaxLot.originalPurchaseDate
{
"maturityDate": "2050-07-15T00:00:00.000Z"
}{
"maturityDate": "2050-07-15"
}What to update: if you send a full timestamp for any of these fields, truncate it to the date component.
state renamed to region on Address (v5.0 and later)
The state property on the Address schema was renamed to region.
What to update: any response-mapping code that sets state needs to set region instead.
Country and currency codes updated (v5.3 and later)
Country codes moved to the ISO 3166-1 alpha-2 standard, and currency codes were updated to the ISO 4217 list current as of January 1, 2023. AN and CS are no longer valid country codes; HRK is no longer a valid currency code.
What to update: For HRK (Croatian kuna), return EUR instead, as Croatia has adopted the euro. For AN (Netherlands Antilles) and CS (Serbia and Montenegro) map each account to the appropriate code: CW (Curaçao), SX (Sint Maarten), or BQ (Bonaire, Sint Eustatius and Saba) for former AN accounts, and RS (Serbia) or ME (Montenegro) for former CS accounts.
Commercial account types moved to their own schema (v5.3 and later)
COMMERCIALDEPOSIT, COMMERCIALLOAN, COMMERCIALLINEOFCREDIT, and COMMERCIALINVESTMENT are no longer valid values of DepositAccountType, LoanAccountType, LocAccountType, and InvestmentAccountType. They're now reported under a dedicated CommercialAccountType, using a new commercialAccount wrapper key in the /accounts list response:
{
"depositAccount": {
"accountType": "COMMERCIALDEPOSIT"
}
}{
"commercialAccount": {
"accountType": "COMMERCIALDEPOSIT"
}
}What to update: if you report commercial accounts, switch them from their prior account-type wrapper to commercialAccount.
Account and transaction responses are no longer wrapped (v6.0 and later)
GET /accounts, GET /accounts/{accountId}, and GET /accounts/{accountId}/transactions no longer wrap the account or transaction object in a named property that identified its type (for example depositAccount or depositTransaction). Each object is returned directly and must carry a required discriminator field, accountCategory, identifying its type:
{
"depositAccount": {
"accountId": "12345",
"accountNumberDisplay": "...5678"
}
}{
"accountCategory": "DEPOSIT_ACCOUNT",
"accountId": "12345",
"accountNumberDisplay": "...5678"
}The accepted values differ by endpoint:
| Endpoint | Accepted accountCategory values |
|---|---|
GET /accounts | ANNUITY_ACCOUNT, COMMERCIAL_ACCOUNT, DEPOSIT_ACCOUNT, DIGITAL_WALLET (v6.2 and later), INSURANCE_ACCOUNT, INVESTMENT_ACCOUNT, LOAN_ACCOUNT, LOC_ACCOUNT |
GET /accounts/{accountId} | DEPOSIT_ACCOUNT, INVESTMENT_ACCOUNT, LOAN_ACCOUNT, LOC_ACCOUNT |
GET /accounts/{accountId}/transactions | DEPOSIT_ACCOUNT, INVESTMENT_ACCOUNT, LOAN_ACCOUNT, LOC_ACCOUNT |
The accountCategory field itself is new in v6.0; the categories it names correspond to the wrapper keys it replaces.
What to update: any response-mapping code keyed on the wrapper property name (depositAccount, investmentAccount, etc.) needs to key on accountCategory instead, and your mapping must explicitly set that field on every account and transaction you return.
Investment holdings use a securityIds array (v6.0 and later)
An investment holding previously identified its security with a single securityId/securityIdType pair. That pair is replaced by a securityIds array of { id, idType } objects, allowing a holding to report multiple identifier types for the same security.
{
"securityId": "037833100",
"securityIdType": "CUSIP"
}{
"securityIds": [{ "id": "037833100", "idType": "CUSIP" }]
}What to update: map your existing single identifier into a one-element securityIds array at minimum; add additional entries if you have more than one identifier type available for a security.
Telephone number country format has stricter validation (v6.3 and later)
telephones[].country now must match the pattern of an optional leading + followed by 1-3 digits, no leading zero. (Previously any string up to 3 characters was accepted.) maxLength also increased from 3 to 4 to accommodate the optional +.
What to update: confirm every telephones[].country value you send is valid.
Non-breaking changes
Statement status is no longer a fixed set of values (v6.2 and later)
The statement status enum, which had constrained the field to AVAILABLE, PROCESSING, and FAILED, was removed entirely. status is now an unconstrained string.
What to update: no action is required.
Line of credit schema names changed (v6.0 and later)
LocAccount, LocAccountDescriptor, LocAccountType, LocTransaction, and LocTransactionType are renamed to LineOfCreditAccount, LineOfCreditAccountDescriptor, LineOfCreditAccountType, LineOfCreditTransaction, and LineOfCreditTransactionType respectively. The LOC_ACCOUNT discriminator value and every field name and JSON response shape are unchanged.
What to update: regenerate client code or server stubs if you generate them directly from Plaid's OpenAPI file.
New endpoint: asset transfer networks (v6.0 and later)
GET /accounts/{accountId}/asset-transfer-networks returns the identifiers needed to submit inter-institution investment account transfers via ACATS, DTC, or ATON.
This endpoint backs Investments Move. Without it, the requesting party falls back to asking the end user to manually enter account and holdings details, which increases the rate of rejected (NIGO) transfer requests reaching your transfer desk. Implementing the endpoint reduces that rejection rate by supplying verified data up front.
Telephone number purpose schema renamed, CELL deprecated (v6.3 and later)
The type field on a telephone number now references TelephoneNumberPurpose instead of TelephoneNumberType, and adds BOTH and PERSONAL values. Every previously valid type value, including CELL, is still valid. CELL is marked deprecated in favor of reporting a separate network field as CELLULAR, but existing implementations that keep sending CELL are not broken by this change.
What to update: no action is required. Optionally, move cell numbers to type: PERSONAL (or HOME/BUSINESS, as applicable) plus network: CELLULAR.
After migrating
- Re-run the Validator against your updated build before requesting production access for the new version.
- Update any internal documentation or generated client code that references the old wrapped response shape,
Loc*schema names, orstateonAddress.