Skip to content

Commit 97010a5

Browse files
committed
feat(plaid): add the Plaid bank-data integration
1 parent fed891f commit 97010a5

31 files changed

Lines changed: 2973 additions & 21 deletions

apps/docs/components/icons.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5513,6 +5513,18 @@ export function AsanaIcon(props: SVGProps<SVGSVGElement>) {
55135513
)
55145514
}
55155515

5516+
export function PlaidIcon(props: SVGProps<SVGSVGElement>) {
5517+
return (
5518+
<svg {...props} viewBox='0 0 48 48' fill='none' xmlns='http://www.w3.org/2000/svg'>
5519+
<path
5520+
fill='currentColor'
5521+
fillRule='evenodd'
5522+
d='M18.637 0L4.09 3.81.081 18.439l5.014 5.148L0 28.65l3.773 14.693 14.484 4.047 5.096-5.064 5.014 5.147 14.547-3.81 4.008-14.63-5.013-5.146 5.095-5.063L43.231 4.13 28.745.083l-5.094 5.063L18.637 0zM9.71 6.624l7.663-2.008 3.351 3.44-4.887 4.856L9.71 6.624zm16.822 1.478l3.405-3.383 7.63 2.132-6.227 6.187-4.808-4.936zM4.672 17.238l2.111-7.705 6.125 6.288-4.886 4.856-3.35-3.44zm29.547-1.243l6.227-6.189 1.986 7.74-3.404 3.384-4.809-4.935zm-15.502-.127l4.887-4.856 4.807 4.936-4.886 4.856-4.808-4.936zm-7.814 7.765l4.886-4.856 4.81 4.936-4.888 4.856-4.808-4.936zm15.503.127l4.886-4.856L36.1 23.84l-4.887 4.856-4.807-4.936zM4.57 29.927l3.406-3.385 4.807 4.937-6.225 6.186-1.988-7.738zm14.021 1.598l4.887-4.856 4.808 4.936-4.886 4.856-4.809-4.936zm15.502.128l4.887-4.856 3.351 3.439-2.11 7.705-6.128-6.288zm-24.656 8.97l6.226-6.189 4.81 4.936-3.406 3.385-7.63-2.133zm16.843-1.206l4.886-4.856 6.126 6.289-7.662 2.007-3.35-3.44z'
5523+
/>
5524+
</svg>
5525+
)
5526+
}
5527+
55165528
export function PipedriveIcon(props: SVGProps<SVGSVGElement>) {
55175529
const pathId = useId()
55185530
return (

apps/docs/components/ui/icon-mapping.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ import {
175175
PersonaIcon,
176176
PineconeIcon,
177177
PipedriveIcon,
178+
PlaidIcon,
178179
PolymarketIcon,
179180
PostgresIcon,
180181
PosthogIcon,
@@ -464,6 +465,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
464465
persona: PersonaIcon,
465466
pinecone: PineconeIcon,
466467
pipedrive: PipedriveIcon,
468+
plaid: PlaidIcon,
467469
polymarket: PolymarketIcon,
468470
postgresql: PostgresIcon,
469471
posthog: PosthogIcon,

apps/docs/content/docs/en/integrations/meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@
187187
"pinecone",
188188
"pipedrive",
189189
"pipedrive-service-account",
190+
"plaid",
190191
"polymarket",
191192
"postgresql",
192193
"posthog",
Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
---
2+
title: Plaid
3+
description: Read bank accounts, balances, transactions, and identity data via Plaid
4+
---
5+
6+
import { BlockInfoCard } from "@/components/ui/block-info-card"
7+
8+
<BlockInfoCard
9+
type="plaid"
10+
color="#111111"
11+
/>
12+
13+
## Usage Instructions
14+
15+
Integrates Plaid into the workflow. Sync categorized transactions, list linked bank accounts with real-time balances, fetch verified account and routing numbers, retrieve account-holder identity, look up supported institutions, and manage Item tokens across the sandbox and production environments.
16+
17+
18+
19+
## Actions
20+
21+
### Plaid Sync Transactions
22+
23+
Incrementally sync transactions for a linked Item. Omit the cursor on the first call to get full history, then pass the returned cursor to fetch only changes; loop while hasMore is true. If Plaid returns TRANSACTIONS_SYNC_MUTATION_DURING_PAGINATION, discard the pages from the current batch and restart the loop from the cursor the batch started with
24+
25+
#### Input
26+
27+
| Parameter | Type | Required | Description |
28+
| --------- | ---- | -------- | ----------- |
29+
| `clientId` | string | Yes | Plaid client ID \(from the Plaid Dashboard under Team Settings → Keys\) |
30+
| `secret` | string | Yes | Plaid API secret for the selected environment |
31+
| `environment` | string | No | Plaid environment: 'production' \(default\) or 'sandbox' |
32+
| `cursor` | string | No | Cursor from a previous sync \(nextCursor\); omit to start from the beginning |
33+
| `count` | number | No | Number of updates to fetch per page \(1-500, default 100\) |
34+
| `accountId` | string | No | Scope the sync \(and cursor\) to a single account ID |
35+
| `includeOriginalDescription` | boolean | No | Include the unmodified original_description from the institution |
36+
| `daysRequested` | number | No | Days of history to request \(1-730, default 90\). Only applies before Transactions is initialized on the Item |
37+
38+
#### Output
39+
40+
| Parameter | Type | Description |
41+
| --------- | ---- | ----------- |
42+
| `added` | array | Transactions added since the cursor |
43+
| `modified` | array | Transactions modified since the cursor |
44+
| `removed` | array | Transactions removed since the cursor |
45+
|`transaction_id` | string | ID of the removed transaction |
46+
|`account_id` | string | Account the transaction belonged to |
47+
| `nextCursor` | string | Cursor to pass to the next sync call to fetch only new changes |
48+
| `hasMore` | boolean | Whether more updates are available; if true, call again with nextCursor |
49+
| `updateStatus` | string | Sync readiness: NOT_READY, INITIAL_UPDATE_COMPLETE, or HISTORICAL_UPDATE_COMPLETE |
50+
51+
### Plaid Get Accounts
52+
53+
List the accounts linked to an Item with their names, types, and balances. Balances may be cached; use Get Balances for real-time values
54+
55+
#### Input
56+
57+
| Parameter | Type | Required | Description |
58+
| --------- | ---- | -------- | ----------- |
59+
| `clientId` | string | Yes | Plaid client ID \(from the Plaid Dashboard under Team Settings → Keys\) |
60+
| `secret` | string | Yes | Plaid API secret for the selected environment |
61+
| `environment` | string | No | Plaid environment: 'production' \(default\) or 'sandbox' |
62+
| `accountIds` | string | No | Comma-separated account IDs to filter to \(defaults to all accounts\) |
63+
64+
#### Output
65+
66+
| Parameter | Type | Description |
67+
| --------- | ---- | ----------- |
68+
| `accounts` | array | Accounts linked to the Item |
69+
| `count` | number | Number of accounts returned |
70+
71+
### Plaid Get Balances
72+
73+
Get real-time balances for the accounts linked to an Item. Forces a live fetch from the institution, so it can take up to 30 seconds
74+
75+
#### Input
76+
77+
| Parameter | Type | Required | Description |
78+
| --------- | ---- | -------- | ----------- |
79+
| `clientId` | string | Yes | Plaid client ID \(from the Plaid Dashboard under Team Settings → Keys\) |
80+
| `secret` | string | Yes | Plaid API secret for the selected environment |
81+
| `environment` | string | No | Plaid environment: 'production' \(default\) or 'sandbox' |
82+
| `accountIds` | string | No | Comma-separated account IDs to filter to \(defaults to all accounts\) |
83+
| `minLastUpdatedDatetime` | string | No | Oldest acceptable balance timestamp \(ISO 8601\). Only required for Capital One non-depository accounts |
84+
85+
#### Output
86+
87+
| Parameter | Type | Description |
88+
| --------- | ---- | ----------- |
89+
| `accounts` | array | Accounts with refreshed real-time balances |
90+
| `count` | number | Number of accounts returned |
91+
92+
### Plaid Get Identity
93+
94+
Get account-holder identity information (names, emails, phone numbers, and addresses) for the accounts linked to an Item
95+
96+
#### Input
97+
98+
| Parameter | Type | Required | Description |
99+
| --------- | ---- | -------- | ----------- |
100+
| `clientId` | string | Yes | Plaid client ID \(from the Plaid Dashboard under Team Settings → Keys\) |
101+
| `secret` | string | Yes | Plaid API secret for the selected environment |
102+
| `environment` | string | No | Plaid environment: 'production' \(default\) or 'sandbox' |
103+
| `accountIds` | string | No | Comma-separated account IDs to filter to \(defaults to all accounts\) |
104+
105+
#### Output
106+
107+
| Parameter | Type | Description |
108+
| --------- | ---- | ----------- |
109+
| `accounts` | array | Accounts with their owners identity data |
110+
|`owners` | json | Account owners, each with names, phone_numbers, emails, and addresses arrays |
111+
| `count` | number | Number of accounts returned |
112+
113+
### Plaid Get Auth
114+
115+
Get account and routing numbers for the depository accounts linked to an Item (ACH for US, EFT for Canada, BACS for UK, IBAN/BIC internationally). Check each account verification_status before relying on micro-deposit-verified accounts; null means the institution authenticated instantly
116+
117+
#### Input
118+
119+
| Parameter | Type | Required | Description |
120+
| --------- | ---- | -------- | ----------- |
121+
| `clientId` | string | Yes | Plaid client ID \(from the Plaid Dashboard under Team Settings → Keys\) |
122+
| `secret` | string | Yes | Plaid API secret for the selected environment |
123+
| `environment` | string | No | Plaid environment: 'production' \(default\) or 'sandbox' |
124+
| `accountIds` | string | No | Comma-separated account IDs to filter to \(defaults to all accounts\) |
125+
126+
#### Output
127+
128+
| Parameter | Type | Description |
129+
| --------- | ---- | ----------- |
130+
| `accounts` | array | Depository accounts on the Item |
131+
| `numbers` | json | Account and routing numbers grouped by scheme |
132+
|`ach` | json | US accounts: account_id, account, routing, wire_routing, and is_tokenized_account_number entries \(tokenized numbers come from institutions like Chase and stop working if the Item is deleted\) |
133+
|`eft` | json | Canadian accounts: account_id, account, institution, and branch entries |
134+
|`international` | json | International accounts: account_id, iban, and bic entries |
135+
|`bacs` | json | UK accounts: account_id, account, and sort_code entries |
136+
137+
### Plaid Get Item
138+
139+
Get metadata and health status for a linked Item, including its institution, enabled products, and any error state
140+
141+
#### Input
142+
143+
| Parameter | Type | Required | Description |
144+
| --------- | ---- | -------- | ----------- |
145+
| `clientId` | string | Yes | Plaid client ID \(from the Plaid Dashboard under Team Settings → Keys\) |
146+
| `secret` | string | Yes | Plaid API secret for the selected environment |
147+
| `environment` | string | No | Plaid environment: 'production' \(default\) or 'sandbox' |
148+
149+
#### Output
150+
151+
| Parameter | Type | Description |
152+
| --------- | ---- | ----------- |
153+
| `item` | json | Item metadata |
154+
|`item_id` | string | Unique ID of the Item |
155+
|`institution_id` | string | Plaid institution ID the Item is linked to |
156+
|`institution_name` | string | Name of the linked institution |
157+
|`webhook` | string | Webhook URL set on the Item |
158+
|`error` | json | Error state of the Item, null when healthy |
159+
|`available_products` | json | Products available but not yet billed for the Item |
160+
|`billed_products` | json | Products the Item has been billed for |
161+
|`products` | json | All products enabled on the Item |
162+
|`consent_expiration_time` | string | When access consent expires, if the institution enforces expiration |
163+
|`update_type` | string | Item update type \(background or user_present_required\) |
164+
|`created_at` | string | When the Item was created |
165+
| `status` | json | Item health: last successful/failed transaction and investment updates and the last webhook fired |
166+
167+
### Plaid Search Institutions
168+
169+
Search financial institutions supported by Plaid by name
170+
171+
#### Input
172+
173+
| Parameter | Type | Required | Description |
174+
| --------- | ---- | -------- | ----------- |
175+
| `clientId` | string | Yes | Plaid client ID \(from the Plaid Dashboard under Team Settings → Keys\) |
176+
| `secret` | string | Yes | Plaid API secret for the selected environment |
177+
| `environment` | string | No | Plaid environment: 'production' \(default\) or 'sandbox' |
178+
| `query` | string | Yes | Institution name to search for, e.g. 'Chase' |
179+
| `countryCodes` | string | No | Comma-separated ISO country codes to search in \(defaults to 'US'\) |
180+
| `products` | string | No | Comma-separated products the institutions must support, e.g. 'transactions,auth' |
181+
182+
#### Output
183+
184+
| Parameter | Type | Description |
185+
| --------- | ---- | ----------- |
186+
| `institutions` | array | Institutions matching the search |
187+
| `count` | number | Number of institutions returned |
188+
189+
### Plaid Get Institution
190+
191+
Get details for a financial institution by its Plaid institution ID
192+
193+
#### Input
194+
195+
| Parameter | Type | Required | Description |
196+
| --------- | ---- | -------- | ----------- |
197+
| `clientId` | string | Yes | Plaid client ID \(from the Plaid Dashboard under Team Settings → Keys\) |
198+
| `secret` | string | Yes | Plaid API secret for the selected environment |
199+
| `environment` | string | No | Plaid environment: 'production' \(default\) or 'sandbox' |
200+
| `institutionId` | string | Yes | Plaid institution ID, e.g. 'ins_109508' |
201+
| `countryCodes` | string | No | Comma-separated ISO country codes \(defaults to 'US'\) |
202+
203+
#### Output
204+
205+
| Parameter | Type | Description |
206+
| --------- | ---- | ----------- |
207+
| `institution` | json | Institution details |
208+
209+
### Plaid Exchange Public Token
210+
211+
Exchange a public token from Plaid Link (or the sandbox) for a permanent access token and Item ID
212+
213+
#### Input
214+
215+
| Parameter | Type | Required | Description |
216+
| --------- | ---- | -------- | ----------- |
217+
| `clientId` | string | Yes | Plaid client ID \(from the Plaid Dashboard under Team Settings → Keys\) |
218+
| `secret` | string | Yes | Plaid API secret for the selected environment |
219+
| `environment` | string | No | Plaid environment: 'production' \(default\) or 'sandbox' |
220+
| `publicToken` | string | Yes | Public token returned by Plaid Link onSuccess \(or the sandbox token creator\) |
221+
222+
#### Output
223+
224+
| Parameter | Type | Description |
225+
| --------- | ---- | ----------- |
226+
| `accessToken` | string | Access token for the linked Item; store it securely and pass it to the other Plaid operations |
227+
| `itemId` | string | ID of the Item the token belongs to |
228+
229+
### Plaid Create Sandbox Public Token
230+
231+
Create a sandbox public token for a test institution without going through Plaid Link. Sandbox only — exchange the result for an access token to test other operations
232+
233+
#### Input
234+
235+
| Parameter | Type | Required | Description |
236+
| --------- | ---- | -------- | ----------- |
237+
| `clientId` | string | Yes | Plaid client ID \(from the Plaid Dashboard under Team Settings → Keys\) |
238+
| `secret` | string | Yes | Plaid API secret for the selected environment |
239+
| `institutionId` | string | Yes | Sandbox institution ID, e.g. 'ins_109508' \(First Platypus Bank\) |
240+
| `initialProducts` | string | Yes | Comma-separated products to enable, e.g. 'transactions' or 'auth,identity' |
241+
| `webhook` | string | No | Webhook URL to associate with the Item |
242+
243+
#### Output
244+
245+
| Parameter | Type | Description |
246+
| --------- | ---- | ----------- |
247+
| `publicToken` | string | Sandbox public token to exchange for an access token |
248+
249+

apps/sim/blocks/blocks/brex.ts

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { BrexIcon } from '@/components/icons'
22
import type { BlockConfig, BlockMeta } from '@/blocks/types'
33
import { AuthMode, IntegrationType } from '@/blocks/types'
4-
import { normalizeFileInput } from '@/blocks/utils'
4+
import { normalizeFileInput, toOptionalBoolean, toOptionalFiniteNumber } from '@/blocks/utils'
55
import type { BrexResponse } from '@/tools/brex/types'
66

77
/** Coerces a required money-amount field to a finite number, throwing on blank/non-numeric input rather than silently sending 0 or NaN to Brex. */
@@ -16,23 +16,6 @@ function toRequiredAmount(value: unknown, fieldLabel: string): number {
1616
return parsed
1717
}
1818

19-
/** Coerces an optional numeric field to a finite number, throwing on non-numeric input instead of silently forwarding NaN. Preserves explicit 0. */
20-
function toOptionalFiniteNumber(value: unknown, fieldLabel: string): number | undefined {
21-
if (value == null || (typeof value === 'string' && value.trim() === '')) return undefined
22-
const parsed = Number(value)
23-
if (!Number.isFinite(parsed)) {
24-
throw new Error(`${fieldLabel} must be a valid number`)
25-
}
26-
return parsed
27-
}
28-
29-
/** Normalizes a boolean field that may arrive as a string (e.g. from a dynamic <Block.output> reference) instead of an actual boolean. */
30-
function toOptionalBoolean(value: unknown): boolean | undefined {
31-
if (value == null) return undefined
32-
if (typeof value === 'boolean') return value
33-
return String(value).toLowerCase() === 'true'
34-
}
35-
3619
const PAGINATED_OPERATIONS = new Set([
3720
'list_expenses',
3821
'list_card_transactions',

0 commit comments

Comments
 (0)