Connect bank accounts securely via Plaid for seamless off-ramp destinations
Plaid integration allows your customers to securely connect their bank accounts without manually entering account numbers and routing information. Grid handles the complete Plaid Link flow, automatically creating external accounts when customers authenticate their banks.
Plaid integration requires Grid to manage your Plaid configuration. Contact
support to enable Plaid for your platform.
The Plaid flow involves collaboration between your platform, Grid, Plaid, and the customer’s bank:
Request link token: Your platform requests a Plaid Link token from Grid for a specific customer
Initialize Plaid Link: Display Plaid Link UI to your customer using the link token
Customer authenticates: Customer selects their bank and authenticates using Plaid Link
Exchange tokens: Plaid returns a public token; your platform sends it to Grid’s callback URL
Async processing: Grid exchanges the public token with Plaid and retrieves account details
External account created: Grid creates the external account and sends a webhook notification. The external account is available for transfers and payments
linkToken: Use this to initialize Plaid Link in your frontend
callbackUrl: Where to POST the public token after Plaid authentication completes. The URL follows the pattern https://api.lightspark.com/grid/{version}/plaid/callback/{linkToken}. While you can construct this manually, we recommend using the provided URL for forward compatibility.
expiration: Link tokens typically expire after 4 hours
requestId: Unique identifier for debugging purposes
Link tokens are single-use and will expire. If the customer doesn’t complete
the flow, you’ll need to request a new link token.
Create a backend endpoint that receives the public token from your frontend and forwards it to Grid’s callback URL:
Copy
Ask AI
// Backend endpoint: POST /api/plaid/exchange-tokenapp.post('/api/plaid/exchange-token', async (req, res) => { const { publicToken, accountId } = req.body; const customerId = req.user.gridCustomerId; // From your auth try { // Get the callback URL (you stored this when requesting the link token) const callbackUrl = await getStoredCallbackUrl(customerId); // Forward to Grid's callback URL with proper authentication const response = await fetch(callbackUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ publicToken: publicToken, accountId: accountId, }), }); if (!response.ok) { throw new Error(`Grid API error: ${response.status}`); } const result = await response.json(); res.json({ success: true, message: result.message }); } catch (error) { console.error('Error exchanging token:', error); res.status(500).json({ error: 'Failed to process bank account' }); }});
Response from Grid (HTTP 202 Accepted):
Copy
Ask AI
{ "message": "External account creation initiated. You will receive a webhook notification when complete.", "requestId": "req_def456ghi789"}
A 202 Accepted response indicates Grid has received the token and is
processing it asynchronously. The external account will be created in the
background.
const { open } = usePlaidLink({ token: linkToken, onExit: (error, metadata) => { if (error) { console.error("Plaid error:", error); // Show user-friendly error message setError("Unable to connect to your bank. Please try again."); } else { // User closed the modal without completing console.log("User exited without connecting"); } },});
Gracefully handle Plaid errors and offer alternatives:
Copy
Ask AI
const { open } = usePlaidLink({ token: linkToken, onSuccess: handleSuccess, onExit: (error, metadata) => { if (error) { console.error("Plaid error:", error); // Show error-specific messaging if (error.error_code === "ITEM_LOGIN_REQUIRED") { setError( "Your bank requires you to log in again. Please try reconnecting." ); } else if (error.error_code === "INSTITUTION_NOT_RESPONDING") { setError( "Your bank is temporarily unavailable. Please try again later or connect manually." ); // Offer manual entry option setShowManualEntry(true); } else { setError( "Unable to connect to your bank. Would you like to enter your account details manually?" ); setShowManualEntry(true); } } else { // User exited without completing console.log("User closed Plaid without connecting"); } },});{ showManualEntry && <ManualBankAccountForm onSubmit={handleManualEntry} />;}