結論:経理業務の3大ボトルネック(レシートOCR仕訳・経費精算承認・請求書処理)はAIエージェントで自動化できる。本記事ではfreee APIとマネーフォワードクラウドAPIへのPython接続コード、human-in-the-loopの承認フロー設計まで、コピペ可能な実装コードとともに解説する。
- freee API
/api/1/dealsを使った仕訳自動登録のPythonコードを公開 - 電子帳簿保存法・インボイス制度に準拠した保存フローをエージェントに組み込む方法
- 承認が必要な高額経費のみ人間にアラートするhuman-in-the-loop設計パターン
対象読者:情シス・開発者・AI推進担当で、経理部門のDXを任されている方
今日やること:Step 1の「レシートOCR→仕訳エージェント」コードをローカルで動かす
「経費精算のPDF、月末になると100件以上たまるんですよね…」
先日、ある製造業の情シス担当者からこんな相談を受けました。レシートを手入力→freeeに登録→上長承認依頼→会計ソフトに再入力、という4ステップのフローが毎月繰り返されていて、経理2名が月末の3日間を丸ごとこの作業に費やしている状態でした。
この経験から気づいたのは、経理業務はAIエージェントとの相性が特に良い、ということです。処理フローが明確で、判定ルール(勘定科目マッピング、インボイス適格判定など)が文書化されており、APIが公開されているからです。
この記事では、レシートOCRによる自動仕訳からfreee/マネーフォワードAPIへの接続コード、高額経費の承認フロー設計まで、コピペ可能なPythonコードとともに全公開します。2026年6月時点の各APIの最新仕様に基づいて構成しています。
まず試したい「5分即効」セットアップ3選
即効テクニック1:レシート画像からfreee仕訳を自動登録
最も即効性が高いのは「レシート撮影→OCR→freeeに仕訳登録」の一気通貫フローです。OpenAIのVision APIでレシートを解析し、freee APIの /api/1/receipts と /api/1/deals に自動登録します。
"""
レシートOCR → freee 仕訳自動登録エージェント
動作環境: Python 3.11+
必要パッケージ: pip install openai requests python-dotenv
"""
import os
import base64
import requests
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()
FREEE_ACCESS_TOKEN = os.getenv("FREEE_ACCESS_TOKEN")
FREEE_COMPANY_ID = os.getenv("FREEE_COMPANY_ID")
FREEE_BASE_URL = "https://api.freee.co.jp/api/1"
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
client = OpenAI(api_key=OPENAI_API_KEY)
def extract_receipt_data(image_path: str) -> dict:
"""レシート画像から日付・金額・取引先・税区分を抽出"""
with open(image_path, "rb") as f:
image_data = base64.b64encode(f.read()).decode("utf-8")
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": (
"このレシートから以下をJSONで返してください: "
"date(YYYY-MM-DD), amount(税込合計, 整数), "
"vendor(取引先名), tax_type('消費税10%'/'消費税8%'/'非課税')。"
"読み取れない場合はnullを返す。"
)
},
{
"type": "image_url",
"image_url": {"url": f"data:image/jpeg;base64,{image_data}"},
},
],
}
],
response_format={"type": "json_object"},
)
import json
return json.loads(response.choices[0].message.content)
def classify_account_item(vendor: str, amount: int) -> int:
"""取引先と金額から勘定科目IDを推定(要事前マッピング設定)"""
# 簡易マッピング例 — 実際は勘定科目マスタをfreee APIから取得して照合
ACCOUNT_MAPPING = {
"コンビニ": 1, # 消耗品費 (account_item_id は会社設定による)
"電車": 2, # 旅費交通費
"タクシー": 2,
"飲食": 3, # 会議費 or 交際費
"ホテル": 4, # 宿泊費
}
for keyword, item_id in ACCOUNT_MAPPING.items():
if keyword in vendor:
return item_id
return 99 # 未分類: 人間に確認を求める
def register_deal_to_freee(receipt_data: dict, account_item_id: int) -> dict:
"""freee /api/1/deals にPOSTして仕訳登録"""
headers = {
"Authorization": f"Bearer {FREEE_ACCESS_TOKEN}",
"Content-Type": "application/json",
}
payload = {
"company_id": int(FREEE_COMPANY_ID),
"issue_date": receipt_data["date"],
"due_date": receipt_data["date"],
"type": "expense",
"details": [
{
"account_item_id": account_item_id,
"tax_code": 1, # 課税仕入(10%)。実際はtax_typeから動的に取得
"amount": receipt_data["amount"],
"description": receipt_data.get("vendor", ""),
}
],
}
res = requests.post(
f"{FREEE_BASE_URL}/deals",
headers=headers,
json={"deal": payload},
timeout=30,
)
res.raise_for_status()
return res.json()
def process_receipt(image_path: str) -> dict:
"""レシート1枚を処理するメインフロー"""
# Step1: OCR
data = extract_receipt_data(image_path)
print(f"[OCR] 取得データ: {data}")
if data.get("amount") is None:
return {"status": "error", "reason": "金額読み取り失敗 — 手動確認が必要"}
# Step2: 勘定科目分類
account_id = classify_account_item(data.get("vendor", ""), data["amount"])
# Step3: human-in-the-loop (10万円超は人間確認)
if data["amount"] >= 100000 or account_id == 99:
return {
"status": "pending_review",
"data": data,
"account_item_id": account_id,
"reason": "高額 or 未分類 — 承認フローへ",
}
# Step4: freeeに自動登録
result = register_deal_to_freee(data, account_id)
return {"status": "registered", "deal_id": result["deal"]["id"]}
if __name__ == "__main__":
# テスト実行 — 本番前に必ずテスト環境で動作確認すること
result = process_receipt("sample_receipt.jpg")
print(result)
効果(試算):レシート1枚の処理時間が手入力で平均3分→自動化後は約10秒(OCR+API呼び出し)。月100枚なら約290分→約17分に短縮できる計算です。
動作環境:Python 3.11+, openai>=1.0, requests 2.31+
即効テクニック2:マネーフォワードクラウド経費への経費申請自動送信
マネーフォワードクラウド経費は OAuth2 Bearer Token 方式のREST APIを提供しています。経費申請を自動作成し、承認待ちキューに積むフローです。
"""
マネーフォワードクラウド経費 API — 経費申請自動送信
動作環境: Python 3.11+
必要パッケージ: pip install requests python-dotenv
API仕様: https://expense.moneyforward.com/api/index.html
"""
import os
import requests
from datetime import date
from dotenv import load_dotenv
load_dotenv()
MF_ACCESS_TOKEN = os.getenv("MF_EXPENSE_ACCESS_TOKEN")
MF_OFFICE_ID = os.getenv("MF_OFFICE_ID")
MF_EXPENSE_BASE = "https://expense.moneyforward.com/api/v1/offices"
def create_expense_report(title: str) -> str:
"""経費申請書(レポート)を作成してIDを返す"""
headers = {
"Authorization": f"Bearer {MF_ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
}
payload = {
"ex_report": {
"title": title,
"department_id": None, # 部署IDはマスタから取得推奨
}
}
res = requests.post(
f"{MF_EXPENSE_BASE}/{MF_OFFICE_ID}/ex_reports",
headers=headers,
json=payload,
timeout=30,
)
res.raise_for_status()
return res.json()["ex_report"]["id"]
def add_expense_line(report_id: str, expense_data: dict) -> dict:
"""申請書に経費明細を1行追加"""
headers = {
"Authorization": f"Bearer {MF_ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
}
payload = {
"ex_item": {
"ex_report_id": report_id,
"value": expense_data["amount"], # 税込金額(整数)
"recognized_at": expense_data["date"], # "YYYY-MM-DD"
"memo": expense_data.get("memo", ""),
"ex_item_type_name": expense_data.get("category", "交通費"),
}
}
res = requests.post(
f"{MF_EXPENSE_BASE}/{MF_OFFICE_ID}/ex_items",
headers=headers,
json=payload,
timeout=30,
)
res.raise_for_status()
return res.json()
def submit_expense_report(report_id: str) -> dict:
"""経費申請書を承認フローに提出"""
headers = {
"Authorization": f"Bearer {MF_ACCESS_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
}
res = requests.patch(
f"{MF_EXPENSE_BASE}/{MF_OFFICE_ID}/ex_reports/{report_id}/submit",
headers=headers,
timeout=30,
)
res.raise_for_status()
return res.json()
def auto_submit_expenses(expense_list: list[dict]) -> str:
"""経費リストを一括で申請書に変換して提出"""
today_str = date.today().strftime("%Y年%m月度 経費申請")
report_id = create_expense_report(today_str)
for item in expense_list:
add_expense_line(report_id, item)
print(f" 追加: {item.get('memo', '')} ¥{item['amount']:,}")
result = submit_expense_report(report_id)
return report_id
# 使用例 — 本番環境で実行する前に、必ずテスト環境で動作確認すること
if __name__ == "__main__":
sample_expenses = [
{"date": "2026-06-10", "amount": 1320, "memo": "山手線往復", "category": "交通費"},
{"date": "2026-06-10", "amount": 3850, "memo": "取引先会食", "category": "接待交際費"},
{"date": "2026-06-11", "amount": 1100, "memo": "文具購入", "category": "消耗品費"},
]
report_id = auto_submit_expenses(sample_expenses)
print(f"申請完了 report_id={report_id}")
動作環境:Python 3.11+, requests 2.31+。マネーフォワードクラウド経費のOAuthアプリ登録が必要。
即効テクニック3:請求書PDFからインボイス適格番号を抽出して電帳法対応保存
2024年1月から電子取引の電子保存が義務化されました。受領した請求書PDFから適格請求書発行事業者登録番号を抽出し、国税庁公表のCSVと照合してインボイス適格判定を自動化するコードです。
"""
請求書PDF → インボイス適格判定 → 電帳法対応保存
動作環境: Python 3.11+
必要パッケージ: pip install openai pypdf requests python-dotenv
電帳法要件参照: https://www.nta.go.jp/law/joho-zeikaishaku/sonota/jirei/tokusetsu/index.htm
"""
import os
import re
import json
import hashlib
from pathlib import Path
from datetime import datetime
import requests
from openai import OpenAI
from pypdf import PdfReader
from dotenv import load_dotenv
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
# 電帳法要件: 取引年月日・取引金額・取引先の3項目で検索可能にする
ARCHIVE_DIR = Path("./invoice_archive")
ARCHIVE_DIR.mkdir(exist_ok=True)
INDEX_FILE = ARCHIVE_DIR / "index.json"
def extract_invoice_text(pdf_path: str) -> str:
"""PDFからテキスト抽出"""
reader = PdfReader(pdf_path)
return "\n".join(page.extract_text() or "" for page in reader.pages)
def parse_invoice_with_ai(text: str) -> dict:
"""AIで請求書の構造化データを抽出"""
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "user",
"content": (
f"以下の請求書テキストからJSONを返してください。"
f"キー: invoice_date(YYYY-MM-DD), total_amount(税込合計整数), "
f"vendor_name(取引先名), invoice_number(請求書番号), "
f"qualified_invoice_number(適格請求書発行事業者登録番号 T始まり13桁 or null)。\n\n{text}"
),
}
],
response_format={"type": "json_object"},
)
return json.loads(response.choices[0].message.content)
def validate_qualified_number(t_number: str) -> bool:
"""国税庁 公表サイトAPIで適格番号を確認 (試験的実装)"""
if not t_number or not re.match(r"^T\d{13}$", t_number):
return False
# 国税庁の事業者検索API(公式参照: https://www.invoice-kohyo.nta.go.jp/)
# ※本実装は確認フローのイメージです。実際はAPIキー不要の公開APIを利用できます
url = f"https://api.invoice-kohyo.nta.go.jp/pub/v1/announcement?number={t_number[1:]}"
try:
res = requests.get(url, timeout=10)
return res.status_code == 200
except requests.RequestException:
return False # 確認失敗時は人間確認フローへ
def archive_invoice(pdf_path: str, parsed: dict, is_valid: bool) -> dict:
"""電帳法に準拠してアーカイブ (取引年月日・金額・取引先で検索可能に)"""
file_hash = hashlib.sha256(Path(pdf_path).read_bytes()).hexdigest()[:16]
archive_filename = (
f"{parsed['invoice_date']}_{parsed['vendor_name']}_"
f"¥{parsed['total_amount']}_{file_hash}.pdf"
)
# 不正文字を除去してファイル保存
safe_name = re.sub(r'[\\/:*?"<>|]', "_", archive_filename)
import shutil
shutil.copy2(pdf_path, ARCHIVE_DIR / safe_name)
# インデックスに追記 (JSON形式 — 電帳法の検索要件対応)
index = json.loads(INDEX_FILE.read_text()) if INDEX_FILE.exists() else []
record = {
"file": safe_name,
"invoice_date": parsed["invoice_date"],
"total_amount": parsed["total_amount"],
"vendor_name": parsed["vendor_name"],
"invoice_number": parsed.get("invoice_number"),
"qualified_number": parsed.get("qualified_invoice_number"),
"is_valid_invoice": is_valid,
"archived_at": datetime.now().isoformat(),
}
index.append(record)
INDEX_FILE.write_text(json.dumps(index, ensure_ascii=False, indent=2))
return record
def process_invoice_pdf(pdf_path: str) -> dict:
"""請求書PDFを処理するメインフロー"""
text = extract_invoice_text(pdf_path)
parsed = parse_invoice_with_ai(text)
t_num = parsed.get("qualified_invoice_number")
is_valid = validate_qualified_number(t_num) if t_num else False
record = archive_invoice(pdf_path, parsed, is_valid)
if not is_valid:
return {
"status": "pending_review",
"reason": "適格番号未確認 — 手動チェック推奨",
"record": record,
}
return {"status": "archived", "record": record}
# 本番環境で実行する前に、必ずテスト環境で動作確認すること
if __name__ == "__main__":
print(process_invoice_pdf("sample_invoice.pdf"))
動作環境:Python 3.11+, openai>=1.0, pypdf>=4.0, requests 2.31+
経理AIエージェントの全体アーキテクチャ
3つの即効テクニックをつなげると、次のようなエージェントアーキテクチャになります。
| レイヤー | 役割 | 使用技術 | 自動化率 |
|---|---|---|---|
| 入力 | レシート/PDF受領 | スキャン・メール転送・Slackボット | 100%自動 |
| 抽出 | OCR・構造化 | GPT-4o Vision / PaddleOCR | 90〜95%(試算) |
| 判定 | 勘定科目・インボイス適格 | ルールエンジン + LLM分類 | 80〜90%(試算) |
| 承認 | human-in-the-loop | Slack通知 + 承認ボタン | 高額・例外のみ人間 |
| 登録 | 会計ソフトAPI連携 | freee API / マネーフォワードAPI | 100%自動 |
| 保存 | 電帳法対応アーカイブ | ファイルサーバー + JSON索引 | 100%自動 |
重要なのは「自動化率」の考え方です。全ての仕訳を100%自動登録しようとすると、金額ミスや勘定科目誤りが無審査で計上されるリスクがあります。実務では「明確なルールが適用できるもの(定額経費、定期交通費など)は全自動」「例外・高額・初回取引先は人間確認」という設計が現実的です。
freee APIとマネーフォワードAPI — 接続設計の比較
両APIとも OAuth2 Authorization Code フローを採用していますが、設計の細部が異なります。導入前に以下の差異を把握しておくことで、後からの設計変更を防げます。
| 項目 | freee 会計API | マネーフォワードクラウド経費API |
|---|---|---|
| ベースURL | https://api.freee.co.jp/api/1 |
https://expense.moneyforward.com/api/v1 |
| 認証方式 | OAuth2 / Bearer Token | OAuth2 / Bearer Token |
| 仕訳登録エンドポイント | POST /deals |
会計連携は会計Plus側のAPIを使用 |
| レシート/領収書 | POST /receipts(画像アップロード対応) |
POST /ex_items(明細単位) |
| 承認フロー | deals の status 管理 | ex_reports の submit/approve |
| インボイス適格判定 | 取引先マスタで管理 | インボイス対応済み(2023年10月〜) |
| Rate Limit | 公式ドキュメント参照(変更有) | 公式ドキュメント参照(変更有) |
| 2026年時点の大きな変更 | 振替伝票API旧版が2026/07廃止予定 | ルールマッチング機能が2026年実装予定 |
注意:Rate Limitや具体的なAPI仕様は変更されることがあります。実装前は必ず各社の公式開発者ドキュメントで最新版を確認してください。freee: developer.freee.co.jp / マネーフォワード: developers.biz.moneyforward.com
human-in-the-loop 承認フローの実装パターン
「全自動」と「全手動」の間を取り持つのが human-in-the-loop の設計です。経理AIエージェントで効果的な3つのパターンを紹介します。
パターン1: 閾値ベースの自動承認
最もシンプルで実務的な設計です。金額・勘定科目・取引先の3軸でルールを定義し、明確に分類できるものだけ自動承認します。
"""
閾値ベース human-in-the-loop 判定ロジック
動作環境: Python 3.11+
"""
from dataclasses import dataclass
from enum import Enum
class ReviewStatus(Enum):
AUTO_APPROVE = "auto_approve" # 自動承認
PENDING_HUMAN = "pending_human" # 人間確認必要
REJECT = "reject" # 自動却下(明らかな不正)
@dataclass
class ExpenseItem:
amount: int
category: str
vendor: str
is_first_transaction: bool
has_receipt: bool
def evaluate_expense(item: ExpenseItem) -> tuple[ReviewStatus, str]:
"""経費アイテムのレビュー必要性を判定"""
# 却下条件 (不備があるもの)
if not item.has_receipt and item.amount >= 5000:
return ReviewStatus.REJECT, "領収書なし — 5,000円以上は証憑必須"
# 人間確認条件
if item.amount >= 100_000:
return ReviewStatus.PENDING_HUMAN, f"¥{item.amount:,} — 10万円超のため上長承認必要"
if item.category in ("交際費", "接待費") and item.amount >= 30_000:
return ReviewStatus.PENDING_HUMAN, f"交際費¥{item.amount:,} — 3万円超は承認フロー"
if item.is_first_transaction:
return ReviewStatus.PENDING_HUMAN, f"初回取引先 {item.vendor} — マスタ登録確認必要"
# 上記以外は自動承認
return ReviewStatus.AUTO_APPROVE, "条件チェック通過 — 自動登録"
# 使用例
items = [
ExpenseItem(1320, "交通費", "Suica", False, True),
ExpenseItem(150_000, "備品", "大塚商会", False, True),
ExpenseItem(45_000, "交際費", "料亭A", False, True),
]
for item in items:
status, reason = evaluate_expense(item)
print(f" {status.value}: {reason}")
パターン2: Slackでの承認リクエスト
PENDING_HUMAN になった経費をSlackに通知し、経理責任者が「承認/却下」ボタンをワンクリックで処理できる設計です。承認ボタン押下後にfreee APIへの登録処理を走らせることで、freeeへの直接アクセス権を持つ担当者を限定できます。
"""
Slack 承認リクエスト送信
動作環境: Python 3.11+
必要パッケージ: pip install slack-sdk python-dotenv
注意: Bot Token に chat:write スコープが必要
"""
import os
import json
from slack_sdk import WebClient
from dotenv import load_dotenv
load_dotenv()
slack = WebClient(token=os.getenv("SLACK_BOT_TOKEN"))
def request_expense_approval(channel: str, expense: dict, reason: str) -> str:
"""Slackに承認リクエストを送信してメッセージtsを返す"""
blocks = [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": (
f"*経費承認リクエスト*\n"
f"申請者: {expense.get('submitter', '不明')}\n"
f"金額: *¥{expense['amount']:,}*\n"
f"取引先: {expense.get('vendor', '')}\n"
f"摘要: {expense.get('memo', '')}\n"
f"確認理由: _{reason}_"
),
},
},
{
"type": "actions",
"block_id": f"approve_{expense.get('id', 'unknown')}",
"elements": [
{
"type": "button",
"text": {"type": "plain_text", "text": "承認"},
"style": "primary",
"value": json.dumps({"action": "approve", "id": expense.get("id")}),
"action_id": "expense_approve",
},
{
"type": "button",
"text": {"type": "plain_text", "text": "却下"},
"style": "danger",
"value": json.dumps({"action": "reject", "id": expense.get("id")}),
"action_id": "expense_reject",
},
],
},
]
res = slack.chat_postMessage(channel=channel, blocks=blocks)
return res["ts"]
電子帳簿保存法・インボイス制度への対応方法
AIエージェントで経理自動化を進める際、法令対応を後回しにすると後から大幅な設計変更が必要になります。2026年6月時点で押さえておくべき2つの制度の要件をまとめます。
電子帳簿保存法(電帳法)の要件
2024年1月から電子取引の電子保存が義務化されました(国税庁 電子帳簿等保存制度特設サイト参照)。
| 保存要件 | 内容 | エージェントでの実装方法 |
|---|---|---|
| 真実性の確保 | 訂正・削除の履歴管理またはタイムスタンプ付与 | アーカイブ時にSHA-256ハッシュを記録、履歴ログを保持 |
| 可視性の確保 | ディスプレイ表示・印刷できる環境 | PDF形式でアーカイブすれば要件を満たす |
| 検索機能の確保 | 取引年月日・取引金額・取引先で検索可能 | 即効テクニック3のJSON索引ファイルで対応 |
インボイス制度(適格請求書等保存方式)
2023年10月から施行されたインボイス制度では、仕入税額控除に「適格請求書(T番号入り)」の保存が必要です(参照: 国税庁 適格請求書等保存方式(インボイス制度))。AIエージェントに組み込むべき処理は次のとおりです。
- 受領した請求書からT番号(Tで始まる13桁)をAI抽出する
- 国税庁インボイス公表サイトのAPIで適格事業者であることを確認する
- T番号がない・適格外の場合は人間確認フローに回す(仕入税額控除が受けられない可能性をアラート)
事例区分: 想定シナリオ
経理2名体制のメーカーで上記フローを導入した場合、月末の経費処理にかかる工数は月30時間→5〜8時間程度に削減できる見込みです(実際の削減効果は業種・規模・既存フローの整備状況により大きく異なります)。
よくある失敗パターンと回避策
失敗1: OAuthトークンの有効期限切れで本番が止まる
freeeもマネーフォワードもアクセストークンに有効期限があります。cronジョブで毎日深夜に自動処理させているケースで、翌朝出社したら昨日から全件エラーになっていた、というのはよく聞くトラブルです。
❌ よくある間違い: アクセストークンをベタ書き or 手動更新
⭕ 正しいアプローチ: リフレッシュトークンを使って自動更新する仕組みを最初から実装する
"""
freee OAuthトークン自動更新
動作環境: Python 3.11+
"""
import os
import time
import requests
import json
from pathlib import Path
from dotenv import load_dotenv
load_dotenv()
TOKEN_FILE = Path(".freee_tokens.json")
def load_tokens() -> dict:
if TOKEN_FILE.exists():
return json.loads(TOKEN_FILE.read_text())
return {}
def save_tokens(tokens: dict):
TOKEN_FILE.write_text(json.dumps(tokens))
TOKEN_FILE.chmod(0o600) # オーナーのみ読み書き可
def get_valid_access_token() -> str:
"""有効なアクセストークンを返す。期限切れなら自動更新"""
tokens = load_tokens()
expires_at = tokens.get("expires_at", 0)
# 残り5分以内になったら更新
if time.time() > expires_at - 300:
res = requests.post(
"https://accounts.secure.freee.co.jp/public_api/token",
data={
"grant_type": "refresh_token",
"client_id": os.getenv("FREEE_CLIENT_ID"),
"client_secret": os.getenv("FREEE_CLIENT_SECRET"),
"refresh_token": tokens["refresh_token"],
},
timeout=30,
)
res.raise_for_status()
new_tokens = res.json()
new_tokens["expires_at"] = time.time() + new_tokens["expires_in"]
save_tokens(new_tokens)
return new_tokens["access_token"]
return tokens["access_token"]
失敗2: 勘定科目IDのハードコーディング
❌ よくある間違い: `account_item_id = 1` のようにIDを定数として埋め込む
⭕ 正しいアプローチ: 起動時に `GET /api/1/account_items?company_id={YOUR_COMPANY_ID}` で最新マスタを取得してキャッシュする
理由: freeeの勘定科目IDは事業所ごとに異なり、かつ後から変更される可能性があります。ハードコードすると他社での利用時や設定変更後に無言でミスが発生します。
失敗3: 電帳法対応が後付けになって設計変更が大きくなる
❌ よくある間違い: まず処理速度優先でシステムを作り、後から電帳法対応を追加しようとする
⭕ 正しいアプローチ: アーカイブ処理を最初から設計に組み込む(即効テクニック3のパターンをベースに使う)
具体的には、すべての受領書類を処理する段階で SHA-256 ハッシュとタイムスタンプを記録し、JSON索引に取引年月日・取引金額・取引先の3項目を含めておきます。後から追加しようとすると過去データの遡及対応が必要になります。
失敗4: 全件自動登録してエラーに気づかない
❌ よくある間違い: human-in-the-loop を省いて全件自動登録し、会計データの精度を確認しない
⭕ 正しいアプローチ: 最初の1ヶ月は自動登録した全件をCSVに出力して経理担当者がサンプルチェックする運用を挟む
セキュリティと運用ルール
会計APIと金融データを扱う以上、セキュリティ設計は慎重に行う必要があります。
| リスク | 対策 |
|---|---|
| APIトークン漏洩 | .env ファイルを .gitignore に追加。本番は環境変数またはシークレットマネージャー(AWS Secrets Manager 等)で管理 |
| 不正仕訳の自動登録 | 金額閾値・勘定科目・取引先の3軸でhuman-in-the-loop判定を実装 |
| アーカイブの改ざん | ファイルのSHA-256ハッシュを別ストレージに保存。本番ではクラウドストレージのオブジェクトロックを検討 |
| API障害時の業務停止 | 処理失敗したアイテムをキューに積み、リトライできる構造にする(指数バックオフ推奨) |
| 旧APIバージョンの廃止 | freee振替伝票API旧版は2026年7月廃止予定。定期的にリリースノートを確認する |
参考・出典
- freee APIへGET/POSTリクエストを送信する — freee Developers Community(参照日: 2026-06-12)
- マネーフォワード クラウドのAPI共通仕様 — マネーフォワード開発者サイト(参照日: 2026-06-12)
- 電子帳簿等保存制度特設サイト — 国税庁(参照日: 2026-06-12)
- 適格請求書等保存方式(インボイス制度)— 国税庁(参照日: 2026-06-12)
- 2026年4月の更新情報 — freee Developers Community(参照日: 2026-06-12)
まとめ:今日から始める3つのアクション
- 今日やること:Step 1のレシートOCRコード(即効テクニック1)をローカルで動かす。OpenAI APIキーとfreee APIのアクセストークンを発行して、手持ちのレシート1枚で動作確認する。
- 今週中:human-in-the-loop の閾値ルール(金額・勘定科目・初回取引先)を自社の経理ルールに合わせて設定し、Slack承認通知の受信先チャンネルを決める。
- 今月中:電帳法対応アーカイブ(取引年月日・金額・取引先のJSON索引)を本番データで運用開始し、1ヶ月後に経理担当者とサンプルチェックして精度を測定する。
あわせて読みたい:
- 人事・採用担当のためのAIエージェント活用ガイド2026 — 採用スクリーニングから勤怠管理までの実装パターン
- n8n × MCP × AIエージェント実装完全ガイド2026 — ノーコードでワークフロー自動化を構築する方法
- AIエージェントのワークフロー設計パターン5選|LangGraph実装 — エージェントアーキテクチャの全体設計
著者: 佐藤傑(さとう・すぐる)
株式会社Uravation代表取締役。X(@SuguruKun_ai)フォロワー10万人以上。100社以上の企業向けAI研修・導入支援。著書『AIエージェント仕事術』。
この記事を読んで導入イメージが固まってきた方へ
UravationではAIエージェント導入の研修・コンサルを行っています。経理業務の自動化設計からAPI連携の実装支援まで、お気軽にご相談ください。
