Add financial insights to your agent
Use financial insights to let your agent answer questions such as “What did I spend on dining this month?” The agent reads transactions, balances, and account details from the financial accounts a customer chooses to share through Link.
Financial insights are available for US customers. The data comes from the Link API at api.link.com, not the Stripe API.
Before you begin
You need a customer with a US Link account who can authorize access to the financial accounts they choose to share.
Choose an integration
Choose how your application connects to Link before setting up authorization:
- Local agent: Install Link CLI, then follow the CLI setup. You don’t need to complete the hosted payments guide.
- Hosted application: Complete the OAuth prerequisites, then follow the hosted setup. Choose the financial data actions in this guide before redirecting the customer to Link.
Link CLI and the TypeScript SDK support transactions, sources, balances, and precomputed insights. The Go and Python SDKs support transactions, sources, and balances. The data retrieval examples on this page use Link CLI.
Choose the data to request
Source actions specify which financial data the customer can share. Request only the actions your feature needs. Customers choose which accounts to share and can opt in to future accounts.
| Source action | Reads | Registration |
|---|---|---|
read_link_transactions | Transactions from the customer’s Link wallet. | Not required. |
read_external_transactions | Transactions from connected external accounts. | Required. |
read_balances | Account balances. | Required. |
read_source_details | Account names, types, and last four digits. | Required. |
The registration column applies to the Stripe account whose publishable key starts a hosted authorization flow. See Financial Connections registration.
Connect with Link CLI
For a local agent, request source actions when logging in. This example requests all four actions. Remove any your feature doesn’t need:
link-cli auth login --client-name "My Agent" \
--scope "userinfo:read" \
--source-actions read_link_transactions \
--source-actions read_external_transactions \
--source-actions read_balances \
--source-actions read_source_detailsFollow the returned verification URL to authorize access. To add actions to an existing session, use auth upgrade with the additional --source-actions values. After authorization, continue to List connected accounts.
Authorize a hosted application
For a hosted application, configure registration and the authorization request before sending the customer through OAuth. If you’re using Link CLI’s local flow, continue to List connected accounts.
Register for Financial Connections
If you request external transactions, balances, or account details, the Stripe account whose publishable key starts authorization must be registered for Financial Connections. Registration isn’t required if you only request read_link_transactions.
- Open Financial Connections settings in the Dashboard.
- Complete the application form and accept the terms.
Use the same account whose publishable key you pass to the authorization URL.
Request financial data scopes
Add authorization_details to the OAuth authorization URL. This parameter contains a URL-encoded JSON array of the source actions you need:
[
{
"type": "source",
"actions": [
"read_link_transactions",
"read_external_transactions",
"read_balances",
"read_source_details"
]
}
]URL-encode the array before adding it to the URL. To request payments and insights together, keep payment_methods.agentic in scope. For insights only, use userinfo:read:
https://login.link.com/auth?key=pk_live_YOUR_PUBLISHABLE_KEY&client_id=YOUR_CLIENT_ID&redirect_uri=https://yourapp.com/callback&response_type=code&scope=userinfo:read&state=RANDOM_STATE_VALUE&code_challenge=YOUR_PKCE_CODE_CHALLENGE&code_challenge_method=S256&authorization_details=ENCODED_AUTHORIZATION_DETAILSReplace ENCODED_AUTHORIZATION_DETAILS with the encoded array. Then exchange the authorization code for tokens. Read the granted authorization_details from the response: a customer can approve only some accounts or actions.
Use the resulting access token with your SDK client. Your application handles token refresh and revocation.
List connected accounts
List the sources the customer shared, along with what each one can do:
link-cli sources list --format json{
"data": [
{
"id": "csmrpd_abc123",
"name": "BANK SAVINGS",
"type": "bank_account",
"capabilities": {
"balances": { "status": "eligible" },
"transactions": { "status": "eligible" }
},
"external_connection": { "status": "active" },
"bank_account": { "last4": "5115" },
"granted_actions": [
"read_balances",
"read_external_transactions",
"read_source_details",
"read_link_transactions"
]
}
],
"has_more": false
}A capability status is eligible or pending. Sources use card and bank_account. Don’t confuse these with the card_details and bank_account_details fields on payment methods.
Retrieve transactions
List transactions for the accounts the customer shared. This example requests up to 50 transactions for a date range:
link-cli transactions list \
--limit 50 \
--start-date 2026-06-01 \
--end-date 2026-06-30 \
--format json{
"data": [
{
"id": "lbctxn_abc123",
"source_id": "csmrpd_abc123",
"amount": 4999,
"currency": "usd",
"created_date": "2026-06-15",
"description": "ACME Coffee Shop",
"status": "succeeded",
"category": null,
"origin": "external_connection"
}
],
"has_more": true
}| Option | Description |
|---|---|
--limit | Number of results, from 1 to 100. |
--start-date, --end-date | Inclusive dates in YYYY-MM-DD format. |
--origin | link or external_connection. |
--category | Filter by category. |
--source <id> | Limit results to a source. Repeatable. |
--starting-after, --ending-before | Pagination cursors. |
Amounts use the smallest unit of the currency. Negative amounts are outflows and positive amounts are inflows. status is an open set, so handle values you haven’t seen before, and category can be null.
To page through results, pass the id of the last transaction as --starting-after while has_more is true:
link-cli transactions list \
--limit 100 \
--start-date 2026-06-01 \
--starting-after lbctxn_abc123 \
--format jsonRetrieve balances
List balances for the shared accounts. Each result identifies its source account and the time the balance applies to:
link-cli balances list --format json{
"data": [
{
"source_id": "csmrpd_abc123",
"type": "cash",
"current": 31005,
"currency": "usd",
"as_of": "2026-07-15T00:00:00Z",
"cash": {
"available": { "usd": 31005 }
}
}
],
"has_more": false
}Bank accounts return a cash balance: current is the posted balance and cash.available excludes pending transactions. Cards return a credit balance: current is the posted balance and credit.used includes pending transactions. Pass --source to limit the results to one account.
Handle pending data
Right after a customer connects an account, the external data might still be loading. The API responds with HTTP 202 and this body:
{
"code": "external_data_retrieval_pending",
"description": "We are still retrieving external financial data. Please try again in a few seconds."
}Retry after a few seconds. Data is usually ready within 30 seconds of connecting.
Use insights
Insights are precomputed answers about a customer’s finances. List the types available, then retrieve the ones you need. New types can appear without a Link CLI release, so list them instead of hard-coding IDs.
link-cli insights list-available-types --format json
link-cli insights list --insight INSIGHT_ID --format jsonEach available type has an id, a description, and the authorization_remediation to request if the customer hasn’t granted access yet:
{
"data": [
{
"id": "top_brand_by_transaction_count_per_category_t180d",
"description": "Top brands",
"authorization_remediation": {
"authorization_details": [
{ "type": "source", "actions": ["read_link_transactions"] }
]
}
},
{
"id": "top_5_brands_by_transaction_count_per_category_t180d",
"description": "Top 5 brands for each shopping category in the last 180 days based on transaction count",
"authorization_remediation": {
"authorization_details": [
{
"type": "source",
"actions": ["read_link_transactions", "read_external_transactions"]
}
]
}
}
],
"has_more": false
}An insight comes back in one of three states:
ready: includesas_of(a Unix timestamp) anddata, a list of entries that each have alabeland a typedvalue. Values likenumber_of_itemscarry alabeland acount. Handle value types you haven’t seen before.pending: has onlyid,description, andstatus. The insight is still being computed, so retry after a few seconds.no_data: has anerror_codeofmissing_permissionsand anerror_message, and can includeauthorization_remediation. Request the additional source actions withauth upgradeif the customer hasn’t granted them.
{
"id": "top_brand_by_transaction_count_per_category_t180d",
"description": "Top brands",
"status": "ready",
"as_of": 1790723779,
"data": [
{
"label": "Clothing",
"value": {
"type": "number_of_items",
"number_of_items": { "label": "Marine Layer", "count": 2 }
}
}
]
}The top_5_brands_by_transaction_count_per_category_t180d insight returns up to five brands per shopping category, ranked by transaction count. Each entry’s label includes its rank and category:
{
"id": "top_5_brands_by_transaction_count_per_category_t180d",
"description": "Top 5 brands for each shopping category in the last 180 days based on transaction count",
"status": "ready",
"as_of": 1790723779,
"data": [
{
"label": "Brand #1 for Clothing and accessories",
"value": {
"type": "number_of_items",
"number_of_items": { "label": "Marine Layer", "count": 4 }
}
},
{
"label": "Brand #2 for Clothing and accessories",
"value": {
"type": "number_of_items",
"number_of_items": { "label": "Acme", "count": 3 }
}
}
]
}Paginate every list
All list commands take --limit (1–100) and --starting-after. Transactions, sources, and balances also take --ending-before. Insights don’t. Responses are { "data": [...], "has_more": true } with no separate cursor, so use the last item’s identifier as the next cursor:
| Resource | Cursor |
|---|---|
| Transactions | The last transaction’s id |
| Sources | The last source’s id |
| Balances | The last balance’s source_id |
| Insights | The last insight’s id |
Keep your filters unchanged while you page through a result set.
Configure your agent’s skill file
Link CLI ships an agent skill for financial insights that covers command selection, pagination, and how to answer spending questions. Install the bundled skills:
npx skills add stripe/link-cliFind the financial insights skill in the Link CLI repository.
Test your integration
After completing the authorization path for your integration, verify that your application can read the data the customer granted. The following checks use Link CLI and live data:
- Authorize with the source actions your feature needs.
- Connect at least one account.
- Run
link-cli sources list. Capabilities can showpendingbriefly, theneligible. - Run
link-cli transactions list --limit 5. - Run
link-cli balances list. - Ask your agent a spending question end to end.
Customer controls
Customers control access per account and can revoke it in the Link app. After a customer revokes access, calls for that source return an authorization error. Prompt the customer to reconnect instead of retrying.
Next steps
Use these guides to extend your integration:
Set up the OAuth flow and SDK client.
Review commands, limits, and environment variables.
Install skills and run Link CLI as an MCP server.