deal-management
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseResources
资源
| File | When to use |
|---|---|
| Lifecycle stage API values + the contact-side updates that pair with deal moves. |
| Filter cookbook for stalled / no-activity / past-close-date deals with dynamic dates. |
| 文件 | 使用场景 |
|---|---|
| 生命周期阶段API值 + 与交易变动对应的联系人端更新。 |
| 用于筛选停滞/无活动/超期交易的过滤器指南,支持动态日期。 |
Foundations
基础准备
Read first — JSONL piping, batch read, pagination, and the dry-run/digest/confirm flow live there. Reshape recipes are in . is the source of truth. Object types are plural (, , ). For property reference: — don't hardcode property tables.
bulk-operations/SKILL.mdbulk-operations/resources/json-patterns.mdhubspot <command> --helpcontactsdealscompanieshubspot properties list --type deals先阅读——JSONL管道、批量读取、分页以及试运行/摘要/确认流程都在其中。重塑方案在中。是权威参考。对象类型为复数形式(、、)。如需属性参考:——不要硬编码属性表。
bulk-operations/SKILL.mdbulk-operations/resources/json-patterns.mdhubspot <command> --helpcontactsdealscompanieshubspot properties list --type deals1. Discover pipelines and stages
1. 发现销售管道和阶段
Pipeline and stage IDs are portal-specific. Always discover at runtime — never hardcode across portals.
bash
hubspot pipelines list --type deals --format jsonl管道和阶段ID是门户专属的。务必在运行时获取——切勿跨门户硬编码。
bash
hubspot pipelines list --type deals --format jsonl{"id":"default","label":"Sales Pipeline","displayOrder":0}
{"id":"default","label":"Sales Pipeline","displayOrder":0}
{"id":"a1b2c3d4-0000-0000-0000-000000000000","label":"Enterprise Pipeline","displayOrder":1}
{"id":"a1b2c3d4-0000-0000-0000-000000000000","label":"Enterprise Pipeline","displayOrder":1}
hubspot pipelines stages --type deals --pipeline default --format jsonl
hubspot pipelines stages --type deals --pipeline default --format jsonl
{"id":"appointmentscheduled","label":"Appointment Scheduled","displayOrder":0}
{"id":"appointmentscheduled","label":"Appointment Scheduled","displayOrder":0}
{"id":"qualifiedtobuy","label":"Qualified To Buy","displayOrder":1}
{"id":"qualifiedtobuy","label":"Qualified To Buy","displayOrder":1}
...
...
{"id":"closedwon","label":"Closed Won","displayOrder":5}
{"id":"closedwon","label":"Closed Won","displayOrder":5}
{"id":"closedlost","label":"Closed Lost","displayOrder":6}
{"id":"closedlost","label":"Closed Lost","displayOrder":6}
Grab a specific stage ID by label:
```bash
QUALIFIED=$(hubspot pipelines stages --type deals --pipeline default --format jsonl \
| jq -r 'select(.label=="Qualified To Buy") | .id')The IDs shown above (, , etc.) are HubSpot's standard deal pipeline stages — but discover yours every run since portals can rename or remove them.
appointmentscheduledclosedwondefault
通过标签获取特定阶段ID:
```bash
QUALIFIED=$(hubspot pipelines stages --type deals --pipeline default --format jsonl \
| jq -r 'select(.label=="Qualified To Buy") | .id')上面显示的ID(、等)是HubSpot标准的交易管道阶段——但每次运行都要获取自己的阶段,因为门户可能会重命名或删除它们。
appointmentscheduledclosedwondefault2. Qualify an MQL into a deal
2. 将MQL转化为交易
Find connected MQLs without a deal, then for each: create the deal, associate to contact + company, promote lifecycle.
bash
undefined找到未关联交易的已连接MQL,然后为每个线索:创建交易,关联到联系人+公司,提升生命周期阶段。
bash
undefined1. find ready MQLs
1. 查找就绪的MQL
hubspot objects search --type contacts
--filter "lifecyclestage=marketingqualifiedlead AND hs_lead_status=CONNECTED AND num_associated_deals=0"
--properties email,firstname,lastname,company,hubspot_owner_id
--filter "lifecyclestage=marketingqualifiedlead AND hs_lead_status=CONNECTED AND num_associated_deals=0"
--properties email,firstname,lastname,company,hubspot_owner_id
hubspot objects search --type contacts
--filter "lifecyclestage=marketingqualifiedlead AND hs_lead_status=CONNECTED AND num_associated_deals=0"
--properties email,firstname,lastname,company,hubspot_owner_id
--filter "lifecyclestage=marketingqualifiedlead AND hs_lead_status=CONNECTED AND num_associated_deals=0"
--properties email,firstname,lastname,company,hubspot_owner_id
2. for one contact: company lookup, deal create, associate, promote
2. 针对单个联系人:查找公司、创建交易、关联、提升阶段
hubspot associations list --from contacts:<contact_id> --to companies # → <company_id>
hubspot objects create --type deals
--property "dealname=Acme Corp - Inbound"
--property pipeline=default --property dealstage=qualifiedtobuy
--property amount=0 --property hubspot_owner_id=<owner_id>
--property "dealname=Acme Corp - Inbound"
--property pipeline=default --property dealstage=qualifiedtobuy
--property amount=0 --property hubspot_owner_id=<owner_id>
hubspot associations list --from contacts:<contact_id> --to companies # → <company_id>
hubspot objects create --type deals
--property "dealname=Acme Corp - Inbound"
--property pipeline=default --property dealstage=qualifiedtobuy
--property amount=0 --property hubspot_owner_id=<owner_id>
--property "dealname=Acme Corp - Inbound"
--property pipeline=default --property dealstage=qualifiedtobuy
--property amount=0 --property hubspot_owner_id=<owner_id>
returns {"id":"<deal_id>","ok":true,...}
返回 {"id":"<deal_id>","ok":true,...}
hubspot associations create --from deals:<deal_id> --to contacts:<contact_id>
hubspot associations create --from deals:<deal_id> --to companies:<company_id>
hubspot objects update --type contacts <contact_id>
--property lifecyclestage=salesqualifiedlead --property hs_lead_status=OPEN_DEAL
--property lifecyclestage=salesqualifiedlead --property hs_lead_status=OPEN_DEAL
undefinedhubspot associations create --from deals:<deal_id> --to contacts:<contact_id>
hubspot associations create --from deals:<deal_id> --to companies:<company_id>
hubspot objects update --type contacts <contact_id>
--property lifecyclestage=salesqualifiedlead --property hs_lead_status=OPEN_DEAL
--property lifecyclestage=salesqualifiedlead --property hs_lead_status=OPEN_DEAL
undefinedBulk pattern — many MQLs at once
批量模式——同时处理多个MQL
objects createbash
undefinedobjects createbash
undefined1. snapshot MQLs to a file (preserves order for the join)
1. 将MQL快照保存到文件(保留顺序用于后续关联)
hubspot objects search --type contacts
--filter "lifecyclestage=marketingqualifiedlead AND hs_lead_status=CONNECTED AND num_associated_deals=0"
--properties email,firstname,lastname,company,hubspot_owner_id \
--filter "lifecyclestage=marketingqualifiedlead AND hs_lead_status=CONNECTED AND num_associated_deals=0"
--properties email,firstname,lastname,company,hubspot_owner_id \
/tmp/mqls.jsonl
hubspot objects search --type contacts
--filter "lifecyclestage=marketingqualifiedlead AND hs_lead_status=CONNECTED AND num_associated_deals=0"
--properties email,firstname,lastname,company,hubspot_owner_id \
--filter "lifecyclestage=marketingqualifiedlead AND hs_lead_status=CONNECTED AND num_associated_deals=0"
--properties email,firstname,lastname,company,hubspot_owner_id \
/tmp/mqls.jsonl
2. one deal per MQL — output preserves order
2. 每个MQL对应一个交易——输出保留输入顺序
jq -c '{properties:{
dealname: ((.properties.firstname // "") + " " + (.properties.lastname // "") + " - " + (.properties.company // "Unknown")),
pipeline:"default", dealstage:"qualifiedtobuy", amount:"0", dealtype:"newbusiness",
hubspot_owner_id:(.properties.hubspot_owner_id // "")
}}' /tmp/mqls.jsonl
| hubspot objects create --type deals > /tmp/deals.jsonl
| hubspot objects create --type deals > /tmp/deals.jsonl
jq -c '{properties:{
dealname: ((.properties.firstname // "") + " " + (.properties.lastname // "") + " - " + (.properties.company // "Unknown")),
pipeline:"default", dealstage:"qualifiedtobuy", amount:"0", dealtype:"newbusiness",
hubspot_owner_id:(.properties.hubspot_owner_id // "")
}}' /tmp/mqls.jsonl
| hubspot objects create --type deals > /tmp/deals.jsonl
| hubspot objects create --type deals > /tmp/deals.jsonl
3. abort if any create failed — paste would zip null deal IDs onto real contacts
3. 如果有创建失败则终止——paste会将无效的交易ID与真实联系人配对
jq -e 'select(.ok==false)' /tmp/deals.jsonl > /dev/null && { echo "Some deal creates failed — inspect /tmp/deals.jsonl" >&2; exit 1; }
jq -e 'select(.ok==false)' /tmp/deals.jsonl > /dev/null && { echo "部分交易创建失败——请检查/tmp/deals.jsonl" >&2; exit 1; }
4. pair contact <-> new deal by line for the association call
4. 按行配对联系人<->新交易,用于关联调用
paste <(jq -r '.id' /tmp/mqls.jsonl) <(jq -r '.id' /tmp/deals.jsonl)
| jq -cR 'split("\t") | {from:("deals:" + .[1]), to:("contacts:" + .[0])}'
| hubspot associations create
| jq -cR 'split("\t") | {from:("deals:" + .[1]), to:("contacts:" + .[0])}'
| hubspot associations create
paste <(jq -r '.id' /tmp/mqls.jsonl) <(jq -r '.id' /tmp/deals.jsonl)
| jq -cR 'split("\t") | {from:("deals:" + .[1]), to:("contacts:" + .[0])}'
| hubspot associations create
| jq -cR 'split("\t") | {from:("deals:" + .[1]), to:("contacts:" + .[0])}'
| hubspot associations create
5. promote lifecycle on every contact
5. 提升所有联系人的生命周期阶段
jq -c '{id, properties:{lifecyclestage:"salesqualifiedlead", hs_lead_status:"OPEN_DEAL"}}' /tmp/mqls.jsonl
| hubspot objects update --type contacts
| hubspot objects update --type contacts
Company associations need a separate per-contact pass via `hubspot associations list --from contacts:<id> --to companies` — a contact may have zero or many companies.
Pre-qualification checks are just filters on the search: has email, has a company, no open deal, has an owner — all in the `--filter` already. See `resources/lifecycle-stage-progression.md` for the full stage progression and contact-side updates.jq -c '{id, properties:{lifecyclestage:"salesqualifiedlead", hs_lead_status:"OPEN_DEAL"}}' /tmp/mqls.jsonl
| hubspot objects update --type contacts
| hubspot objects update --type contacts
公司关联需要通过`hubspot associations list --from contacts:<id> --to companies`单独遍历每个联系人——一个联系人可能没有或关联多个公司。
预资格检查只需在搜索中添加过滤器:有邮箱、有公司、无未结交易、有负责人——这些都已包含在`--filter`中。完整的阶段推进和联系人端更新请参阅`resources/lifecycle-stage-progression.md`。3. Advance or reassign in bulk
3. 批量推进或重新分配交易
bash
undefinedbash
undefinedmove every deal in one stage to the next — preview, then re-run without --dry-run
将某个阶段的所有交易推进到下一阶段——先预览,然后去掉--dry-run重新运行
hubspot objects search --type deals --filter "dealstage=qualifiedtobuy"
| jq -c '{id, properties:{dealstage:"presentationscheduled"}}'
| hubspot objects update --type deals --dry-run
| jq -c '{id, properties:{dealstage:"presentationscheduled"}}'
| hubspot objects update --type deals --dry-run
hubspot objects search --type deals --filter "dealstage=qualifiedtobuy"
| jq -c '{id, properties:{dealstage:"presentationscheduled"}}'
| hubspot objects update --type deals --dry-run
| jq -c '{id, properties:{dealstage:"presentationscheduled"}}'
| hubspot objects update --type deals --dry-run
reassign open deals from one rep to another
将未结交易从一位负责人重新分配给另一位
OLD=$(hubspot owners list --format jsonl | jq -r 'select(.email=="old@co.com") | .id')
NEW=$(hubspot owners list --format jsonl | jq -r 'select(.email=="new@co.com") | .id')
hubspot objects search --type deals --filter "hubspot_owner_id=$OLD AND hs_is_closed!=true"
| jq -c "{id, properties:{hubspot_owner_id:"$NEW"}}"
| hubspot objects update --type deals --dry-run
| jq -c "{id, properties:{hubspot_owner_id:"$NEW"}}"
| hubspot objects update --type deals --dry-run
For >100 rows, the dry-run emits a digest line; re-pipe with `--digest <hash> --confirm <count>`. Full flow in `bulk-operations/SKILL.md`.OLD=$(hubspot owners list --format jsonl | jq -r 'select(.email=="old@co.com") | .id')
NEW=$(hubspot owners list --format jsonl | jq -r 'select(.email=="new@co.com") | .id')
hubspot objects search --type deals --filter "hubspot_owner_id=$OLD AND hs_is_closed!=true"
| jq -c "{id, properties:{hubspot_owner_id:"$NEW"}}"
| hubspot objects update --type deals --dry-run
| jq -c "{id, properties:{hubspot_owner_id:"$NEW"}}"
| hubspot objects update --type deals --dry-run
如果行数超过100,试运行会输出一条摘要行;重新管道时使用`--digest <hash> --confirm <count>`。完整流程请参阅`bulk-operations/SKILL.md`。4. Find stalled deals
4. 查找停滞交易
Filter cookbook with dynamic dates lives in . The core query:
resources/stalled-deal-queries.mdbash
undefined包含动态日期的过滤器指南在中。核心查询:
resources/stalled-deal-queries.mdbash
undefinedopen deals with no activity in 30 days (macOS / Linux date examples in resources)
30天无活动的未结交易(资源中有macOS/Linux日期示例)
hubspot objects search --type deals
--filter "hs_last_activity_date<$(date -v-30d +%Y-%m-%d) AND hs_is_closed!=true"
--properties dealname,dealstage,closedate,hubspot_owner_id,hs_last_activity_date
--filter "hs_last_activity_date<$(date -v-30d +%Y-%m-%d) AND hs_is_closed!=true"
--properties dealname,dealstage,closedate,hubspot_owner_id,hs_last_activity_date
Pipe the result into an update (extend close dates, move stage, set a flag) or into task creation. For follow-up tasks/calls/notes against stalled deals, see the `sales-execution` skill — don't duplicate activity-object property handling here.
```bashhubspot objects search --type deals
--filter "hs_last_activity_date<$(date -v-30d +%Y-%m-%d) AND hs_is_closed!=true"
--properties dealname,dealstage,closedate,hubspot_owner_id,hs_last_activity_date
--filter "hs_last_activity_date<$(date -v-30d +%Y-%m-%d) AND hs_is_closed!=true"
--properties dealname,dealstage,closedate,hubspot_owner_id,hs_last_activity_date
可将结果传入更新操作(延长截止日期、移动阶段、设置标记)或任务创建。针对停滞交易的跟进任务/通话/备注,请参阅`sales-execution`技能——此处请勿重复处理活动对象属性。
```bashextend close dates for everything past due
为所有超期交易延长截止日期
hubspot objects search --type deals
--filter "closedate<$(date +%Y-%m-%d) AND hs_is_closed!=true"
| jq -c '{id, properties:{closedate:"2026-06-30"}}'
| hubspot objects update --type deals --dry-run
--filter "closedate<$(date +%Y-%m-%d) AND hs_is_closed!=true"
| jq -c '{id, properties:{closedate:"2026-06-30"}}'
| hubspot objects update --type deals --dry-run
undefinedhubspot objects search --type deals
--filter "closedate<$(date +%Y-%m-%d) AND hs_is_closed!=true"
| jq -c '{id, properties:{closedate:"2026-06-30"}}'
| hubspot objects update --type deals --dry-run
--filter "closedate<$(date +%Y-%m-%d) AND hs_is_closed!=true"
| jq -c '{id, properties:{closedate:"2026-06-30"}}'
| hubspot objects update --type deals --dry-run
undefined5. Close
5. 完成交易
Closing is a stage update + (YYYY-MM-DD). and are read-only — HubSpot derives them from the stage.
closedatehs_is_closedhs_is_closed_wonbash
undefined完成交易是阶段更新 + (YYYY-MM-DD格式)。和是只读属性——HubSpot会根据阶段自动推导它们的值。
closedatehs_is_closedhs_is_closed_wonbash
undefinedsingle
单个交易
hubspot objects update --type deals <deal_id>
--property dealstage=closedwon --property closedate=2026-05-15
--property dealstage=closedwon --property closedate=2026-05-15
hubspot objects update --type deals <deal_id>
--property dealstage=closedwon --property closedate=2026-05-15
--property dealstage=closedwon --property closedate=2026-05-15
bulk — preview first
批量处理——先预览
hubspot objects search --type deals --filter "dealstage=contractsent AND hubspot_owner_id=<owner_id>"
| jq -c '{id, properties:{dealstage:"closedwon", closedate:"2026-05-15"}}'
| hubspot objects update --type deals --dry-run
| jq -c '{id, properties:{dealstage:"closedwon", closedate:"2026-05-15"}}'
| hubspot objects update --type deals --dry-run
Win/loss analysis (close reasons, win rate, ARR roll-up) is in the `sales-reporting` skill.hubspot objects search --type deals --filter "dealstage=contractsent AND hubspot_owner_id=<owner_id>"
| jq -c '{id, properties:{dealstage:"closedwon", closedate:"2026-05-15"}}'
| hubspot objects update --type deals --dry-run
| jq -c '{id, properties:{dealstage:"closedwon", closedate:"2026-05-15"}}'
| hubspot objects update --type deals --dry-run
输赢分析(关闭原因、赢单率、ARR汇总)在`sales-reporting`技能中。Known constraints
已知限制
- Bulk MQL → deal needs a two-pass shell flow: associations must be built from output, not in the same pipe.
objects create - is forward-only in most portal settings — backward transitions may be rejected.
lifecyclestage - is a date string (
closedate). Datetime activity props (YYYY-MM-DD) also accept a date string forhs_last_activity_date/<comparisons.> - No sequences/cadences API in the CLI — create a follow-up task via instead.
sales-execution
- 批量将MQL转为交易需要两步shell流程:关联必须从的输出构建,不能在同一管道中完成。
objects create - 在大多数门户设置中,只能向前推进——反向转换可能会被拒绝。
lifecyclestage - 是日期字符串(
closedate)。日期时间活动属性(YYYY-MM-DD)在进行hs_last_activity_date/<比较时也接受日期字符串。> - CLI中没有序列/节奏API——请通过创建跟进任务。
sales-execution