🟢 HubSpot 開発者向け実践教科書 — 2026年版 Developer Edition
Chapter 2  ·  CRM API Complete Guide

CRM API
完全ガイド

Objects API・Search API・Associations API・Batch API の全体像と実装パターン。 レート制限の回避策・ページネーション・大量データ処理まで、実務レベルの CRM API 活用を体系的に学ぶ。

CRM API v3
Node.js SDK 利用例
所要時間:約120分
2-1 CRM API の全体像

HubSpot CRM API v3 は Object ベースの RESTful API。まず構造を把握する。

🏗 CRM API の基本構造

HubSpot CRM API はオブジェクト(Object)単位で設計されています。 Contacts・Companies・Deals・Tickets などの標準オブジェクトに加え、カスタムオブジェクトも同じ API パターンで操作できます。 各オブジェクトには「プロパティ(Properties)」「アソシエーション(Associations)」「エンゲージメント(Engagements)」が紐づきます。

オブジェクトAPI パス用途
Contacts/crm/v3/objects/contacts見込み客・顧客の個人情報
Companies/crm/v3/objects/companies取引先企業情報
Deals/crm/v3/objects/deals商談・案件
Tickets/crm/v3/objects/ticketsサポートチケット
Products/crm/v3/objects/products商品・製品カタログ
Line Items/crm/v3/objects/line_items商談に紐づく明細行
Quotes/crm/v3/objects/quotes見積書
Custom Objects/crm/v3/objects/{objectType}カスタムオブジェクト(4章で詳説)
ベース URL: すべての CRM API リクエストのベース URL は https://api.hubapi.com です。 認証ヘッダーは Authorization: Bearer {ACCESS_TOKEN} を使用します。
2-2 Objects API — CRUD 操作

コンタクトを例に、作成・取得・更新・削除の基本操作をマスターする。

Contacts エンドポイント一覧
GET
/crm/v3/objects/contacts
コンタクト一覧を取得(ページネーション対応)
GET
/crm/v3/objects/contacts/{contactId}
特定コンタクトを ID で取得
POST
/crm/v3/objects/contacts
新しいコンタクトを作成
PATCH
/crm/v3/objects/contacts/{contactId}
コンタクトのプロパティを更新
DELETE
/crm/v3/objects/contacts/{contactId}
コンタクトをアーカイブ(論理削除)
Node.js — コンタクト CRUD
import { Client } from '@hubspot/api-client'; const client = new Client({ accessToken: process.env.HUBSPOT_ACCESS_TOKEN }); // ── 作成 ────────────────────────────── const newContact = await client.crm.contacts.basicApi.create({ properties: { email: 'taro@example.com', firstname: '太郎', lastname: '山田', phone: '090-1234-5678', company: '株式会社サンプル', }, }); console.log('Created:', newContact.id); // ── 取得(ID 指定)──────────────────── const contact = await client.crm.contacts.basicApi.getById( newContact.id, ['email', 'firstname', 'lastname', 'hs_lead_status'] ); // ── 更新 ────────────────────────────── await client.crm.contacts.basicApi.update(newContact.id, { properties: { hs_lead_status: 'IN_PROGRESS', lifecyclestage: 'opportunity', }, }); // ── 削除(アーカイブ)────────────────── await client.crm.contacts.basicApi.archive(newContact.id);
Node.js — 一覧取得とページネーション
// 全コンタクトをページネーションで取得 async function getAllContacts() { const allContacts = []; let after = undefined; do { const page = await client.crm.contacts.basicApi.getPage( 100, // limit(最大100) after, // ページネーショントークン ['email', 'firstname', 'lastname', 'createdate'] ); allContacts.push(...page.results); after = page.paging?.next?.after; // 次ページトークン // レート制限対策:100ms待機 if (after) await new Promise(r => setTimeout(r, 100)); } while (after); return allContacts; }
アーカイブ vs 完全削除: archive() は論理削除(アーカイブ)で、30日間は復元可能です。 完全削除(GDPR 対応など)が必要な場合は gdprDeleteApi.purge() を使用しますが、復元不可のため注意してください。
2-3 Search API — 高度な絞り込み検索

フィルター・ソート・全文検索を組み合わせて CRM データを柔軟に検索する。

🔍 Search API の特徴

Search API は POST /crm/v3/objects/{objectType}/search エンドポイントで、 複数のフィルターグループ(OR 条件)フィルター(AND 条件)を組み合わせた複雑な絞り込みが可能です。 1リクエストで最大 10,000件まで取得でき、ページネーションにも対応しています。

演算子意味
EQ等しいlifecyclestage = "customer"
NEQ等しくないhs_lead_status ≠ "UNQUALIFIED"
GT / GTEより大きい / 以上createdate > 特定日時
LT / LTEより小さい / 以下amount < 100000
CONTAINS_TOKENトークンを含む(部分一致)email contains "@example.com"
INリスト内のいずれかcountry IN ["JP", "US", "UK"]
NOT_INリスト内のいずれでもないlifecyclestage NOT IN ["other"]
HAS_PROPERTYプロパティが存在するphone が設定されている
NOT_HAS_PROPERTYプロパティが存在しないemail が未設定
BETWEEN範囲内amount BETWEEN 10000 AND 50000
Node.js — Search API 実装例
// 例:顧客ステージが "customer" で、過去30日以内に作成されたコンタクトを検索 const thirtyDaysAgo = Date.now() - (30 * 24 * 60 * 60 * 1000); const searchResult = await client.crm.contacts.searchApi.doSearch({ filterGroups: [ { filters: [ { propertyName: 'lifecyclestage', operator: 'EQ', value: 'customer', }, { propertyName: 'createdate', operator: 'GTE', value: thirtyDaysAgo.toString(), }, ], }, ], properties: ['email', 'firstname', 'lastname', 'createdate'], sorts: [{ propertyName: 'createdate', direction: 'DESCENDING' }], limit: 100, after: 0, }); console.log(`Total: ${searchResult.total}`); console.log(searchResult.results);
Node.js — OR 条件(複数フィルターグループ)
// 例:ライフサイクルが "lead" OR "opportunity" のコンタクト // filterGroups の配列が OR 条件、groups 内の filters が AND 条件 const result = await client.crm.contacts.searchApi.doSearch({ filterGroups: [ { filters: [{ propertyName: 'lifecyclestage', operator: 'EQ', value: 'lead' }], }, { filters: [{ propertyName: 'lifecyclestage', operator: 'EQ', value: 'opportunity' }], }, ], properties: ['email', 'lifecyclestage', 'hubspot_owner_id'], limit: 200, });
Node.js — Search API で全件取得(ページネーション)
async function searchAll(objectType, filterGroups, properties = []) { const results = []; let after = 0; while (true) { const page = await client.crm[objectType].searchApi.doSearch({ filterGroups, properties, limit: 100, after, }); results.push(...page.results); if (!page.paging?.next?.after) break; after = page.paging.next.after; await new Promise(r => setTimeout(r, 200)); // throttle } return results; } // 使用例 const allDeals = await searchAll('deals', [ { filters: [{ propertyName: 'dealstage', operator: 'EQ', value: 'closedwon' }] }, ], ['dealname', 'amount', 'closedate']);
⚠ Search API の上限: 1回の検索で取得できるレコード数の上限は 10,000件です。10,000件を超えるデータを取得する場合は、 日付範囲などでデータを分割して複数回リクエストするか、Exports API の利用を検討してください。
2-4 Associations API — オブジェクト間の関連付け

コンタクト・会社・商談などのオブジェクトを相互に関連付け、CRM の関係性を表現する。

🔗 Associations の基本概念

HubSpot では異なるオブジェクト間の関係を「アソシエーション」として管理します。 例えば「コンタクト → 会社」「コンタクト → 商談」「商談 → 会社」などが代表的な関係です。 v3 API では アソシエーションタイプ を指定することで、関係の種類(主担当・関係者・意思決定者など)も表現できます。

よく使うアソシエーションfromObjecttoObjecttypeId
コンタクト → 会社(主所属)contactscompanies1
会社 → コンタクトcompaniescontacts2
コンタクト → 商談contactsdeals4
商談 → コンタクトdealscontacts3
会社 → 商談companiesdeals6
商談 → 会社dealscompanies5
コンタクト → チケットcontactstickets16
Node.js — Associations CRUD
// コンタクトと会社を関連付ける await client.crm.associations.v4.basicApi.create( 'contacts', // fromObjectType contactId, // fromObjectId 'companies', // toObjectType companyId, // toObjectId [{ associationCategory: 'HUBSPOT_DEFINED', associationTypeId: 1 }] ); // コンタクトに関連する会社を取得 const associations = await client.crm.associations.v4.basicApi.getPage( 'contacts', contactId, 'companies' ); console.log(associations.results.map(a => a.toObjectId)); // アソシエーションを削除 await client.crm.associations.v4.basicApi.archive( 'contacts', contactId, 'companies', companyId );
Node.js — オブジェクト作成と同時に関連付け
// 商談を作成しながらコンタクトと会社を一度に関連付ける const newDeal = await client.crm.deals.basicApi.create({ properties: { dealname: 'エンタープライズ契約 2026', amount: '5000000', dealstage: 'appointmentscheduled', pipeline: 'default', closedate: '2026-06-30', }, associations: [ { to: { id: contactId }, types: [{ associationCategory: 'HUBSPOT_DEFINED', associationTypeId: 3 }], }, { to: { id: companyId }, types: [{ associationCategory: 'HUBSPOT_DEFINED', associationTypeId: 5 }], }, ], });
2-5 Batch API — 大量データの効率処理

複数レコードを1リクエストでまとめて操作し、API コール数とレート制限への負荷を削減する。

⚡ Batch API の特徴

Batch API は1リクエストで最大 100件のレコードをまとめて操作できます。 1件ずつ操作するより最大100倍効率的で、レート制限(100req/10sec)を大幅に緩和できます。 作成・読み取り・更新・削除のすべての操作に対応しています。

Node.js — Batch 作成
// 最大100件のコンタクトを一括作成 const batchCreateResult = await client.crm.contacts.batchApi.create({ inputs: [ { properties: { email: 'user1@example.com', firstname: 'ユーザー1' } }, { properties: { email: 'user2@example.com', firstname: 'ユーザー2' } }, { properties: { email: 'user3@example.com', firstname: 'ユーザー3' } }, // ... 最大100件 ], }); console.log(`Created ${batchCreateResult.results.length} contacts`);
Node.js — Batch 更新
// 複数のコンタクトを一括更新 const batchUpdateResult = await client.crm.contacts.batchApi.update({ inputs: [ { id: '101', properties: { lifecyclestage: 'customer' } }, { id: '102', properties: { lifecyclestage: 'customer' } }, { id: '103', properties: { hs_lead_status: 'UNQUALIFIED' } }, ], });
Node.js — 大量データを Batch で処理するユーティリティ
/** * 大量のレコードを100件ずつチャンクに分けて Batch API で処理する * @param {Array} items - 処理対象の配列 * @param {Function} batchFn - Batch API を呼び出す関数 * @param {number} chunkSize - チャンクサイズ(最大100) */ async function processBatch(items, batchFn, chunkSize = 100) { const results = []; for (let i = 0; i < items.length; i += chunkSize) { const chunk = items.slice(i, i + chunkSize); const result = await batchFn(chunk); results.push(...result.results); // レート制限対策:チャンク間に 200ms 待機 if (i + chunkSize < items.length) { await new Promise(r => setTimeout(r, 200)); } } return results; } // 使用例:500件のコンタクトを一括更新 const updates = contactIds.map(id => ({ id, properties: { custom_sync_status: 'synced' }, })); await processBatch(updates, (chunk) => client.crm.contacts.batchApi.update({ inputs: chunk }) );
2-6 Properties API — カスタムプロパティの管理

プロパティの一覧取得・作成・更新を API で管理する。

プロパティ型fieldType用途
stringtext / textareaテキスト入力
numbernumber数値(金額・スコアなど)
enumerationselect / radio / checkbox選択式。options リストが必要
datedate日付(YYYY-MM-DD)
datetimedate日時(Unix ミリ秒)
boolbooleancheckboxTrue / False
Node.js — カスタムプロパティの作成
// コンタクトにカスタムプロパティを追加 const newProperty = await client.crm.properties.coreApi.create( 'contacts', { name: 'custom_score', label: 'カスタムスコア', type: 'number', fieldType: 'number', groupName: 'contactinformation', description: '外部システムから同期したスコア値', displayOrder: -1, hasUniqueValue: false, } ); // enumeration プロパティの作成(選択肢付き) const enumProperty = await client.crm.properties.coreApi.create( 'contacts', { name: 'customer_tier', label: '顧客ティア', type: 'enumeration', fieldType: 'select', groupName: 'contactinformation', options: [ { label: 'プラチナ', value: 'platinum', displayOrder: 1 }, { label: 'ゴールド', value: 'gold', displayOrder: 2 }, { label: 'シルバー', value: 'silver', displayOrder: 3 }, ], } );
2-7 レート制限の実践的な対処

429 エラーを防ぎ、大量データ処理を安全に行うためのパターンを学ぶ。

📊 レート制限の仕様

10秒あたり: 100リクエスト
1日あたり: プランに依存
Burst: 短時間の急増は 429 を返す
Batch API: 1req = 最大100件分

✅ 推奨対策

Batch API 優先: 単件操作を避ける
Exponential Backoff: 429時にリトライ
キュー処理: 同時実行数を制限
オフピーク処理: 夜間バッチ実行

Node.js — レート制限対応ラッパー(本番推奨)
import pLimit from 'p-limit'; // npm install p-limit /** * レート制限・リトライ・同時実行制御を組み合わせた API ラッパー */ const limit = pLimit(5); // 同時実行を最大5に制限 async function safeApiCall(fn, maxRetries = 4) { for (let attempt = 0; attempt < maxRetries; attempt++) { try { return await fn(); } catch (err) { const status = err.response?.status; const isRetryable = status === 429 || status === 502 || status === 503; if (isRetryable && attempt < maxRetries - 1) { const retryAfter = err.response?.headers['retry-after']; const wait = retryAfter ? parseInt(retryAfter) * 1000 : Math.pow(2, attempt) * 1000; console.warn(`Rate limited. Retrying in ${wait}ms (attempt ${attempt + 1})`); await new Promise(r => setTimeout(r, wait)); } else { throw err; } } } } // 使用例:100件のコンタクトを並列 & レート制限付きで処理 const promises = contactIds.map(id => limit(() => safeApiCall(() => client.crm.contacts.basicApi.getById(id, ['email', 'firstname']) )) ); const contacts = await Promise.all(promises);
2-8 Timeline API — カスタムイベントの記録

外部システムのイベント(購入・ログイン・操作履歴など)を HubSpot のタイムラインに記録する。

📅 Timeline API のユースケース

外部システムで起きたアクション(ECサイトでの購入・SaaSへのログイン・アプリ内操作など)を HubSpot のコンタクトタイムラインに記録することで、営業・サポートチームがすべての顧客行動を HubSpot だけで確認できるようになります。

Node.js — Timeline イベントの作成
// Step 1: イベントテンプレートを作成(初回のみ) const template = await client.crm.timeline.templatesApi.create(appId, { name: '商品購入', headerTemplate: '{{contactName}} が {{productName}} を購入しました', detailTemplate: '注文 ID: {{orderId}} / 金額: ¥{{amount}}', tokens: [ { name: 'productName', type: 'string', label: '商品名' }, { name: 'orderId', type: 'string', label: '注文 ID' }, { name: 'amount', type: 'number', label: '金額' }, ], objectType: 'CONTACT', }); // Step 2: イベントを記録 await client.crm.timeline.eventsApi.create({ eventTemplateId: template.id, objectId: contactId, tokens: { productName: 'Proプラン', orderId: 'ORD-2026-001', amount: 49800, }, timestamp: new Date().toISOString(), });
2-9 この章のまとめ

次章(Marketing & CMS API)に進む前に確認する。

✅ Chapter 2 チェックリスト

  • CRM API v3 のオブジェクト構造(Contacts / Companies / Deals など)を理解した
  • Objects API で CRUD 操作(作成・取得・更新・削除)を実装できる
  • ページネーションを使って全レコードを取得できる
  • Search API のフィルター・ソート・OR 条件を組み合わせた検索を実装できる
  • Search API の10,000件上限と回避策を理解した
  • Associations API でオブジェクト間の関連付けを作成・削除できる
  • オブジェクト作成時に associations を同時に指定できる
  • Batch API で100件単位の一括操作を実装できる
  • 大量データを chunk 処理するユーティリティを実装できる
  • レート制限対応(exponential backoff + p-limit)を理解した
  • Properties API でカスタムプロパティを作成できる
  • Timeline API で外部イベントを HubSpot に記録できる
次章(Chapter 3)について: Marketing Hub と CMS に関連する API を学びます。Forms API・Email API・Blog API・Pages API・HubDB API の実装パターンを、 マーケティング自動化の観点から解説します。