On first sync, call POST /transactions/sync with access_token and no cursor; store the next_cursor from the response and process all items in the added array
On subsequent syncs, pass the stored cursor in the request body; the response returns added, modified, and removed arrays representing changes since the last cursor position
Upsert records from added and modified into your transaction store using transaction_id as the stable key; delete or tombstone records whose transaction_ids appear in removed
If has_more is true in the response, immediately call /transactions/sync again with the new next_cursor until has_more is false — do not wait for a webhook between pages
Subscribe to the TRANSACTIONS webhook (transactions sync_updates_available) and trigger a sync cycle when you receive it rather than polling on a fixed schedule
Handle TRANSACTIONS_REMOVED webhooks separately if your integration listens for them; reconcile any removed transaction_ids against your store even if you did not initiate a sync
Known gotchas
Cursors are per access_token and are invalidated if you call /transactions/refresh or if Plaid forces a full re-sync; detect a HISTORICAL_UPDATE_COMPLETE webhook or a full reset by checking the response for a null cursor returned with a 400 TRANSACTIONS_SYNC_MUTATION_DURING_PAGINATION error
Pending transactions appear in added with pending: true and may later reappear in modified (once cleared) or removed (if they fall off without clearing); your upsert logic must handle all three cases for the same transaction_id
The /transactions/sync endpoint does not return all historical transactions on first call for older accounts; use the count returned in total_transactions on the initial Items response to estimate coverage
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp