Reactive CRM 集成指南 ← 返回网站

ReactiveCRM 集成指南

为希望与 ReactiveCRM 构建自定义集成的公司(租户)提供的技术文档:导入线索和客户、创建交易、发送营销事件以及导出数据。

本文档仅涵盖外部集成中最常用的 API。内部参考数据和管理服务端点被有意排除在外。

1. 集成概述

典型的集成流程如下:

文本
您的系统(后端 / 服务端代理)
    |
    | 1. POST /api/auth/login  (获取访问 + 刷新令牌)
    v
ReactiveCRM
    | 2. 引用: GET /api/users/paged, GET /api/statuses, GET /api/stages, GET /api/lead-sources
    |    (获取 ownerId、authorId、statusId 等的 UUID)
    v
    | 3. 核心操作:
    |      POST /api/leads/create              — 创建线索
    |      POST /api/clients/create            — 创建客户
    |      POST /api/contacts/create           — 创建联系人
    |      POST /api/deals/create              — 创建交易
    |      POST /api/dashboard/marketing/events — 发送营销事件
    |      POST /api/leads/import/batch         — 批量导入线索
    v
    | 4. 读取 / 导出:
    |      GET /api/leads/paged                 — 带过滤器的分页读取
    |      GET /api/export/leads                — 所有线索的 NDJSON 导出

关键安全规则:绝不要从最终用户的浏览器直接调用 CRM API。将 CRM 令牌和内部标识符保存在您的后端(或 Serverless 函数)中。

2. 认证

2.1. 获取令牌

认证端点不需要令牌:

方法URL描述
POST/api/auth/login使用用户名 + 密码登录,返回访问 + 刷新令牌
POST/api/auth/refresh将刷新令牌交换为新的令牌对
POST/api/auth/logout撤销刷新令牌
bash
curl -X POST "$CRM_BASE_URL/api/auth/login" \
  -H "Content-Type: application/json" \
  -d '{"username": "integration", "password": "secret123"}'
json
{
  "token": "eyJhbGciOiJIUzI1NiJ9...",
  "refreshToken": "a8f3k2m9Qx7Tt1Vv...",
  "tokenType": "Bearer",
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "firstName": "集成",
    "lastName": "机器人",
    "tenantId": "660e8400-e29b-41d4-a716-446655440001"
  },
  "tenant": {
    "id": "660e8400-e29b-41d4-a716-446655440001",
    "name": "Zunga Corp"
  }
}

2.2. 令牌处理规则

2.3. 基础设置

文本
CRM_BASE_URL=https://crm.example.com

以下所有示例都假设使用这些头信息:

http
Authorization: Bearer <CRM_ACCESS_TOKEN>
Content-Type: application/json

3. 分页 API 约定

所有形式为 GET /api/*/paged 的列表端点都遵循相同的约定:

参数类型默认值描述
page整数0页码,从 0 开始
size整数每个端点不同页面大小
sort字符串createdAt,desc排序格式为 字段,方向。方向:asc 或 desc

分页响应结构

json
{
  "content": [ { "..." } ],
  "page": 0,
  "size": 20,
  "totalElements": 137,
  "totalPages": 7
}

日期过滤

使用 字段From / 字段To 参数进行范围过滤(ISO 8601):

文本
createdAtFrom=2026-01-01T00:00:00Z
createdAtTo=2026-01-31T23:59:59Z

排序

始终使用 ?sort=字段,方向:

文本
?sort=createdAt,desc
?sort=name,asc

某些过滤器字段有专用的范围参数(例如 dealAmountFrom/dealAmountTo)。

过滤语义

4. 引用(获取 UUID)

在创建实体之前,请获取相关引用数据的 UUID。主要引用包括:

4.1. 用户(GET /api/users/paged)

用于 ownerId、authorId、developingManagerIds。

bash
curl "$CRM_BASE_URL/api/users/paged?page=0&size=50&sort=createdAt,asc" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

响应示例(content 片段):

json
[
  {
    "id": "7a786a66-3617-48c1-921d-97f4aaefcd35",
    "firstName": "Roman",
    "lastName": "Posledovskiy",
    "username": "roman",
    "email": "roman@example.com",
    "tenantId": "660e8400-e29b-41d4-a716-446655440001"
  }
]

4.2. 状态(GET /api/statuses)

用于线索、交易和交易参与方客户的 statusId。返回一个数组:

bash
curl "$CRM_BASE_URL/api/statuses" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"
json
[
  {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "New",
    "entityType": "LEAD"
  },
  {
    "id": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
    "name": "In progress",
    "entityType": "STAGE"
  }
]

4.3. 阶段(GET /api/stages)

用于交易的 stageId:

bash
curl "$CRM_BASE_URL/api/stages" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

4.4. 线索来源(GET /api/lead-sources)

返回线索来源的树形结构。用于线索的 leadSourceId:

bash
curl "$CRM_BASE_URL/api/lead-sources" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"
json
[
  {
    "id": "cccc0001-0000-0000-0000-000000000001",
    "name": "Website",
    "children": [
      {
        "id": "cccc0001-0000-0000-0000-000000000002",
        "name": "Feedback form",
        "children": []
      }
    ]
  }
]

5. 线索

5.1. 创建线索(POST /api/leads/create)

bash
curl -X POST "$CRM_BASE_URL/api/leads/create" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "网站咨询:咨询",
    "ownerId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
    "authorId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
    "leadSourceId": "cccc0001-0000-0000-0000-000000000002",
    "statusId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "quality": "WARM"
  }'

请求字段:

字段类型必填描述
message字符串否消息 / 咨询文本
ownerIduuid是负责用户
authorIduuid是创建线索的用户
clientIduuid否关联客户
contactIduuid否关联联系人
leadSourceIduuid否线索来源树节点
statusIduuid否状态
quality枚举否HOT、WARM、COOL、COLD

201 Created 响应示例:

json
{
  "id": "22222222-2222-2222-2222-222222222222",
  "message": "网站咨询:咨询",
  "status": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "New"
  },
  "quality": "WARM",
  "dealId": null,
  "createdAt": "2026-09-05T20:00:00Z",
  "updatedAt": "2026-09-05T20:00:00Z",
  "version": 0,
  "author": {
    "id": "7a786a66-3617-48c1-921d-97f4aaefcd35",
    "firstName": "Roman",
    "lastName": "Posledovskiy"
  },
  "owner": {
    "id": "7a786a66-3617-48c1-921d-97f4aaefcd35",
    "firstName": "Roman",
    "lastName": "Posledovskiy"
  }
}

请保留返回的 id — 营销事件的 leadId 需要用到它(参见第 8 节)。

5.2. 分页读取(GET /api/leads/paged)

bash
curl "$CRM_BASE_URL/api/leads/paged?page=0&size=20&createdAtFrom=2026-09-01T00:00:00Z&sort=createdAt,desc" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

关键过滤器:

参数类型模式描述
statusIduuid精确按状态过滤
leadSourceIduuid精确按线索来源过滤
quality枚举精确HOT、WARM、COOL、COLD
message字符串ILIKE消息中的子字符串
search字符串ILIKE(OR)跨消息、联系人、邮箱、电话搜索
contactEmail字符串ILIKE按联系人邮箱
contactPhone字符串ILIKE按联系人电话
company字符串ILIKE按公司名称
clientIduuid精确按客户 ID
createdAtFrom / createdAtTo日期-时间范围按创建日期
updatedAtFrom / updatedAtTo日期-时间范围按更新日期
createdByuuid精确按线索作者

还有关联交易的过滤器:dealStatusId、dealStageId、dealAmountFrom/dealAmountTo、dealProbabilityFrom/dealProbabilityTo。

排序:createdAt、updatedAt、message、quality、状态/来源等(字段,方向 格式)。

5.3. 获取单个线索(GET /api/leads/{id})

bash
curl "$CRM_BASE_URL/api/leads/$LEAD_ID" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

5.4. 批量导入线索(POST /api/leads/import/batch)

如需批量导入大量线索,请使用批处理端点。它接受一个线索数组,创建导入历史记录,并允许回滚整个导入。

bash
curl -X POST "$CRM_BASE_URL/api/leads/import/batch" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fileName": "leads-2026-09-05.csv",
    "leads": [
      {
        "message": "咨询 #1",
        "ownerId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
        "authorId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
        "quality": "WARM"
      },
      {
        "message": "咨询 #2",
        "ownerId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
        "authorId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
        "quality": "COOL"
      }
    ]
  }'

响应示例:

json
{
  "importId": "44444444-4444-4444-4444-444444444444",
  "imported": 2,
  "total": 2,
  "skipped": []
}

历史记录与回滚:

bash
# 导入历史
curl "$CRM_BASE_URL/api/leads/import/history" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

# 回滚导入
curl -X POST "$CRM_BASE_URL/api/leads/import/rollback/$IMPORT_ID" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

5.5. 快速网站线索(POST /api/site/leads)

对于网站表单,有一个组合端点,可在一次请求中原子性地创建联系人、其主要电话和邮箱、线索、联系人-线索关联以及营销事件 — 通过 externalId 实现幂等性。

请参阅专门指南:site-lead-multi-contract.md。

6. 客户与联系人

6.1. 创建客户(POST /api/clients/create)

bash
curl -X POST "$CRM_BASE_URL/api/clients/create" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "COMPANY",
    "name": "Romashka LLC",
    "taxId": "7700000001",
    "regNumber": "1234567890",
    "country": "RU",
    "phone": "+7-495-000-00-01",
    "email": "info@romashka.ru",
    "website": "https://romashka.ru",
    "ownerId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
    "authorId": "7a786a66-3617-48c1-921d-97f4aaefcd35"
  }'

关键字段:

字段类型适用对象描述
type枚举全部INDIVIDUAL 或 COMPANY(必填)
name字符串全部显示名称(必填)
firstName / lastName字符串INDIVIDUAL名/姓
taxId字符串COMPANY税号(INN)
regNumber字符串COMPANY注册号
legalAddress字符串COMPANY法定地址
phone / email / website字符串全部联系方式
country字符串全部ISO 国家代码
ownerIduuid全部负责用户
authorIduuid全部作者
developingManagerIdsuuid[]全部开发经理

6.2. 分页读取客户(GET /api/clients/paged)

bash
curl "$CRM_BASE_URL/api/clients/paged?page=0&size=20&type=COMPANY&search=Romashka&sort=name,asc" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

关键过滤器:name、type(INDIVIDUAL/COMPANY)、country、taxId、email、phone、lastName(个人)、search(按名称/税号/电话)、createdAtFrom/createdAtTo、createdBy、developingManagerId。

6.3. 重复检查(GET /api/clients/duplicates)

在创建客户之前,检查是否已存在相似客户:

bash
# 按税号和名称
curl "$CRM_BASE_URL/api/clients/duplicates?type=COMPANY&taxId=7700000001&name=Romashka" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

6.4. 创建联系人(POST /api/contacts/create)

bash
curl -X POST "$CRM_BASE_URL/api/contacts/create" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "Ivan",
    "lastName": "Petrov",
    "dateOfBirth": "1990-05-15",
    "gender": "MALE",
    "countryCode": "RU",
    "ownerId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
    "authorId": "7a786a66-3617-48c1-921d-97f4aaefcd35"
  }'

字段:firstName(必填)、lastName、patronymicName、dateOfBirth(date)、gender(MALE/FEMALE)、countryCode、ownerId、authorId。

6.5. 分页读取联系人(GET /api/contacts/paged)

bash
curl "$CRM_BASE_URL/api/contacts/paged?page=0&size=20&search=Petrov&sort=createdAt,desc" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

7. 交易

7.1. 创建交易(POST /api/deals/create)

bash
curl -X POST "$CRM_BASE_URL/api/deals/create" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "服务器硬件交付",
    "clientId": "9f128931-69fd-493a-9a08-be5be0e6603d",
    "statusId": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
    "stageId": "dddd0001-0000-0000-0000-000000000001",
    "probability": 60,
    "amount": 150000.00,
    "ownerId": "7a786a66-3617-48c1-921d-97f4aaefcd35",
    "authorId": "7a786a66-3617-48c1-921d-97f4aaefcd35"
  }'

关键字段:

字段类型必填描述
name字符串是交易名称
clientIduuid是客户 ID
statusIduuid否状态(阶段状态)
stageIduuid否销售阶段
probability整数否概率 0-100
amount数字否金额
plannedAmount数字否计划金额
discountPercent整数否折扣 0-100
startDate / expectedCloseDate日期-时间否日期
ownerIduuid否所有者
leadIduuid否关联线索
contactIduuid否关联联系人
productIdsuuid[]否产品(简化格式)
dealProducts数组否交易行项目(完整格式)
dealParties数组否交易参与方

7.2. 分页读取交易(GET /api/deals/paged)

bash
curl "$CRM_BASE_URL/api/deals/paged?page=0&size=20&stageKind=OPEN&sort=createdAt,desc" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

关键过滤器:name(ILIKE)、clientId、clientName、statusId、stageId、stageKind(OPEN/WON/LOST)、ownerId、search、startDateFrom/startDateTo、expectedCloseDateFrom/expectedCloseDateTo、actualCloseDateFrom/actualCloseDateTo、createdAtFrom/createdAtTo。

8. 营销事件(归因)

要发送 UTM 标签、广告标识符和流量来源,请使用:

POST /api/dashboard/marketing/events

bash
curl -X POST "$CRM_BASE_URL/api/dashboard/marketing/events" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "eventType": "lead_submitted",
    "occurredAt": "2026-09-05T20:00:00Z",
    "visitorId": "visitor-8b7f",
    "sessionId": "session-31ac",
    "leadId": "22222222-2222-2222-2222-222222222222",
    "externalId": "site-form-submit-20260905-000123",
    "source": "website",
    "channel": "paid",
    "utmSource": "google",
    "utmMedium": "cpc",
    "utmCampaign": "summer-consulting",
    "utmContent": "banner-a",
    "utmTerm": "crm consultation",
    "gclid": "EAIaIQobChMI-example",
    "landingUrl": "https://www.example.com/consultation",
    "referrer": "https://www.google.com/",
    "metadata": {
      "formName": "consultation",
      "pageType": "landing"
    }
  }'

响应示例:

json
{
  "accepted": true,
  "duplicate": false,
  "eventId": "33333333-3333-3333-3333-333333333333"
}

规则:

详情请参见 site-leads-integration-guide.md。

9. 数据导出(NDJSON)

导出端点以 NDJSON 格式返回租户的所有记录(每行一个 JSON 对象,以 \n 分隔)。

端点描述
GET /api/export/leads所有租户线索
GET /api/export/clients所有租户客户
GET /api/export/contacts所有租户联系人
bash
curl "$CRM_BASE_URL/api/export/leads" \
  -H "Authorization: Bearer $CRM_ACCESS_TOKEN"

响应示例(行流):

文本
{"id":"550e8400-e29b-41d4-a716-446655440001","message":"网站咨询","quality":"WARM","statusName":"New","createdAt":"2026-08-20T10:00:00+03:00","ownerName":"Ivan Ivanov","clientName":"Romashka LLC","contactFirstName":"Petr","contactLastName":"Petrov","leadSourceName":"Paid search"}
{"id":"550e8400-e29b-41d4-a716-446655440002","message":"电话","quality":"COOL","statusName":"In progress","createdAt":"2026-08-19T09:00:00+03:00","ownerName":"Maria Smirnova","clientName":null}

重要:NDJSON 不是有效的 JSON 数组。请通过 ReadableStream 逐行读取响应(不要对整个响应调用 JSON.parse())。

10. 端到端集成示例

以下场景创建了一个网站线索,关联了联系人和客户,创建了交易,并发送了营销事件。

bash
CRM_BASE_URL=https://crm.example.com
CRM_TOKEN="<access-token>"

# 1. 登录
curl -s -X POST "$CRM_BASE_URL/api/auth/login" \
  -H "Content-Type: application/json" \
  -d '{"username": "integration", "password": "secret123"}' | tee /tmp/login.json

CRM_TOKEN=$(jq -r '.token' /tmp/login.json)

OWNER_ID=$(curl -s "$CRM_BASE_URL/api/users/paged?page=0&size=50" \
  -H "Authorization: Bearer $CRM_TOKEN" | jq -r '.content[0].id')

# 2. 创建客户
curl -s -X POST "$CRM_BASE_URL/api/clients/create" \
  -H "Authorization: Bearer $CRM_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"type\": \"COMPANY\",
    \"name\": \"Romashka LLC\",
    \"taxId\": \"7700000001\",
    \"country\": \"RU\",
    \"ownerId\": \"$OWNER_ID\",
    \"authorId\": \"$OWNER_ID\"
  }" | tee /tmp/client.json

CLIENT_ID=$(jq -r '.id' /tmp/client.json)

# 3. 创建联系人
curl -s -X POST "$CRM_BASE_URL/api/contacts/create" \
  -H "Authorization: Bearer $CRM_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"firstName\": \"Ivan\",
    \"lastName\": \"Petrov\",
    \"countryCode\": \"RU\",
    \"ownerId\": \"$OWNER_ID\",
    \"authorId\": \"$OWNER_ID\"
  }" | tee /tmp/contact.json

CONTACT_ID=$(jq -r '.id' /tmp/contact.json)

# 4. 创建线索
curl -s -X POST "$CRM_BASE_URL/api/leads/create" \
  -H "Authorization: Bearer $CRM_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"message\": \"网站咨询\",
    \"clientId\": \"$CLIENT_ID\",
    \"contactId\": \"$CONTACT_ID\",
    \"ownerId\": \"$OWNER_ID\",
    \"authorId\": \"$OWNER_ID\",
    \"quality\": \"WARM\"
  }" | tee /tmp/lead.json

LEAD_ID=$(jq -r '.id' /tmp/lead.json)

# 5. 创建关联线索的交易
curl -s -X POST "$CRM_BASE_URL/api/deals/create" \
  -H "Authorization: Bearer $CRM_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"name\": \"为 Ivan Petrov 提供咨询\",
    \"clientId\": \"$CLIENT_ID\",
    \"leadId\": \"$LEAD_ID\",
    \"contactId\": \"$CONTACT_ID\",
    \"amount\": 50000.00,
    \"ownerId\": \"$OWNER_ID\",
    \"authorId\": \"$OWNER_ID\"
  }"

# 6. 发送营销事件
curl -s -X POST "$CRM_BASE_URL/api/dashboard/marketing/events" \
  -H "Authorization: Bearer $CRM_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"eventType\": \"lead_submitted\",
    \"occurredAt\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",
    \"leadId\": \"$LEAD_ID\",
    \"externalId\": \"request-$(uuidgen)\",
    \"source\": \"website\",
    \"channel\": \"direct\",
    \"landingUrl\": \"https://www.example.com/form\",
    \"metadata\": {\"formName\": \"consultation\"}
  }"

11. 幂等性与错误处理

12. 快速开始

  1. 认证:通过 POST /api/auth/login 进行认证;保存 token 和 refreshToken。
  2. 添加:在每个请求中添加 Authorization: Bearer <token>。遇到 401 时,通过 /api/auth/refresh 刷新。
  3. 获取引用:一次获取引用(用户/状态/阶段/线索来源)并缓存 UUID。
  4. 创建实体:按逻辑顺序创建:客户 → 联系人 → 线索 → 交易。
  5. 使用分页端点:进行带服务端过滤和排序的读取。
  6. 导出:使用 NDJSON 端点并逐行读取流。
  7. 批量导入:使用批处理端点(/api/leads/import/batch、/api/clients/import/batch)并支持回滚。
  8. 发送营销归因:通过 POST /api/dashboard/marketing/events 并使用稳定的 externalId。
  9. 绝不存储 或在营销事件的 metadata 中传递 PII。
  10. 查看各 API 的详细文档:site-leads-integration-guide.md。