Plaid logo
Docs
ALL DOCS

Transactions

  • Introduction to Transactions
  • Add Transactions to your app
  • Transactions webhooks
  • Transaction states
  • Transactions Sync migration guide
  • Personal Finance Category migration guide
  • Transactions partners
  • Troubleshooting
Plaid logo
Docs
Close search modal
Ask Bill!
Ask Bill!
Hi! I'm Bill! You can ask me all about the Plaid API. Try asking questions like:
  • Which countries does Investments support?
  • Why is /transactions/sync/ better than /get?
  • Do access tokens expire?
Note: Bill isn't perfect. He's just a robot platypus that reads our docs for fun. You should treat his answers with the same healthy skepticism you might treat any other answer on the internet. This chat may be logged for quality and training purposes. Please don't send Bill any PII -- he's scared of intimacy. All chats with Bill are subject to Plaid's Privacy Policy.
Plaid.com
Log in
Get API Keys
Open nav

Transactions Sync migration guide

Learn how to migrate from the /transactions/get endpoint to the /transactions/sync endpoint

Overview

/transactions/sync is a newer endpoint that replaces /transactions/get and provides a simpler and easier model for managing transactions updates. While /transactions/get provides all transactions within a date range, /transactions/sync instead uses a cursor to provide all new, modified, and removed transactions that occurred since your previous request. With this cursor-based pagination, you do not need to worry about making redundant API calls to avoid missing transactions. Updates returned by /transactions/sync can be patched into your database, allowing you to avoid a complex transaction reconciliation process or having to keep track of which updates have already been applied.

This guide outlines how to update your existing /transactions/get integration to use the /transactions/sync endpoint and simplify your Plaid integration.

Looking for an example in code? Check out Pattern on GitHub for a complete, best-practice implementation of the Transactions Sync API within a sample app.

Update your client library

If you are using client libraries, you may need to update your current library to use /transactions/sync. The following are the minimum Plaid client library versions required to support /transactions/sync for each language:

  • Python: 9.4.0
  • Node: 10.4.0
  • Ruby: 15.5.0
  • Java: 11.3.0
  • Go: 3.4.0

Detailed upgrade notes are language-specific may be found in the README and Changelog of the specific library. See the library's repo on the Plaid GitHub for more information.

Update callsites and pagination logic

Replace all instances of /transactions/get with /transactions/sync. /transactions/sync has a slightly different call signature from /transactions/get and does not have the count parameter inside the options object and uses a cursor instead of a start_date and end_date. Pagination logic is also different and relies on the has_more flag instead of the transactions_count value. Note that when requesting paginated updates with /transactions/sync, unlike when using /transactions/get, it is important to retrieve all available updates before persisting the transactions updates to your database.

Unlike /transactions/get, /transactions/sync does not allow specifying a date range within which to retrieve transactions. If your implementation requires getting transactions within a certain date range, implement transaction filtering after calling /transactions/sync.

For copy-and-pastable examples of how to call /transactions/sync, including complete pagination logic, see the API reference code samples for /transactions/sync.

If a call to /transactions/sync fails when retrieving a paginated update as a result of the TRANSACTIONS_SYNC_MUTATION_DURING_PAGINATION error, the entire pagination request loop must be restarted beginning with the cursor for the first page of the update, rather than retrying only the single request that failed.

Update callsites for Item data

Unlike /transactions/get, /transactions/sync does not return an Item object. If your app relies on getting Item data, such as Item health status, use /item/get.

Update webhook handlers

When using /transactions/sync, you should not listen for the webhooks HISTORICAL_UPDATE, DEFAULT_UPDATE, INITIAL_UPDATE, or TRANSACTIONS_REMOVED. While these webhooks will still be sent in order to maintain backwards compatibility, they are not required for the business logic used by /transactions/sync.

Instead, update your webhook handlers to listen for the SYNC_UPDATES_AVAILABLE webhook and to call /transactions/sync when this webhook is received.

Update initial call trigger

Unlike the /transactions/get webhooks, the SYNC_UPDATES_AVAILABLE webhook will not be fired for an Item unless /transactions/sync has been called at least once for that Item. For this reason, you must call /transactions/sync at least once before any sync webhook is received. After that point, rely on the SYNC_UPDATES_AVAILABLE webhook.

Unlike /transactions/get, /transactions/sync will not return the PRODUCT_NOT_READY error if transactions data is not yet ready when /transactions/sync is first called. Instead, you will receive a response with no transactions and a null cursor. Even if no transactions data is available, this call will still initialize the SYNC_UPDATES_AVAILABLE webhook, and it will fire once data becomes available.

The first call to /transactions/sync once historical updates are available will often have substantially higher latency (up to 8x) than the equivalent call in a /transactions/get-based implementation. Depending on your application's logic, you may need to adjust user-facing messaging or hard-coded timeout settings.

Update transaction reconciliation logic

The response to /transactions/sync includes the patches you will need to apply in the added, removed, and modified arrays within its response. You should apply these to your transactions records. Any additional logic required to fetch or reconcile transactions data can be removed.

Migrating existing Items

You likely already have transactions stored for existing Items. If you onboard an existing Item onto /transactions/sync with "cursor": "" in the request body, the endpoint will return all historical transactions data associated with that Item up until the time of the API call (as "adds"). You may reconcile these with your stored copy of transactions to ensure that it reflects the the Item's true state.

If you have a large number of Items to update, this reconciliation process may be slow and generate excessive system load. One other option for onboarding existing Items onto /transactions/sync is using "cursor": "now" in the request body. The endpoint will return a response containing no transaction updates, but only a cursor that will allow you to retrieve all transactions updates associated with that Item going forward, after the time of the API call. Accordingly, you should ensure that your local copy of transactions for an Item is up-to-date at the time you call /transactions/sync with "cursor": "now" for it, or else any transaction updates that occurred between the time that you last pulled fresh data and the time of your /transactions/sync call may be missing.

"cursor": "now" will work exactly like a cursor that was found by starting with "cursor": "" and paginating through all updates, with the only difference being that a transaction created before, but modified after, those requests would be returned as "added" if using "cursor": "now", and "modified" if using "cursor": "".

If you ever want to completely rebuild your local copy of transactions for an Item previously onboarded with "cursor": "now", you may still do so with "cursor": "".

Note that we strongly recommend that this cursor only be used with Items for which you've already used with /transactions/get, and not any new Items, which should always be onboarded with "cursor": "".

Test your integration

You can perform basic testing of your integration's business logic in Sandbox, using the /sandbox/item/fire_webhook endpoint to simulate SYNC_UPDATES_AVAILABLE. If this testing succeeds, you should then test your integration with internal test accounts before releasing it to your full userbase.

Example code

For a full working example of a Plaid-powered app using /transactions/sync, see Plaid Pattern.

Was this helpful?
Developer community
GitHub
GitHub
Stack Overflow
Stack Overflow
YouTube
YouTube
Discord
Discord