Skip to main content
Each Account exposes a current_balance (and an available_balance for MX accounts), plus its transactions through GET /accounts/{id}/transactions. This guide explains how fresh that data is, how to tell, and how to pull fresher data on demand.

How fresh is GET /accounts?

The balances you read are a cached snapshot from the last successful refresh — not a live call to the bank on every request. LedgerSync refreshes every active connection automatically about once a day, so under normal conditions the numbers are less than 24 hours old. Every Account carries a last_refreshed_at timestamp — the moment its data was last refreshed. Read it to decide whether you already have fresh-enough data or need to force a refresh.
For most use cases you do not need to call /refresh. The daily auto-refresh keeps active connections current, and GET /accounts always returns the latest snapshot. Reach for /refresh only when you need fresher-than-daily data.

Forcing a refresh

When you need up-to-the-moment data (a user tapped “refresh”, you’re reconciling something time-sensitive), call POST /connections/{id}/refresh:
It returns 202 Accepted with an operation_id and starts the refresh asynchronously, so balances are not updated by the time the call returns. All three connectable sources (Finicity, MX, and FDE) answer this call the same way: 202 now, the outcome later on a webhook.
A refresh keeps the accounts you already have current. It is not uniformly a discovery call. On MX and FDE it also picks up an account the client opened after linking; on Finicity it never does, because a Finicity refresh only touches the accounts already attached to the connection. See Adding a new account.
1

POST /connections/{id}/refresh

You get 202 and an operation_id.
2

Wait for the account.refresh.completed webhook

It fires when the fresh data is in (or account.refresh.failed on a terminal failure). Listen for the webhook — don’t poll GET /accounts in a loop.
3

Re-read GET /accounts (and /transactions)

The snapshot now reflects the fresh pull and last_refreshed_at has advanced.
See Connection lifecycle and Webhooks for the account.refresh.completed / account.refresh.failed payload shapes, and the Refresh a connection endpoint in the API Reference for the full contract.
MX aggregates on its own schedule, several times a day, and refreshes through this same async webhook flow. A refresh you request triggers an MX aggregation, and the result arrives on the account.refresh.completed webhook, so the shape of the call matches Finicity and FDE.What is not the same is what comes back. An MX aggregation re-reads the member’s full account list, so it also picks up accounts the client opened after linking. FDE does the same on its extraction run. A Finicity refresh does not, and no amount of refreshing will surface an account the client never shared. See Adding a new account.

Refreshing many connections at once

You can refresh all of a customer’s banks in one batch — each connection is a separate POST /connections/{id}/refresh call. That’s well within the rate limits (live keys allow 60 requests/minute), and there is no separate concurrency cap on refresh: the limit that applies is the normal request rate.
  • Fire the batch, then wait on the account.refresh.completed webhooks — don’t poll operations or /accounts in a tight loop.
  • Watch the X-RateLimit-* headers and back off before you hit zero — see Rate limits.
  • Each refresh triggers a real aggregation at the bank, so space large batches out rather than firing hundreds at once.
A refresh is asynchronous and eventually-consistent. Don’t block a user flow waiting for /refresh to finish — show the cached balance immediately (with last_refreshed_at), and update your UI when the webhook arrives.