mcpField
H
hubspot-api

hubspot-api

github.com/anthropics营销与增长7443 次安装3 周前更新
代码仓库

关于 hubspot-api

hubspot-api 是用于操作 HubSpot CRM API 的技能,适合管理 CRM 记录及其关联。它说明标准和自定义对象的常见操作,并附带可输出 TSV 或 JSONL 的搜索脚本。

主要功能

  1. 01列出、读取、创建、更新和归档记录
  2. 02使用筛选、排序和分页搜索
  3. 03批量读取、创建、更新和合并写入
  4. 04读取和创建带类型的关联
  5. 05发现属性、管道和阶段
  6. 06将搜索结果导出为 TSV 或 JSONL

适用场景

  1. 01查找符合筛选条件的 CRM 记录
  2. 02更新或归档联系人和交易记录
  3. 03批量创建或合并写入记录
  4. 04关联对象前检查关联类型

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/anthropics/claude-tag-plugins --skill hubspot-api

安装后在 Claude Code 中输入/hubspot-api确认已加载。

附带文件references/api.mdscripts/hs_search.sh

详细介绍

HubSpot 的 CRM API(v3)在各对象类型间保持统一:每个对象都位于 https://api.hubapi.com/crm/v3/objects/{objectType} 下,并支持相同的基本、搜索、批量和关联操作。

(HubSpot 正在推出基于日期的路径版本(/crm/objects/2026-03/...),作为后续版本的命名方式。以下 v3/v4 路径目前仍可使用;HubSpot 已宣布 v4 将于 2027-03-30 停止支持,而 v3 的停止支持日期尚未确定。目前无需迁移。)

关键概念:

  • 对象类型通过名称(contacts、companies、deals、tickets)或数字形式的 objectTypeId(0-1、0-2、0-3、0-5)来标识。自定义对象使用 2-<n> 或其 p_<name> 别名。两种形式都可用于 URL。
  • 读取时需显式选择属性。 列表和获取调用只返回少量默认属性 (hs_object_id、createdate、lastmodifieddate,以及各类型的默认属性,例如联系人的 email / firstname)。请始终使用 properties= 传入以逗号分隔的所需字段,否则返回的记录看起来会是空的。
  • 每种对象类型都有自己的主要显示属性和去重键。 联系人按 email 去重;公司按 domain 去重;交易和工单没有去重键。创建记录前请确认对应的键。
  • 关联具有类型。 常见关联(contact_to_company、deal_to_contact 等)有内置类型 ID。你也可以定义自定义关联标签。

请求设置

身份验证由运行时处理——凭据会注入发送到此 API 的出站请求中,因此无需进行任何设置。不要尝试创建、生成、刷新或验证令牌或密钥。凭据变量仅用于确保请求格式正确;如果某个变量未设置,请将其设为任意占位值。持续出现 401/403 错误表示此工作区未配置凭据——请报告此情况,而不是排查身份验证问题。

每个请求都会携带 bearer 标头。已配置的凭据具有一组作用域 (crm.objects.contacts.read、crm.objects.deals.write 等),用于控制其可访问的内容。

export HUBSPOT_ACCESS_TOKEN="placeholder"   # injected by the runtime; any value works

健全性检查 — 确认工作区已正确连接:

curl -sS "https://api.hubapi.com/crm/v3/objects/contacts?limit=1" \
  -H "Authorization: Bearer ${HUBSPOT_ACCESS_TOKEN}" | jq .

403 表示请求已通过身份验证,但已配置的凭据缺少执行所尝试操作所需的作用域。

为简洁起见,以下示例使用一个辅助函数。定义一次,或将 -H 标志添加到每条 curl 命令中:

hsapi() { curl -sS "$@" -H "Authorization: Bearer ${HUBSPOT_ACCESS_TOKEN}" -H "Content-Type: application/json"; }

核心操作

以下操作使用 contacts,但相同路径也适用于 companies、deals、tickets 和任何自定义对象——只需替换 {objectType} 部分。

1. 列出记录

使用游标分页、按属性筛选,不支持搜索。

hsapi -G "https://api.hubapi.com/crm/v3/objects/contacts" \
  --data-urlencode "limit=50" \
  --data-urlencode "properties=email,firstname,lastname,lifecyclestage,hubspot_owner_id" \
  --data-urlencode "archived=false" | jq '.results[] | {id, props: .properties}'

失败时,响应为 {"status":"error", "message":..., "category":...},且没有 .results ——参见错误处理。编写脚本时请进行一次防护(jq 'if .results then … else . end');为清晰起见,以下示例展示的是未经处理的投影。

添加 associations=companies,deals,即可在每条记录中内联关联 ID。

2. 获取一条记录
hsapi -G "https://api.hubapi.com/crm/v3/objects/contacts/CONTACT_ID" \
  --data-urlencode "properties=email,firstname,lastname,phone,company" \
  --data-urlencode "associations=companies,deals" | jq .

若要使用唯一属性而不是内部 ID 获取记录(例如通过电子邮件),请添加 idProperty=email,并将电子邮件放入路径中:

hsapi -G "https://api.hubapi.com/crm/v3/objects/contacts/[email protected]" \
  --data-urlencode "idProperty=email" \
  --data-urlencode "properties=email,firstname,lastname" | jq .
3. 创建记录
hsapi -X POST "https://api.hubapi.com/crm/v3/objects/contacts" \
  -d '{
    "properties": {
      "email": "[email protected]",
      "firstname": "Alice",
      "lastname": "Nguyen",
      "lifecyclestage": "lead"
    }
  }' | jq 'if .status == "error" then . else {id, createdAt} end'

若要在一次调用中创建并建立关联,请添加 associations 数组:

hsapi -X POST "https://api.hubapi.com/crm/v3/objects/deals" \
  -d '{
    "properties": {
      "dealname": "Acme expansion",
      "pipeline": "default",
      "dealstage": "appointmentscheduled",
      "amount": "15000"
    },
    "associations": [
      {"to": {"id": "COMPANY_ID"}, "types": [{"associationCategory": "HUBSPOT_DEFINED", "associationTypeId": 341}]}
    ]
  }' | jq .

341 是 deal_to_company。请参阅 references/api.md 中的关联类型表,或实时查询(操作 8)。

4. 更新记录

只对要更改的属性执行 PATCH。其他所有内容都保持不变。

hsapi -X PATCH "https://api.hubapi.com/crm/v3/objects/contacts/CONTACT_ID" \
  -d '{"properties": {"lifecyclestage": "marketingqualifiedlead", "phone": "+1-555-0100"}}'

通过唯一属性更新的方式与读取相同——附加 ?idProperty=email,并将电子邮件放入路径中。

5. 归档 / 删除记录

HubSpot 的“删除”是软删除(记录会进入回收站约 90 天)。成功时返回 204,响应正文为空,因此请打印状态码:

hsapi -X DELETE "https://api.hubapi.com/crm/v3/objects/contacts/CONTACT_ID" -w '\n%{http_code}\n'

批量删除:使用 POST /crm/v3/objects/contacts/batch/archive,并传入 {"inputs": [{"id": "..."}, ...]}。

6. 搜索记录(scripts/hs_search.sh)

通过捆绑脚本搜索任意对象类型(路径相对于此技能目录):脚本会构建 filterGroups/sorts/query 请求体,向 /crm/v3/objects/{type}/search 发送请求,遍历所有页面中的 paging.next.after,并输出 TSV 或 JSONL。

scripts/hs_search.sh --object contacts \
  --filter lifecyclestage:EQ:lead \
  --filter createdate:GTE:2024-01-01T00:00:00Z \
  --sort createdate:desc --limit 200
  • --object TYPE(必填)可以是 contacts、companies、deals、tickets,也可以是任何对象类型名称 / objectTypeId。实例特定信息请参阅上文的 HUBSPOT_ACCESS_TOKEN。
  • --filter PROP:OP:VALUE(可重复)会在一个 filterGroup 中对筛选条件执行 AND 操作。OP 会转换为大写;IN / NOT_IN 接受逗号分隔的列表(dealstage:IN:won,lost → values;对于字符串属性,值必须为小写),BETWEEN 接受 low,high(amount:BETWEEN:100,500 → value + highValue),HAS_PROPERTY / NOT_HAS_PROPERTY 不接受值。--query TEXT 会添加自由文本短语匹配。
  • --properties LIST 同时用于请求和 TSV 列;默认值按类型而定(联系人为 email,firstname,lastname,createdate 等),其他类型则必须指定。--sort PROP[:desc] 用于对结果排序。
  • --limit N 限制获取的行数(默认值为 100,0 = 获取全部 — 搜索最多返回 10,000 条结果);--page-size N(最大值为 200);--json 会为每条记录输出一个 JSON 对象,而不是带表头的 TSV。匹配总数和行数会输出到 stderr。
  • 退出代码:0 表示成功,1 表示请求失败或 API 错误(stderr 中会显示 category 和 message),或参数错误。

如果脚本报错,请阅读脚本 — 它只有普通的 curl + jq — 并根据 references/api.md 进行调试。

脚本会输出一个执行 AND 操作的 filterGroup。如需 OR 分组,请通过 hsapi 发送原始请求体 — 限制为 5 个分组、每组 6 个筛选条件、总计 18 个筛选条件。搜索最终一致:几秒前创建或更新的记录可能尚未出现 — 如需写入后立即读取,请按 ID 直接执行 GET。

7. 批量读取 / 创建 / 更新 / 插入或更新

batch/* 端点只需一次往返即可处理最多 100 条记录(部分端点的上限较低 — 请参阅 references/api.md)。这五种操作都采用相同的 {"inputs": [...]} 结构。

# batch read by id
hsapi -X POST "https://api.hubapi.com/crm/v3/objects/contacts/batch/read" \
  -d '{"inputs": [{"id": "101"}, {"id": "102"}], "properties": ["email", "firstname"]}'

# upsert by a unique property (create if new, update if the key matches)
hsapi -X POST "https://api.hubapi.com/crm/v3/objects/contacts/batch/upsert" \
  -d '{"inputs": [{"idProperty": "email", "id": "[email protected]", "properties": {"firstname": "Alice"}}]}'

batch/create 和 batch/update 分别接受 {"inputs": [{"properties": {...}}]} 和 {"inputs": [{"id": "...", "properties": {...}}]}。

8. 列出和创建关联

使用 v4 关联端点 — 它们较新,并包含你实际需要的标签 / 类型信息。它们与 v3 并存。

# what's associated with this contact?
hsapi "https://api.hubapi.com/crm/v4/objects/contacts/CONTACT_ID/associations/companies" | jq '.results'

# discover association type ids between two object types
hsapi "https://api.hubapi.com/crm/v4/associations/contacts/companies/labels" | jq '.results'

# create an association (PUT — idempotent)
hsapi -X PUT "https://api.hubapi.com/crm/v4/objects/contacts/CONTACT_ID/associations/companies/COMPANY_ID" \
  -d '[{"associationCategory": "HUBSPOT_DEFINED", "associationTypeId": 1}]'

# remove (204 on success, empty body)
hsapi -X DELETE "https://api.hubapi.com/crm/v4/objects/contacts/CONTACT_ID/associations/companies/COMPANY_ID" -w '\n%{http_code}\n'
9. 发现属性(架构)

读取对象类型的属性目录,了解字段名称、类型以及枚举字段(管道、阶段、生命周期阶段等)的 options。创建或筛选之前请先执行此操作 — 猜测属性名称是导致 400 错误的最常见原因。

hsapi "https://api.hubapi.com/crm/v3/properties/contacts" | \
  jq '.results[] | {name, label, type, fieldType, options: (.options | length)}'

# one property with its option values
hsapi "https://api.hubapi.com/crm/v3/properties/deals/dealstage" | jq '{name, options: [.options[] | {label, value}]}'
10. 管道和阶段

交易和工单位于具有顺序阶段的管道中。dealstage / hs_pipeline_stage 属性中应填写阶段和管道的 ID(而非标签)。

hsapi "https://api.hubapi.com/crm/v3/pipelines/deals" | \
  jq '.results[] | {id, label, stages: [.stages[] | {id, label, displayOrder}]}'

分页

列表端点(GET /crm/v3/objects/{type}、属性列表、关联列表)和搜索(POST .../search)都使用游标分页:有更多结果时,响应会包含 paging.next.after;将其作为 after 传回(GET 使用查询参数,搜索使用请求体字段)。列表的 limit 最大值为 100,搜索为 200;此外,单次搜索最多返回 10,000 条结果 — 如需更多结果,请缩小筛选范围。错误响应体没有 .paging — 请为循环设置上限,并在 .status == "error" 时退出。

速率限制

Free/Starter 账户的私有应用令牌每 10 秒可发起 100 次请求,Professional/Enterprise 账户每 10 秒可发起 190 次请求(另有根据账户等级调整的每日上限)。搜索端点每个账户每秒最多可发起 5 次请求,其响应不包含速率限制标头。其他所有响应都包含:

X-HubSpot-RateLimit-Max          requests allowed per interval
X-HubSpot-RateLimit-Remaining    requests left in the current interval
X-HubSpot-RateLimit-Interval-Milliseconds   interval length
X-HubSpot-RateLimit-Daily / -Daily-Remaining

遇到 429 时,休眠 X-HubSpot-RateLimit-Interval-Milliseconds 指定的时间(若缺失,则休眠约 10 秒),然后重试。优先使用批量端点——一次包含 100 条记录的批量调用只计为一次请求。

错误处理

错误采用 JSON 格式:{"status": "error", "message": "...", "correlationId": "...", "category": "..."}。在投影 .results / .id 前检查 .status——错误封装中不包含这些字段,直接投影只会输出 null。始终显示 message 和 category。

  • 400 VALIDATION_ERROR — 属性名称或值无效、筛选器格式错误、枚举值不正确。查看 errors[],其中会指出出错字段。检查属性目录(op 9)。
  • 401 INVALID_AUTHENTICATION — 凭据缺失或遭拒。检查是否已设置 HUBSPOT_ACCESS_TOKEN;如果问题仍然存在,则说明该工作区未配置此凭据——请报告此问题。
  • 403 MISSING_SCOPES — 已配置的凭据缺少此端点所需的范围。消息会指出缺少的范围——请报告。
  • 404 OBJECT_NOT_FOUND — ID 错误、objectType 不正确,或记录已删除/归档。尝试使用 archived=true。
  • 409 CONFLICT — 唯一键冲突(例如,创建联系人的邮箱已存在)。改用 upsert,或更新现有记录。
  • 429 RATE_LIMITS — 请求体中的 policyName 会说明触发了哪种限制:秒级/突发限制 → 按 X-HubSpot-RateLimit-Interval-Milliseconds 指定的时间休眠,然后重试;DAILY → 停止请求,该限制会在账户本地时间午夜重置。
  • 5xx — 暂时性错误。使用退避策略重试。

深入了解

references/api.md 提供更完整的端点目录,包括各对象类型的完整默认属性列表、内置关联类型 ID 表、批量限制、所有者/管道/属性管理端点、自定义对象架构、列表以及互动对象类型(备注、通话、任务、会议、电子邮件)。需要上文未涵盖的端点或 ID 时,请阅读该文件。

评论

支持 Markdown