@xenterprises/fastify-xplaid
v1.1.1
Published
Fastify plugin for Plaid financial data integration - bank account linking, transactions, and identity verification
Readme
xPlaid
Fastify plugin for Plaid financial data integration - bank account linking, transactions, identity verification, and more.
Installation
npm install xplaid plaidUsage
import Fastify from "fastify";
import xPlaid from "xplaid";
const fastify = Fastify();
await fastify.register(xPlaid, {
clientId: process.env.PLAID_CLIENT_ID,
secret: process.env.PLAID_SECRET,
environment: "sandbox", // 'sandbox' | 'development' | 'production'
});
// The plugin is now available at fastify.xplaidConfiguration Options
| Option | Type | Required | Default | Description |
|--------|------|----------|---------|-------------|
| clientId | string | Yes | - | Your Plaid client ID |
| secret | string | Yes | - | Your Plaid secret |
| environment | string | No | 'sandbox' | Plaid environment: 'sandbox', 'development', or 'production' |
| active | boolean | No | true | Enable/disable the plugin |
Link Flow
The Plaid Link flow is the primary way users connect their bank accounts:
1. Create a Link Token
// Create a link token for the frontend
const linkToken = await fastify.xplaid.link.createToken({
userId: "user_123",
clientName: "My App",
products: ["transactions", "auth"],
countryCodes: ["US"],
language: "en",
// Optional: webhook for real-time updates
webhook: "https://myapp.com/webhooks/plaid",
// Optional: redirect URI for OAuth flows
redirectUri: "https://myapp.com/oauth-callback",
});
// Return linkToken.link_token to your frontend2. Exchange Public Token
After the user completes Plaid Link, exchange the public token for an access token:
// Exchange the public token from Plaid Link
const result = await fastify.xplaid.link.exchangePublicToken("public-token-from-link");
// Store these securely
const accessToken = result.access_token;
const itemId = result.item_id;3. Get Link Token Info
const tokenInfo = await fastify.xplaid.link.getToken("link-token-id");Accounts
// Get all accounts for an item
const accounts = await fastify.xplaid.accounts.get(accessToken);
// Get real-time balance
const balance = await fastify.xplaid.accounts.getBalance(accessToken, {
accountIds: ["account_id_1", "account_id_2"], // Optional: filter by accounts
});Transactions
Sync Transactions (Recommended)
The sync endpoint is the recommended way to get transactions:
// Initial sync - get all available transactions
let cursor = null;
let allTransactions = [];
let response = await fastify.xplaid.transactions.sync(accessToken, { cursor });
allTransactions.push(...response.added);
cursor = response.next_cursor;
// Store the cursor for future syncs
// On subsequent syncs, pass the cursor to get only new/updated transactionsGet Transactions (Legacy)
const transactions = await fastify.xplaid.transactions.get(accessToken, {
startDate: "2024-01-01",
endDate: "2024-12-31",
count: 100,
offset: 0,
accountIds: ["account_id"], // Optional
});Refresh Transactions
Force a refresh of transaction data:
await fastify.xplaid.transactions.refresh(accessToken);Identity
Get identity information (name, email, phone, address) from the bank:
const identity = await fastify.xplaid.identity.get(accessToken, {
accountIds: ["account_id"], // Optional
});Auth
Get ACH routing and account numbers:
const auth = await fastify.xplaid.auth.get(accessToken, {
accountIds: ["account_id"], // Optional
});
// Returns account numbers including:
// - ACH routing numbers
// - Account numbers
// - Wire routing numbers (if available)Investments
Get Holdings
const holdings = await fastify.xplaid.investments.getHoldings(accessToken, {
accountIds: ["account_id"], // Optional
});Get Investment Transactions
const investmentTx = await fastify.xplaid.investments.getTransactions(accessToken, {
startDate: "2024-01-01",
endDate: "2024-12-31",
count: 100,
offset: 0,
accountIds: ["account_id"], // Optional
});Liabilities
Get loan and credit card liability information:
const liabilities = await fastify.xplaid.liabilities.get(accessToken, {
accountIds: ["account_id"], // Optional
});
// Returns credit, mortgage, and student loan detailsItem Management
Get Item Info
const item = await fastify.xplaid.items.get(accessToken);Remove an Item
Permanently delete an item and revoke access:
await fastify.xplaid.items.remove(accessToken);Get Institution
const institution = await fastify.xplaid.items.getInstitution("ins_123", {
countryCodes: ["US"],
includeOptionalMetadata: true,
includeStatus: true,
});Search Institutions
const institutions = await fastify.xplaid.items.searchInstitutions({
query: "Chase",
products: ["transactions"],
countryCodes: ["US"],
count: 10,
offset: 0,
});Webhooks
Update Webhook URL
await fastify.xplaid.webhooks.update(accessToken, "https://myapp.com/new-webhook-url");Get Verification Key
Verify webhook signatures:
const key = await fastify.xplaid.webhooks.getVerificationKey("key_id_from_webhook_header");Constants
The plugin exposes useful constants:
const { ENVIRONMENTS, PRODUCTS, COUNTRY_CODES } = fastify.xplaid.constants;
// Or import directly
import { ENVIRONMENTS, PRODUCTS, COUNTRY_CODES } from "xplaid";
// ENVIRONMENTS
ENVIRONMENTS.SANDBOX // 'sandbox'
ENVIRONMENTS.DEVELOPMENT // 'development'
ENVIRONMENTS.PRODUCTION // 'production'
// PRODUCTS
PRODUCTS.AUTH // 'auth'
PRODUCTS.TRANSACTIONS // 'transactions'
PRODUCTS.IDENTITY // 'identity'
PRODUCTS.INVESTMENTS // 'investments'
PRODUCTS.LIABILITIES // 'liabilities'
PRODUCTS.ASSETS // 'assets'
// COUNTRY_CODES
COUNTRY_CODES.US // 'US'
COUNTRY_CODES.CA // 'CA'
COUNTRY_CODES.GB // 'GB'
COUNTRY_CODES.IE // 'IE'
COUNTRY_CODES.FR // 'FR'
COUNTRY_CODES.ES // 'ES'
COUNTRY_CODES.NL // 'NL'Raw Client Access
For advanced use cases, access the underlying Plaid client directly:
const plaidClient = fastify.xplaid.raw;
// Use any Plaid API method
const response = await plaidClient.sandboxItemFireWebhook({
access_token: accessToken,
webhook_code: "DEFAULT_UPDATE",
});Error Handling
Plaid errors include detailed error codes:
try {
const accounts = await fastify.xplaid.accounts.get(accessToken);
} catch (error) {
if (error.response?.data) {
const plaidError = error.response.data;
console.error("Plaid error:", {
errorType: plaidError.error_type,
errorCode: plaidError.error_code,
errorMessage: plaidError.error_message,
displayMessage: plaidError.display_message,
});
}
}Common error types:
INVALID_REQUEST- Invalid parametersINVALID_INPUT- Invalid input dataINSTITUTION_ERROR- Bank is unavailableRATE_LIMIT_EXCEEDED- Too many requestsAPI_ERROR- Plaid internal errorITEM_ERROR- Item-specific error (e.g., login required)
Configuration Access
const config = fastify.xplaid.config;
// {
// clientId: '***id', // Masked for security
// environment: 'sandbox'
// }Complete Example
import Fastify from "fastify";
import xPlaid from "xplaid";
const fastify = Fastify({ logger: true });
await fastify.register(xPlaid, {
clientId: process.env.PLAID_CLIENT_ID,
secret: process.env.PLAID_SECRET,
environment: process.env.PLAID_ENV || "sandbox",
});
// Create link token endpoint
fastify.post("/api/create-link-token", async (request, reply) => {
const { userId } = request.body;
const linkToken = await fastify.xplaid.link.createToken({
userId,
clientName: "My Finance App",
products: ["transactions"],
countryCodes: ["US"],
language: "en",
});
return { linkToken: linkToken.link_token };
});
// Exchange public token endpoint
fastify.post("/api/exchange-token", async (request, reply) => {
const { publicToken, userId } = request.body;
const result = await fastify.xplaid.link.exchangePublicToken(publicToken);
// Store accessToken and itemId in your database
// associated with the userId
return { success: true };
});
// Get transactions endpoint
fastify.get("/api/transactions", async (request, reply) => {
const { userId } = request.user; // From your auth middleware
// Retrieve accessToken from your database for this user
const accessToken = await getAccessTokenForUser(userId);
const transactions = await fastify.xplaid.transactions.sync(accessToken);
return { transactions: transactions.added };
});
await fastify.listen({ port: 3000 });Testing
npm testLicense
ISC
