Composio 与 HubSpot 集成实战:OAuth 认证配置、故障排查与 Webhook 触发器完全指南
【免费下载链接】composioComposio powers 1000+ toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composio
本指南以 Composio 开源仓库中的 HubSpot 支持文档为主体,系统讲解如何在 Composio 上为 HubSpot 配置 OAuth 认证(含 scope 规划与白标化)、排查常见的连接与令牌交换故障、通过自定义工具调用 HubSpot API,并为每个客户应用配置基于 Webhook 的触发器。读完本文,你将掌握一套可直接落地的 HubSpot + Composio 集成方案,并能独立定位 400 令牌交换失败、授权循环、scope 缺失等高频问题。
HubSpot 认证的两种模式:Composio 托管应用与自定义 OAuth App
Composio 为 HubSpot 提供两种认证路径,二者的取舍直接决定你的 scope 自由度、品牌呈现与配额归属(参考 custom-app-vs-managed-app.mdx):
- Composio 托管应用(managed app):由 Composio 统一注册并维护 HubSpot OAuth 应用,开箱即用、最快上手。代价是用户在 OAuth 授权页看到的是 Composio 的品牌与默认 scope 集合,且配额与其他用户共享。
- 自定义 Auth Config(customer-owned credentials):使用你自己的 HubSpot OAuth 应用凭证(Client ID / Client Secret)创建自定义认证配置。适合白标化、需要额外 scope、需要独立配额或生产环境由团队自主掌控的场景。
仓库中 HubSpot 的 toolkit slug 位于 ts/packages/cli/src/generated/toolkit-slugs.ts(hubspot),在 SDK 与 CLI 中以hubspot标识该 toolkit。
自定义 Auth Config 的核心字段
从 custom-auth-hubspot.png 界面截图可以看到,创建 HubSpot 自定义 Auth Config 时主要填写以下字段(详见 custom-auth-configs.mdx):
| 字段 | 说明 |
|---|---|
| Use your own developer credentials | 切换为使用你自己的 HubSpot 开发者应用凭证 |
| Client id | 你在 HubSpot Developer Portal 创建的 OAuth 应用的客户端 ID |
| Client secret | 对应的客户端密钥,必须与 HubSpot 应用当前值一致 |
| Base URL | 默认https://api.hubapi.com,即 HubSpot API 请求的基础地址 |
| Redirect URI | 默认https://backend.composio.dev/api/v1/auth-apps/add,需要添加到 HubSpot 应用的 OAuth 允许重定向列表 |
| Optional Scopes | 可选的 HubSpot API 权限范围,以空格分隔 |
| Access Token | OAuth2 流程完成后由 Composio 自动注入,无需手动填写 |
创建完成后,在代码中通过auth_config_id发起连接即可(参考 custom-auth-configs.mdx):
connection_request = composio.connected_accounts.initiate( user_id="user_id", auth_config_id="ac_1234", ) connected_account = connection_request.wait_for_connection() print(connected_account)const connReq = await composio.connectedAccounts.initiate(userId, "ac_1234"); console.log(connReq.redirectUrl); const connection = await composio.connectedAccounts.waitForConnection(connReq.id);配置 HubSpot OAuth Scopes 与品牌化
HubSpot 对 scope 的处理比其他 OAuth 服务更严格,配置前需要理解三条核心规则(本文主体来自 toolkits-hubspot.md,其详细版见 public.md)。
1. 按最小权限选择联系人 scope
对于 HubSpot CRM 联系人,最小必要 scope 是crm.objects.contacts.read与crm.objects.contacts.write。涉及敏感联系人字段时,还需要对应的敏感 scope,例如crm.objects.contacts.sensitive.read与crm.objects.contacts.sensitive.write。按业务实际所需选取,避免一次授予过大权限。
2. 用工具映射 scope,而非靠猜
在配置应用之前,先用HubSpot 官方的 scope 文档与Composio 的 scopes/tools API将你要使用的工具/动作映射到所需的 scope 集合。这样可以得到精确的 scope 清单,比凭经验猜测可靠得多。
3. 保持 HubSpot 应用与 Composio Auth Config 的 scope 一致
HubSpot 要求在 OAuth 之前,scope 必须先声明在应用配置中;连接时 HubSpot 不会动态调整 scope。因此:
- 配置在 Composio auth config 上的 scope 集合,必须与 HubSpot 应用设置保持一致;
- HubSpot 对required scopes非常严格:配置在 HubSpot 应用上的必需 scope,必须出现在 OAuth 请求/安装 URL 的
scope参数中,否则安装会失败; - optional scopes应通过 HubSpot 的
optional_scope参数请求(在 Composio 中对应的可编辑字段名为optional_scopes)。如果选中的 HubSpot 账号/用户无法授予某个可选 scope,HubSpot 会直接省略它,最终令牌中将不包含该 scope——所以不要假设可选 scope 已授予,在依赖可选能力前先检查令牌/已授予的 scope。
FAQ 文档 hubspot.md 给出了 Composio 与 HubSpot 开发者应用的 scope 分类匹配规则:
- Composio 的
scopes字段中的 scope,必须在 HubSpot 中配置为Required(必需)或Conditionally required(条件必需); - Composio 的
optional_scopes字段中的 scope,必须在 HubSpot 中配置为Optional(可选); - 不要在 Composio 中请求 HubSpot 开发者应用未启用的 scope。
对应到 API 创建 Auth Config 的 credentials 结构:
{ "credentials": { "scopes": "oauth crm.objects.contacts.read", "optional_scopes": "crm.objects.companies.read crm.objects.deals.read" } }读取 Auth Config 时,要同时检查credentials.scopes与credentials.optional_scopes,两者共同代表 Composio 可为该配置请求的 HubSpot 权限。
推荐的 scope 布局:最小必需 + 可选扩展
FAQ 推荐的自定义 HubSpot OAuth scope 方案是把必需清单保持最小:
oauth将工具相关的 HubSpot 权限放入optional_scopes,并在 HubSpot 开发者应用中将同样的权限标记为可选。这样做的核心好处是灵活性:HubSpot 要求 OAuth URL 中的 scope 分类与开发者应用中的分类一致,如果日后把某个权限从可选改为必需,所有使用该应用的 Auth Config 都必须同步通过scopes请求它,否则新安装可能失败。把工具权限保持可选,就能在不强制所有 Auth Config 联动的情况下逐步扩展权限。若某权限对产品功能是硬性要求,则应保持必需,并确保它在 HubSpot 中为 Required 且通过 Composioscopes发送。
两种合法的配置示例(源自 hubspot.md):
示例 A:所有权限都在 HubSpot 中标记为必需
{ "credentials": { "scopes": "oauth crm.objects.contacts.read crm.objects.companies.read crm.objects.deals.read", "optional_scopes": "" } }示例 B:仅oauth为必需,工具权限全部可选
{ "credentials": { "scopes": "oauth", "optional_scopes": "crm.objects.contacts.read crm.objects.contacts.write crm.objects.companies.read crm.objects.companies.write crm.objects.deals.read crm.objects.deals.write tickets timeline" } }两种方式都有效,关键是Composio 与 HubSpot 在"哪些必需、哪些可选"上达成一致。修改 scope 后需要重连受影响的 HubSpot 账号:已存在的连接会保留原始授权时授予的 scope;可选 scope 可以让连接在门户无法授予全部权限时依然成功,但如果某个工具后续需要用户未授予的权限,该工具仍可能报错。
白标化:客户可见的 OAuth 授权页
若要为客户提供白标 OAuth 体验,请使用客户自己的 HubSpot OAuth 应用凭证 / 自定义 Auth Config(参考 white-labeling.mdx):
- 自行掌控授权页的品牌与同意(consent)呈现,避免客户在 OAuth 页面上看到 Composio 托管应用的品牌;
- 托管应用在 HubSpot 审批通过前,用户在连接时会看到"Connecting an unverified app"警告(连接仍可工作,但需要用户明确接受)。如果该警告阻塞了上线,使用自定义 Auth Config 即可掌控应用身份、审核状态与同意页(见 hubspot.md)。
从 SDK 层面,通过auth_configs.create传入自定义凭证即可(参考 controlling-scopes.mdx):
auth_config = composio.auth_configs.create( toolkit="hubspot", options={ "type": "use_custom_auth", "auth_scheme": "OAUTH2", "name": "HubSpot", "credentials": { "client_id": os.environ["HUBSPOT_CLIENT_ID"], "client_secret": os.environ["HUBSPOT_CLIENT_SECRET"], "scopes": "oauth crm.objects.contacts.read", "optional_scopes": "crm.objects.companies.read crm.objects.deals.read", }, }, )const authConfig = await composio.authConfigs.create('hubspot', { type: 'use_custom_auth', authScheme: 'OAUTH2', name: 'HubSpot', credentials: { client_id: process.env.HUBSPOT_CLIENT_ID!, client_secret: process.env.HUBSPOT_CLIENT_SECRET!, scopes: 'oauth crm.objects.contacts.read', optional_scopes: 'crm.objects.companies.read crm.objects.deals.read', }, });注意:修改 scope 只影响新连接。已存在的连接保留用户此前授予的 scope,若要向现有用户应用新 scope,需要让其重新认证。
排查 HubSpot OAuth 连接故障
令牌交换 400:先查 Client Secret,再查 scope 对齐
多个客户自有 HubSpot OAuth 故障案例表明,令牌交换阶段返回 400 时,第一优先级是核对 client secret(详见 public.md):
- 从 HubSpot 应用复制当前正确的 client secret;
- 更新 Composio 自定义 Auth Config 使其一致;
- 如果 secret 曾被轮换,或从错误的 HubSpot 应用复制了 secret,HubSpot 会在令牌交换时返回 400。
接着检查 scope 对齐。HubSpot 对必需 scope 极其严格:
- 配置在 HubSpot 应用上的必需 scope 必须出现在 OAuth 请求/安装 URL 的
scope参数中,安装才能成功; - 如果 Composio Auth Config 请求的必需 scope 与客户自有 HubSpot 应用配置的必需 scope 不匹配,授权/令牌交换都会失败;
- 可选 scope 通过 HubSpot 的
optional_scope参数请求,若账号无法授予则可能被省略,令牌中不会包含它,使用前务必检查实际授予的 scope。
对于 Composio 托管的 HubSpot Auth Config,不要修改默认 scope 集合。需要不同的必需/可选 scope 配置时,应通过自定义 Composio Auth Config 使用自己的 HubSpot OAuth 应用。对于托管配置,你只能移除托管应用上已存在的可选 scope,无法添加新 scope,也无法移除对托管配置非可选的 scope(见 hubspot.md)。
授权循环:检查 HubSpot 工作区与登录状态
如果 HubSpot 流程在 Composio 侧正常工作的情况下反复循环,请在正确的 HubSpot 工作区登录状态下重试,并确认 OAuth 应用是 public 且配置正确。
常见故障清单
FAQ 汇总了以下高频排查项(详见 hubspot.md):
- scope 不匹配或回调错误:确认每个请求的 scope 都已在 HubSpot 启用,且在 HubSpot 与 Composio 两侧的分类一致;
- 工具报缺失 scope:在 Auth Config 与 HubSpot 开发者应用中补充该 scope,然后重连账号;
- 联系人列表/搜索 limit 错误:
HUBSPOT_SEARCH_CONTACTS_BY_CRITERIA与HUBSPOT_LIST_CONTACTS_PAGE单次请求的limit最大为 100; - Webhook 设置错误:HubSpot webhook 要求public 应用并具备 App ID 与 Developer API Key,私有/内部应用无法接收 webhook;
- 刷新或过期错误:常见原因包括用户在 HubSpot 中撤销了应用授权、HubSpot 应用凭证变更、refresh token 失效,或连接被用不同应用配置重新授权。轮换自定义 OAuth 凭证或修改 HubSpot 开发者应用后,需要重连受影响的 HubSpot 账号。
断开连接
要断开 HubSpot,删除对应的 connected account 即可。删除连接账号会断开 HubSpot 账号与 Composio 的关联,并停止刷新该 access token。
调用 HubSpot API 与 Toolkit 版本管理
通过认证请求创建自定义 HubSpot 工具
你可以创建一个自定义工具,向 HubSpot API 端点发送已认证的请求——Composio 会为已连接的账号处理认证。如果需要,也可以直接携带连接配置/自定义请求头调用 Provider。
营销对象与 CRM 属性的差异
对于 HubSpot 营销对象(如 campaigns),HubSpot不像 CRM 对象那样暴露 properties API。这类对象的字段可能需要直接在 HubSpot 门户中查看或配置,无法通过常规属性接口读写。
升级旧版 SDK 与 Toolkit 版本
旧版本 HubSpot SDK/toolkit 使用双前缀 slug,例如HUBSPOT_HUBSPOT_LIST_CONTACTS;新版本改为单前缀,例如HUBSPOT_LIST_CONTACTS。升级 SDK 后,要显式使用最新的 HubSpot toolkit 版本,否则可能引用到已废弃的 slug。
此外,HubSpot toolkit 的输出结构在近期迭代中发生过形态变化:
- 2025-12-10 起,HubSpot(与 Outlook、Notion 等共 57 个 toolkit)的返回结果从通用的
response_data对象升级为强类型字段;若你的代码在latest版本下后处理旧的response_data结构,需要适配新的扁平化、类型化响应(见 changelog 12-10-25); - 2026-01-07 起,工具执行错误统一返回包含
status_code与message的标准结构,HubSpot 也属于采用anyOf联合类型的 157 个 toolkit 之一,字段接受null或多类型值时 schema 会完整保留(见 changelog 01-07-26)。
为每个客户应用配置 HubSpot 触发器
HubSpot 的 Webhook API 需要明确指定接收 Webhook 通知的 HubSpot 应用(详见 toolkits-hubspot.md):
- 从 HubSpot 的 webhook 应用文档或开发者应用设置中获取App ID;
- 配置触发器时使用该 App ID;
- 对于使用客户自有 HubSpot 应用的触发器,
app_id与 developer API key 都是必需的——因为每个应用各自接收自己的 webhook 投递(每个客户需要自己的 HubSpot 应用来完成 webhook 投递)。
这与 Composio 的自定义 OAuth Webhook 机制相衔接:当触发类型带有requires_webhook_endpoint_setup标志时,需要为你的 OAuth 应用注册 Composio 的 ingress URL(形如https://backend.composio.dev/api/v3.1/webhook_ingress/{toolkit_slug}/{we_xxx}/trigger_event),使事件能到达 Composio(详见 custom-oauth-webhooks.mdx)。同时牢记 HubSpot 侧的前提:webhook 接收要求public 应用,私有/内部应用无法接收 webhook。
参考资料
- 本文主体:docs/kb/articles/toolkits-hubspot.md,扩展版见 docs/kb/source/toolkits/hubspot/public.md
- HubSpot 认证 FAQ:docs/content/toolkits/faq/hubspot.md
- 自定义认证配置:docs/content/docs/auth-configuration/custom-auth-configs.mdx
- 白标化:docs/content/docs/auth-configuration/white-labeling.mdx
- Scope 控制(含 Python / TypeScript 示例):docs/content/docs/authentication/controlling-scopes.mdx
- 托管 vs 自定义认证:docs/content/docs/authentication/custom-app-vs-managed-app.mdx
- 自定义 OAuth Webhook:docs/content/docs/setting-up-triggers/custom-oauth-webhooks.mdx
- Toolkit slug 定义:ts/packages/cli/src/generated/toolkit-slugs.ts
【免费下载链接】composioComposio powers 1000+ toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composio
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考