Skip to main content
A client links Chase, and three months later they open a second checking account under the same Chase login. Nothing in the API creates that Account for you: an Account exists once the source hands it to LedgerSync. What you call to make that happen depends on the connection’s source, and the two answers are genuinely different, so read the table before you write the retry.
You can read the source off the connection id: con_MX_1224, con_FDE_882, con_FINICITY_41294. See The two id formats.

The short answer

On a Finicity connection, POST /connections/{id}/refresh will never return an account the client did not already share. It matches the accounts the connection already holds and updates those. Calling it more often does not change that. This is the single most common wasted integration loop on this path.

Why Finicity is different

A refresh is a data pull, not a consent change. On MX and FDE the pull happens to carry the full account list, so an account that appeared since the last pass simply shows up and gets inserted. On Finicity the account list is fixed at consent time: the client picks which accounts to share inside a Connect session, and Finicity only offers the unshared ones again inside another Connect session. So the Finicity answer is not an API call that adds an account. It is an API call that mints a session for a human, and the human does the adding.

Finicity: reauthorize the active connection

POST /v3/connections/{connection_id}/reauthorize is documented as the repair path for failed and disconnected connections, but it is not gated on status. A healthy active connection is a valid target, and that is exactly the case here: nothing is broken, the client just has an account you were never offered.
1

Call reauthorize on the active connection

200 OK
Send Content-Length: 0 explicitly. The endpoint takes no body, and the load balancer in front of the API rejects a body-less POST without that header with 411 Length Required.
2

Send the client reauth_url

Redirect the client to it, or email it. The link stays valid until action.expires_at, which is days out rather than minutes, and it can be opened more than once, so a client who closes the tab can come back to the same link.
reauth_url is a bearer link. Whoever holds it can act on that connection, without logging in to anything of yours. Send it over a channel you trust, keep it out of application logs, and do not park it in a shared inbox.
3

The client signs in and ticks the new account

The hosted page runs the source’s own reconnect flow against the existing connection. The client authenticates, and the bank shows the full account list. This is the only moment an account they skipped the first time is offered again. You do not control how many accounts they tick, and they may well tick several.
4

Re-list accounts and diff

Nothing is pushed to you when the session ends with a new account attached. Re-read GET /accounts and diff on account id, as below.
The link does not always lead back to Finicity. For some institutions, American Express in particular, LedgerSync reconnects the bank through MX instead. Reauthorize on a con_FINICITY_* connection then returns a URL that runs an MX add-bank flow, and every account the client ticks arrives on a new con_MX_* connection with new acc_ ids. The original Finicity connection keeps its old accounts under their old ids, and the new account never appears on it.Branch on the source field of the reauthorize response: it is the source the returned URL actually leads to. When it differs from the source encoded in the connection id you passed, expect a new connection, and re-list at the client level (GET /accounts?client_id=...) rather than filtering on the connection id you started from. Treat the accounts that arrive as new records, not as a rename of the ones you hold.
Do not loop, do not schedule. Every call mints a session a human has to sit through, and a completed session ends in a real aggregation at the institution. Statements the newly shared accounts bring back are fetched from the bank and are not free, so re-running the flow on a timer spends money for nothing. Call reauthorize once, in response to something a person actually asked for, and then wait for the client to open the link you already sent instead of minting another one.

MX and FDE: a refresh is enough

On MX, a refresh triggers a member aggregation, and the aggregation result re-reads the member’s whole account list and inserts anything unknown. On FDE, a refresh re-runs extraction and inserts sub-accounts it has not seen. In both cases the new account lands on the same connection, so your con_ id is unchanged and only the new account carries a new acc_ id.
You get 202 Accepted and an operation_id. The pull is asynchronous, and account.refresh.completed fires when it lands. See Keeping data fresh.
Do not send an MX or FDE client through reauthorize to add an account. It puts them through a re-login for something a plain refresh does on its own, with no client interaction at all. On MX the scheduled aggregation would have picked it up even without the refresh.

Detect the new account: re-list and diff

There is no account-added webhook. connection.active does not fire when an already-active connection stays active, and account.refresh.completed tells you a refresh finished, not that the account set changed. Comparing account lists is the supported way to learn that an account arrived.
1

Snapshot the ids you hold

Before you refresh or send the link, record the set of id values from GET /accounts for that client. Page through with next_cursor until has_more is false (see Pagination).
2

Re-list after the flow

On the MX-redirect case above, drop connection_id and list by client_id alone, because the accounts landed on a connection id you have never seen.
3

Diff on id

Any acc_ id in the new list that is not in your snapshot is a new account. Persist it, then read its transactions and statements exactly as you would for any other account. Ids are stable, so this diff is safe to run repeatedly.
When to run the second read:
  • MX and FDE have a cue. Re-list when account.refresh.completed arrives for that connection.
  • Finicity has none, because the client finishes the session on their own time. Re-list when the client tells you they are done, and otherwise on a slow schedule for a day or so after you sent the link. A tight poll adds nothing, since nothing changes until a human opens the link.

What does not work

  • Refreshing a Finicity connection again. It updates the accounts already attached and returns 202 every time, so the loop looks healthy and never produces the account.
  • Waiting for a webhook. No event announces a new account, and no event fires when an active connection stays active.
  • Creating a second connection to the same bank. POST /clients/{id}/connections builds a fresh connection. When the aggregator issues a new underlying login, the accounts the client re-picks come back with new con_, acc_ and txn_ ids, so you hold the same accounts twice and a delta pull duplicates transactions you already have. Keep re-initiate for connections that genuinely need rebuilding, and see Handling failed and disconnected.

Connection lifecycle

Statuses, reauthorize vs re-initiate, and the two id formats.

Keeping data fresh

What a refresh does, and what it does not do, per source.

Webhooks

The full event catalog, and what it deliberately does not contain.

Connect a bank

The hosted link and the initiate to active walkthrough.