
カスタム社内ツール向けHubSpot API連携:Node + Pythonガイド(2026年版)
HubSpot API連携をセットアップするために、まだHubSpot APIキーを探し回っていますか?探すのはやめましょう。HubSpotは2022年11月30日に静的なAPIキーを廃止しました。現在のNode SDK(@hubspot/api-client、現在はv14)でも、APIキーは受け付けません。単一アカウント向けの社内ツールにおいて適切な認証情報は、プライベートアプリのアクセストークンです。このガイドでは、最初の create contact 呼び出しから署名検証付きWebhookまで、NodeとPythonの両方で実際のHubSpotから社内ツールへの同期処理を構築します。
簡潔な答え: HubSpot API連携により、カスタム社内ツールはHubSpotのv3 REST APIを通じてCRMデータの読み書きが可能になります。単一アカウント向けの社内ツールでは、プライベートアプリのアクセストークンを使用して認証を行い(HubSpotは2022年にAPIキーを廃止)、ポーリングではなくWebhookを使ってリアルタイムに変更を同期させます。
ここで構築するものは以下の通りです:
- プライベートアプリトークン認証と、NodeおよびPythonによる最初の
create contact呼び出し - ペイロードを信頼する前に
X-HubSpot-Signature-v3を検証するWebhookレシーバー - 429エラーに耐性があり、内部のチケット発行システムやERPレコードへ100件単位でバッチ同期する処理
カスタム社内ツールにおけるHubSpot API連携の仕組み
HubSpot API連携は、カスタム社内ツール(チケット管理アプリ、ERP、請求ダッシュボード、顧客ポータルなど)を、HubSpotの v3 REST API を介してHubSpotのCRMに接続します。あなたのツールは プライベートアプリのアクセストークン を使用してHTTPS経由でCRMオブジェクト(連絡先、案件、企業、またはカスタムオブジェクト)を読み書きし、リアルタイムの変更はWebhookを通じて取り込まれます。
HubSpotのCRMを、HTTP経由で通信するデータベースと考えてください。すべてのレコードはタイプとIDを持つオブジェクトです。あなたが構築している hubspot crm api integration は2つの役割を果たします。HubSpotへデータをプッシュする(チケットがオープンされた際に連絡先を作成する)ことと、HubSpotからデータをプルすること(内部ダッシュボードの描画時に案件を読み取る)です。
同期は2つの方向のいずれかで実行されます。一方向同期は、HubSpotからあなたのツールへ、あるいはあなたのツールからHubSpotへの変更をコピーします。双方向同期はその両方を行いますが、ループ防止が必要であり、これについては後ほど説明します。また、毎分HubSpotに「新しいものはありますか?」と問う(ポーリング)代わりに、Webhookを登録することで、レコードが変更された瞬間にHubSpotから通知を受け取ることができます。
ホスティングされたCRMを統合するよりも、データを完全に自分で管理したい場合、オープンソースCRMをセルフホストすることは、コミットする前に検討すべき別の道筋です。しかし、HubSpotがすでに信頼できる情報源(Single Source of Truth)である場合、他のすべてがそれに接続する方法はAPIとなります。
単一アカウント向けの社内ツールであれば、OAuthやアプリマーケットプレイスへの掲載は不要です。プライベートアプリトークンとWebhookがあれば、それだけで連携は完結します。
2026年の認証:なぜHubSpot APIキーはもう存在しないのか
単一アカウント向けの社内ツールにおける HubSpot API認証 には、プライベートアプリのアクセストークン を使用してください。これはHubSpotアカウント内で一度生成する静的なBearerトークンであり、ツールが触れるオブジェクトに対して正確にスコープが設定されています。リフレッシュフローも有効期限もありません。OAuthはパブリックなマルチアカウントアプリ用であり、運用チームが内部的に使用するダッシュボード用ではありません。
プライベートアプリトークン vs 廃止されたAPIキー
ここで注意すべき点は、この検索結果にたどり着いた開発者の半数がつまずく罠です。HubSpotは2022年11月30日にAPIキーを終了しており、現在では完全にサポートされていません。オートコンプリートはまだ「hubspot api key」を提案しますが、これは筋肉記憶が追いついていないためであり、取得できるキーは存在しません。代わりに hubspot private app を作成してください。設定で作成し、必要なスコープを付与し、Authタブからアクセストークンをコピーします。セットアップについてはHubSpotのプライベートアプリの概要を参照してください。
| 方法 | ユースケース | 有効期限またはリフレッシュ? | 適した用途 |
|---|---|---|---|
| APIキー | 削除済み | 2022年11月に終了 | なし(廃止済み) |
| プライベートアプリアクセストークン | 単一アカウント向け社内ツール | いいえ、静的、リフレッシュ不要 | ここでのデフォルトである社内ツール |
| OAuth 2.0 | パブリックまたはマルチアカウントアプリ | はい、トークンは約6時間で失効し、リフレッシュが必要 | 他の企業のポータルに掲載するアプリ |
| サービスキー(2026年2月時点のパブリックベータ) | アカウントレベル、データ専用の認証情報 | ドキュメントによるとアカウントスコープ | データ専用のサーバージョブ(まだベータ版) |
トークン自体に関する2つのルール。最小権限の原則を守ってください。ツールが案件の読み取りと連絡先の書き込みのみを行う場合、crm.objects.contacts.write と crm.objects.deals.read のみを要求し、それ以上は求めないでください。また、トークンは環境変数またはシークレットマネージャーに保管し、Authorization: Bearer ヘッダーで送信してください。ハードコーディングしたり、ブラウザに送信したりしてはいけません。
結論はシンプルです。社内ツールには プライベートアプリのアクセストークン を使用してください。これが後に他の企業が自社のポータルにインストールするパブリックなマルチアカウントアプリになる場合にのみ、OAuthを検討してください。
最初のHubSpot API呼び出し:NodeとPythonで連絡先を作成する
典型的な最初の呼び出しは create contact であり、公式SDKを使えば数行で実装できます。クライアントをインストールし、環境変数から取得したプライベートアプリトークンで初期化し、連絡先を作成して案件を読み戻します。これは企業、チケット、および hubspot custom objects api 呼び出しでも再利用するパターンであり、変わるのオブジェクトタイプのみです。
以下は @hubspot/api-client (v14) を使用したNodeバージョンです:
// npm i @hubspot/api-client (v14.x)
import { Client } from "@hubspot/api-client";
// Private app token from a secret manager or env var, never hard-coded
const hubspot = new Client({ accessToken: process.env.HUBSPOT_PRIVATE_APP_TOKEN });
// Create a contact
const { id } = await hubspot.crm.contacts.basicApi.create({
properties: {
email: "[email protected]",
firstname: "Ada",
lastname: "Lovelace",
lifecyclestage: "lead",
},
associations: [],
});
console.log("Created contact", id);
// Read a deal by ID
const deal = await hubspot.crm.deals.basicApi.getById(
"1234567890",
["dealname", "amount", "dealstage"],
);
console.log(deal.properties.dealname, deal.properties.amount);そして、Pythonの hubspot-api-client (v12) で同じことを行います:
# pip install hubspot-api-client (v12.x)
import os
from hubspot import HubSpot
from hubspot.crm.contacts import SimplePublicObjectInputForCreate
# Private app token from the environment, not source control
client = HubSpot(access_token=os.environ["HUBSPOT_PRIVATE_APP_TOKEN"])
# Create a contact
contact = client.crm.contacts.basic_api.create(
simple_public_object_input_for_create=SimplePublicObjectInputForCreate(
properties={
"email": "[email protected]",
"firstname": "Ada",
"lastname": "Lovelace",
"lifecyclestage": "lead",
}
)
)
print("Created contact", contact.id)
# Read a deal by ID
deal = client.crm.deals.basic_api.get_by_id(
deal_id="1234567890",
properties=["dealname", "amount", "dealstage"],
)
print(deal.properties["dealname"], deal.properties["amount"])プロのヒント:本番環境ではなく、HubSpotの 開発者サンドボックス でテストしてください。本番環境での誤った作成呼び出しは、営業チームが清理しなければならない実際のゴミレコードを残してしまいます。トークン、スコープ、およびオブジェクトモデルの動作はサンドボックスでも同一です。
リアルタイムでHubSpotから社内ツールへ同期するには?
ポーリングではなく Webhook を使用してください。関心のあるオブジェクトとイベント(例えば deal.propertyChange)に対してプライベートアプリでWebhookサブスクリプションを登録し、あなたがホストするHTTPSエンドポイントを指定します。一致する変更が発生した瞬間、HubSpotは小さなJSON配列をPOSTします。監視が必要な対象に対してサブスクリプションが存在しない場合にのみ、ポーリングを使用してください。
その利点は効率性です。ポーリングは毎分「新しいものはありますか?」と問いかけ、レート制限を消費します。一方、Webhook は案件が変更された瞬間に通知します。この違いは規模が大きくなると重要になり、Webhookは今や珍しくなく主流です。Postmanの2025 State of the API Report(5,700人以上の開発者を対象とした調査)では、約半数のチームがWebhookに依存していることがわかりました。
プライベートアプリのWebhooksタブでサブスクリプションを登録し、ターゲットURLを設定し、イベントを選択します。HubSpotはイベントオブジェクトの配列を送信し、それぞれに subscriptionType、objectId、および変更内容が含まれます。以下はExpressを使用したNodeでのレシーバースタブです:
import express from "express";
const app = express();
// Capture the raw body: you need the exact bytes to validate the signature next
app.use(express.json({
verify: (req, _res, buf) => { req.rawBody = buf.toString("utf8"); },
}));
// HubSpot POSTs an array of events to this URL
app.post("/webhooks/hubspot", (req, res) => {
const events = req.body; // [{ subscriptionType: "deal.propertyChange", objectId: 1234, ... }]
for (const event of events) {
console.log("HubSpot event:", event.subscriptionType, event.objectId);
// Do NOT trust this payload yet. The next section validates it before we act.
}
res.sendStatus(200);
});
app.listen(3000, () => console.log("Listening on :3000"));ここから実践的な構築が始まります。例えば、小規模製造業者のERPレコードへ案件を同期していると仮定します。Webhookが発火し、ハンドラーが一致するERPチケットを作成または更新すると、運用チームはHubSpotに触れることなく変更を確認できます。これは、音声エージェントをCRMに同期させる際と同じリアルタイムアプローチですが、トリガーが電話ではなくプロパティの変更である点が異なります。注意点:上記のスタブはPOSTされたものを何でも信頼しています。本番公開前にこれを修正してください。
偽造されたペイロードを絶対に信頼しないためのWebhook署名検証(v3)
受信するすべてのWebhookを v3署名 で検証してください。HubSpotは各リクエストをアプリシークレットで署名し、2つのヘッダー X-HubSpot-Signature-v3 と X-HubSpot-Request-Timestamp を送信します。5分以上古いものは拒否し、ソース文字列を メソッド + 完全なURL + 生ボディ + タイムスタンプ として再構築し、アプリシークレットでHMAC-SHA256ハッシュ化し、Base64エンコードして、定数時間で比較します。
これを省略すると、Webhook URLを推測した誰でも案件更新を偽造できてしまいます。検証は必須です。HubSpotのリクエスト検証ドキュメントとv3署名の変更履歴に正確な手順が記載されています。以下はExpressミドルウェアとしてそのまま使用できるコードです:
import crypto from "crypto";
const CLIENT_SECRET = process.env.HUBSPOT_APP_SECRET; // from your private app settings
const MAX_AGE_MS = 5 * 60 * 1000; // reject anything older than 5 minutes
export function validateHubSpotSignature(req, res, next) {
const signature = req.header("X-HubSpot-Signature-v3");
const timestamp = req.header("X-HubSpot-Request-Timestamp");
// 1. Reject stale requests (replay protection)
if (!signature || !timestamp || Date.now() - Number(timestamp) > MAX_AGE_MS) {
return res.sendStatus(401);
}
// 2. Rebuild the exact source string: method + full URL + raw body + timestamp
const uri = `https://${req.get("host")}${req.originalUrl}`;
const source = `${req.method}${uri}${req.rawBody}${timestamp}`;
// 3. HMAC-SHA256 with the app secret, base64-encoded
const hash = crypto
.createHmac("sha256", CLIENT_SECRET)
.update(source, "utf8")
.digest("base64");
// 4. Constant-time compare against the header
const expected = Buffer.from(hash);
const received = Buffer.from(signature);
if (expected.length !== received.length ||
!crypto.timingSafeEqual(expected, received)) {
return res.sendStatus(401);
}
next();
}両方のスタックをカバーするため、Python関数としての同じチェックも示します:
import base64
import hashlib
import hmac
import os
import time
CLIENT_SECRET = os.environ["HUBSPOT_APP_SECRET"].encode("utf-8")
MAX_AGE_MS = 5 * 60 * 1000 # 5 minutes
def is_valid_signature(method, uri, body, signature, timestamp):
# 1. Reject stale requests
if not signature or not timestamp:
return False
if int(time.time() * 1000) - int(timestamp) > MAX_AGE_MS:
return False
# 2. method + full URL + raw body + timestamp
source = f"{method}{uri}{body}{timestamp}".encode("utf-8")
# 3. HMAC-SHA256, base64
digest = hmac.new(CLIENT_SECRET, source, hashlib.sha256).digest()
expected = base64.b64encode(digest).decode("utf-8")
# 4. Constant-time compare
return hmac.compare_digest(expected, signature)人々が半日ハマる落とし穴:HubSpotは 完全なターゲットURL(スキーム、ホスト、パスを合わせたもの)に署名します。プロキシ、ロードバランサー、またはngrokトンネルの背後では、req.get("host") がHubSpotが署名したパブリックホストではなく、内部ホストを報告することがあります。正当なペイロードなのに検証が失敗し続ける場合は、再構築した正確なURIをログに記録し、パブリックWebhook URLと一文字ずつ比較してください。
レート制限、429エラー、およびBatch API:本番環境で実行したこと
プライベートアプリは、Free/Starterプランで10秒あたり100リクエスト(秒間約10回)、Pro/Enterpriseプランで10秒あたり190リクエスト(秒間約19回)の制限があり、日次キャップは250,000から1,000,000の間です。罠は、CRM Search が別枠で 秒間4リクエスト に制限されており、バッチエンドポイントはリクエストあたり最大 100レコード しか受け付けないことです。HubSpotの使用ガイドラインに階層がリストされています。
| 階層 | 10秒あたり | 秒間あたり | 日次キャップ | 備考 |
|---|---|---|---|---|
| Free / Starter(プライベートアプリ) | 100 | ~10 | 250,000 | CRM Searchは別枠で秒間4リクエストに制限 |
| Pro / Enterprise(プライベートアプリ) | 190 | ~19 | 最大1,000,000 | バッチエンドポイントはリクエストあたり最大100レコード |
理論が赤いステージングダッシュボードと衝突した瞬間の話です。今年春のバックフィル作業中、社内チケット管理ツールから約8,000件の既存レコードをHubSpotにプッシュし、それぞれをCRM Searchルックアップで enrich しました。Node側では @hubspot/api-client v14、Python enrichment ワーカーでは hubspot-api-client v12を実行していました。バルク書き込みは順調でした。しかし、Search呼び出しは1分以内に失敗しました。ワーカーが秒間約15リクエストでSearchを発行していたため、別途予算立てていなかった秒間4リクエストという硬性の上限を超えてしまったのです。
2つの変更でこれを解決しました。第一に、X-HubSpot-RateLimit-* レスポンスヘッダーを読み取り、429エラー時にバックオフするリトライラッパーです:
// Wrap any HubSpot call; retries on 429 with exponential backoff
async function withRetry(fn, maxRetries = 5) {
let attempt = 0;
while (true) {
try {
return await fn();
} catch (err) {
const status = err.code ?? err.response?.status;
if (status !== 429 || attempt >= maxRetries) throw err;
// Honor HubSpot's reset window if the header is present
const headers = err.response?.headers ?? {};
const resetMs = Number(headers["x-hubspot-ratelimit-interval-milliseconds"]) || 0;
const backoff = Math.max(resetMs, 2 ** attempt * 500); // 0.5s, 1s, 2s, 4s...
console.warn(`429 hit, retry ${attempt + 1} in ${backoff}ms`);
await new Promise((r) => setTimeout(r, backoff));
attempt++;
}
}
}第二に、レコードを1件ずつ書き込むのをやめました。バッチエンドポイントは POST /crm/v3/objects/{objectType}/batch/create につき最大100レコードを受け付けるため、バックフィルを8,000回の単一POSTではなく、80回のバッチ呼び出しに分割しました:
// HubSpot batch endpoints accept at most 100 records per request
function chunk(arr, size = 100) {
const out = [];
for (let i = 0; i < arr.length; i += size) out.push(arr.slice(i, i + size));
return out;
}
// POST /crm/v3/objects/contacts/batch/create, chunked to 100 at a time
async function batchCreateContacts(records) {
for (const group of chunk(records, 100)) {
const inputs = group.map((r) => ({
properties: { email: r.email, firstname: r.firstName, lastname: r.lastName },
associations: [],
}));
await withRetry(() => hubspot.crm.contacts.batchApi.create({ inputs }));
console.log(`Wrote ${group.length} contacts`);
}
}Searchワーカーを秒間4リクエストに制限し、書き込みをバッチ処理することで、リトライで溺れていた実行を静かに完了させることができました。このセクションから1つだけ数字を覚えるなら、それは4です。CRM Searchのキャップは本番環境で痛手を負わせる制限であり、多くのまとめ記事が言及し忘れているものです。ちなみに、かつての「連絡先用バッチ上限10件」という制限は撤廃されており、現在はオブジェクトタイプに関わらず100件です。
双方向へ:無限ループなしでHubSpotへ変更を書き戻す
双方向同期 は、読み取りだけでなく、社内ツールからHubSpotへの変更も書き戻します。危険なのはフィードバックループです。あなたの書き戻しが、ハンドラーを発火させたまさにそのWebhookをトリガーし、それが再び書き込みを行い、永遠に続きます。これを防ぐには、冪等性キー(すでに適用した変更をスキップ)とソースフラグ(自社ツールが引き起こしたインバウンドイベントを無視)を使用します。
const processed = new Set(); // use Redis or a unique DB constraint in production
async function writeBackToHubSpot(record) {
// Dedup key: object id + a hash of the change we're about to apply
const key = `${record.id}:${record.updatedHash}`;
if (processed.has(key)) return; // already synced this exact change
processed.add(key);
await withRetry(() =>
hubspot.crm.contacts.basicApi.update(record.id, {
// Tag the source so the resulting webhook is ignored by our own receiver
// (check for source: "internal-tool" before acting on an inbound event)
properties: { internal_status: record.status, last_sync_source: "internal-tool" },
})
);
}このパターンは小さく見えますが、これを省略すると、同期処理が一晩で書き込み量を倍増させてしまうことがあります。両方向のデータがクリーンになったら、チームはしばしばそれを下流のAI SDRパイプラインやレポート層へ流し込みます。双方向同期の別の視点を得たい場合、NangoのHubSpot統合チュートリアルはNodeのみの優れた参考資料ですが、ループ防止のアイデアは自分で移植する必要があります。
社内で構築すべきか、統合パートナーを外注すべきか?
同期が 小規模で安定しており、所有者がいる 場合に社内で構築してください。一方向のフロー、少数のオブジェクト、そしてHubSpotの年2回程度の破壊的変更に対応できるエンジニアがいる場合です。双方向同期、カスタムオブジェクトのモデリングが必要な場合、またはチーム内に継続的なメンテナンスを担当できる人がいない場合はパートナーを外注してください。決定要因は初期構築ではなく、1年後に誰がそれを見守っているかです。
率直なチェックリストはこちらです。自分で構築する場合: 方向が一方向、標準オブジェクトを同期、Webhookエンドポイントをホストできる開発者がいる、ペイロードが失敗し始めたときに気づく人がいる。上記すべてがあなたの青写真です。
パートナーを外注する場合: 複数のオブジェクト間でループ防止付きの双方向同期が必要、型付けされた関連付けを持つカスタムオブジェクトをモデリングしている、複数のシステム(HubSpot、ERP、請求システム)を接続している、またはメンテナンス担当者が既にキャパシティいっぱいである。HubSpotは日付ベースのAPIバージョニングを採用しており、破壊的変更は年2回程度ですが、これが最も忙しい週に発生し、所有者がいない場合に穏やかではなくなります。最初のデプロイではなく、そのメンテナンスの尻尾こそが、社内統合を静かに沈没させる原因です。所有したくない場合は、私たちのカスタムCRM統合サービスをご利用ください。
主なポイント
- HubSpot APIキーはもう存在しません。単一アカウント向け社内ツールには プライベートアプリのアクセストークン を使用し、OAuthはパブリックなマルチアカウントアプリ専用です。
- Webhookペイロードを信頼する前に、常に
X-HubSpot-Signature-v3を検証してください。完全なターゲットURLを使用してソース文字列を再構築します。 - 秒間4リクエストのCRM Search キャップを尊重し、429バックオフを用いて 100件 単位で大きな書き込みをバッチ処理します。
- リアルタイム同期にはポーリングよりWebhookを優先し、HubSpot統合はより広範なビジネス向けAIツールスタックの一部です。
メンテナンス側で行き詰まっていますか?出荷前にセカンドオピニオンが必要です?無料の統合コンサルティングを予約してください。どちらでも構いません。上記のコードは自由に実行できます。
著者について
Mert Batur GurbuzはTechsy.ioの共同創設者であり、同チームはB2Bクライアント向けにAIエージェント、自動化システム、音声/SDRパイプラインを提供しています。バーミンガム大学で学び、Techsyチームが実際に本番環境で使用しているLLMツールスタックについて執筆しています。資格:Techsy.io共同創設者、バーミンガム大学。LinkedInでつながる。
よくある質問
2026年でもHubSpot APIキーは必要ですか?
いいえ。HubSpotは2022年11月30日に静的APIキーを終了しており、完全にサポートされていません。習慣的にオートコンプリートが「hubspot api key」を提案しますが、取得できるものは何もありません。単一アカウント向け社内ツールには、設定でプライベートアプリを作成し、そのアクセストークンを使用してください。
HubSpotにおけるプライベートアプリトークンとOAuthの違いは何ですか?
プライベートアプリのアクセストークンは、単一のHubSpotアカウント用の静的な認証情報であり、有効期限もリフレッシュフローもなく、社内ツールに最適です。OAuth 2.0は、他の企業が自社のポータルにインストールするパブリックなマルチアカウントアプリ用です。そのトークンは約6時間で失効し、リフレッシュサイクルが必要です。
2026年のHubSpot APIレート制限はどうなっていますか?
プライベートアプリは秒間約10リクエスト(Free/Starterで10秒あたり100、Pro/Enterpriseで190)の制限があり、日次キャップは250,000から1,000,000です。CRM Search APIは別枠で秒間4リクエストに制限されており、バッチエンドポイントはリクエストあたり最大100レコードを受け付けます。
HubSpotのWebhook署名を検証するにはどうすればよいですか?
v3の手順を使用します。X-HubSpot-Request-Timestamp が5分以上古いリクエストを拒否し、メソッド、完全なターゲットURL、生ボディ、タイムスタンプを組み合わせたソース文字列を構築します。アプリシークレットでHMAC-SHA256ハッシュ化し、結果をBase64エンコードして、定数時間で X-HubSpot-Signature-v3 と比較します。
NodeとPython、どちらのHubSpot SDKを使用すべきですか?
どちらも公式でメンテナンスされています。Nodeは @hubspot/api-client (v14)、Pythonは hubspot-api-client (v12) を使用します。これらは同じv3 CRMオブジェクトモデルを公開しているため、スタックに合う方を選んでください。このガイドでは、両言語で同一の認証および署名検証コードを提供しています。
カスタム社内ツールとHubSpotをリアルタイムで同期するにはどうすればよいですか?
関心のあるオブジェクトとイベントに対してプライベートアプリでWebhookサブスクリプションを登録し、一致する変更が発生した際にHubSpotがPOSTするHTTPSエンドポイントをホストします。署名を検証し、変更を社内ツールに書き込みます。Webhookサブスクリプションでカバーされていないものが必要な場合にのみポーリングを使用してください。
HubSpot Service Keyとは何ですか?使用すべきですか?
Service Keyは、HubSpotが2026年2月にパブリックベータ版としたアカウントレベルのデータ専用認証情報です。データのみを扱うサーバーサイドジョブを対象としています。今日の標準的な社内ツールでは、プライベートアプリのアクセストークンの方が依然として安全で文書化されたデフォルトです。Service Keyは卒業するまでベータ版として扱ってください。
本番環境に影響を与えずにHubSpot統合をテストできますか?
はい。HubSpot開発者サンドボックスを作成し、プライベートアプリトークンをそこに向けます。スコープ、オブジェクトモデル、Webhook、レート制限は本番環境と同じように動作するため、営業チームが後で清理しなければならないゴミレコードを残さずに、テスト用の連絡先を作成したりWebhookを発火させたりできます。
HubSpotバッチAPIは一度に何件のレコードを受け取れますか?
バッチエンドポイント(POST /crm/v3/objects/{objectType}/batch/create およびその更新・upsert兄弟)は、リクエストあたり最大100レコードを受け付けます。大きなペイロードは100件ごとのグループに分割してください。一部のチュートリアルでまだ引用されている古い「連絡先用10レコード」の上限は撤廃されており、現在はオブジェクトタイプに関わらず100件です。
社内で構築すべきか、エージェンシーを外注すべきか?
同期が一方向で、標準オブジェクトを使用し、HubSpotの年2回の破壊的変更に対応できる所有者がいる場合は社内で構築してください。双方向同期、カスタムオブジェクトのモデリング、またはメンテナンスを担当できる人がいない場合はパートナーを外注してください。最初のデプロイは簡単ですが、その後の1年間の維持管理が真のコストです。