Contents
HubSpot カスタムレポート API(Reports API v2)概観
最終更新日:2026‑04‑14 ※本稿の内容はすべて公式ドキュメント (https://developers.hubspot.com/docs/api/reports) を基にしています。
1. エンドポイントとバージョン情報(公式通り)
| 操作 | HTTP メソッド | 正式エンドポイント* | 主な必須パラメータ |
|---|---|---|---|
| レポート作成 | POST | /reports/v2/reports |
name, filters, columns(JSON ボディ) |
| 単一レポート取得 | GET | /reports/v2/reports/{reportId} |
パスパラメータ reportId |
| レポート一覧取得 | GET | /reports/v2/reports |
limit, offset(クエリ) |
| レポート更新 | PATCH | /reports/v2/reports/{reportId} |
reportId + 更新フィールド(JSON ボディ) |
| レポート削除 | DELETE | /reports/v2/reports/{reportId} |
パスパラメータ reportId |
* ベース URL は https://api.hubapi.com。エンドポイントは 2025 年 12 月時点で公式に固定されていますが、将来的なバージョン変更がある場合は必ず Developers Docs → Reports API を確認してください。
典型的なレスポンス(取得系)
|
1 2 3 4 5 6 7 8 9 |
{ "id": 123456, "name": "Quarterly MQL Funnel", "createdAt": "2024-03-12T08:15:30Z", "updatedAt": "2025-01-07T14:02:11Z", "filters": [...], "columns": [...] } |
2. カスタムレポートが提供する主な価値
| ユースケース | 期待できる効果 |
|---|---|
| MQL → SQL コンバージョン率の可視化 | 広告ソース別・キャンペーン別にリアルタイムで集計し、投資対効果を即座に把握。 |
| 顧客ライフサイクル分析 | 取引ステージとメールエンゲージメントを横断的に結合し、ファネルのボトルネックを特定。 |
| 外部 BI ツールへの自動供給 | Power BI・Tableau・Looker Studio に API 経由でデータを流すことで、レポート更新頻度と正確性が劇的に向上。 |
公式ガイド: Reports → Custom Reports (https://knowledge.hubspot.com/reports/create-custom-reports)
3. 認証方式の比較 – Private App Token vs OAuth 2.0
3.1 Private App Token(推奨シナリオ)
| 項目 | 内容 |
|---|---|
| 取得手順 | HubSpot UI → Settings → Integrations → Private Apps → 「Create private app」→ 必要スコープを選択 → 作成後に表示される Access token をコピー。 |
| 有効期限 | 現在は 無期限(トークン自体が失効しない)。ただし、セキュリティ上のベストプラクティスとして 6‑12 ヶ月ごとにローテーションを推奨。 |
| 利用方法 | Authorization: Bearer {ACCESS_TOKEN} を HTTP ヘッダーに付与。 |
| 適用対象 | 社内バッチ処理、ETL パイプライン、サーバー間通信など「手軽さ」が重視されるケース。 |
公式ドキュメント: https://developers.hubspot.com/docs/api/private-apps
3.2 OAuth 2.0(Authorization Code)
| 項目 | 内容 |
|---|---|
| 取得フロー | 開発者ポータルで OAuth app を作成 → client_id/client_secret 発行 → ユーザー同意画面経由で認可コード取得 → アクセストークンとリフレッシュトークンを交換。 |
| 有効期限 | アクセストークンは 6 時間(デフォルト)まで、リフレッシュトークンで再取得可能。 |
| メリット | ユーザー単位のスコープ制御、PKCE など最新のセキュリティ機構が利用できる。 |
| 適用対象 | 外部 SaaS パートナーや顧客に代わって API を呼び出すケース。 |
公式ガイド: https://developers.hubspot.com/docs/api/oauth
4. 実装ハンズオン(cURL / Node.js / Python)
以下は レポート一覧取得 の最小サンプルです。YOUR_PRIVATE_TOKEN は実際のトークンに置き換えてください。
4.1 cURL
|
1 2 3 4 |
curl -G "https://api.hubapi.com/reports/v2/reports" \ -d limit=20 -d offset=0 \ -H "Authorization: Bearer YOUR_PRIVATE_TOKEN" |
4.2 Node.js (axios)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import axios from 'axios'; const token = 'YOUR_PRIVATE_TOKEN'; const url = 'https://api.hubapi.com/reports/v2/reports'; (async () => { try { const { data } = await axios.get(url, { params: { limit: 20, offset: 0 }, headers: { Authorization: `Bearer ${token}` } }); console.log(data); } catch (e) { console.error(e.response?.data || e.message); } })(); |
4.3 Python (requests)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import requests TOKEN = 'YOUR_PRIVATE_TOKEN' BASE = 'https://api.hubapi.com/reports/v2/reports' resp = requests.get( BASE, params={'limit': 20, 'offset': 0}, headers={'Authorization': f'Bearer {TOKEN}'} ) resp.raise_for_status() print(resp.json()) |
5. ページング・フィルタリング・日付範囲のベストプラクティス
- ページング
limitの上限は 100。-
次ページはレスポンス内の
paging.next.after(またはoffset)で取得できるため、ループ処理で全件をシームレスに集められる。 -
フィルタリング
filtersは JSON 文字列として渡す。例: 作成日が 2024 年のレポートだけ取得したい場合
|
1 2 3 4 5 6 |
{ "property": "createdate", "operator": "BETWEEN", "values": ["2024-01-01T00:00:00Z","2024-12-31T23:59:59Z"] } |
- 日付フォーマット
- HubSpot は ISO 8601(UTC) を必須とする。タイムゾーンが混在しないように
Zで終端させる。
Python 例:フィルタ+ページング
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
import requests, time TOKEN = 'YOUR_PRIVATE_TOKEN' BASE = 'https://api.hubapi.com/reports/v2/reports' def fetch_all(start_iso: str, end_iso: str): offset = 0 all_reports = [] filter_json = ( f'{{"property":"createdate","operator":"BETWEEN",' f'"values":["{start_iso}","{end_iso}"]}}' ) while True: params = { 'limit': 100, 'offset': offset, 'filters': filter_json } r = requests.get( BASE, params=params, headers={'Authorization': f'Bearer {TOKEN}'} ) r.raise_for_status() data = r.json() all_reports.extend(data.get('results', [])) paging = data.get('paging') if not paging or not paging.get('next'): break offset = paging['next']['after'] time.sleep(0.1) # 10 req/秒 超過防止 return all_reports reports = fetch_all( '2024-01-01T00:00:00Z', '2024-12-31T23:59:59Z' ) print(f'取得件数: {len(reports)}') |
6. 外部 BI ツールへの連携
6.1 Looker Studio(旧 Data Studio) – Community Connector
-
Apps Script プロジェクト作成
https://script.google.com→ 新規プロジェクト。 -
HTTP 呼び出し実装(例:Node.js‑like の UrlFetchApp)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
function getReports(request) { const token = PropertiesService.getScriptProperties() .getProperty('HUBSPOT_TOKEN'); const url = 'https://api.hubapi.com/reports/v2/reports'; const params = { method: 'GET', muteHttpExceptions: true, headers: { Authorization: `Bearer ${token}` }, payload: null }; const response = UrlFetchApp.fetch(url, params); const json = JSON.parse(response.getContentText()); return { schema: [{ name: 'id', dataType: 'NUMBER' }, ...], rows: json.results.map(r => ({ values: [r.id, r.name] })) }; } |
- Connector の公開 → Looker Studio で「コミュニティ コネクタ」→作成したスクリプトを選択。
公式手順: https://developers.google.com/looker-studio/guides/connectors
6.2 Power BI / Tableau – Python スクリプト
Power BI の 「Python スクリプト」 データ取得ステップに以下コードを貼り付けるだけで、DataFrame がテーブルとしてインポートされます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
import requests, pandas as pd TOKEN = 'YOUR_PRIVATE_TOKEN' BASE = 'https://api.hubapi.com/reports/v2/reports' def load_all(): offset, rows = 0, [] while True: r = requests.get( BASE, params={'limit': 100, 'offset': offset}, headers={'Authorization': f'Bearer {TOKEN}'} ) r.raise_for_status() data = r.json() rows.extend(data.get('results', [])) if not data.get('paging') or not data['paging'].get('next'): break offset = data['paging']['next']['after'] return pd.DataFrame(rows) df = load_all() # Power BI が自動で取り込む |
Tableau でも同様に TabPy を介して上記関数を呼び出すだけです。
注意:トークンは 環境変数またはキー保管サービス に格納し、スクリプト内にハードコーディングしないこと。
7. 運用のベストプラクティス
7.1 エラーハンドリングとリトライ
| HTTP ステータス | 主な原因 | 推奨対策 |
|---|---|---|
| 400 | パラメータ不正、JSON 構文エラー | リクエスト前に JSON Schema バリデーションを実施。 |
| 401 | 無効または期限切れトークン | Private App → 新しいアクセストークン取得(UI); OAuth → リフレッシュトークンで再取得。 |
| 403 | スコープ不足、IP 制限違反 | 必要スコープを追加し、HubSpot 管理画面で IP ホワイトリスト設定。 |
| 404 | 指定 ID が存在しない | 事前に GET /reports/v2/reports で有効な ID を確認。 |
| 429 | レートリミット超過(10 req/秒) | 指数バックオフ + jitter を実装。例:retryAfter = max(1, response.headers.get('Retry-After', 0)) * (2 ** attempt) |
Python の指数バックオフサンプル
|
1 2 3 4 5 6 7 8 9 10 11 |
import time, random, requests def request_with_backoff(url, headers, params=None, max_attempts=5): for attempt in range(1, max_attempts + 1): r = requests.get(url, headers=headers, params=params) if r.status_code != 429: return r wait = (2 ** attempt) + random.uniform(0.5, 1.0) time.sleep(wait) raise RuntimeError('Exceeded max retry attempts') |
7.2 レートリミット監視
- ヘッダー
X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Resetをログに残す。 - CloudWatch / Datadog の カスタムメトリクス として可視化し、残量が 20 % 以下になったら Slack 通知を送る仕組みを構築。
7.3 セキュリティ対策
| 項目 | 推奨設定 |
|---|---|
| 最小権限 | 必要なスコープだけ(例:reports.read)を付与。 |
| IP 制限 | Private App → IP restrictions で社内サーバーの固定 IP のみ許可。 |
| トークンローテーション | 半年ごとに新しいアクセストークンを発行し、旧トークンは即時失効。 |
| 監査ログ | HubSpot → Account Settings → Audit Log で API アクセス履歴を定期的にレビュー。 |
8. 2024‑2026 年の主な変更点(公式リリースノート抜粋)
| リリース日 | 内容 | 影響 |
|---|---|---|
| 2024‑07‑15 | customEvent オブジェクトが Reports API に統合。フィルタで objectType = "CUSTOM_EVENT" が使用可能に。 |
カスタムイベント(例:ウェビナー参加)を同一レポートで集計できるようになった。 |
| 2025‑01‑10 | レポート作成リクエストに displayName フィールドが必須化。 |
旧コードは 400 Bad Request を返すため、パラメータ追加が必要。 |
| 2026‑02‑22 | Private App Token の 無期限 が公式ドキュメントで明記。トークンの自動失効機能は廃止。 | トークン管理ポリシーを「ローテーション」中心に変更すべき。 |
| 2026‑03‑30 | X-RateLimit-Limit がエンドポイントごとから アカウント全体 に統一された。上限は 10 req/秒(従来通り)だが、複数エンドポイントで同時にリクエストすると合算される点に注意。 |
レート制御ロジックのスコープを「グローバル」へ変更する必要あり。 |
公式リリースノート: https://developers.hubspot.com/changelog
9. まとめ
- 正確なエンドポイント(
/reports/v2/reports)と最新のレートリミット情報を把握すれば、安定したデータ取得が可能です。 - Private App Token は無期限かつ設定が簡単で、社内バッチや ETL に最適。一方、外部 SaaS 連携では OAuth 2.0 が必須になるケースがあります。
- ページング・フィルタリング・日付範囲は公式フォーマット(ISO 8601)に従い、
limit=100とoffset/afterを組み合わせた実装がベストプラクティスです。 - BI 連携は Looker Studio の Community Connector、Power BI / Tableau の Python スクリプトでシームレスに行えます。トークンの安全保管とリクエストレート管理だけが注意点です。
- エラーハンドリング(特に 429)と 指数バックオフ、そして IP 制限・最小権限 の徹底で運用リスクを低減できます。
次のステップ:本稿のコードを開発環境にコピーし、まずは「レポート一覧取得」だけでも実行してみましょう。その後、ページングロジックとフィルタリングを組み合わせて自社 KPI に合致したデータセットを作成してください。
本記事は 2026‑04‑14 時点の情報に基づき執筆しています。HubSpot の API は頻繁に更新されるため、常に公式ドキュメント を参照する習慣をおすすめします。