マルチ契約ウェブサイトリード受付
このドキュメントは、サイトバックエンドがリードデータ、訪問者の連絡先詳細、マーケティングUTMメトリクスを1つのリクエストでReactiveCRMに送信する単一のAPI契約を説明します。
1. 目的
サイト統合者は、連絡先、電話、メール、リード、マーケティングイベントを個別に作成する必要はありません。1つのリクエストでアトミックに以下を作成する必要があります:
- 連絡先;
- 連絡先の主電話番号;
- 提供された場合の連絡先の主メールアドレス;
- リード;
- 連絡先とリード間のリンク;
- マーケティングイベントとUTMアトリビューション。
いずれかのステップが失敗した場合、リクエスト全体がロールバックされ、部分的に作成されたデータは保存されません。
2. エンドポイント
POST /api/site/leads
Authorization: Bearer <CRM_ACCESS_TOKEN>
Content-Type: application/json
トークンはサイトバックエンドまたはサーバーレス関数からのみ渡す必要があります。CRMトークンをブラウザのJavaScriptに配置しないでください。
テナントは認証トークンから決定されます。提供されたすべてのUUIDはこのテナント内で検証されます。
3. 完全なJSON契約
{
"externalId": "site-form-01J7K9A2M4Y5T6",
"lead": {
"leadSourceId": "7b33b18f-55bd-48a5-a8f0-e450a56dde47",
"quality": "WARM",
"message": "CRM導入についての相談を希望します"
},
"contact": {
"firstName": "イヴァン",
"lastName": "イヴァノフ",
"phone": "+79991234567",
"email": "ivan@example.com"
},
"marketing": {
"occurredAt": "2026-09-06T18:00:00Z",
"visitorId": "visitor-8b7f",
"sessionId": "session-31ac",
"source": "website",
"channel": "paid",
"utmSource": "google",
"utmMedium": "cpc",
"utmCampaign": "summer-consulting",
"utmContent": "banner-a",
"utmTerm": "crm consultation",
"gclid": "EAIaIQobChMI-example",
"fbclid": null,
"landingUrl": "https://example.com/consultation",
"referrer": "https://www.google.com/"
}
}
4. リクエストフィールド
4.1. ルートフィールド
| フィールド | タイプ | 必須 | 説明 |
|---|---|---|---|
externalId | 文字列 | 推奨 | 冪等性のためのフォーム送信の安定した一意のID |
lead | オブジェクト | はい | 作成されるリードのデータ |
contact | オブジェクト | はい | 連絡先担当者のデータ |
marketing | オブジェクト | いいえ | マーケティング訪問のUTMメトリクスと技術データ |
externalIdは最初の送信試行前に生成されます。タイムアウトまたはネットワークエラー後にリクエストを繰り返す場合は、同じ値を使用してください。
4.2. lead オブジェクト
| フィールド | タイプ | 必須 | 説明 |
|---|---|---|---|
leadSourceId | uuid | はい | 現在のテナント内のリードソースのID |
quality | 文字列 | いいえ | 初期評価:HOT、WARM、COOLまたはCOLD |
message | 文字列 | いいえ | 訪問者のメッセージまたは送信に関するコメント |
サイトが事前評価を実行しない場合、qualityフィールドは送信しない方が良いでしょう。
4.3. contact オブジェクト
| フィールド | タイプ | 必須 | 説明 |
|---|---|---|---|
firstName | 文字列 | はい | 連絡先担当者の名 |
lastName | 文字列 | いいえ | 連絡先担当者の姓 |
phone | 文字列 | はい | 主電話番号;E.164形式推奨 |
email | 文字列(メール) | いいえ | 連絡先担当者の主メールアドレス |
送信を処理するために必要な最小データはfirstNameとphoneです。
4.4. marketing オブジェクト
| フィールド | タイプ | 必須 | 説明 |
|---|---|---|---|
occurredAt | 日時 | いいえ | フォーム送信時間;省略時はCRM時間を使用 |
visitorId | 文字列 | いいえ | 匿名訪問者ID |
sessionId | 文字列 | いいえ | サイトセッションID |
source | 文字列 | いいえ | イベントソース、デフォルトはwebsite |
channel | 文字列 | いいえ | チャネル:例 paid、organic、social、email、direct |
utmSource | 文字列 | いいえ | utm_sourceの値 |
utmMedium | 文字列 | いいえ | utm_mediumの値 |
utmCampaign | 文字列 | いいえ | utm_campaignの値 |
utmContent | 文字列 | いいえ | utm_contentの値 |
utmTerm | 文字列 | いいえ | utm_termの値 |
gclid | 文字列 | いいえ | GoogleクリックID |
fbclid | 文字列 | いいえ | Meta/FacebookクリックID |
landingUrl | 文字列 | いいえ | ランディングページURL |
referrer | 文字列 | いいえ | 前のページURL |
個人データはマーケティングオブジェクト内で重複させてはいけません。名前、電話、メール、メッセージ本文はcontactとleadのみで渡されます。
5. 最小リクエスト
{
"externalId": "site-form-550e8400-e29b-41d4-a716-446655440000",
"lead": {
"leadSourceId": "7b33b18f-55bd-48a5-a8f0-e450a56dde47"
},
"contact": {
"firstName": "イヴァン",
"phone": "+79991234567"
}
}
6. 成功レスポンス
最初のリクエスト — 201 Created
{
"leadId": "22222222-2222-2222-2222-222222222222",
"contactId": "33333333-3333-3333-3333-333333333333",
"phoneId": "44444444-4444-4444-4444-444444444444",
"emailId": "55555555-5555-5555-5555-555555555555",
"marketingEventId": "66666666-6666-6666-6666-666666666666",
"duplicate": false,
"createdAt": "2026-09-06T18:00:01Z"
}
メールまたはマーケティングデータが提供されない場合、対応するIDはnullとして返されます。
同じexternalIdでの繰り返し — 200 OK
{
"leadId": "22222222-2222-2222-2222-222222222222",
"contactId": "33333333-3333-3333-3333-333333333333",
"phoneId": "44444444-4444-4444-4444-444444444444",
"emailId": "55555555-5555-5555-5555-555555555555",
"marketingEventId": "66666666-6666-6666-6666-666666666666",
"duplicate": true,
"createdAt": "2026-09-06T18:00:01Z"
}
繰り返しリクエストは2番目のリードまたは連絡先を作成してはいけません。
7. cURL例
curl -X POST "$CRM_BASE_URL/api/site/leads" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"externalId": "site-form-01J7K9A2M4Y5T6",
"lead": {
"leadSourceId": "7b33b18f-55bd-48a5-a8f0-e450a56dde47",
"quality": "WARM",
"message": "折り返し電話してください"
},
"contact": {
"firstName": "イヴァン",
"lastName": "イヴァノフ",
"phone": "+79991234567",
"email": "ivan@example.com"
},
"marketing": {
"utmSource": "google",
"utmMedium": "cpc",
"utmCampaign": "crm-demo",
"landingUrl": "https://example.com/demo"
}
}'
8. TypeScriptインターフェース
type LeadQuality = 'HOT' | 'WARM' | 'COOL' | 'COLD';
interface SiteLeadRequest {
externalId?: string;
lead: {
leadSourceId: string;
quality?: LeadQuality;
message?: string;
};
contact: {
firstName: string;
lastName?: string;
phone: string;
email?: string;
};
marketing?: {
occurredAt?: string;
visitorId?: string;
sessionId?: string;
source?: string;
channel?: string;
utmSource?: string;
utmMedium?: string;
utmCampaign?: string;
utmContent?: string;
utmTerm?: string;
gclid?: string;
fbclid?: string;
landingUrl?: string;
referrer?: string;
};
}
interface SiteLeadResponse {
leadId: string;
contactId: string;
phoneId: string;
emailId: string | null;
marketingEventId: string | null;
duplicate: boolean;
createdAt: string;
}
9. サーバーサイドの例
export async function sendLeadToCrm(payload: SiteLeadRequest): Promise<SiteLeadResponse> {
const response = await fetch(`${process.env.CRM_BASE_URL}/api/site/leads`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRM_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
if (!response.ok) {
const body = await response.text();
throw new Error(`ReactiveCRM returned ${response.status}: ${body}`);
}
return response.json() as Promise<SiteLeadResponse>;
}
10. エラー
| HTTP | 原因 | 統合者の対応 |
|---|---|---|
400 | 形式エラー、必須フィールド欠落、無効なメール/電話/quality | データを修正;変更なしで自動再試行しない |
401 | トークン欠落または無効 | 統合トークンを更新 |
403 | テナントまたは操作へのアクセス権なし | 統合ユーザーとロールを確認 |
404 | 現在のテナントにleadSourceIdが見つからない | サイト設定でソースIDを更新 |
409 | externalIdが互換性のないリクエストに既にリンクされている | ID生成と統合ログを確認 |
5xx | 一時的なCRMエラー | 同じexternalIdで同じリクエストを再試行 |
検証エラーの例:
{
"status": 400,
"error": "Bad Request",
"message": "contact.phone must not be blank",
"path": "/api/site/leads"
}
11. 冪等性
externalIdはテナントとwebsiteソース内で一意でなければなりません。externalIdを最初のリクエスト前に生成し、サイト送信に保存します。- タイムアウト時は、同じ本文と同じ
externalIdでリクエストを再試行します。 - 単一の送信を再試行する際に新しい
externalIdを作成しないでください。 duplicate: trueの場合、送信は既に処理されており、正常に配信されたと見なされます。
12. サイト開発者向けミニガイド
- 最初の訪問時に、UTMタグ、
gclid、fbclid、ランディングURL、リファラーを保存します。 - フォームが送信されたら、安定した
externalIdを生成します。 - フォームをサイトバックエンドに送信します。
- バックエンドがCRMトークンを追加し、
POST /api/site/leadsを呼び出します。 201または200でduplicate: trueの場合、送信は配信されたと見なします。- タイムアウトまたは
5xxの場合、同じexternalIdでリクエストを再試行します。 - CRMトークンをブラウザから直接送信しないでください。
13. CRMマネージャーが得るもの
成功したリクエスト後、CRMには次のリードが含まれます:
leadSourceIdソースが設定されている;- 訪問者のメッセージを保持;
- サイトが提供した場合、初期品質評価を持つ;
- 名前と主電話番号を持つ連絡先にリンク;
- 提供された場合、主メールアドレスにリンク;
- 分析用のUTMメトリクスと広告識別子を保持。
このセットは、マネージャーが送信を確認し、連絡先に電話し、リードを評価するのに十分です。
Reactive CRM