Data mapping guide
Avoid common mapping errors and learn how to handle complex mapping edge cases
Common mapping mistakes to avoid
Sending only the required fields
Send every field you can. The more fields you provide, the better data quality your customers will experience when using Plaid-powered apps. Sending just the required fields alone is the most common source of avoidable rework when integrating with Core Exchange.
Reusing one transactionId across two transactions
A transactionId must be unique within the account, and the PENDING and POSTED versions of the same transaction need different IDs.
When two transactions share an ID, the entire transactions response fails validation, so your customer receives no transactions at all. The usual cause is a pair of offsetting entries: a debit and a credit with the same amount, description, and timestamps, posted under a single ID. Give each entry its own ID.
Using the wrong debitCreditMemo
amount is an absolute value, so debitCreditMemo is the only thing that tells Plaid which direction money moved. DEBIT means money left the account, and CREDIT means money entered it. Don't signal direction by sending a negative amount.
Putting an account in the wrong container
If your accountType looks right but validation rejects the response, check the container field holding the account, not just the accountType inside it: the accountCategory if using API version 6.0 or later, or the wrapper key such as depositAccount when using version 5.x or earlier. Make sure the container name is spelled correctly (with no typos) and corresponds to a valid enum value for that account type. For example, LOAN_ACCOUNT with a CREDITCARD accountType fails, because CREDITCARD isn't a LoanAccountType.
Omitting principalBalance on a loan account, or sending the origination amount
Loan accounts have no currentBalance field. Instead, principalBalance is required on every loan account. Two common mistakes:
- Omitting
principalBalance. Customers see a $0 or empty balance on a loan they know carries a balance. - Setting
principalBalanceas the origination amount instead of the current outstanding balance. The origination amount should go in theoriginalPrincipalfield.
Reporting available credit as a line of credit's balance
On a line of credit, the three balance figures are distinct, and HELOCs in particular are often mapped incorrectly:
currentBalanceis the amount the customer currently owes.availableCreditis what's left to borrow. It's required on every account type exceptCHARGE, and omitting it on the others fails validation for the whole accounts response.creditLineis the credit limit.
Timestamps that omit the UTC offset, or that deviate from RFC 3339
Timestamp fields take an ISO 8601 date-time in the form YYYY-MM-DDThh:mm:ss.nnn[Z|[+|-]hh:mm], and date fields take YYYY-MM-DD. Both follow IETF RFC 3339.
Deviations that Plaid encounters regularly include placeholder offset values, offsets written without the colon (-0400), ISO 8601 basic-form dates (20260420), a date-only value in a field that expects a full timestamp, and a number instead of a date-time string. Sending incorrect values may cause Plaid to reject the entire transaction, or to associate the transaction with the wrong date.
An accountNumberDisplay that isn't the last four digits
Plaid expects the last four digits of this masked number to match the last four digits of the account number. Values that break this include a currency code, a differently-truncated number such as the first eight digits of a twelve-digit account number, and a number carrying separators.
Your customers rely on the mask to recognize their accounts and to detect accounts they've already linked. A mask that changes can also cause the account churn described under accountId below.
Returning an empty /accounts/{accountId}/contact response
holders, emails, addresses, and telephones are all required, and each needs at least one entry. An empty response fails validation, which fails Identity for the whole account. If your customer records regularly have no email or telephone on file, tell Plaid before you launch.
Omitting joint account holders
List every owner of the account in holders, each with the relationship that describes them. Two common errors are returning only one holder for a jointly held account, and marking a sole owner SECONDARY.
Note that Plaid doesn't associate emails, addresses, or telephones with individual holders, so contact details for every owner belong in those account-level arrays.
Returning fully divested positions as holdings
A holding represents a position the customer currently holds. When a sold-out position stays in the holdings array with units and marketValue set to 0, Plaid passes it through as a live holding, and because most systems keep repricing it, the customer sees a position they no longer own with a price that updates daily. Omit positions the customer has fully divested.
Reporting borrowing power as available cash
availableCashBalance is the cash held across all sub-accounts, including sweep funds. On a margin-enabled account, don't map buying power or margin availability into it: doing so reports borrowed funds as cash the customer holds. Likewise, currentValue is the total current value of all investments, not the account's purchasing power.
A cash or sweep position also needs cashAccount set to true, or an explicit isCashEquivalent value in fiAttributes, so that Plaid can classify it as cash rather than as a security.
Data mapping FAQs
What if we can't source a required field, such as availableBalance?
If you can't provide a required field, contact Plaid to discuss possible solutions. Don't omit the field and don't substitute a value you do have.
Are credit cards a line of credit or a loan?
In Core Exchange, if the customer can pay the balance down and draw on it again, use line of credit; if they can only pay it off, use loan. Credit cards therefore correspond to a line of credit with accountType CREDITCARD, under accountCategory LOC_ACCOUNT (or the locAccount wrapper key if using an API version earlier than 6.0).
What's the difference between accountId, accountNumber, accountNumberDisplay, and identifier?
accountId is the account's long-term identity within your organization. It isn't an account number, shouldn't be derived from one, and should never change, even if the account number changes. If it changes, Plaid sees a new account rather than the same one, which causes "account churn" and disruption for your customers using Plaid-linked accounts for long-lived use cases, such as personal financial management.
accountNumberDisplay is the masked number your customer recognizes.
accountNumber is the full account number, and is only used for loan accounts.
For depository accounts, the account number should be returned in the identifier field of GET /accounts/{accountId}/payment-networks. If this number ever changes, begin returning the new number, and Plaid will detect the new number if it ever changes.
How much transaction history should we serve?
Serve as much as your systems retain, up to 24 months. Use cases such as mortgage underwriting and cash flow analysis depend on the full two years being available. Sending more than 24 months does not cause an error, but is unnecessary: Plaid will simply discard any transaction data beyond 730 days.
Note: when Plaid requests a start date older than you support, return the FDX invalid date range error, code 703, with an HTTP 400 status. Returning a shorter window or an empty array instead can look like missing transactions data and result in support tickets.
How should we model multi-currency or foreign currency accounts?
Every account has exactly one required currency.currencyCode, so there's no way to express a single account holding several currencies.
Supported payment networks compatible with Core Exchange cover US and Canadian rails only. Accounts denominated in currencies other than USD or CAD can be listed with balances and transactions, but they aren't Auth-eligible. If your product is built around multi-currency or non-North-American rails, consult with Plaid before you build.
Our security has no CUSIP, ISIN, SEDOL, or ticker. What do we send?
Some securities, such as private funds, non-traded partnerships, and physical collectibles may not have identifier symbols. In this case, set holdingName to the security's name, holdingType to OTHER, and units to the number held, and omit securityId, securityIdType, and symbol.
{
"holdingName": "1794 Flowing Hair Dollar",
"holdingType": "OTHER",
"units": 1,
"marketValue": 7500000.00,
"cashAccount": false,
"currency": {
"currencyCode": "USD"
}
}