FeelConnect▍
ProductsDocsPricingChangelog
Sign inGet API keys

Search documentation

Fuzzy search across every docs page and section

Getting started/Link

Getting started

  • Overview
  • Quickstart
  • Authentication
  • Environments and sandbox
  • Link
  • Going live

API reference

  • Link tokens
  • Institutions
  • Items
  • Accounts
  • Transactions
  • Identity
  • Income
  • Assets
  • Investments
  • Liabilities
  • Recurring
  • Categories
  • AI products

Platform

  • Webhooks
  • Errors
  • Rate limits and quotas
  • SDKs
  • GraphQL
  • MCP and AI agents
  • Changelog
  1. Docs
  2. Getting started
  3. Link
PreviousEnvironments and sandboxNextGoing live

On this page

  • Install
  • Opening Link
  • Options
  • Success metadata
  • Flow lifecycle
  • postMessage protocol
  • Update mode
FeelConnect▍

The developer-first financial data platform.

All systems operational

Products

Universal LinkData APIsAI enrichmentPricing

Developers

DocumentationAPI explorerDashboardGet API keys

Company

HomeChangelogfeels.moneySign in

Legal

PrivacyTermsSecurityData processing
© 2026 FeelConnect. All rights reserved./v1 · FC-Version 2026-07-01

Getting started

Link

Embed the FeelConnect Link modal: SDK options, lifecycle callbacks, postMessage protocol, and update mode for re-authentication.

Link is the user-facing connection flow: institution search, authentication (OAuth simulation, credentials, wallet address, or file upload), optional MFA, account selection, and consent. It renders as an iframe modal your page opens with a link_token.

Install

npm install @feelconnect/link

Opening Link

Create a link_token server-side (reference), then open the modal. The vanilla API returns a handle; the React hook manages the handle's lifecycle for you.

import { useFeelConnectLink } from "@feelconnect/link";
const { open, ready, exit } = useFeelConnectLink({
linkToken,
onSuccess: (publicToken, metadata) => exchangeOnServer(publicToken),
onExit: (error) => error && report(error),
onEvent: (name, data) => analytics.track("link_" + name, data),
});
// <button onClick={open} disabled={!ready}>Connect</button>

Options

LinkOptions
linkTokenstringrequired
Short-lived token from POST /v1/link/token/create. One token, one session.
onSuccess(publicToken, metadata) => voidrequired
Fires when the user completes the flow. Exchange publicToken server-side within 30 minutes. metadata carries the institution and selected accounts.
onExit(error | null) => void
Fires when the user leaves without connecting. error is null on a plain cancel, or { code, message } after a failure.
onEvent(name, data?) => void
Telemetry stream of in-flow events (institution selected, MFA shown, and so on). Treat unknown names as no-ops — the set grows over time.
originstring
Origin of the Link app. Defaults to the hosted FeelConnect origin; override only for self-hosted deployments.

Success metadata

metadata (onSuccess)
{
"institution": {
"id": "inst_meridian_trust",
"name": "Meridian Trust"
},
"accounts": [
{
"id": "acct_9hK2mQxP7cW1nR4tYb8s",
"name": "Everyday Checking",
"mask": "4821",
"type": "depository"
},
{
"id": "acct_5tGb2VnM8kQ4wZ1xLp0d",
"name": "Cashback Card",
"mask": "0093",
"type": "credit"
}
]
}
error (onExit)
{
"code": "INSTITUTION_DOWN",
"message": "This institution is temporarily unavailable."
}

Flow lifecycle

A completed session walks these steps; onEvent fires at each transition:

  • Institution search — typed groups: banks, payment apps, investments, crypto, business.
  • Authentication — OAuth consent simulation, credential form, wallet address entry, or CSV/OFX upload, depending on the institution.
  • MFA challenge — only when the institution (or user_mfa in sandbox) requires it.
  • Account selection — the user picks which accounts to share.
  • Consent — the product scopes from your link_token are shown and granted.
  • Handoff — Link emits success and closes itself.

postMessage protocol

The SDK and iframe communicate with origin-checked postMessage events. You normally never touch these — the SDK maps them onto callbacks — but they matter if you build your own wrapper:

MessageDirectionPayload
fc:readyiframe → parentLink UI has loaded; the modal becomes visible.
fc:eventiframe → parent{ name, … } telemetry, surfaced through onEvent.
fc:successiframe → parent{ public_token, metadata }, surfaced through onSuccess; the SDK closes the modal.
fc:exitiframe → parent{ error? }, surfaced through onExit.

Origin checks

Both sides verify event.origin before trusting a message. If you self-host, pass the same origin to the SDK that serves the /link page.

Update mode

When an institution invalidates credentials, the item's status becomes login_required and you receive an item.error webhook. Reconnect the same item — keeping its item_id, accounts, and cursors — by creating a link token with update_item_id:

curl https://api.feelconnect.dev/v1/link/token/create \
-H "Authorization: Bearer $FEELCONNECT_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"user":{"client_user_id":"user-123"},"products":["transactions"],"update_item_id":"item_7dJ3nWqZ5xC9vK1mTf4g"}'
  • Link skips institution search and jumps straight to re-authentication for that institution.
  • On success the existing item returns to active and a transactions.sync_updates_available webhook follows. Your stored access_token keeps working — update mode needs no exchange, so you can ignore the public_token from onSuccess.
  • If you do exchange it, the item's access_token is rotated: the response carries rotated: true and the previous token stops working immediately, so replace every stored copy.
  • update_item_id must belong to the same client_user_id, otherwise user_mismatch is returned.
  • In sandbox, force this state with /v1/sandbox/item/reset_login.