plaid について
Plaid Banking API を利用する開発者向けの実装リファレンスです。口座接続、金融データ、決済、本人確認に加え、Link フロー、Webhook、環境設定、安全な取り扱いを説明します。
主な機能
- 01Plaid Link による口座接続フロー
- 02取引、残高、口座情報の取得
- 03Auth、Identity、Investments、Liabilities 製品
- 04ACH 送金と Webhook の処理
- 05Sandbox、Development、Production 環境
- 06トークン保護と再認証のガイダンス
活用シーン
- 01フィンテックアプリで銀行口座を接続
- 02取引履歴や現在残高の取得
- 03ACH 送金向けの口座情報読み取り
- 04取引更新や口座接続エラーへの対応
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ raintree-technology/ claude-starter --skill plaidインストール後、Claude Code で/plaidを入力して読み込まれたか確認します。
詳細
Plaid Banking API エキスパート
Plaid は、金融データへのアクセス、決済、本人確認のために、アプリケーションをユーザーの銀行口座に接続します。
使用する場面
- フィンテックアプリで銀行口座を接続する
- Plaid Link フローを実装する
- 取引履歴、残高、口座情報を取得する
- ACH 送金を設定する
- 本人確認・収入確認を行う
- Plaid ウェブフックを処理する
主な製品
| 製品 | 用途 |
|---|---|
| Auth | ACH 用の銀行口座番号・ルーティング番号 |
| Transactions | 取引履歴(最大 24 か月分) |
| Identity | 銀行口座の所有権によるユーザー確認 |
| Balance | リアルタイムの口座残高 |
| Investments | 投資口座の保有資産 |
| Liabilities | ローンおよびクレジットカードのデータ |
クイックスタート
1. SDK をインストールする
npm install plaid react-plaid-link
2. Plaid クライアントを作成する
import { Configuration, PlaidApi, PlaidEnvironments } from "plaid";
const client = new PlaidApi(
new Configuration({
basePath: PlaidEnvironments.sandbox,
baseOptions: {
headers: {
"PLAID-CLIENT-ID": process.env.PLAID_CLIENT_ID,
"PLAID-SECRET": process.env.PLAID_SECRET,
},
},
})
);
3. Link トークンを作成する(サーバー)
// POST /api/plaid/create-link-token
export async function POST(req: Request) {
const response = await client.linkTokenCreate({
user: { client_user_id: userId },
client_name: "Your App",
products: ["auth", "transactions"],
country_codes: ["US"],
language: "en",
});
return Response.json({ link_token: response.data.link_token });
}
4. Plaid Link(クライアント)
import { usePlaidLink } from "react-plaid-link";
function ConnectBank({ linkToken }) {
const { open, ready } = usePlaidLink({
token: linkToken,
onSuccess: async (public_token, metadata) => {
// Exchange for access_token on server
await fetch("/api/plaid/exchange-token", {
method: "POST",
body: JSON.stringify({ public_token }),
});
},
});
return (
<button onClick={() => open()} disabled={!ready}>
Connect Bank Account
</button>
);
}
5. トークンを交換する(サーバー)
// POST /api/plaid/exchange-token
export async function POST(req: Request) {
const { public_token } = await req.json();
const response = await client.itemPublicTokenExchange({
public_token,
});
// Store access_token securely (encrypted in database)
await db.users.update(userId, {
plaid_access_token: response.data.access_token,
plaid_item_id: response.data.item_id,
});
return Response.json({ success: true });
}
データの取得
Auth の取得(口座番号・ルーティング番号)
const response = await client.authGet({ access_token });
const ach = response.data.numbers.ach[0];
console.log("Account:", ach.account);
console.log("Routing:", ach.routing);
取引履歴の取得
const response = await client.transactionsGet({
access_token,
start_date: "2024-01-01",
end_date: "2024-12-31",
});
let transactions = response.data.transactions;
// Handle pagination
while (transactions.length < response.data.total_transactions) {
const more = await client.transactionsGet({
access_token,
start_date: "2024-01-01",
end_date: "2024-12-31",
offset: transactions.length,
});
transactions = transactions.concat(more.data.transactions);
}
取引オブジェクト:
{
transaction_id: "abc123",
amount: 12.34, // Positive = outflow
date: "2024-11-16",
name: "Starbucks",
merchant_name: "Starbucks",
category: ["Food and Drink", "Coffee Shop"],
pending: false,
}
残高の取得
const response = await client.accountsBalanceGet({ access_token });
response.data.accounts.forEach((account) => {
console.log(`${account.name}: $${account.balances.current}`);
});
本人確認情報の取得
const response = await client.identityGet({ access_token });
const owner = response.data.accounts[0].owners[0];
console.log("Name:", owner.names[0]);
console.log("Email:", owner.emails[0].data);
console.log("Phone:", owner.phone_numbers[0].data);
ウェブフック
エンドポイントの設定
// POST /api/plaid/webhook
export async function POST(req: Request) {
const { webhook_type, webhook_code, item_id } = await req.json();
switch (webhook_type) {
case "TRANSACTIONS":
if (webhook_code === "DEFAULT_UPDATE") {
// New transactions available - fetch them
await syncTransactions(item_id);
}
break;
case "ITEM":
if (webhook_code === "ERROR") {
// Connection issue - prompt user to re-authenticate
await notifyUserReauth(item_id);
}
break;
}
return Response.json({ received: true });
}
主なウェブフックイベント:
| イベント | 意味 |
|---|---|
TRANSACTIONS: INITIAL_UPDATE | 最初のバッチの準備完了 |
TRANSACTIONS: DEFAULT_UPDATE | 新しい取引 |
ITEM: ERROR | 接続の問題 |
ITEM: PENDING_EXPIRATION | 認証情報の有効期限が近づいています |
環境
| 環境 | 用途 | ベースパス |
|---|---|---|
| Sandbox | テスト | PlaidEnvironments.sandbox |
| Development | 制限付きの本番利用(100 接続) | PlaidEnvironments.development |
| Production | 本番 | PlaidEnvironments.production |
Sandbox テスト用認証情報
- ユーザー名:
user_good - パスワード:
pass_good - MFA:
1234
エラー処理
再認証(更新モード)
認証情報の有効期限が切れた場合:
// Create link token for update mode
const response = await client.linkTokenCreate({
user: { client_user_id: userId },
client_name: "Your App",
access_token: existingAccessToken, // Triggers update mode
country_codes: ["US"],
language: "en",
});
よくあるエラー
| エラー | 解決方法 |
|---|---|
ITEM_LOGIN_REQUIRED | Link の更新モードで再認証する |
RATE_LIMIT_EXCEEDED | 指数バックオフを実装する |
PRODUCT_NOT_READY | ウェブフックを待つか、再試行する |
セキュリティのベストプラクティス
実施すること:
- データベース内のアクセストークンを暗号化して保存する
- 認証情報には環境変数を使用する
- ウェブフックの署名を検証する
- すべてのエンドポイントで HTTPS を使用する
実施しないこと:
- シークレットキーをクライアント側に公開する
- アクセストークンをログに記録する
- 認証情報をコード内に保存する
Next.js App Router の例
// app/api/plaid/create-link-token/route.ts
import { NextResponse } from "next/server";
import { Configuration, PlaidApi, PlaidEnvironments } from "plaid";
const client = new PlaidApi(
new Configuration({
basePath: PlaidEnvironments.sandbox,
baseOptions: {
headers: {
"PLAID-CLIENT-ID": process.env.PLAID_CLIENT_ID!,
"PLAID-SECRET": process.env.PLAID_SECRET!,
},
},
})
);
export async function POST(req: Request) {
const session = await getSession();
const response = await client.linkTokenCreate({
user: { client_user_id: session.user.id },
client_name: "Your App",
products: ["auth", "transactions"],
country_codes: ["US"],
language: "en",
webhook: `${process.env.NEXT_PUBLIC_URL}/api/plaid/webhook`,
});
return NextResponse.json({ link_token: response.data.link_token });
}
実装チェックリスト
- Plaid アカウントに登録する
- クライアント ID とシークレットを取得する
-
plaidとreact-plaid-linkをインストールする - 環境変数を設定する
- Link トークンのエンドポイントを作成する
- トークン交換エンドポイントを実装する
- フロントエンドに Plaid Link を統合する
- アクセストークンを安全に保存する
- ウェブフックのエンドポイントを設定する
- 再認証エラーを処理する
- Sandbox の認証情報でテストする
リソース
- ドキュメント: https://plaid.com/docs/
- API リファレンス: https://plaid.com/docs/api/
- クイックスタート: https://github.com/plaid/quickstart
コメント
Markdown 対応