Keybe/开发者/CRM 对接协议

CRM 对接协议

BIKY.ai 如何对接您的 CRM 或 DMS:对接方式、字段映射、同步与查重、需要您提供的信息、常见错误与经验总结。

BIKY.ai 可与每个品牌或经销商的 CRM 或 DMS 对接。它会把来自任何渠道的每一条线索推送过去,同步跟进进展(视 CRM 而定,可实时同步,也可在会话结束时同步),并接收顾问在 CRM 中所做的修改。一切都以 SalesCard 为核心:这是 BIKY.ai 中的一条记录,保存线索本身、线索在 Funnel(漏斗)中所处的阶段,以及 CRM 为其分配的 ID。本协议汇总了我们在拉丁美洲完成十五个以上集成项目所积累的经验。

对接方式

共有三种路径,一个 CRM 可以组合使用:您的 CRM 通过 webhook 通知我们;BIKY.ai 调用其 API 查询;进展更新也通过同一个 API 回传。CRM 返回的每个 ID 都会保存在 SalesCard 或联系人上,这样下一次事件发生时会更新原有记录,而不会重复创建。

认证方式由您的 CRM 决定:通过关联应用(connected app)的 OAuth2 client_credentials、由管理员用户授权的 OAuth2、短时效令牌、API 密钥或 Basic Auth。接收 webhook 时,每个流程使用一个带令牌的专属 URL。您还可以启用请求体加密;对于会发送 HMAC 签名的平台,Flows 会校验该签名。网页表单和线索供应商也通过这种方式接入,Meta 表单则作为又一个渠道进入。

此外还有三种变体。部分集成运行在集成平台(iPaaS)上,使用由客户管理员用户授权的 OAuth2 连接器。当 CRM 没有 API,或 API 无法覆盖某个流程时,由机器人(RPA)使用客户分配的账号操作其网页门户。如果您的系统不在本文档之列,BIKY.ai 可以将 SalesCard 的每一次变更发送到您提供的 webhook。

反向调用同样可行:您的 CRM 可以使用您的账户密钥调用 BIKY.ai API,从而创建或查询联系人(按电话、邮箱或 ID),并创建、查询 SalesCard,或在 Funnel 的各阶段之间移动 SalesCard。示例请见 Keybe Postman 集合。该 API 的字段、取值范围和示例详见“API 字段与结构”一节。

CRM 集成

所有数据均通过 HTTPS 传输。不同 CRM 之间有三点差异:由谁发起调用、如何认证、用哪个标识符防止重复。以下是我们积累经验最多的几个集成。

Sale U

  • 对接与认证:入站通过 webhook 推送到带令牌的专属 URL。出站通过 REST API,使用 API 密钥,并在请求体中附带密钥(secret)和时间戳。
  • 传输哪些数据:入站为已分配的线索:姓名、电话、邮箱、经销店、车型和潜客 ID。出站为每一项活动:状态、预约、跟进备注、锁定或释放、意向温度以及结案。
  • 方向与频率:实时。视经销店而定,可双向同步,也可仅从 BIKY.ai 同步到 Sale U。每家经销店都需获得供应商授权。
  • 如何防止重复:按电话查找联系人,按潜客 ID 查找 SalesCard。如果 Sale U 重复推送同一条线索,则更新已有记录。

Salesforce

  • 对接与认证:REST API(标准对象或客户自有的 Apex),有时位于客户的集成层之后。认证方式为通过关联应用的 OAuth2 client_credentials、由管理员用户授权的 OAuth2,或 Basic Auth。
  • 传输哪些数据:出站为线索,包括联系人、车型、来源、经销店和销售顾问,随后是状态和预约。入站为已赢单或已开票的商机。
  • 方向与频率:出站在会话结束、预约创建以及每次状态变更时触发。入站通过定期执行 SOQL 查询(例如每小时一次),按最后修改日期筛选。
  • 如何防止重复:线索 ID 保存在联系人上,后续推送会更新该线索。如果 CRM 自身也做查重,则遵循其规则。

Seekop / SICOP

  • 对接与认证:机器人(RPA)使用每家经销店的账号操作门户。如果经销店开通了 API 权限,则使用 ADF 格式的 REST API 和 API 密钥。
  • 传输哪些数据:入站为 CRM 待处理队列中的线索。出站为线索记录上的跟进信息;通过 API 时,推送潜客(联系人、车型、来源和备注)及其所属经销店,以及预约。
  • 方向与频率:使用机器人时为双向:每隔几分钟读取一次队列,并在线索记录上登记跟进。使用 API 时,在会话结束和预约创建时从 BIKY.ai 推送到 Seekop。
  • 如何防止重复:机器人使用线索在 CRM 中的 ID,并为每个操作设置幂等键。使用 API 时,联系人会被标记为“已发送”。

HubSpot

  • 对接与认证:Flows 连接器,使用由客户用户授权的 OAuth2;部分情况下使用 webhook 或 iPaaS。
  • 传输哪些数据:出站为联系人,视情况还包括约定管道中的一笔交易(deal)。已设计入站同步方案,用于同步进入赢单阶段的交易。
  • 方向与频率:出站在会话结束时或每次购买时触发。已设计通过定期轮询实现入站同步。
  • 如何防止重复:对联系人执行 upsert。已设计在 BIKY.ai 中保存其 ID 并据此匹配的方案。

Microsoft Dynamics 365

  • 对接与认证:由客户或其集成商发布在 API 网关之后的 OData API,请求头中携带订阅密钥。
  • 传输哪些数据:出站为线索及其所属营销活动;预约会被创建和更新。
  • 方向与频率:从 BIKY.ai 到 Dynamics,在会话结束时及每次预约事件发生时触发。
  • 如何防止重复:只推送新线索,不推送修改。预约 ID 保存在联系人上,后续变更都作用于该预约。

主机厂 CRM

  • 对接与认证:JSON REST API,使用短时效令牌;订单以 multipart 方式附带 PDF。不支持 webhook:由专门的服务轮询 API。API 未覆盖的部分由机器人在门户上处理。
  • 传输哪些数据:入站为各经销店的线索及其状态变更。出站包括创建我方线索、跟进、试驾以及预售订单。
  • 方向与频率:入站每分钟轮询一次,并遵守同一经销商两次轮询之间的最小间隔;出站在每次 SalesCard 事件时触发。
  • 如何防止重复:线索编码保存在 SalesCard 上;创建线索时以 SalesCard ID 作为幂等键。

我们完成过的其他集成

其中部分已无活跃账户,但可以重新实施。

系统类型对接方式与数据
Tecnom汽车行业 CRM以 ADF 格式通过 POST 将线索推送到其网页连接器,使用用户名和密码认证。
Syonet 360汽车行业 CRMCRM 通过 webhook 推送线索;BIKY.ai 通过使用 Basic Auth 的 REST API 登记来电、到店和预约。
IntelisisDMSDMS 调用 BIKY.ai API,按 ID 读取联系人和 SalesCard。
Total Dealer售后服务 DMS预约 API。
UpnifyCRM用于潜客和预约的 REST API,所用令牌仅有创建记录的权限。
OdooCRM 与 ERP创建联系人和商机,并附带其 UTM 参数。
Zoho CRMCRM使用 OAuth2 并支持令牌刷新的连接器;Zoho 通过 webhook 发送通知。
RD Station CRMCRMFlows 连接器:创建交易,并在其漏斗各阶段之间移动。
SmarthomeCRM支持读写的 REST API。
ComunikeCRMWebhook。
SICO房地产 CRM出站通过 REST API,凭用户名和密码换取有效期一小时的令牌。
Wasi房地产 CRM将房源库存同步到 BIKY.ai 产品目录。

Flows 还内置了对接 Siigo、Alegra、Defontana 等 ERP 以及一款售后服务 DMS(预约排程)的节点。在线商店(Shopify、VTEX 和 WooCommerce)会与 BIKY.ai 同步产品目录和联系人,并发送弃购、付款和订单变更通知。这些连接器以及支付、物流相关连接器,均列在集成页面上。

数据映射

开发之前,双方会逐个字段确认映射关系;每个封闭列表(来源、车型、经销店、状态)都有各自的对照表。

BIKY.ai 数据CRM 常见字段映射规则
名和姓名、姓部分来源会把全名放进“姓”字段:发送前会先拆分。如果 CRM 要求必填“姓”而 BIKY.ai 中没有,需提前约定填写内容。
手机号码手机带国家代码(墨西哥为 52 加 10 位号码),除非 CRM 或对象要求使用本国号码格式。如果号码分散在多个字段中,需提前约定组合方式。只有在来源能保证国家代码正确时,才会补全国家代码。
邮箱邮箱选填,除非对象要求必填。如果 CRM 会校验格式,则空值不发送;部分 CRM 不接受重音字符或 ñ。
渠道与营销活动(UTM)来源、营销活动转换为 CRM 的来源目录;没有对应项的归入“其他”。每个值填入各自的字段,不做拼接。
意向产品或车型车型、配置使用对照表,并把 CRM 编码保存在产品上:按名称匹配会出错。如果该字段必填,需约定一个默认值。
经销店经销商或门店编码经销店 → 编码对照表,依据 BIKY.ai 中已配置的经销店进行校验,而不是依据商用名称。
负责的销售顾问负责人或顾问顾问在 CRM 中的 ID,需预先导入 BIKY.ai。如果 CRM 按自身规则分配,则不发送该字段。
Funnel 阶段状态或阶段双向对照表(示例见下文)。
预约或试驾预约、事件严格按照 CRM 要求的时区和格式,包含开始和结束时间。每个预约的 ID 都会保存,以便后续更新。
CRM 中的记录 ID不适用保存在联系人或 SalesCard 上,是每次更新的关键标识。
各字段长度不适用开发前确认每个字段的最大长度:超长的 ID、文本或电话号码会被拒绝。

状态与 Funnel 各阶段一一对应。在汽车行业账户中,销售漏斗(Sales Funnel)默认包含以下九个阶段。各阶段的显示名称可能因账户而异;但键值不变,API 使用的正是这个键值。

销售漏斗阶段由谁推动 SalesCard在 CRM 中如何体现
未回复($step_mql$)线索到达时,无论来自任何渠道还是 CRM,都会在此阶段创建 SalesCard。新线索,已分配或未分配。
已回复 MQL($step_responded_mql$)BIKY.ai,在客户回复时推动。首次接触记录为一次跟进。
有意向(SQL)($step_sql$)BIKY,在客户通过资格评估时推动;或 CRM,在其将线索标记为跟进中时推动。跟进中。
已预约($step_scheduling$)BIKY 或顾问,在预约确定时推动。已创建预约或活动。
到店($step_show$)BIKY。预约时间过后一小时,它会向客户和顾问发送 WhatsApp 模板消息,询问客户是否到店,并根据回复推动 SalesCard。已记录到店。
试驾($step_test_drive$)BIKY,在该模板的回复表明已完成试驾时推动。已记录试驾。
预售($step_won$)顾问,填写产品、金额和日期后推动;或 CRM,在其报告该商机已赢单时推动。仍为跟进中;若对接厂商 CRM,则发送预售订单。
已开票($step_billed$)顾问。若对接厂商 CRM,则由 CRM 在标记成交时推动。销售完成。若对接厂商 CRM,BIKY.ai 不会发送此状态,因为它在厂商 CRM 中不可撤销。
已流失($step_lost$)顾问,注明原因后推动;或 CRM,在其将线索标记为流失时推动。已流失,并附原因。

被 CRM 标记为无效的线索不会推动 SalesCard:系统只保存其状态,因为这并不是一笔流失的销售。汽车行业账户还包含售后漏斗(已确认、已接车、诊断、审批、维修中、交车、付款、回访和未批准),需要时可映射到维修车间的 DMS。

同步与重复数据

出站数据根据 CRM 的不同,实时传输或在对话结束时传输。入站数据在 CRM 提供 webhook 时通过 webhook 接收;否则通过定期轮询获取,频率从每分钟一次到每小时一次不等。所有 CRM 集成均不使用 SFTP 或自动文件交换。

以下情况会触发向 CRM 推送数据:

  • 创建 SalesCard:在 CRM 中创建线索,包含联系人、来源、车型和经销店。
  • 顾问或 BIKY 发起联系(电话、邮件或 WhatsApp):生成一条跟进记录。
  • 漏斗中的阶段变更:推送新状态。
  • 预约的创建、改期或取消:推送预约或试驾信息。
  • 对话结束:推送包含完整数据及状态的线索。

历史数据仅通过 CRM 的 API 一次性导入,不会触发任何消息或流程,并保留每条线索的原始日期。

防重复规则:

  1. CRM 返回的每个 id 都会存储在 BIKY.ai 中,后续事件会更新该记录,而不是新建一条。
  2. 入站数据必须具备幂等性:相同的线索 id 或重复的同一事件,只会更新已有的 SalesCard。CRM 会重试,而重试不能再新开一张 SalesCard。
  3. 创建联系人之前,先按标准化后的电话号码进行查找。如果 CRM 自带去重机制,则遵循其规则,并存储其返回的 id。
  4. 在销售漏斗中已有未关闭 SalesCard 的人,不会再新开一张。如果是不同的意向,且 CRM 将其记录为独立线索,则会新开。
  5. 线索只通过单一路径进入。如果某个表单同时向 BIKY.ai 和 CRM 提交数据,同一条线索就会被创建两次。
  6. 与客户确认其 CRM 是否每次推送都会新建记录。在得到答复之前,只发送新记录,不发送修改。

我们需要什么,以及需要多长时间

开发通常是最快的环节,真正决定周期的是资料提供和审批。在我们 2025 年和 2026 年的项目中,接入已连接 CRM 的经销店,有一半在提出申请后不到两周即准备就绪。全新的集成耗时中位数为五周,不含商务阶段。

最容易拖慢项目的因素:无法使用的凭证、与生产环境不一致的沙盒、迟迟未到的目录数据、保密协议、品牌方或 CRM 供应商的审批,以及每家经销店的 WhatsApp 号码。以下是按阶段列出的清单。

0. 开始之前

  • 保密协议,以及贵公司要求的其他法律文件。
  • 安全审查(如适用):我们已获得 ISO/IEC 27001 认证。
  • 如有要求,需获得品牌方或 CRM 供应商对每家经销店的审批。

1. 需求调研

  • 最新的 API 文档:对象、必填字段、各列表(picklist)的允许值、错误代码及调用频率限制。
  • CRM 是通过 webhook 发送通知,还是需要轮询。
  • 需要同步哪些对象(线索、联系人、商机、预约),以及每个字段由哪一方负责。
  • 贵方 CRM 在每次提交时是新建记录,还是更新已有记录。
  • 贵方 CRM 是否也通过自有表单收集线索,以及两者中以哪一方为准。
  • 客户方或其集成商的一名技术负责人。

2. 字段映射

  • 来源和状态目录及其代码,以及哪些状态为终态。
  • 车型或产品清单及其代码,以及该字段为必填时的默认值。
  • 经销店或分支机构在 CRM 中的代码。
  • 顾问 ID(如果 CRM 需要知道由谁跟进线索)。
  • 每个字段的最大长度和格式,包括电话号码。
  • CRM 自身的规则:去重、校验和自动分配。

3. 测试环境

  • 沙盒:凭证有效,且版本、参考数据和经销店均与生产环境一致。
  • 集成凭证:每个环境一个,并对我们需要写入的对象具备权限,形式为连接应用(OAuth2 client_credentials)或技术用户。
  • 事先约定的测试线索:在生产环境中测试会在贵方 CRM 中生成真实记录。

4. 上线与监控

  • 通过双方约定的安全渠道提供生产环境凭证,切勿通过邮件、聊天工具或工单发送。
  • 在轮换或停用凭证前提前告知。
  • 每家经销店的 WhatsApp 号码、其顾问的 ID,以及按经销商集团划分的上线计划。
  • 一名事故处理联系人。

常见错误与监控

几乎所有拒绝都源于数据,而非网络:必填字段为空、格式不被 CRM 接受,或是 CRM 特有的规则。这类错误不会重试,因为重试只会以同样的方式再次失败。我们的做法是修正数据或规则,然后重新发送事件。

错误常见原因我们的处理方式
CRM 返回 200 但实际拒绝拒绝原因写在响应正文中;还有些 CRM 对重复数据返回 201。必须校验响应正文,而不仅是 HTTP 状态码。Flows 会将带有 success: false 的 200 标记为失败;如果 CRM 使用其他错误标识,则在流程内部进行校验。
必填字段为空线索缺少意向车型、产品或邮箱。发送前进行校验,并使用事先约定的默认值。规则过严(例如没有邮箱就不发送)可能会拦下所有线索。
字段超出允许长度id、文本或电话号码超出 CRM 字段长度。在字段映射阶段确认每个字段的长度。
CRM 新增校验CRM 在未通知的情况下开始要求某个字段或格式。当拒绝数量上升时,我们会检查 CRM 发生了哪些变化。
经销店缺少代码线索来自不在对照表中的经销店。每家经销店启用前,先校验对照表。
电话号码无效国家代码重复、多出一个 1,或号码被截断。发送前进行标准化;无法修复的号码标记为无效,不予发送。
日期或时间被拒绝时区、格式问题,或试驾被标记为“已完成”但时间却在未来。采用 CRM 要求的准确时区和格式,并在发送前校验。
凭证过期或已轮换令牌过期,或凭证在轮换过程中被停用。在令牌过期前使用其 refresh token 续期,或重新申请。
请求过多(429)定期查询超出 CRM 的调用限制。为每个经销商设置查询的最小间隔。
CRM 宕机或响应缓慢5xx 错误或超时。专用服务和机器人会以递增的退避间隔进行重试。在 Flows 中,重试按流程单独启用,因为如果 CRM 不具备幂等性,重试可能产生重复数据。
CRM 特有规则客户自定义的校验,例如不允许重新分配负责人。调整提交内容以符合规则,例如交由 CRM 分配负责人。

我们如何监控:

  • 每次执行都会记录在历史中,包括 CRM 节点中发送的数据。
  • 在使用专用服务的集成和机器人中,监控程序每 5 分钟检查一次。它按原因对每次失败进行分类,在看板上展示,并且只针对严重和反复出现的问题发送邮件告警。
  • 每家经销店启用后的头几天,我们会密切跟进。此后,一旦出现投诉,我们会将 CRM 中的线索与 SalesCard 及 BIKY.ai 对话进行核对。

经验总结

几乎所有失败都可以归结为四条规则:存储外部 id;校验每次响应的正文;在开发前确认字段和目录;每家经销店启用前,先用测试线索进行测试。

  • Sale U. 同一条线索多次到达,每次重发都会新开一张 SalesCard。
    • 我们做了哪些调整:清理了重复的 SalesCard,入站流程现在会先按潜在客户 id 查找 SalesCard,再决定是否新建。
    • 如果重来,我们会怎么做:将 SalesCard 与潜在客户 id 关联。
  • Sale U. CRM 开始校验以前接受的字段,旧流程在我们未做任何改动的情况下出现失败。
    • 我们做了哪些调整:修正了受影响流程中的字段。
    • 如果重来,我们会怎么做:当某个集成的拒绝数量上升时发出告警。
  • Sale U. 新经销店没有分配规则,因此其线索被退回 CRM,无人跟进。
    • 我们做了哪些调整:每次开通新账户时,都会复核经销店对照表。
    • 如果重来,我们会怎么做:每家经销店启用前,先用测试线索进行测试。
  • Salesforce. 大量线索因必填字段为空而被拒绝,这个字段就是意向车型。
    • 我们做了哪些调整:向客户索取了 CRM 的完整文档:必填字段、各列表(picklist)的允许值以及目录。
    • 如果重来,我们会怎么做:在启用前约定好默认值。
  • Salesforce. CRM 的一条规则阻止了负责人的重新分配,而这一拒绝在 BIKY.ai 中无法看到。
    • 我们做了哪些调整:通过连接器日志找到了原因。
    • 如果重来,我们会怎么做:记录每一次拒绝,并在需求调研阶段询问校验规则。
  • Salesforce. 赢单查询按创建日期筛选,因此几乎查不到任何数据。它还把售后漏斗中的 SalesCard 推到了销售漏斗的赢单阶段($step_won$)。
    • 我们做了哪些调整:查询现在使用商机的最后修改日期,并按销售漏斗进行筛选。
    • 如果重来,我们会怎么做:启用前,先用六个月的历史数据测试该查询。
  • Salesforce。Meta 表单同时向 BIKY.ai 和 CRM 推送数据,导致每条线索都被创建了两次。
    • 我们的调整:线索现在只通过 CRM 进入。
    • 如果重来,我们会:在需求调研阶段就确定唯一的数据入口。
  • Seekop。将一个账户拆分为按经销店划分的多个账户后,按经销店名称进行的路由不再匹配,部分线索始终没有发送出去。
    • 我们的调整:采用统一的共享模板,各经销店的数据存放在环境变量中,并在同一步骤中关闭原有集成。
    • 如果重来,我们会:绝不依据客户可以修改的名称进行路由。
  • HubSpot。成交交易的匹配只覆盖了少数情况:联系人上没有存储 HubSpot id,而按邮箱查找又会产生误匹配。
    • 我们的调整:我们将匹配逻辑设计为只使用 id,并以完全一致的电话号码作为备用方案。
    • 如果重来,我们会:从第一次发送起就存储外部 id。
  • Zoho。由于令牌没有刷新,访问权限每小时就会过期一次。
    • 我们的调整:改用能够自动刷新令牌的连接器。
    • 如果重来,我们会:始终使用刷新令牌(refresh token),或使用能自动处理刷新的连接器。
  • Dynamics 365。订阅密钥放在了 URL 中,但网关要求将其放在请求头中。此外,CRM 中有一个字段的长度比我们的 id 短。
    • 我们的调整:密钥现在放在请求头中,客户也加长了该字段。
    • 如果重来,我们会:在字段映射阶段检查请求头和字段长度。
  • 多个系统。部分 CRM 要求提供 BIKY.ai 并不总能获得的数据,例如位数完全符合要求的电话号码、姓氏或产品。曾有一条这样的规则导致某个客户的所有线索都被拦截。
    • 我们的调整:我们在需求调研阶段就询问这些规则。
    • 如果重来,我们会:在启用每条规则之前,先用真实数据测算有多少线索符合该规则。
  • 主机厂 CRM。将一笔销售标记为已成交后,该线索会在 CRM 中被永久冻结。
    • 我们的调整:BIKY.ai 从不发送该状态,只读取它。
    • 如果重来,我们会:在需求调研阶段询问哪些状态是不可逆的。
  • 主机厂 CRM。CRM 凭证的一次变更导致线索接入中断。
    • 我们的调整:当查询在一段时间内反复失败时触发告警。
    • 如果重来,我们会:约定每次变更都须提前通知,并通过安全渠道交付新凭证。
  • 主机厂 CRM。沙盒环境中没有该项目经销商的数据,而且会接受生产环境拒绝的值。
    • 我们的调整:我们在沙盒中验证每一个字段,再到生产环境中确认。
    • 如果重来,我们会:从一开始就要求提供与生产环境完全一致的沙盒。
  • 多个系统。国家代码重复、多出一个 1 或缺少国家代码的电话号码,产生了无效联系人和重复的 SalesCard。
    • 我们的调整:在入站流程中对电话号码进行规范化,并按来源设定规则。
    • 如果重来,我们会:在字段映射阶段逐个对象约定电话号码格式。

API 字段与结构

BIKY.ai API 中联系人和 SalesCard 的字段、允许值及规则。

访问方式

每次调用都需在 Authorization: Bearer <key> 请求头中携带账户密钥。Keybe 为每个账户签发一个密钥,并连同 Contacts 和 Funnels 服务的基础 URL 一并提供。

  • {app}:BIKY.ai 账户 id,每个品牌或经销店一个。除电话验证路径外,所有路径中都需包含它。
  • {typeEntity}:people、business 或 office。线索请使用 people。
  • 单个资源以普通对象形式返回。列表以 {data, paginator} 形式返回。paginator 包含 totalDocs、limit、page、totalPages、pagingCounter、hasPrevPage、hasNextPage、prevPage 和 nextPage。
  • 错误以 {statusCode, timestamp, path, message, error} 形式返回。发生验证错误时,message 为校验失败的字段列表,例如 ["responsible should not be empty"]。

联系人与 SalesCard

联系人代表个人。SalesCard 是该联系人在某个 Funnel 中的每一个销售机会。CRM 中的线索通常会同时映射到这两者。

联系人SalesCard
定义BIKY.ai CDP 中的个人或公司一个销售机会,位于某个 Funnel 的某个步骤中
数量每人一个;通过电话或邮箱查找每人可有多个。当某人在销售 Funnel 中已有一个未关闭的 SalesCard 时,不会再新开一个,除非 CRM 登记了一条不同的线索
其 iduuid_id
关联方式不适用persons[] 中存储联系人的 uuid
您的 CRM idexternalIds[],包含 systemName 和 valueutm.sourceCardId 或某个 extendedData 字段

接口端点

资源端点功能
联系人POST /{app}/contacts创建联系人。
联系人POST /{app}/contacts/upsert-or-fallback创建联系人;如果已有联系人使用该电话或邮箱,则更新该联系人。返回 {status, contact},其中 status 为 created、updated 或 fallback。数据无效时,返回该账户的备用(fallback)联系人,并在 reason 中说明原因。
联系人GET /{app}/contacts/{typeEntity}/phone/{phone}按电话查找。
联系人GET /{app}/contacts/{typeEntity}/email/{email}按邮箱查找。
联系人GET /{app}/contacts/{typeEntity}/{uuid}读取联系人。
联系人PATCH /{app}/contacts/{uuid}更新联系人;typeEntity 放在请求体中。
联系人POST /utils/validate-phone使用请求体 {phone} 验证电话号码。
FunnelGET /{app}/funnel/with-steps该账户的 Funnel 及其步骤。
FunnelGET /{app}/{funnelId}/steps某个 Funnel 的步骤,包括键(name)、显示名称(label)和顺序(order)。
SalesCardPOST /{app}/funnel/{funnel}/steps/{step}/cards在某个步骤中创建 SalesCard。
SalesCardPOST /{app}/funnel/{funnel}/steps/{step}/cards/upsert如果同一人在该步骤中已有在 withinHours 时间窗口(默认 1 小时)内创建的 SalesCard,则更新它;否则新建一个。
SalesCardGET /{app}/cards-filter?person={uuid}某个联系人的 SalesCard,按从新到旧排序。
SalesCardGET /{app}/simple/cards/{id}读取 SalesCard。
SalesCardPATCH /{app}/simple/cards/{id}更新 SalesCard,或通过 stepName 将其移至其他步骤。
SalesCardDELETE /{app}/funnel/{funnel}/steps/{step}/cards/{id}删除 SalesCard;该删除为软删除。

联系人字段

字段类型必填含义与取值
typeEntity文本是people、business 或 office。
name文本是名字。
surname文本否姓氏。
phone[]列表否每个电话包含带国家代码的 value(525500001234)、countryCode(52)、country(MX)、isPrimary 和 verify。创建时,value、countryCode 和 isPrimary 为必填;执行 PATCH 时,verify 也为必填。
email[]列表否每个邮箱包含 value、isPrimary 和 verify。创建时,value 和 isPrimary 为必填;执行 PATCH 时,verify 也为必填。
registerChannel[]列表是channel 表示联系人的来源(api、form、import、web、chatWeb、whatsapp、instagram、facebook、tiktok、email、phone、sms、salesforce、hubspot、rdStation、shopify、vtex、other 等)。data 为自由文本,用于记录来源详情。
source对象否归因信息:utmSource、utmMedium、utmCampaign、utmTerm、utmContent、utmPartner、utmKam、utmCloser、channel 和 channelOther。
externalIds[]列表否联系人在其他系统中的 id,每项格式为 {systemName, value}。执行 PATCH 时会替换整个列表,因此建议与 isPushData 配合使用。
extendedData[]列表否账户专属字段:category 和 field 为必填,另需提供 value、valueArray 或 valueMultiple。
documentType、document文本否证件类型和号码(passport、nit、curp、rut、dni 等)。
responsible对象否负责该联系人的顾问:uuid 和 name 为必填,email 和 phone 为选填。
country、province、city、zone文本否所在地。
habeasData对象否授权同意:habeasDataStatus(Confirmed、Unconfirmed、OnlyLegals 或 Blacklist)、各渠道的同意情况、日期、IP、国家及证明材料。
tags文本列表否自由标签。
isPushData布尔值否仅用于 PATCH。为 true 时,所发送的电话和邮箱会追加到现有数据中;为 false 时,则替换现有数据。

SalesCard 字段

字段类型必填含义与取值
name文本是SalesCard 标题,通常为线索姓名。
persons[]文本列表是联系人的 uuid。
responsible对象是负责的顾问或 BIKY:uuid 和 name 必填,email 和 phone 选填。
description文本否顾问可见的自由文本。
amount数字否商机金额。如以文本形式传入,将存储为数字。
productsData[]列表否意向产品:id、sku 和 name 必填;另含价格、首付、贷款金额、品牌及选项。
utm对象否商机归因,包含 sourceCardId,即该商机在您 CRM 中的 id。sourceHistory 会记录 SalesCard 通过 cards/upsert 收到的每一个 source。
extendedData[]列表否账户专属字段。
reason文本否商机赢单或输单时的关闭原因。
priority文本否emergency、lowest、low、medium、high 或 highest。
schedule对象否预约:dataTime、advisor、status 和 meetingUUID 必填;type、location、description 和 entityUUID 选填。
invoiceData对象否发票:单据、车辆(vin、品牌、车型、配置版本、年款及价格)和客户。
stepName文本否仅限 PATCH。目标阶段的键名,例如 $step_sql$。
isPushData布尔值否仅限 PATCH。设为 true 时,extendedData 按 field 合并,productsData 按 id 合并;不设置时,两者均被整体替换。

示例

< > 之间的值由各账户自行提供:Funnel、阶段、顾问和产品的 id。

1. 创建或更新联系人。POST /{app}/contacts/upsert-or-fallback。响应为 {status, contact};contact.uuid 即 SalesCard 中使用的 id。若返回 fallback,原因见 reason,在数据修正之前请勿创建 SalesCard。

{
  "typeEntity": "people",
  "name": "Mariana",
  "surname": "Torres",
  "phone": [{ "value": "525500001234", "countryCode": "52", "country": "MX", "isPrimary": true }],
  "email": [{ "value": "[email protected]", "isPrimary": true }],
  "registerChannel": [{ "channel": "api", "data": "MiCRM" }],
  "source": { "utmSource": "micrm", "utmCampaign": "lanzamiento-octubre" },
  "externalIds": [{ "systemName": "MiCRM_LeadId", "value": "L-000123" }]
}

2. 在第一个阶段创建 SalesCard。POST /{app}/funnel/{funnel}/steps/{step}/cards。响应返回该 SalesCard 及其 _id。

{
  "name": "Mariana Torres",
  "persons": ["<contact uuid>"],
  "responsible": { "uuid": "<advisor uuid>", "name": "<advisor name>" },
  "description": "Lead received from MiCRM.",
  "productsData": [{ "id": "<product id>", "sku": "<sku>", "name": "<model>", "price": 450000 }],
  "utm": { "source": "micrm", "campaign": "lanzamiento-octubre", "sourceCardId": "OPP-000456" }
}

3. 变更阶段。PATCH /{app}/simple/cards/{id}。将 SalesCard 移至“有意向”(SQL)阶段,其他内容保持不变。

{ "stepName": "$step_sql$" }

API 规则

场景API 的处理方式应对方法
创建时的墨西哥电话号码52 + 10 位、521 + 10 位,以及带空格的 +52 55 1234 5678,均存储为 52 + 10 位。若为 10 位且不含国家代码,upsert-or-fallback 将返回 status: fallback 及备用联系人。发送电话号码时请附带国家代码。返回 status: fallback 时,请勿创建 SalesCard:修正数据后重新发送。
按电话号码查询52、521 和 +52 均可查到同一联系人;不含国家代码的 10 位号码返回 404。查询时始终附带国家代码。
已有联系人使用已存在的电话号码调用 upsert-or-fallback,会更新该联系人并返回 status: updated。通过此接口从 CRM 创建联系人,避免重复。
PATCH 中的电话和邮箱未提供 verify 时返回 400。isPushData: true 时为追加;false 时替换现有数据。未经验证时,请发送 verify: false。
PATCH 中的 source 和 externalIds两者均被整体替换;externalIds: [] 会将其删除。发送完整的 externalIds 列表,source 仅在创建时写入。
创建 SalesCard 时未提供 responsible400 responsible should not be empty。始终指定顾问;没有顾问时指定 BIKY。
productsDataid、sku 或 name 为空:400。price 为文本:400。如产品不在目录中,创建 SalesCard 时不传 productsData。
SalesCard 的 PATCHutm 会被合并。未设置 isPushData 时,extendedData 和 productsData 被整体替换。stepName 用于移动 SalesCard。使用 isPushData: true,可追加而不删除。
cards/upsert如该联系人在此阶段已有一张在 withinHours 内创建的 SalesCard,则更新该卡片。当 CRM 可能重试提交时使用。
cards-filter分页从 offset=1 开始;在此端点上 search 不起筛选作用。按 person 筛选,并比对 utm.sourceCardId。
删除 SalesCard删除为软删除:SalesCard 不再出现在 cards-filter 中,但按 id 调用 GET 仍会返回结果。通过 cards-filter 确认删除结果。