How do I set up Plaid /transactions/sync for bank feed reconciliation?
Call /transactions/sync with a null cursor the first time for an Item, store the next_cursor it returns, and pass that cursor back on every later call to fetch only what changed. Loop while has_more is true, and process the added, modified, and removed arrays as three distinct kinds of change — not as one undifferentiated transaction list.
Part of the finance integrations guide.
| First call | cursor: null — returns the first page of transaction history plus a cursor |
|---|---|
| Later calls | Pass the stored next_cursor to fetch only changes since the last sync |
| Pagination signal | has_more: true means more pages exist for this sync; keep calling until false |
| Multi-account note | Each account_id needs its own stored cursor if an Item has multiple accounts |
| Response shape | Three arrays per call: added, modified, removed |
Why sync instead of get
Loopfour's Plaid integration is built on /transactions/sync rather than repeatedly re-fetching the full transaction history. Plaid's own documentation frames the endpoint around a cursor: leave it null for the first call on an Item, and the response returns both a page of transaction data and a cursor to pass on the next call. Every subsequent call with that cursor returns only what changed since the last one — not the whole history again — which is what makes it practical to poll on a schedule without re-processing transactions you've already reconciled.
What the cursor actually tracks, and what breaks if you get it wrong
The cursor has to be persisted per Item (and, if an Item covers multiple accounts, tracked per account_id) — it's Plaid's bookmark for exactly what state you've already seen, not a generic pagination token you can discard between calls. Lose it, and the only recovery is starting over with cursor: null, which re-returns the full transaction history as if nothing had been synced before; a reconciliation process that isn't idempotent against reprocessing old transactions will create duplicate matches when that happens.
Treat added, modified, and removed as three different jobs
Every sync response separates changes into three arrays, and each one calls for different handling: added transactions are new — reconcile them normally; modified transactions are in-place updates to something you've already seen (a merchant name correction, a category change) — update the stored record, don't create a new one; removed transactions need their existing match, if any, treated as orphaned and re-resolved (often against a new transaction that just showed up in the same call's added array with a different transaction_id, for pending-to-posted transitions). Handling all three the same way — as if every entry were a fresh transaction to reconcile — is the most common way this integration goes wrong.
Next step
Map the finance workflow with the most exposure and prove the automation path.
Bring the invoice, contract, payment reconciliation, or customer finance workflow you have to defend at audit. Loopfour can map the trigger, controls, integrations, and approval loop.
Field mapping
What each /transactions/sync response array means for reconciliation state
| Array | What it means | What to do |
|---|---|---|
| added | A transaction new to this Item since the last cursor | Run normal reconciliation matching |
| modified | An existing transaction_id with changed fields (name, category, amount) | Update the stored record in place; don't re-match |
| removed | A transaction_id no longer valid — often a pending transaction that posted under a new id | Orphan any existing match; check this call's added array for a replacement |
Frequently Asked Questions
Sources
Related
Topic
Integrations
Every finance automation vendor publishes an integrations page: a grid of logos, a claim of "seamless" connectivity, and not much else. That page answers a marketing question — does this vendor touch…
Read moreDiagnostic
What breaks when a reconciled Plaid transaction changes to modified or removed?
Plaid transaction data isn't immutable. A pending transaction can be removed from the feed entirely and replaced by a different transaction once it posts, and a bank can remove a transaction outright. If a payment was already matched to the old transaction, that match is orphaned the moment the removal comes through, and the replacement has to be found and re-matched — it doesn't update in place.
Read moreDiagnostic
What breaks when a Xero bank transaction doesn't match the bank statement line?
A BankTransaction created through Xero's API isn't automatically linked to the real bank statement line Xero later imports. Xero's schema tracks this with an IsReconciled flag; its auto-matching compares amount, date, and contact against imported lines, and if those don't line up closely enough, the created transaction and the real line both sit unreconciled instead of resolving into one record.
Read moreComparison
Plaid vs. Stripe: which side of reconciliation are you actually looking at?
Plaid is the bank side: read-only transaction data from the account the money actually lands in. Stripe is the processor side: the system that generated the payment. They aren't two views of the same event that should match directly — both reconcile against a common bank statement line, and disagreeing is normal until that line is found.
Read more