关于 crm-integration
面向开发者的 CRM 集成技能,涵盖 Close CRM、HubSpot 和 Salesforce 的认证、数据操作、Webhook、管道自动化及跨 CRM 同步。
主要功能
- 01配置 Close、HubSpot 和 Salesforce
- 02线索、联系人、商机及活动的增删改查
- 03Webhook 处理器与事件处理
- 04跨 CRM 同步和冲突解决
- 05销售管道自动化与报告
适用场景
- 01将应用连接到 CRM
- 02在 CRM 平台间同步记录
- 03通过 Webhook 处理 CRM 更新
- 04自动化销售管道操作
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ manojbajaj95/ claude-gtm-plugin --skill crm-integration安装后在 Claude Code 中输入/crm-integration确认已加载。
附带文件config.jsonreference/close-deep-dive.md
详细介绍
- Close CRM - SMB 销售的日常主力工具(API 最简单,性价比最高)
- HubSpot - 借助丰富的生态系统,实现营销与销售协同
- Salesforce - 满足企业需求并处理复杂工作流
- 跨 CRM 同步 - 支持冲突解决的双向同步
主要交付内容:
- 配置 API 客户端并设置适当的身份验证
- 对潜在客户、联系人、交易和活动执行 CRUD 操作
- 用于实时同步的 Webhook 处理器
- 管道自动化与报告
工作区上下文
提问前请先阅读引导上下文:strategy/brand.md,了解品牌、受众、产品、渠道、工具、限制和指标;about/me.md,了解个人表达风格;content/ideas.md 和 content/calendar.md,了解内容规划。仅在必要时,将旧版产品营销上下文文件作为备用。将生成的草稿保存到 content/<platform>/drafts/YYYY-MM-DD_short-topic-slug.md,并将长期有效的经验反馈到 strategy/brand.md、about/me.md 或 content/ideas.md。
操作约定
本技能适用于其 frontmatter 范围,内容自成一体:使用本地说明、参考资料、脚本和资源作为操作手册;仅询问缺失的任务特定输入;将超出范围的工作移交给相邻技能,不擅自扩大范围;并返回可执行的成果、决策、计划、草稿或诊断。
<quick_start> Close CRM(API Key 身份验证):
import httpx
class CloseClient:
BASE_URL = "https://api.close.com/api/v1"
def __init__(self, api_key: str):
self.client = httpx.Client(
base_url=self.BASE_URL,
auth=(api_key, ""), # Basic auth, password empty
timeout=30.0,
)
def create_lead(self, data: dict) -> dict:
response = self.client.post("/lead/", json=data)
response.raise_for_status()
return response.json()
def search_leads(self, query: str) -> list:
response = self.client.post("/data/search/", json={
"query": {"type": "query_string", "value": query},
"results_limit": 100
})
return response.json()["data"]
# Usage
close = CloseClient(os.environ["CLOSE_API_KEY"])
leads = close.search_leads("company:Coperniq")
HubSpot(Python SDK):
from hubspot import HubSpot
from hubspot.crm.contacts import SimplePublicObjectInputForCreate
client = HubSpot(access_token=os.environ["HUBSPOT_ACCESS_TOKEN"])
# Create contact
contact = client.crm.contacts.basic_api.create(
SimplePublicObjectInputForCreate(properties={
"email": "[email protected]",
"firstname": "Jane",
"lastname": "Smith"
})
)
print(f"Created: {contact.id}")
Salesforce(JWT Bearer):
import jwt
from datetime import datetime, timedelta
class SalesforceClient:
def __init__(self, client_id: str, username: str, private_key: str):
self.auth_url = "https://login.salesforce.com"
self._authenticate(client_id, username, private_key)
def _authenticate(self, client_id, username, private_key):
payload = {
"iss": client_id,
"sub": username,
"aud": self.auth_url,
"exp": int((datetime.utcnow() + timedelta(minutes=3)).timestamp())
}
assertion = jwt.encode(payload, private_key, algorithm="RS256")
response = httpx.post(f"{self.auth_url}/services/oauth2/token", data={
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion": assertion
})
self.access_token = response.json()["access_token"]
self.instance_url = response.json()["instance_url"]
</quick_start>
<success_criteria> CRM 集成在满足以下条件时视为成功:
- API 身份验证成功,且没有错误
- 所有实体类型的 CRUD 操作均能完成
- 遵守速率限制(Close:100 req/10s;HubSpot:因套餐层级而异)
- Webhook 能正确触发和处理
- 数据实现双向同步且不产生重复项 </success_criteria>
<crm_comparison>
平台比较
| 功能 | Close | HubSpot | Salesforce |
|---|---|---|---|
| 身份验证 | API Key | OAuth 2.0 / Private App | JWT Bearer |
| 速率限制 | 100 req/10s | 按套餐层级为 100-200 req/10s | 100k req/day |
| 适用场景 | SMB 销售,追求简便 | 营销与销售 | 企业 |
| 起始价格 | $49/user/mo | 免费(功能有限) | $25/user/mo |
| API 访问 | 所有套餐 | Starter+($45+) | 所有套餐 |
| Webhooks | 所有套餐 | Pro+($800+) | 所有套餐 |
实体映射
| 概念 | Close | HubSpot | Salesforce |
|---|---|---|---|
| 公司 | lead | company | Account |
| 人员 | contact | contact | Contact / Lead |
| 交易 | opportunity | deal | Opportunity |
| 活动 | activity | engagement | Task / Event |
| 自定义字段 | custom.cf_xxx | properties | Field__c |
管道阶段映射
| 阶段 | Close | HubSpot | Salesforce |
|---|---|---|---|
| 新建 | Lead | appointmentscheduled | Prospecting |
| 已筛选 | Contacted | qualifiedtobuy | Qualification |
| 演示 | Opportunity | presentationscheduled | Needs Analysis |
| 提案 | Proposal | decisionmakerboughtin | Proposal/Price Quote |
| 赢单 | Won | closedwon | Closed Won |
| 丢单 | Lost | closedlost | Closed Lost |
| </crm_comparison> |
<close_patterns>
Close CRM(日常主力工具)
查询语言(用于 Smart Views)
# Leads with no activity in 30 days
'sort:date_updated asc date_updated < "30 days ago"'
# High-value opportunities
'opportunities.value >= 50000 opportunities.status_type:active'
# Custom field filtering
'custom.cf_industry = "MEP Contractor"'
# Multiple trade types (your ICP)
'custom.cf_trades:HVAC OR custom.cf_trades:Electrical'
核心操作
# Create lead with contacts
lead = close.create_lead({
"name": "ABC Mechanical",
"url": "https://abcmech.com",
"contacts": [{
"name": "John Smith",
"title": "Owner",
"emails": [{"email": "[email protected]", "type": "office"}],
"phones": [{"phone": "555-1234", "type": "office"}]
}],
"custom.cf_tier": "Gold",
"custom.cf_source": "sales-agent"
})
# Create opportunity
opp = close._request("POST", "/opportunity/", json={
"lead_id": lead["id"],
"value": 50000,
"confidence": 50,
"status_id": "stat_xxx" # Pipeline stage
})
# Log activity
close._request("POST", "/activity/note/", json={
"lead_id": lead["id"],
"note": "Initial discovery call - interested in demo"
})
速率限制标头(符合 RFC 标准)
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1704067200
查询语言、Smart Views、序列和报告请参阅
reference/close-deep-dive.md。 </close_patterns>
<hubspot_patterns>
HubSpot 集成
Python SDK 模式
from hubspot import HubSpot
from hubspot.crm.deals import SimplePublicObjectInputForCreate
from hubspot.crm.contacts import PublicObjectSearchRequest
client = HubSpot(access_token=os.environ["HUBSPOT_ACCESS_TOKEN"])
# Create deal with association
deal = client.crm.deals.basic_api.create(
SimplePublicObjectInputForCreate(properties={
"dealname": "Enterprise Deal",
"amount": "50000",
"dealstage": "appointmentscheduled",
"pipeline": "default"
})
)
# Search contacts by email domain
search = PublicObjectSearchRequest(
filter_groups=[{
"filters": [{
"propertyName": "email",
"operator": "CONTAINS",
"value": "@example.com"
}]
}],
properties=["email", "firstname", "lastname"],
limit=50
)
results = client.crm.contacts.search_api.do_search(search)
关联类型
| 起点 | 终点 | 类型 ID |
|---|---|---|
| 联系人 | 公司 | 1 |
| 联系人 | 交易 | 4 |
| 公司 | 交易 | 6 |
| 交易 | 联系人 | 3 |
批量操作、自定义属性和工作流请参阅
reference/hubspot-patterns.md。 </hubspot_patterns>
<salesforce_patterns>
Salesforce 集成
SOQL 查询模式
-- Parent-child relationship (Contacts of Account)
SELECT Id, Name, (SELECT LastName, Email FROM Contacts)
FROM Account WHERE Industry = 'Technology'
-- Child-parent relationship
SELECT Id, FirstName, Account.Name, Account.Industry
FROM Contact WHERE Account.Industry = 'Technology'
-- Semi-join (Accounts with open Opportunities)
SELECT Id, Name FROM Account
WHERE Id IN (SELECT AccountId FROM Opportunity WHERE IsClosed = false)
</salesforce_patterns>
REST API v59.0
def create_opportunity(self, data: dict) -> dict:
"""Required: Name, StageName, CloseDate."""
response = self.client.post(
f"{self.instance_url}/services/data/v59.0/sobjects/Opportunity/",
headers={"Authorization": f"Bearer {self.access_token}"},
json=data
)
return response.json()
# Composite API (batch up to 200 records)
def composite_create(self, records: list) -> dict:
return self.client.post(
f"{self.instance_url}/services/data/v59.0/composite/sobjects",
json={"allOrNone": False, "records": records}
)
JWT 设置、Platform Events 和 bulk API 请参阅
reference/salesforce-patterns.md。 </salesforce_patterns>
<webhook_patterns>
Webhook 处理程序
Close Webhook(FastAPI)
from fastapi import FastAPI, Request, HTTPException
import hmac, hashlib
app = FastAPI()
@app.post("/webhooks/close")
async def close_webhook(request: Request):
body = await request.body()
signature = request.headers.get("Close-Sig")
expected = hmac.new(
CLOSE_WEBHOOK_SECRET.encode(), body, hashlib.sha256
).hexdigest()
if not hmac.compare_digest(signature, expected):
raise HTTPException(401, "Invalid signature")
data = await request.json()
event_type = data["event"]["event_type"]
handlers = {
"lead.created": handle_lead_created,
"opportunity.status_changed": handle_opp_stage_change,
}
if handler := handlers.get(event_type):
await handler(data["event"]["data"])
return {"status": "ok"}
Close Webhook 事件
lead.created, lead.updated, lead.deleted, lead.status_changed
contact.created, contact.updated
opportunity.created, opportunity.status_changed
activity.note.created, activity.call.created, activity.email.created
unsubscribed_email.created
</webhook_patterns>
<sync_architecture>
跨 CRM 同步
架构
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Close │────▶│ Sync Layer │◀────│ HubSpot │
│ (Primary) │◀────│ (Postgres) │────▶│ (Marketing)│
└─────────────┘ └──────────────┘ └─────────────┘
同步记录架构
CREATE TABLE crm_sync_records (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
entity_type VARCHAR(50) NOT NULL,
close_id VARCHAR(100) UNIQUE,
hubspot_id VARCHAR(100) UNIQUE,
salesforce_id VARCHAR(100) UNIQUE,
email VARCHAR(255),
company_name VARCHAR(255),
last_synced_at TIMESTAMPTZ,
sync_source VARCHAR(50),
sync_hash VARCHAR(64)
);
CREATE INDEX idx_sync_email ON crm_sync_records(email);
冲突解决
from enum import Enum
class ConflictStrategy(Enum):
CLOSE_WINS = "close" # Close is source of truth
LAST_WRITE_WINS = "lww" # Most recent update wins
def resolve_conflict(close_record, hubspot_record, strategy):
if strategy == ConflictStrategy.CLOSE_WINS:
merged = close_record.copy()
for key, value in hubspot_record.items():
if key not in merged or not merged[key]:
merged[key] = value
return merged
去重、迁移脚本和批量同步请参阅
reference/sync-patterns.md。 </sync_architecture>
<file_locations>
参考文件
特定 CRM:
reference/close-deep-dive.md- 查询语言、Smart Views、序列、报告reference/hubspot-patterns.md- SDK 模式、批量操作、工作流reference/salesforce-patterns.md- JWT 身份验证、SOQL、Platform Events、bulk API
运维:
reference/sync-patterns.md- 跨 CRM 同步、去重、迁移reference/automation.md- Webhook 设置、序列、工作流
模板:
templates/close-client.py- 完整的 Close API 客户端templates/hubspot-client.py- HubSpot SDK 封装templates/sync-service.py- 跨 CRM 同步服务 </file_locations>
用户需要 CRM 集成: → 询问使用哪种 CRM(推荐 Close,因其简单易用) → 提供身份验证设置和基本 CRUD
用户需要 Close CRM:
→ 提供 API 密钥设置和查询语言
→ 参考:reference/close-deep-dive.md
用户需要 HubSpot:
→ 提供 SDK 设置和搜索模式
→ 参考:reference/hubspot-patterns.md
用户需要 Salesforce:
→ 提供 JWT 身份验证和 SOQL 模式
→ 参考:reference/salesforce-patterns.md
用户需要在 CRM 之间同步:
→ 提供同步架构和冲突解决方案
→ 参考:reference/sync-patterns.md
用户需要 Webhook: → 提供指定 CRM 的处理程序模式 → 包含签名验证
<env_setup>
环境变量
# Close CRM
export CLOSE_API_KEY="api_xxx"
export CLOSE_WEBHOOK_SECRET="whsec_xxx"
# HubSpot
export HUBSPOT_ACCESS_TOKEN="pat-xxx"
# Salesforce
export SF_CLIENT_ID="xxx"
export SF_USERNAME="[email protected]"
export SF_PRIVATE_KEY_PATH="./salesforce.key"
export SF_INSTANCE_URL="https://yourorg.my.salesforce.com"
# Dependencies: httpx pyjwt hubspot-api-client python-dotenv
</env_setup>
<example_session>
示例会话
用户:“我需要将经过增强的销售线索从我的 sales-agent 推送到 Close CRM”
Claude:
- 以下是将增强后的数据推送到 Close 的模式:
async def push_to_close(close_client, enriched_data: dict) -> str:
lead_data = {
"name": enriched_data["company_name"],
"url": enriched_data.get("website"),
"custom.cf_tier": enriched_data["tier"],
"custom.cf_source": "sales-agent",
"contacts": [{
"name": c["name"],
"title": c.get("title"),
"emails": [{"email": c["email"]}] if c.get("email") else []
} for c in enriched_data.get("contacts", [])]
}
result = close_client.create_lead(lead_data)
return result["id"]
-
确保在 Close 中设置了以下自定义字段:
cf_tier(选项:Gold、Silver、Bronze)cf_source(选项:sales-agent、inbound、referral)
-
速率限制:每 10 秒 100 个请求。批量导入时,请在请求之间添加
asyncio.sleep(0.1)。 </example_session>