Contents
1. freee API と BigQuery をつなげる全体像
freee が提供する取引データ(Deals)を BigQuery に取り込めば、会計情報とマーケティング指標を同一の分析基盤で扱えるようになります。本セクションでは、認証・取得・格納 の 4 つのフェーズに分けた全体フローと、各フェーズで注意すべきポイントを解説します。
1‑1. 全体フローと主要コンポーネント
以下の手順でデータ連携が完了します。
- OAuth2 による安全な認証 – アクセストークンはリフレッシュトークンで自動更新でき、期限切れを防止します。
- API から取引データ取得(ページネーション) –
limitとoffset、またはcursorを利用して全件取得します。 - BigQuery 用テーブル設計 – 日付でパーティション化したテーブルを事前に作成し、スキーマは Avro/JSON から自動生成できます。
- データロード – GCS 経由のバッチロードか、ストリーミングインサートか用途に合わせて選択します。
1‑2. OAuth2 認証のポイント
- 認可エンドポイント:
https://accounts.secure.freee.co.jp/public_api/authorize - トークンエンドポイント:
https://accounts.secure.freee.co.jp/public_api/token - リフレッシュトークンを永続化(Secret Manager 推奨)し、コンテナ起動時に取得すればコード中に資格情報が残りません。
1‑3. データ取得とページネーションのベストプラクティス
- limit / offset パターンはシンプルですが、レートリミットや大量データでのオフセット計算誤差に注意が必要です。
- cursor パターンは
next_cursorが返るエンドポイントで推奨され、取得漏れを防ぎます。取得したカーソルは Firestore など永続ストレージに保存し、次回リクエスト時に再利用します。
1‑4. BigQuery 側のテーブル設計
- パーティションキーは
issue_date(文字列または DATE)を使用し、日次パーティションテーブル (deals_YYYYMMDD) を作成するとクエリコストが大幅に削減できます。 - スキーマ例(Avro)
|
1 2 3 4 5 6 7 8 9 10 11 |
{ "type": "record", "name": "Deal", "fields": [ {"name":"id","type":"long"}, {"name":"issue_date","type":"string"}, {"name":"amount","type":"double"}, {"name":"updated_at","type":"string"} ] } |
- ロード方式はデータ量とリアルタイム性の要件で選択。日次バッチはコストが低く、リアルタイムダッシュボードにはストリーミングが適しています。
2. ノーコードツールで手軽に実装する方法
プログラミング経験がなくても、CData Sync と Syncflow を使えば UI 操作だけで freee データを BigQuery に同期できます。本セクションでは両ツールの設定フローと増分ロードのポイントを具体的に示します。
2‑1. CData Sync のセットアップ手順
- データソース登録 – 管理コンソールで「REST API」を選び、freee のクライアント ID/シークレット、認可・トークンエンドポイントを入力します。
- Secret Manager 連携 – 認証情報は GCP Secret Manager に格納し、CData 側で参照させることでコードベースに資格情報が残りません(公式ドキュメント参照)。
- 接続先(BigQuery)設定 – プロジェクト ID とデータセット名を入力し、サービスアカウントキーを Secret Manager 経由で指定します。
2‑2. Syncflow の設定ポイント
- ジョブ作成時に「増分ロード条件」を
updated_at > {{last_sync_time}}と設定すると、前回取得以降のレコードだけが対象になります。 - UI 上で カーソル管理 を有効化すれば、ページング情報が自動的に保持されます。
2‑3. 増分ロードの具体例
| 項目 | 設定値 |
|---|---|
| エンドポイント | /deals |
| テーブルマッピング | project.dataset.deals(自動生成) |
| 増分条件 | updated_at > {{last_sync_time}} |
| スケジュール | 毎日 02:00 実行 |
この構成であれば、非エンジニアでも 1 日に 1 回 の増分同期を数クリックで完了できます。
3. カスタム実装:Cloud Run + Cloud Scheduler
柔軟な制御が必要な場合は、Python スクリプトをコンテナ化し Cloud Run 上で実行、Cloud Scheduler が定期的に呼び出すパターンが有効です。ここでは主要コードとデプロイ手順を詳述します。
3‑1. Python スクリプトの構成要素
スクリプトは次の 4 機能に分かれます。
| 関数 | 役割 |
|---|---|
get_access_token() |
リフレッシュトークンからアクセストークンを取得(自動更新) |
fetch_all_deals() |
ページネーションまたはカーソルで全件取得しイテレータとして返す |
write_avro() |
取得した JSON を Avro ファイルに変換 |
load_to_bigquery() |
GCS にアップロードした Avro を BigQuery のパーティションテーブルへロード |
コードは 例外処理 と 指数バックオフリトライ(urllib3.util.retry.Retry)を組み込み、レートリミット 429 発生時にも安全に再試行します。
3‑2. コンテナ化とデプロイ手順
- Dockerfile(抜粋)
|
1 2 3 4 5 6 7 8 9 |
FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY *.py ./ ENV PYTHONUNBUFFERED=1 CMD ["python", "-m", "main"] |
- Secret Manager にシークレットを格納
-
FREEE_CLIENT_ID、FREEE_CLIENT_SECRET、FREEE_REFRESH_TOKEN、GCS_BUCKETを作成。 -
サービスアカウントに最小権限付与
| ロール | 必要なリソース |
|---|---|
roles/run.invoker |
Cloud Run 自身 |
roles/storage.objectCreator |
対象 GCS バケット |
roles/bigquery.dataEditor |
指定データセット |
roles/secretmanager.secretAccessor |
上記シークレット |
- デプロイコマンド
|
1 2 3 4 5 6 7 8 |
gcloud run deploy freee-sync \ --image gcr.io/$PROJECT_ID/freee-sync:latest \ --region asia-northeast1 \ --platform managed \ --service-account freee-sync-sa@$PROJECT_ID.iam.gserviceaccount.com \ --set-secrets FREEE_CLIENT_ID=freee-client-id:latest,FREEE_CLIENT_SECRET=freee-client-secret:latest,\ FREEE_REFRESH_TOKEN=freee-refresh-token:latest,GCS_BUCKET=gcs-bucket:latest |
3‑3. Cloud Scheduler で定期実行
|
1 2 3 4 5 6 |
gcloud scheduler jobs create http freee-sync-job \ --schedule "0 */6 * * *" \ # 6時間ごとに実行 --http-method POST \ --uri https://freee-sync-xxxxxx-uc.a.run.app/ \ --oidc-service-account-email freee-sync-sa@$PROJECT_ID.iam.gserviceaccount.com |
この構成なら 増分取得(updated_at)だけを処理でき、1 時間ごとに実行してもレートリミット超過の心配は少なくなります。
4. 増分取得設計とセキュリティベストプラクティス
大量データを毎回全件取得するとコストが膨らむため、差分抽出と厳格な権限管理が不可欠です。本節では実装パターンと GCP の推奨設定をまとめます。
4‑1. updated_at と cursor の使い分け
updated_at: 時間スタンプでフィルタリングできるエンドポイントは、ジョブ開始時に前回取得した最大日時を保持し、updated_since=...パラメータで差分だけ取得します。シンプルかつ信頼性が高いです。cursor: ページング用のトークンが返るエンドポイントではnext_cursorを永続化(例:Firestore)し、次回リクエストに渡すことで「漏れなし」の取得が可能です。
4‑2. IAM ロールと最小権限の実装例
| 目的 | 推奨ロール | 補足 |
|---|---|---|
| Cloud Run 実行 | roles/run.invoker |
必要なサービスだけに付与 |
| GCS バケット書き込み | roles/storage.objectCreator |
バケット単位で限定 |
| BigQuery データ書き込み | roles/bigquery.dataEditor |
データセットレベルで制限 |
| Secret Manager 参照 | roles/secretmanager.secretAccessor |
シークレットごとに個別付与 |
4‑3. 秘密情報管理と暗号化
- Secret Manager に API キー・クライアントシークレットを保存し、ランタイムで取得。環境変数への平文格納は避けます。
- TLS (HTTPS): freee のエンドポイント、Cloud Run ↔ GCS、GCS ↔ BigQuery すべて TLS が自動適用されます。
- 静止データ暗号化: GCS バケットに顧客管理キー(CMEK)を設定し、Avro ファイルが保存時にも暗号化されるようにします。
5. 運用・モニタリング・コスト最適化
システム稼働後は 可観測性 と 費用感覚 が重要です。以下の手法で安定運用とコスト抑制を実現します。
5‑1. ログ・エラーレポートの活用方法
-
Cloud Run の標準出力・標準エラーは自動的に Cloud Logging に転送されます。
loggingライブラリで以下を記録すると可視化しやすくなります。 -
INFO: API 呼び出し成功件数、取得レコード数 -
WARNING/ERROR: HTTP 429(レートリミット)や 5xx エラーのスタックトレース -
Error Reporting を有効化すると同一エラーパターンが集約され、Slack 等への通知設定が簡単に行えます。
5‑2. 再実行戦略とデッドレターキュー
- 即時リトライ:
requestsのRetryオブジェクトで指数バックオフ(最大 5 回)を設定。 - デッドレタートピック: Cloud Scheduler が失敗したジョブは Pub/Sub デッドレターキューへ送信し、別プロセスで手動再処理できます。
5‑3. コスト試算とパフォーマンス比較
| 項目 | バッチロード(GCS → BigQuery) | ストリーミングインサート |
|---|---|---|
| 単価 | $5 / TB(データロード) | $0.05 / GB(ストリーム) |
| レイテンシ | 10‑30 分(ファイル生成+ロード) | 秒単位 |
| 推奨用途 | 月次決算、過去データ再処理 | リアルタイムダッシュボード |
実務例: 取引データは日次で十分なケースが多く、バッチロードを採用すればコストを最大 80% 削減できます。パーティションキーに issue_date を使用するとクエリ時のスキャン量も削減可能です。
5‑4. よくある落とし穴と回避策
| 落とし穴 | 原因 | 回避策 |
|---|---|---|
| ページネーション漏れ | offset の計算ミス、next_cursor を無視 |
while True ループでレスポンスの has_more / next_cursor があるか必ず確認 |
| レートリミット超過(429) | 高頻度ジョブや同時インスタンス多数 | Scheduler の実行間隔を最低 5 分に設定し、バックオフロジックを実装 |
| スキーマ不整合 | JSON フィールドが可変、NULL が多い | Avro スキーマで union(nullable)を使用し、BigQuery の ALLOW_FIELD_ADDITION オプションを有効化 |
6. まとめ
- 全体フローは「OAuth2 認証 → データ取得(ページネーション) → BigQuery テーブル設計 → ロード」の4ステップで完結します。
- ノーコードツール(CData Sync / Syncflow)は UI 操作だけで増分ロードや Secret Manager 連携が実現でき、非エンジニアでも即日導入可能です。
- カスタム実装は Cloud Run + Cloud Scheduler の組み合わせで柔軟性を確保し、Python スクリプトによりページネーション・Avro変換・自動リトライが行えます。
- 増分取得は
updated_atとcursorを使い分け、取得したカーソルは永続化して再利用します。 - セキュリティは最小権限のサービスアカウントと Secret Manager に集約し、通信・保存時は TLS と CMEK で暗号化します。
- 運用面では Cloud Logging/Error Reporting を活用した可観測性確保と、リトライ/デッドレターキューによる堅牢な再実行設計が必須です。バッチロードを基本にコスト最適化しつつ、必要に応じてストリーミングでリアルタイム性を補完すれば、freee の会計データを安全かつ自動的に BigQuery に取り込み、迅速な意思決定が可能になるでしょう。