フリーランスエンジニアの請求書管理を Claude Code + freee で半自動化する
受注から請求書送付・入金確認まで、フリーランスの請求フローをClaude CodeとfreeeAPIで実装する実践ガイド。工数記録→見積生成→freee API 請求書ドラフト→メール下書きまでのワークフローを、実際のコード例を交えて解説。
エンジニアのゆとです。
フリーランスになって最初に気づくのは「コードを書く仕事」より「コードを書く以外の仕事」が多いという事実だ。
請求書を作る。クライアントにメールを送る。入金を確認する。領収書を整理する。源泉徴収の計算をする。確定申告の数字を揃える。
どれも本業じゃないのに、やらないと詰む。エンジニアとしてのスキルとはまったく関係ないところで時間を取られる。
僕が受託メインで動いていた時期、月末の3〜4日はほぼ事務作業に費やしていた。案件が5本並行していた月は「これ、何をやってる人間なんだろう」という気分になった。
この記事では、Claude Code と freee API を組み合わせて請求フローを半自動化した方法を書く。「AIに全部やらせる」という話ではなく、「判断はエンジニアがする、作業はシステムに任せる」という設計の話だ。
フリーランスの請求フローを分解する
まず、請求業務の全体像を整理しておく。自動化対象を決めるには、まず「何をやっているのか」を正確に把握する必要がある。
典型的な受託案件の請求フローは以下のようになる。
受注確定
↓
工数記録(日次)
↓
月末集計(請求金額の算出)
↓
請求書作成(PDF生成 or freee上で作成)
↓
請求書送付メール
↓
入金確認(銀行口座確認 or freeeの入金消込)
↓
翌月の帳簿整理
このフローで「判断」が必要なのは基本的に最初の受注確定と、イレギュラーな場合の対処だけだ。それ以外の「月末集計」「請求書作成」「送付メール」「入金確認」は、ほぼ定型作業になる。
定型作業は自動化できる。あるいは少なくとも、作業時間を大幅に削れる。
工数記録の設計から始める
自動化の出発点は「工数記録のデータが機械可読な状態になっている」こと。
Notionのデータベースでも、GitHubのIssueでも、CSVファイルでもいい。とにかく「誰に、何をして、何時間かかったか」が構造化データとして取れる状態が前提になる。
僕が使っているのはシンプルなJSONログだ。
{
"entries": [
{
"date": "2026-04-01",
"client_id": "client_abc",
"task": "Webhook受信エンドポイント実装",
"hours": 3.5,
"unit_price": 8000
},
{
"date": "2026-04-01",
"client_id": "client_abc",
"task": "既存コードベースのリファクタリング",
"hours": 2.0,
"unit_price": 8000
}
]
}
これを毎日ターミナルから timetrack.py add みたいな形で追記するだけ。手動入力なので3秒あれば終わる。
Claude Code との接続ポイントはここだ。月末にこのJSONを読ませて、請求書のドラフトを生成させる。
Claude Code で工数から見積書・請求書を生成する
工数データが溜まった状態で、Claude Code に以下のようなプロンプトを渡すと、請求書の下書きが秒で出てくる。
claude
work_log_2026-04.json を読んで、client_abc 向けの請求書ドラフトを作成してほしい。
以下の形式で出力:
- 件名(例:「2026年4月分 業務委託費のご請求」)
- 明細行(日付、作業内容、時間、単価、小計)
- 合計金額
- 消費税(10%)
- 請求合計
- 支払期限(発行日から30日)
- 振込先情報(銀行名、支店名、口座番号)は [BANK_INFO] として後で差し込む
出力は Markdown でそのまま来るので、あとはfreee APIに渡すデータに変換するだけだ。
ここで重要なのは、Claude Code に「判断」をさせていないということ。「この金額が正しいか」「クライアントへの注釈が必要かどうか」はエンジニア側が目視で確認する。CCはあくまで「集計と整形」の担当だ。
freee API で請求書ドラフトを自動作成する
freeeには公式APIがあって、請求書(invoices)の作成・更新・取得が全部APIでできる。
まず必要なのは認証。freee APIはOAuth 2.0を使っている。個人事業主であれば、freeeのデベロッパーコンソールでアプリを作成してアクセストークンを取得する。
# freee developer console でアプリ作成後
# https://developer.freee.co.jp/
実際の請求書作成は以下のスクリプトで動く。
#!/usr/bin/env python3
"""
create_invoice_draft.py
工数JSONを読んでfreee APIで請求書ドラフトを作成する
"""
import json
import os
import requests
from datetime import date, timedelta
from pathlib import Path
FREEE_API_BASE = "https://api.freee.co.jp"
ACCESS_TOKEN = os.environ["FREEE_ACCESS_TOKEN"]
COMPANY_ID = int(os.environ["FREEE_COMPANY_ID"])
def load_work_log(path: str, client_id: str) -> list[dict]:
"""工数ログから特定クライアントのエントリを抽出"""
data = json.loads(Path(path).read_text())
return [e for e in data["entries"] if e["client_id"] == client_id]
def build_invoice_payload(entries: list[dict], partner_id: int) -> dict:
"""freee API用のinvoiceペイロードを構築"""
today = date.today()
due_date = today + timedelta(days=30)
invoice_contents = []
for entry in entries:
subtotal = int(entry["hours"] * entry["unit_price"])
invoice_contents.append({
"order": len(invoice_contents) + 1,
"type": "normal",
"description": f"{entry['date']} {entry['task']}",
"qty": entry["hours"],
"unit": "時間",
"unit_price": entry["unit_price"],
"tax_code": 1, # 10%
"amount": subtotal,
})
return {
"company_id": COMPANY_ID,
"issue_date": today.isoformat(),
"due_date": due_date.isoformat(),
"partner_id": partner_id,
"invoice_status": "draft", # ドラフトで作成、送信は手動
"message": "いつもお世話になっております。\n下記の通りご請求申し上げます。",
"invoice_contents": invoice_contents,
}
def create_invoice(payload: dict) -> dict:
"""freee APIでinvoiceを作成する"""
resp = requests.post(
f"{FREEE_API_BASE}/api/1/invoices",
headers={
"Authorization": f"Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json",
},
json={"invoice": payload},
)
resp.raise_for_status()
return resp.json()
if __name__ == "__main__":
import sys
work_log_path = sys.argv[1] # 例: work_log_2026-04.json
client_id = sys.argv[2] # 例: client_abc
partner_id = int(sys.argv[3]) # freee上のパートナーID
entries = load_work_log(work_log_path, client_id)
if not entries:
print(f"No entries found for {client_id}")
sys.exit(1)
payload = build_invoice_payload(entries, partner_id)
result = create_invoice(payload)
invoice = result["invoice"]
print(f"Draft created: Invoice #{invoice['invoice_number']}")
print(f"Total: ¥{invoice['total_amount']:,}")
print(f"Due: {invoice['due_date']}")
print(f"freee URL: https://secure.freee.co.jp/invoices/{invoice['id']}")
実行するとfreee上にドラフト状態の請求書が作成される。
export FREEE_ACCESS_TOKEN="your_token"
export FREEE_COMPANY_ID="12345"
python create_invoice_draft.py work_log_2026-04.json client_abc 67890
# Draft created: Invoice #INV-2026-042
# Total: ¥44,000
# Due: 2026-05-31
# freee URL: https://secure.freee.co.jp/invoices/...
ドラフト状態なので、人間が確認してから「送信」を押す。全自動送信にしないのは意図的だ。請求書の金額ミスは信頼に直結する。確認ステップは省かない。
Claude Code でメール下書きを生成する
請求書のドラフトが出来たら、次は送付メールの下書きだ。これもCCにやらせる。
claude
freeeで作成したINV-2026-042の内容をもとに、
client_abcへの請求書送付メールの下書きを作ってほしい。
クライアント情報:
- 会社名: 株式会社サンプル
- 担当者: 田中様
- 支払サイト: 月末締め翌月末払い
トーン: 丁寧だが簡潔。長い前置きは不要。
件名・本文のセットで出して。
出てきた下書きを微調整して送るだけ。メールの文章を毎回ゼロから書く必要がなくなる。
LaunchAgent で月次自動実行する
毎月末に手動でスクリプトを叩くのが面倒なら、macOSのLaunchAgentで自動化できる。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.yutolab.invoice-draft</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/python3</string>
<string>/Users/yuto/scripts/monthly_invoice.py</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Day</key>
<integer>28</integer>
<key>Hour</key>
<integer>9</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<key>EnvironmentVariables</key>
<dict>
<key>FREEE_ACCESS_TOKEN</key>
<string>your_token</string>
<key>FREEE_COMPANY_ID</key>
<string>12345</string>
</dict>
<key>StandardOutPath</key>
<string>/tmp/invoice_draft.out</string>
<key>StandardErrorPath</key>
<string>/tmp/invoice_draft.err</string>
</dict>
</plist>
毎月28日の朝9時に全クライアント分のドラフトが自動で作られる。29日に確認して送信、という運用になる。
# LaunchAgentの登録
cp com.yutolab.invoice-draft.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.yutolab.invoice-draft.plist
# 手動テスト実行
launchctl start com.yutolab.invoice-draft
GitHub Actions で動かすことも技術的には可能だが、freeeのアクセストークンをGitHubのSecretに入れる構成は個人的には避けている。ローカルLaunchAgentのほうがシンプルで制御しやすい。
freee API の実務的なベストプラクティス
実際に動かして気づいたことをまとめておく。
アクセストークンの有効期限はデフォルトで24時間。リフレッシュトークンを使った自動更新の仕組みが必要になる。以下はシンプルなリフレッシュ実装だ。
import requests
def refresh_token(refresh_token: str, client_id: str, client_secret: str) -> dict:
resp = requests.post(
"https://accounts.secure.freee.co.jp/public_api/token",
data={
"grant_type": "refresh_token",
"refresh_token": refresh_token,
"client_id": client_id,
"client_secret": client_secret,
},
)
resp.raise_for_status()
return resp.json() # access_token, refresh_token, expires_in を含む
新しいアクセストークンとリフレッシュトークンをどこかに保存しておく必要がある。ファイルに書くだけでもいいが、1Password CLIと組み合わせてVaultに保存するのがセキュアだ。
パートナーID(クライアントID)の取得は最初だけ手動でやる必要がある。freeeの管理画面でクライアントを登録すると、APIでパートナー一覧が取れる。
def get_partners(company_id: int, access_token: str) -> list[dict]:
resp = requests.get(
f"https://api.freee.co.jp/api/1/partners",
headers={"Authorization": f"Bearer {access_token}"},
params={"company_id": company_id},
)
resp.raise_for_status()
return resp.json()["partners"]
これを一度実行してクライアントIDを手元のJSONに保存しておくと、以降のスクリプトで使い回せる。
マネーフォワードとの違い:API使いやすさの観点
freeeを選んだ理由の一つがAPIのドキュメントの質だ。
マネーフォワードクラウド請求書にもAPIはある。ただ、APIのカバレッジと日本語ドキュメントの整備状況はfreeeのほうが一歩進んでいる印象だった。freeeのAPIリファレンスはSwagger UIで動かせて、ブラウザ上でリクエストのテストができる。
どちらが絶対的に優れているわけではないが、「エンジニアが自前で自動化ロジックを組む」という用途ではfreeeが扱いやすかった。
料金・自動仕訳の精度・UIの使いやすさという観点での比較は、別記事で詳しく書いている。
記事が見つかりません:
開業届〜年次決算で Claude Code が役立つ場面
請求書以外の経理フローでも、CCは局所的に使える。
開業届を出す前後は、「どの書類を、どの順番で揃えるか」の整理にCCが便利だ。国税庁のサイトや freeeのヘルプを読みながら「個人事業主の開業届に必要な書類一式をチェックリスト形式でまとめて」と聞くと、抜け漏れなく整理してくれる。
確定申告前は、工数ログと経費記録をまとめてCCに渡して「この年の経費で計上し忘れていそうなものはないか、洗い出して」と聞くのが有効だ。「Wi-Fiルーターは按分できるはずでは」「このSaaS代は全額経費になるか確認した?」みたいな指摘が出てくる。あくまで「確認の補助」として使うのが正しい使い方で、税務判断はちゃんと税理士か税務署に確認する。
減価償却の計算や、インボイス制度の登録番号の確認など、調べればわかることをCCに聞いて確認するのも時間節約になる。
ハマりどころ
実際に動かして詰まった点を正直に書いておく。
freee APIのサンドボックス環境は本番とは別のアカウントが必要で、最初のセットアップに時間がかかる。テスト環境での動作確認をスキップして本番でいきなり動かすと、ドラフトの消去ミスなどで困ることがある。面倒でもサンドボックスで試す。
工数記録が日付をまたぐプロジェクト(月初に始まって月をまたぐ案件)の扱いは注意が必要だ。月末締めの場合、4月分として請求するエントリをどう定義するか、ルールを最初に決めておかないと集計がずれる。
freeeのAPIレートリミットは1分あたり数十リクエスト程度(公式には明記されていない)。大量のパートナー・請求書を一度に処理しようとするとエラーが出ることがある。time.sleep(1) を入れてリクエスト間隔を空けるのが無難だ。
アクセストークンの保管場所は慎重に選ぶ。スクリプト内にベタ書きは論外として、環境変数でもプロセス情報から見える。個人のMacでのみ動かすなら macOS Keychain を使う方法がある。
APIキーを含むシークレット全般の管理を強化したいなら、1Password CLIとClaude Codeを組み合わせた構成も有効だ。詳細は 1Password CLI × Claude Code で .env を Vault化する完全ガイド を参照してほしい。
import subprocess
def get_freee_token() -> str:
"""macOS Keychainからトークンを取得"""
result = subprocess.run(
["security", "find-generic-password", "-s", "freee-api-token", "-w"],
capture_output=True, text=True
)
return result.stdout.strip()
freee会計を使っていない場合
freeeを使っていない人が「このためだけにfreeeを契約するか」というと、それは状況による。
freeeのスタンダードプランが年額26,136円(2026年4月時点)。請求書管理だけなら freee請求書(旧Misocaがfreeeブランドになったもの)の無料プランでも月5件まで作成できる。会計ソフトとして使うなら通常のfreee会計プランが対象だ。
月に10件以上請求書を出すフリーランス、または確定申告もfreeeでやりたいなら年額投資として妥当だと思う。APIを組む手間を考えると「そもそもfreeeをちゃんと使えばいいのでは」という話でもあるので、自分の工数ボリュームに応じて判断してほしい。
まとめ:半自動化の設計思想
この記事で紹介した構成をまとめると、こうなる。
- 工数記録: 手動(JSON、3秒/エントリ)
- 月末集計・請求書ドラフト生成: Claude Code + Python
- freeeへのドラフト作成: freee API
- 送付メール下書き: Claude Code
- 請求書の「送信」ボタン: 人間が押す
- 入金確認: freeeの自動消込 or 手動確認
完全自動化にしていないのは意図的だ。請求書の送信は信頼に直結する行為なので、人間の目を通す確認ステップを外さない。それ以外の「誰がやっても同じ結果になる定型作業」だけをシステムに任せる。
Claude Codeは「なんでもやってくれる便利ツール」として使うより、「特定の定型作業を定義して委譲する」という使い方のほうが長く安定して機能する。請求書の自動化はその典型的なユースケースだ。
フリーランスエンジニア × CC の活用全般については、以下の記事でまとめている。
記事が見つかりません:
関連記事




本記事はプロモーションを含みます。記事内リンクからの申し込みで筆者に紹介報酬が発生します。内容は独自調査・実装に基づいており、報酬によって評価が変わることはありません。 #PR