freee会計API 取引先自動連携ガイド(OAuth/トークンローテーション/DRY-RUN)
Next.js+SupabaseアプリからfreeeのOAuth接続・refresh_tokenローテーション対応・取引先の自動紐付け/新規作成をDRY-RUN安全に実装する手順
約13.5万トークンの節約 (API料金換算で約200円分)。 要件定義・技術調査・試行錯誤ぶんのトークンがまるごと不要になります。※ 出品者申告とレビューに基づく推定値。モデル・タスク内容により変動します。
この巻物について
「freee会計API 取引先自動連携ガイド(OAuth/トークンローテーション/DRY-RUN)」は、経理・バックオフィスカテゴリのAI指示書(MDファイル)です。Next.js+SupabaseアプリからfreeeのOAuth接続・refresh_tokenローテーション対応・取引先の自動紐付け/新規作成をDRY-RUN安全に実装する手順この巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約13.5万トークン(API料金換算で約200円)・90%のトークンを節約できます。
- カテゴリ
- 経理・バックオフィス
- 対応AI
- claude-code、cursor、codex-cli
- ライセンス
- 商用利用可 (再販不可)
- 価格
- 無料
- ゼロから開発時
- 約15万トークン
- この巻物使用時
- 約1.5万トークン
- 節約量
- 約13.5万トークン (約200円)
- 更新日
- 2026-08-20
使い方 (AIに渡す3つの方法)
いちばん簡単なのはワンライナー。Claude Code のターミナルに貼るだけです。
claude "https://makimono-md.vercel.app/api/v1/files/freee-api-oauth-dry-run/raw を読み込んで、この指示書どおりに実装して"
中身
freee会計APIと自社アプリの「取引先」自動連携 — OAuth・トークンローテーション・DRY-RUN安全パターン
前提
Next.js + Supabase(Postgres)構成のアプリで、自社の受注管理DBにある顧客(customer)を、freee会計の「取引先(partner)」と自動で紐付け/新規登録したい場合のリファレンス実装。他のDB(MySQL, Prisma等)・他のフレームワークでも設計思想はそのまま流用できる。
落とし穴1: freeeのrefresh_tokenは使い捨て(ローテーション)
freeeのOAuth refresh_tokenは1回使うと無効化され、レスポンスに含まれる新しいrefresh_tokenに置き換わる。これを知らずに固定の環境変数(.env)にrefresh_tokenを書いていると、初回のトークン更新後にアプリが動かなくなる。
対策: refresh_tokenをDBの専用テーブルで管理し、更新の都度DBへ書き戻す。
create table if not exists public.freee_tokens (
id text primary key default 'default',
client_id text not null,
client_secret text not null,
refresh_token text not null,
access_token text not null,
access_expires_at timestamptz not null,
company_id integer not null,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now()
);
alter table public.freee_tokens enable row level security;
revoke all on public.freee_tokens from anon, authenticated; -- service_roleのみ扱う
// lib/freee-token-service.ts の骨格
export async function getValidAccessToken(): Promise<string> {
const row = await getTokenRow(); // DBから1行取得
if (row.access_token && row.access_expires_at > Date.now() + 120_000) {
return row.access_token; // 有効期限5分前まではそのまま使う
}
const res = await fetch("https://accounts.secure.freee.co.jp/public_api/token", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
grant_type: "refresh_token",
client_id: row.client_id,
client_secret: row.client_secret,
refresh_token: row.refresh_token,
}),
});
const json = await res.json();
// 新しいrefresh_tokenを必ずDBに書き戻す。ここを忘れると次回の更新で失敗する
await saveTokenRow({
access_token: json.access_token,
refresh_token: json.refresh_token,
access_expires_at: Date.now() + json.expires_in * 1000,
});
return json.access_token;
}
初回OAuth接続(人間が1回だけ操作する部分)
freeeは1つのfreeeアカウントが複数の事業所(company)を持てるため、認可URLにprompt=select_companyを付けて選択させる。接続後は必ずAPI(GET /api/1/companies)で実際の事業所名を取得して、想定した会社と一致するか確認すること(選択ミスに気づかず別会社に書き込む事故を防ぐ)。
https://accounts.secure.freee.co.jp/public_api/authorize?response_type=code&client_id=<CLIENT_ID>&redirect_uri=urn:ietf:wg:oauth:2.0:oob&prompt=select_company
認可コードは単回・短命(数分で失効)。表示されたらすぐにトークン交換スクリプトへ渡す。
落とし穴2: Next.js App Router の route.ts は決まったexportしか許されない
route.tsから独自のヘルパー関数をexportすると、Next.jsのビルド時型検証(.next/types/...)が「route.tsはGET/POST等の決まった名前以外をexportできない」というエラーを出し、ビルドが失敗する。ヘルパー関数は別のlibファイルに置き、route.tsからimportして使うこと。この制約は気づきにくく、tsc --noEmit単体では見逃す(Next.jsのbuild/typecheckコマンドで初めて出る)ので注意。
会社名の突合ロジック(表記ゆれの吸収)
function normalizeCompanyName(value: string): string {
return value
.normalize("NFKC") // 半角カナ→全角、㈱→(株)等の互換分解を含む
.toLowerCase()
.replace(/(\(株\)|\(有\)|株式会社|有限会社|合同会社|一般社団法人|医療法人|学校法人|特定非営利活動法人)/g, "")
.replace(/[\s ・,.\-_]/g, "");
}
NFKC正規化を先に行うこと。順序を間違えると(例: 法人格の除去を先にやってからNFKCする)、㈱のような合字が正規化後に別の文字列へ変わり、除去パターンが効かなくなる。
自動登録ロジックの安全設計
- 既定はDRY-RUN。書き込み系の新機能は必ず「何をする予定か」をログ・レスポンスで返すだけのモードを既定にし、明示的なフラグ(
FREEE_DRY_RUN_DEFAULT=false)でのみ実書き込みを許可する。 - 既存の取引先が見つかれば紐付けのみ、無ければ新規作成。新規作成を先に試すと重複取引先を量産する。
- 一度紐付けたら二重実行しないようDBに
freee_partner_idのような列を持ち、is nullを対象条件に含める(冪等性)。 - 除外条件を忘れない: 論理削除(archived)された内部処理レコードや、自社の内部会計処理用の顧客レコード(自社名そのもの)は対象から除外する。これを忘れると、社内処理の記録が誤って取引先登録の対象に混ざる。
- ローカルで
next devを起動し、実際にcron routeをcurlで叩いてDRY-RUNの出力を目視確認してからデプロイする(型チェックが通るだけでは、クエリ条件の抜け漏れ等のロジックバグは検出できない)。
まとめ
- refresh_tokenはDB管理+都度書き戻し(env固定は数時間で壊れる)
- 接続後は実際の事業所名をAPIで確認(選択ミス対策)
- route.tsから独自関数をexportしない(Next.js App Routerの制約)
- 会社名正規化はNFKC→法人格除去→記号除去の順
- 新機能はDRY-RUN既定、既存紐付け優先、冪等性列、除外条件を忘れない
よくある質問
+「freee会計API 取引先自動連携ガイド(OAuth/トークンローテーション/DRY-RUN)」とは何ですか?
Next.js+SupabaseアプリからfreeeのOAuth接続・refresh_tokenローテーション対応・取引先の自動紐付け/新規作成をDRY-RUN安全に実装する手順
+どれくらいトークン(費用)を節約できますか?
ゼロから開発すると約15万トークンかかりますが、この巻物を使えば約1.5万トークンで済みます。差し引き約13.5万トークン(API料金換算で約200円)・90%の節約です。
+どうやって使いますか?
無料です。MDファイルを Claude Code などのAIに読み込ませるだけ。ワンライナーをターミナルに貼れば実装が始まります。要件定義や技術調査を省いて実装だけにトークンを使えます。
+どのAIツールに対応していますか?
claude-code、cursor、codex-cli に対応しています。
+商用利用できますか?
ライセンスは「商用利用可 (再販不可)」です。
🤝 自分でAIを動かすのは、まだ不安…という方へ
この巻物の内容を、AIを使うプロに丸ごと任せることもできます。姉妹サービスAI代行堂なら「LINEで頼むだけで、仕事が完成」。
関連する巻物
請求書PDF→会計CSV 自動変換パイプラインMD
メール添付やフォルダ投込みの請求書PDFから金額・日付・取引先を抽出し、会計ソフト取込用CSVに変換するパイプラインを AI に作らせる指示書。Claude API の構造化抽出プロンプト込み。
請求書・領収書を「別シートに1行入れるだけ」で作る GAS 帳票テンプレ
スプレッドシートに 帳票/データ/設定 の3シートを組み、入力1行で印刷用帳票が完成する構成をGASで作る。セル値の読み戻しでは検出できない印刷時の文字切れを、PDF書き出しの目視で潰すまでを含む。
この巻物、誰かのトークンも救えます
𝕏 で節約レシートをシェア