@revfleet/hscli 0.8.7 โ†’ 0.8.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/CHANGELOG.md +247 -0
  2. package/CONTRIBUTING.md +120 -0
  3. package/README.md +42 -8
  4. package/brand/readme-hero.svg +25 -0
  5. package/dist/cli.js +35 -0
  6. package/dist/cli.js.map +1 -1
  7. package/dist/commands/account/index.js +5 -6
  8. package/dist/commands/account/index.js.map +1 -1
  9. package/dist/commands/api/index.js +43 -3
  10. package/dist/commands/api/index.js.map +1 -1
  11. package/dist/commands/auth/index.js +74 -13
  12. package/dist/commands/auth/index.js.map +1 -1
  13. package/dist/commands/cms/hubdb.js +31 -0
  14. package/dist/commands/cms/hubdb.js.map +1 -1
  15. package/dist/commands/cms/index.js +27 -0
  16. package/dist/commands/cms/index.js.map +1 -1
  17. package/dist/commands/cms/source-code.js +21 -0
  18. package/dist/commands/cms/source-code.js.map +1 -1
  19. package/dist/commands/communication-preferences/index.js +11 -12
  20. package/dist/commands/communication-preferences/index.js.map +1 -1
  21. package/dist/commands/crm/activities.d.ts +3 -0
  22. package/dist/commands/crm/activities.js +186 -0
  23. package/dist/commands/crm/activities.js.map +1 -0
  24. package/dist/commands/crm/index.js +4 -0
  25. package/dist/commands/crm/index.js.map +1 -1
  26. package/dist/commands/crm/migration.d.ts +3 -0
  27. package/dist/commands/crm/migration.js +155 -0
  28. package/dist/commands/crm/migration.js.map +1 -0
  29. package/dist/commands/crm/properties.js +105 -18
  30. package/dist/commands/crm/properties.js.map +1 -1
  31. package/dist/commands/crm/property-batch.d.ts +34 -0
  32. package/dist/commands/crm/property-batch.js +205 -0
  33. package/dist/commands/crm/property-batch.js.map +1 -0
  34. package/dist/commands/crm/shared.d.ts +1 -0
  35. package/dist/commands/crm/shared.js +3 -4
  36. package/dist/commands/crm/shared.js.map +1 -1
  37. package/dist/commands/doctor/index.js +119 -1
  38. package/dist/commands/doctor/index.js.map +1 -1
  39. package/dist/commands/events/index.js +7 -8
  40. package/dist/commands/events/index.js.map +1 -1
  41. package/dist/commands/forms/index.js +47 -6
  42. package/dist/commands/forms/index.js.map +1 -1
  43. package/dist/commands/forms/legacy-v2.d.ts +6 -0
  44. package/dist/commands/forms/legacy-v2.js +350 -0
  45. package/dist/commands/forms/legacy-v2.js.map +1 -0
  46. package/dist/commands/forms/property-preflight.d.ts +20 -0
  47. package/dist/commands/forms/property-preflight.js +99 -0
  48. package/dist/commands/forms/property-preflight.js.map +1 -0
  49. package/dist/commands/guide/index.d.ts +3 -0
  50. package/dist/commands/guide/index.js +231 -0
  51. package/dist/commands/guide/index.js.map +1 -0
  52. package/dist/commands/marketing/index.js +3 -4
  53. package/dist/commands/marketing/index.js.map +1 -1
  54. package/dist/commands/settings/index.js +249 -14
  55. package/dist/commands/settings/index.js.map +1 -1
  56. package/dist/core/auth.d.ts +7 -1
  57. package/dist/core/auth.js +45 -7
  58. package/dist/core/auth.js.map +1 -1
  59. package/dist/core/http.d.ts +43 -0
  60. package/dist/core/http.js +227 -57
  61. package/dist/core/http.js.map +1 -1
  62. package/dist/core/output.d.ts +2 -0
  63. package/dist/core/output.js +1 -1
  64. package/dist/core/output.js.map +1 -1
  65. package/dist/core/plugins.d.ts +5 -2
  66. package/dist/core/plugins.js +18 -1
  67. package/dist/core/plugins.js.map +1 -1
  68. package/dist/core/scopes.d.ts +29 -0
  69. package/dist/core/scopes.js +415 -0
  70. package/dist/core/scopes.js.map +1 -0
  71. package/dist/core/telemetry-context.d.ts +13 -0
  72. package/dist/core/telemetry-context.js +30 -0
  73. package/dist/core/telemetry-context.js.map +1 -0
  74. package/dist/mcp/ext-tools.d.ts +1 -1
  75. package/dist/mcp/ext-tools.js +52 -1
  76. package/dist/mcp/ext-tools.js.map +1 -1
  77. package/dist/mcp/hubspot-modules.d.ts +30 -0
  78. package/dist/mcp/hubspot-modules.js +305 -0
  79. package/dist/mcp/hubspot-modules.js.map +1 -0
  80. package/dist/mcp/server.d.ts +2 -0
  81. package/dist/mcp/server.js +120 -48
  82. package/dist/mcp/server.js.map +1 -1
  83. package/docs/ARCHITECTURE.md +39 -0
  84. package/docs/CAPABILITY_LIBRARY.md +639 -0
  85. package/docs/CMS_SETUP.md +349 -0
  86. package/docs/COMMAND_COMPATIBILITY.md +24 -0
  87. package/docs/COMMAND_TREE.md +199 -0
  88. package/docs/COMMERCE_SETUP.md +400 -0
  89. package/docs/COMPARISON.md +146 -0
  90. package/docs/COOKBOOK.md +896 -0
  91. package/docs/INTEGRATIONS_NOTIFICATIONS_SETUP.md +352 -0
  92. package/docs/MARKETING_SETUP.md +509 -0
  93. package/docs/MCP.md +172 -0
  94. package/docs/OPERATIONAL_PLAYBOOKS.md +322 -0
  95. package/docs/OPERATIONS_SETUP.md +362 -0
  96. package/docs/PLUGIN_GUIDE.md +158 -0
  97. package/docs/POLICY_EXAMPLE.json +57 -0
  98. package/docs/PORTAL_SETUP.md +684 -0
  99. package/docs/PUBLISHING.md +154 -0
  100. package/docs/RELEASE_GOVERNANCE.md +34 -0
  101. package/docs/REPORTING_SETUP.md +310 -0
  102. package/docs/ROADMAP-DATE-BASED-API.md +103 -0
  103. package/docs/ROADMAP_PHASE1_TO_3.md +96 -0
  104. package/docs/SAFETY_MODEL.md +40 -0
  105. package/docs/SALES_SETUP.md +369 -0
  106. package/docs/SERVICE_SETUP.md +403 -0
  107. package/docs/TESTING_PLAN.md +89 -0
  108. package/docs/TIERS.md +320 -0
  109. package/docs/TUTORIALS/audit-portal-writes.md +150 -0
  110. package/docs/TUTORIALS/secure-agent-writes.md +177 -0
  111. package/docs/TUTORIALS/trace-replay-repro.md +147 -0
  112. package/docs/WHY_HOW_WHAT.md +81 -0
  113. package/package.json +7 -2
@@ -0,0 +1,639 @@
1
+ # hscli Capability Library
2
+
3
+ > **Scope.** Every CRM, Marketing, Sales, Service, Content, and Admin job a
4
+ > HubSpot user performs through the UI, mapped to the hscli CLI + MCP
5
+ > commands that replicate it.
6
+ >
7
+ > **Verification.** Every โš ๏ธ and โŒ entry below was probed directly against
8
+ > HubSpot's public API on 2026-04-23 (portal 147975758, EU1). Exact
9
+ > HTTP status + error message recorded in Appendix C. Nothing in this
10
+ > doc is "claimed from priors" โ€” if we couldn't reproduce it we removed
11
+ > it.
12
+ >
13
+ > **Legend:**
14
+ > - โœ… Full parity โ€” endpoint works via hscli
15
+ > - โš ๏ธ Partial โ€” endpoint works but shape-restricted, or requires a
16
+ > workaround (each case has specifics below)
17
+ > - โŒ HubSpot API-locked โ€” no public endpoint exists (verified: 404 on
18
+ > every reasonable path)
19
+ > - ๐Ÿšง hscli-allowlist-blocked โ€” HubSpot serves the path, hscli's
20
+ > `INVALID_PATH_SCOPE` guard rejects it. Fixable in hscli.
21
+ > - ๐Ÿ”’ Enterprise-tier endpoint (exists but portal tier gates access)
22
+
23
+ ---
24
+
25
+ ## 1. CRM data operations
26
+
27
+ ### Contacts, Companies, Deals, Tickets
28
+
29
+ | Job | Command | Status |
30
+ |---|---|---|
31
+ | Create / read / update / archive | `hscli crm {type} create|get|update|delete` | โœ… |
32
+ | List (paginated + filters) | `hscli crm {type} list --limit N --after <cursor>` | โœ… |
33
+ | Complex search | `hscli crm {type} search --data '{"filterGroups":[...]}'` | โœ… |
34
+ | Batch CRUD | `hscli crm {type} batch-create|batch-update|batch-archive` | โœ… |
35
+ | Merge (dedupe) | `hscli crm contacts merge --primary <id> --merge-from <id>` | โœ… |
36
+ | Bulk import (CSV/JSON) | `hscli crm imports create --data '{...}'` | โœ… |
37
+
38
+ ### Engagements (calls, meetings, emails, notes, tasks)
39
+
40
+ All five types: `hscli crm engagements {type} create|get|update|delete|list` plus batch variants. โœ…
41
+
42
+ ### Properties + pipelines + associations + owners
43
+
44
+ | Job | Command | Status |
45
+ |---|---|---|
46
+ | Property CRUD + enum edits | `hscli crm properties create|batch-create|update|delete|list|get` | โœ… |
47
+ | Property groups | `hscli crm properties groups create|list|update|delete` | โœ… |
48
+ | Schema description | `hscli crm describe <objectType>` | โœ… |
49
+ | Pre-flight payload validation | `hscli crm validate <objectType> --data '{...}'` | โœ… |
50
+ | Pipelines + stages | `hscli crm pipelines create|update|list + pipelines stages โ€ฆ` | โœ… |
51
+ | Associations + labels (v4) | `hscli crm associations + associations labels` | โœ… |
52
+ | Owners | `hscli crm owners list|get` | โœ… |
53
+
54
+ ### Custom objects
55
+
56
+ | Job | Command | Status |
57
+ |---|---|---|
58
+ | Define / update schemas | `hscli crm custom-objects schemas create|update|list|get` | โœ… |
59
+ | CRUD records | `hscli crm custom-objects records create|get|list|update|delete` | โœ… |
60
+
61
+ ### Commerce + Sales-Hub objects
62
+
63
+ All readable + writable via standard CRM endpoints:
64
+
65
+ | Object | Command | Notes |
66
+ |---|---|---|
67
+ | `hscli crm quotes` | โœ… | Quotes CRUD via `/crm/v3/objects/quotes`. **Verified on this portal.** |
68
+ | `hscli crm quote-templates` | โœ… | Quote template records readable via `/crm/v3/objects/quote_templates`. |
69
+ | `hscli crm products` | โœ… | Product catalog CRUD. |
70
+ | `hscli crm line_items` | โœ… | Quote / deal line items. |
71
+ | `hscli crm invoices` | ๐Ÿ”’ | Commerce Hub gated; API available on eligible portals. |
72
+ | `hscli crm commerce_payments` | ๐Ÿ”’ | Same. |
73
+ | `hscli crm subscriptions` | ๐Ÿ”’ | Subscription billing. |
74
+ | `hscli crm goals` | โœ… | Goal targets via `/crm/v3/objects/goal_targets`. **Verified.** |
75
+ | Forecasts (read-only) | `hscli api request --path "/crm/v4/objects/forecast"` | โœ… โ€” records + schema both accessible. **Verified.** |
76
+
77
+ ### Playbooks (Sales Hub Enterprise)
78
+
79
+ - Playbook object schema accessible at `/crm/v3/schemas/playbooks`. **Verified.**
80
+ - Playbook-record CRUD works via the standard custom-object pattern:
81
+ `hscli crm custom-objects records create --schema-id <playbook_schema_id> --data '{...}'` โœ…
82
+ - Original library claimed "Playbook content authoring โŒ UI-only" โ€” **that was wrong.** Corrected.
83
+
84
+ ### Incremental sync (ETL)
85
+
86
+ `hscli crm sync` โ€” cursor-based delta sync feeding external warehouses. โœ…
87
+
88
+ ---
89
+
90
+ ## 2. Marketing operations
91
+
92
+ ### Marketing emails
93
+
94
+ | Job | Command | Status | Notes |
95
+ |---|---|---|---|
96
+ | Create DRAFT / AUTOMATED_DRAFT email | `hscli marketing emails create --data '{...}'` | โœ… | |
97
+ | List / get / update / archive | `hscli marketing emails list|get|update` | โœ… | |
98
+ | Per-email statistics | via `hscli api request --path "/marketing/v3/emails/statistics/{id}"` | โš ๏ธ | Per-email stats path `/marketing/v3/emails/{id}/statistics` returns 404. Aggregate stats live under `/email-events/v1/events` โ€” use `hscli email-events campaign <campaignId>`. |
99
+ | **Revision history** | `hscli marketing emails revisions <id>` | โœ… | `GET /marketing/v3/emails/{id}/revisions`. |
100
+ | **Restore past revision to DRAFT** | `hscli marketing emails revision-restore <id> <revisionId>` | โœ… | `POST /marketing/v3/emails/{id}/revisions/{revisionId}/restore-to-draft`. |
101
+ | **Unpublish** | `hscli marketing emails unpublish <id>` | โœ… | `POST /marketing/v3/emails/{id}/unpublish`. |
102
+ | **Reset draft to last-published state** | `hscli marketing emails draft-reset <id>` | โœ… | `POST /marketing/v3/emails/{id}/draft/reset`. |
103
+ | **Publish v3 email** | `hscli marketing emails publish <id>` | โœ… | `POST /marketing/v3/emails/{id}/publish`. Verified live. |
104
+ | Create in published `AUTOMATED` state directly | n/a | โŒ | API explicitly rejects with *"Creating an email in the published state AUTOMATED is not allowed. Consider using AUTOMATED_DRAFT."* Use `create` + `publish` instead. |
105
+ | Update state `AUTOMATED_DRAFT` โ†’ `AUTOMATED` via PATCH/PUT | n/a | โŒ | PATCH returns 400 "Error validating request"; PUT returns 405. Must use `/publish` endpoint. |
106
+ | **Clone v3 email** | `hscli marketing emails clone <id> --name '<name>'` | โœ… | `POST /marketing/v3/emails/clone` โ€” id goes in the **body**, not the path. Verified live 2026-04-23. Earlier miss (I only tried `/clone`, `/copies`, etc. with id in path). |
107
+ | **A/B test variant authoring** | `hscli marketing emails ab-variant --content-id <id> --name '<name>'` | โœ… | `POST /marketing/v3/emails/ab-test/create-variation` with `{contentId, variationName}` body. Verified live 2026-04-23. Returned email has `isAb: true`. |
108
+ | **Multi-module body via flexAreas** | `content.flexAreas.main.sections + content.widgets` | โš ๏ธ | Only `@hubspot/rich_text`, `@hubspot/email_footer`, and the `preview_text` widget render in the in-editor iframe. `@hubspot/button`, `@hubspot/divider`, `@hubspot/header`, `@hubspot/linked_image`, `@hubspot/email_linked_image` persist in the DB but silently no-op in the editor canvas. Workaround: compose body as multiple rich_text sections with inline HTML. |
109
+ | **Body image** | inline `<img>` in rich_text, src = HubFS URL | โš ๏ธ | Renders only in the **webversion preview URL** (`https://{portal}.hubspotpreview-{hublet}.com/_hcms/preview/email/{id}?preview_key=โ€ฆ`). The in-editor iframe sandboxes cross-origin images. First upload the image via `POST /files/v3/files/import-from-url/async` to get a HubFS URL. |
110
+ | Merge-tag chip markup | n/a | โŒ | Chip is an in-edit React overlay, not persistent markup. Tested 5 variants (span + data attrs + various classes) โ€” none reproduce the chip. HubSpot's own UI-created emails also store raw `{{ }}` in their widget HTML. |
111
+ | Upload custom email template | `POST /cms/v3/source-code/published/content/{path}` | โš ๏ธ | Endpoint returns 415 "Unsupported Media Type" with JSON body โ€” it expects `text/plain` or `multipart/form-data`. hscli's `api request` currently hardcodes `Content-Type: application/json`. Fix in hscli needed to unlock full uploads. |
112
+
113
+ ### Landing pages
114
+
115
+ | Job | Command | Status |
116
+ |---|---|---|
117
+ | Create / update / list / get | `hscli marketing landing-pages create|update|list|get` + `hscli cms landing-pages โ€ฆ` | โœ… |
118
+ | Populate layout with drag-drop modules | `layoutSections` + `widgets` | โœ… โ€” unlike emails, page canvas renders `@hubspot/button`, `@hubspot/divider`, `@hubspot/header`, `@hubspot/form`, etc. |
119
+ | Attach template | `templatePath: "@hubspot/growth/templates/homepage.html"` | โš ๏ธ โ€” template must exist on portal, else "template missing" modal. |
120
+ | Publish page | state transition via update | โœ… |
121
+ | Site pages (non-landing) | `hscli cms site-pages` | โœ… |
122
+
123
+ ### Forms
124
+
125
+ - `hscli forms create|get|list|update|translate-v2` โœ…
126
+ - Legacy `/forms/v2/forms` exports can be translated to `/marketing/v3/forms` payloads during create/update, with target-property preflight and automatic 3-field group splitting โœ…
127
+ - `hscli submissions list <formGuid>` โœ…
128
+ - `hscli submissions search <portalId> <formGuid>` โœ…
129
+ - Embed codes: generated client-side from form id โœ…
130
+
131
+ ### Lists (static + dynamic)
132
+
133
+ | Job | Command | Status |
134
+ |---|---|---|
135
+ | Create static list | `hscli lists create --data '{... "processingType":"MANUAL"}'` | โœ… |
136
+ | Create dynamic list (filter rules) | `--data '{..., "processingType":"DYNAMIC", "filterBranch":{...}}'` | โœ… |
137
+ | Membership CRUD | `hscli lists add-members|remove-members|memberships` | โœ… |
138
+ | Folders | `hscli lists folders โ€ฆ` | โœ… |
139
+
140
+ ### Campaigns
141
+
142
+ - `hscli marketing campaigns list|get|create|update|delete` โœ…
143
+ - Per-campaign contacts / assets / revenue / budget โœ…
144
+
145
+ ### Ads (Google / Meta / LinkedIn)
146
+
147
+ - `hscli marketing ads accounts|campaigns|audiences` โœ…
148
+ - Running ads requires the Ads Hub tier ๐Ÿ”’
149
+
150
+ ### Social
151
+
152
+ - `hscli marketing social posts list|get|create|delete` โ€” scheduled posts โœ…
153
+ - Interactive inbox actions (like, reply) โŒ โ€” no public endpoint found.
154
+
155
+ ### SEO
156
+
157
+ - `hscli marketing seo topic-clusters|recommendations` โœ…
158
+ - `hscli cms seo-audit` โ€” site-wide SEO audit โœ…
159
+
160
+ ### Marketing events
161
+
162
+ - `hscli marketing events create|list|update|delete` โœ…
163
+ - Event attendees + external-id mapping โœ…
164
+
165
+ ### Transactional email (single-send API)
166
+
167
+ - `hscli marketing transactional send` ๐Ÿ”’ โ€” requires Transactional Email add-on.
168
+
169
+ ### Subscription / communication preferences
170
+
171
+ - `hscli marketing subscriptions subscription-types` โœ…
172
+ - `hscli communication-preferences subscribe|unsubscribe|status` โœ…
173
+ - GDPR-compliant consent management โœ…
174
+
175
+ ---
176
+
177
+ ## 3. Sales operations
178
+
179
+ ### Sequences (sales cadences)
180
+
181
+ - `hscli sales sequences list|get|enroll|pause|resume` โœ…
182
+ - Template + enrollment analytics โœ…
183
+
184
+ ### Meetings
185
+
186
+ - `hscli sales meetings list|get|create|update` โœ…
187
+ - Availability schedules โœ…
188
+ - Scheduled meetings (record layer) โœ…
189
+
190
+ ### Calling
191
+
192
+ - `hscli sales calling` โ€” call records + engagement hooks โœ…
193
+
194
+ ### Quotes
195
+
196
+ - `hscli crm quotes` โ€” CRUD โœ… (requires Sales Hub Pro+ on some tiers ๐Ÿ”’)
197
+ - Quote templates readable via `hscli crm quote_templates` โœ…
198
+ - E-signature submission | โŒ | Verified 404 on `POST /crm/v3/objects/quotes/{id}/esignature`. |
199
+
200
+ ### Forecasts
201
+
202
+ - Read accessible via `/crm/v4/objects/forecast` โœ…
203
+ - Forecast category authoring | โŒ | Verified 404 on `/crm/v3/forecasts/categories` + `/analytics/v2/reports/sales/forecast`. |
204
+
205
+ ---
206
+
207
+ ## 4. Service / Support
208
+
209
+ ### Tickets
210
+
211
+ - Full CRUD via `hscli crm tickets` โœ…
212
+ - Pipelines via `hscli crm pipelines` โœ…
213
+ - SLA policies | โŒ | Verified 404 on `/conversations/v3/sla-policies` + 400 on `/crm/v3/objects/sla_policies`. No public SLA endpoint. |
214
+
215
+ ### Conversations (inbox)
216
+
217
+ | Job | Command | Status |
218
+ |---|---|---|
219
+ | List threads | `hscli conversations threads list` | โœ… |
220
+ | Get thread + messages | `hscli conversations threads get|messages list` | โœ… |
221
+ | Post a message | `hscli conversations messages send` | โœ… |
222
+ | Inboxes / channels | `hscli conversations inboxes|channels|channel-accounts` | โœ… |
223
+ | Custom channels (app-dev) | `hscli conversations custom-channels` | โœ… |
224
+
225
+ ### Chatflows / chatbots
226
+
227
+ - `hscli service chatflows` โŒ โ€” Verified 404 on `/conversations/v3/chatflows` (list + get). hscli's `chatflows` subcommand currently 404s on every verb. Authoring + decision-tree config are UI-only.
228
+
229
+ ### Feedback / surveys
230
+
231
+ - `hscli reporting feedback` โ€” aggregate analytics โœ…
232
+ - Survey definition endpoints | ๐Ÿšง | `/feedback/v3/*` and `/feedback/v4/*` return `INVALID_PATH_SCOPE` from hscli's own allowlist โ€” **not** a HubSpot-side block. One-line hscli fix would unlock survey CRUD. |
233
+
234
+ ### Knowledge base
235
+
236
+ - `hscli service kb` โš ๏ธ โ€” partial; HubSpot's public KB API surface is inconsistent across portals.
237
+
238
+ ---
239
+
240
+ ## 5. Automation
241
+
242
+ ### Workflows
243
+
244
+ HubSpot exposes TWO public workflow APIs:
245
+
246
+ **๐ŸŽฏ Legacy v3 `/automation/v3/workflows`** โ€” accepts populated `actions[]` on create. Dual-backed: workflows created via v3 also appear via v4 (`migrationStatus.flowId`) and render in the modern HubSpot canvas UI with visible action nodes. Contact-based only.
247
+
248
+ **v4 `/automation/v4/flows`** โ€” current API. Works for metadata + enrollment triggers. `actions[]` on create returns 500 (schema internal). Recommended: create via v3, read/list via either.
249
+
250
+ | Job | Command | Status | Evidence |
251
+ |---|---|---|---|
252
+ | **Create multi-step workflow** (DELAY ยท EMAIL ยท SET_PROPERTY ยท BRANCH ยท WEBHOOK ยท UPDATE_LIST ยท TASK ยท TICKET ยท DEAL ยท NOTIFICATION) | `hscli workflows v3 create --data '{...}'` | โœ… | **Verified 2026-04-23:** 5-step DELAYโ†’EMAILโ†’DELAYโ†’SET_PROPERTYโ†’BRANCH workflow created via one CLI call; renders in HubSpot canvas at `/workflows/{portal}/platform/flow/{migrationStatus.flowId}/edit` as a full multi-node canvas. |
253
+ | List / get / delete v3 workflow | `hscli workflows v3 list|get|delete` | โœ… | Full CRUD via `/automation/v3/workflows/*`. |
254
+ | Enroll / unenroll contact | `hscli workflows v3 enroll|unenroll <workflowId> <email>` | โœ… | `/automation/v3/workflows/{id}/enrollments/contacts/{email}`. |
255
+ | Get contact's current enrollments | `hscli workflows v3 enrollments <email>` | โœ… | `/automation/v3/contacts/{email}/workflowEnrollments`. |
256
+ | Enrollment criteria (`segmentCriteria` list filters) | v3 payload `segmentCriteria` field | โœ… | Standard contact-list filter shape (see HubSpot Contact Lists API). |
257
+ | Goals (`goalCriteria`) | v3 payload `goalCriteria` field | โœ… | Same list-filter shape as enrollment. |
258
+ | Create v4 flow (metadata + enrollment trigger, no actions) | `hscli workflows flows create` | โœ… | `type: "CONTACT_FLOW", flowType: "WORKFLOW"` required. |
259
+ | `LIST_BASED` enrollment criteria on v4 | `enrollmentCriteria.listFilterBranch` | โœ… | Works with property filters (IS_ANY_OF, IS_EQUAL_TO, etc.). |
260
+ | List / get / update v4 flow metadata | `hscli workflows flows list|get|update` | โœ… | |
261
+ | **Populate `actions[]` on v4** | POST / PATCH `/automation/v4/flows` | โŒ | **Re-verified.** POST with `actions:[...]` โ†’ 500. PATCH โ†’ 405. Action schema is internal-only. **Workaround: create via v3 instead** โ€” the same workflow surfaces on v4 (`migrationStatus.flowId`) with all actions intact. |
262
+ | **Enable / disable a v4 flow** | `hscli workflows flows enable|disable <flowId>` | โœ… | `PUT /automation/v4/flows/{id}` with full flow body including `revisionId` and `isEnabled`. Verified live 2026-04-23. PATCH returns 405 (why we missed it first time) โ€” PUT is the correct verb. |
263
+ | **Resolve v3โ†”v4 workflow id pair** | `hscli workflows id-map <idV3OrV4>` | โœ… | No dedicated endpoint; wrapper reads `migrationStatus.flowId` / `migrationStatus.workflowId` from the v3 or v4 GET response. Useful for migration tooling + when you need to jump from one API to the other. |
264
+ | Re-enroll contacts | `shouldReEnroll: true` in v4 flow; `allowContactToTriggerMultipleTimes` in v3 | โœ… | |
265
+
266
+ #### v3 action catalog (what you can actually ship)
267
+
268
+ All supported `type` values on v3 `actions[]`:
269
+
270
+ `DELAY` ยท `EMAIL` (send marketing email by `emailContentId`) ยท `SET_CONTACT_PROPERTY` ยท `SET_COMPANY_PROPERTY` ยท `COPY_PROPERTY` ยท `COPY_COMPANY_PROPERTY` ยท `ADD_SUBTRACT_PROPERTY` ยท `BRANCH` (with `acceptActions`/`rejectActions`) ยท `WEBHOOK` ยท `UPDATE_LIST` (add/remove static list) ยท `TASK` ยท `TICKET` ยท `DEAL` ยท `NOTIFICATION` ยท `SMS_NOTIFICATION` ยท `LEAD_ASSIGNMENT` ยท `WORKFLOW_ENROLLMENT` ยท `CREATE_SFDC_TASK` ยท `UPDATE_EMAIL_SUBSCRIPTION` ยท `SET_SALESFORCE_CAMPAIGN_MEMBERSHIP`
271
+
272
+ BRANCH example:
273
+
274
+ ```json
275
+ {"type":"BRANCH",
276
+ "filters":[[{"operator":"EQ","property":"industry","value":"COMPUTER_SOFTWARE","type":"string"}]],
277
+ "acceptActions":[{"type":"SET_CONTACT_PROPERTY","propertyName":"hs_lead_status","newValue":"CONNECTED"}],
278
+ "rejectActions":[{"type":"SET_CONTACT_PROPERTY","propertyName":"hs_lead_status","newValue":"ATTEMPTED_TO_CONTACT"}]}
279
+ ```
280
+
281
+ ### Sequences
282
+
283
+ - `hscli sales sequences` โœ… (see ยง3)
284
+
285
+ ### Custom workflow actions (app-dev)
286
+
287
+ - `hscli automation actions` โ€” define code blocks that surface in other portals' workflow canvases โœ…
288
+
289
+ ### Scoring
290
+
291
+ - Score properties: `hscli crm properties create --data '{"type":"number", "hubspotDefined":false ...}'` โœ…
292
+ - Score-formula / equation configuration โŒ โ€” UI-only (no public endpoint).
293
+
294
+ ---
295
+
296
+ ## 6. CMS (Content Hub)
297
+
298
+ ### Website pages
299
+
300
+ - `hscli cms site-pages create|get|list|update` โœ…
301
+ - Templates, layoutSections, widgets โœ…
302
+
303
+ ### Landing pages
304
+
305
+ - `hscli cms landing-pages + hscli marketing landing-pages` โœ…
306
+
307
+ ### Blog
308
+
309
+ - `hscli cms blog-posts` + `blog-authors|blog-tags|blog-settings` โœ…
310
+
311
+ ### Redirects
312
+
313
+ - `hscli cms redirects create|list|update|delete` โœ…
314
+
315
+ ### Domains
316
+
317
+ - Read: `hscli cms domains list|get` โœ… (verified)
318
+ - Add new domain | โŒ | Verified 405 on `POST /cms/v3/domains`. Domain connection + TLS provisioning is UI-only. |
319
+
320
+ ### HubDB (relational content tables)
321
+
322
+ - `hscli cms hubdb create|list|get|rows|delete` โœ…
323
+ - **Export**: `hscli cms hubdb export <tableId> --format CSV|XLSX|XLS [--output <path>]` โœ… โ€” returns file content inline or writes to disk.
324
+ - Row CRUD + schema โœ…
325
+ - **Import** (CSV/XLSX upload) | โœ… | `hscli cms hubdb import <tableId> --file <path> --config '{"format":"CSV","columnMappings":[โ€ฆ]}'`. Real multipart; transport verified. CSV-specific imports require a Content-Hub plan tier that supports them (API returns "CSV imports are not supported" on incompatible portals โ€” XLSX works broadly). |
326
+
327
+ ### Source code + module library
328
+
329
+ - `hscli cms source-code get|metadata|extract` โœ…
330
+ - **Module schema discovery**: `/cms/v3/source-code/published/content/@hubspot/{module}.module/fields.json` returns the full field schema for any HubSpot-built module. See ยง9 for the inventory.
331
+ - **Upload custom modules/templates** | โœ… | `hscli cms source-code upload <env> <destPath> --file <local>`. Uses real `multipart/form-data` with a FormData-generated boundary. Verified live 2026-04-23. Also: `hscli cms upload <destPath> --file <local>` targets the legacy `content/filemapper/v1/upload/*` endpoint (what `hs upload` actually uses under the hood). |
332
+ - Path validator rejects `/` in `@hubspot/button.module/fields.json` โ€” use `hscli api request` as workaround until fix lands.
333
+
334
+ ### Site search
335
+
336
+ - `hscli site-search search|indexed` โœ…
337
+
338
+ ### Memberships
339
+
340
+ - Via `hscli crm custom-objects records` on the membership object โš ๏ธ โ€” partial.
341
+ - Member-facing UI (registration, gated content) โŒ โ€” CMS-rendering-only.
342
+
343
+ ---
344
+
345
+ ## 7. Developer / Operations Hub
346
+
347
+ ### Webhooks
348
+
349
+ - `hscli webhooks list|subscribe|delete` โœ…
350
+ - Requires developer-app context ๐Ÿ”’
351
+
352
+ ### Custom behavioral events
353
+
354
+ - `hscli events send|list|definitions` โœ…
355
+
356
+ ### Feature flags (app-dev)
357
+
358
+ - `hscli feature-flags list|get|create|update|delete` โœ…
359
+
360
+ ### Integrations metadata
361
+
362
+ - `hscli integrations me|timeline` โœ…
363
+ - `hscli integrators timeline-event-templates` โœ…
364
+
365
+ ### Extensions (calling, videoconferencing, accounting)
366
+
367
+ - `hscli extensions calling|videoconferencing|accounting` โœ…
368
+
369
+ ### Media Bridge (video/media partners)
370
+
371
+ - `hscli media-bridge properties|schemas|settings|events` โœ…
372
+
373
+ ### Visitor identification (chat widget)
374
+
375
+ - `hscli visitor-identification token` โœ…
376
+
377
+ ### Exports
378
+
379
+ - `hscli exports create|list|get|status` โœ…
380
+
381
+ ### Timeline
382
+
383
+ - `hscli timeline event-templates|events` โœ…
384
+
385
+ ---
386
+
387
+ ## 8. Admin / Security
388
+
389
+ ### Users + teams
390
+
391
+ - `hscli settings users list|create|update|delete` โœ…
392
+ - `hscli settings teams list|create|update|delete` โœ…
393
+ - `hscli settings permission-sets list|get|create|update|delete` โœ… โ€” internal `/api/app-users/v1/permission-sets` endpoint; requires browser session cookie + `x-hubspot-csrf-hubspotapi`, not bearer-token auth.
394
+
395
+ ### Business units
396
+
397
+ - `hscli settings business-units list|create|update|delete` ๐Ÿ”’ โ€” Marketing Hub Enterprise gated. Verified 404 on `/business-units/v3/` + `/settings/v3/business-units` on this (non-Enterprise) portal.
398
+
399
+ ### Multi-currency
400
+
401
+ - `hscli settings currencies list|create|update|delete` โœ…
402
+
403
+ ### Audit logs
404
+
405
+ - `hscli account audit-logs` โ€” account-wide (Enterprise ๐Ÿ”’)
406
+ - `hscli cms audit-logs` โ€” CMS-content audit log โœ…
407
+ - `hscli audit` โ€” hscli-side operational audit of every request โœ…
408
+
409
+ ### GDPR
410
+
411
+ - `hscli settings gdpr delete --email contact@example.com` โœ…
412
+
413
+ ### Private apps
414
+
415
+ - `hscli account private-apps list` โœ…
416
+ - `hscli account api-usage` โœ…
417
+
418
+ ### Brand kits
419
+
420
+ - โŒ โ€” Verified 404 on `/crm/v3/objects/brand_kits`, `/business-units/v3/business-units`, `/settings/v3/brand-kits`. No public endpoint.
421
+
422
+ ---
423
+
424
+ ## 9. HubSpot module library (CMS drag-and-drop)
425
+
426
+ ### Schema discovery endpoint
427
+
428
+ ```bash
429
+ hscli api request \
430
+ --path "/cms/v3/source-code/published/content/@hubspot/{module}.module/fields.json"
431
+ ```
432
+
433
+ Returns every field: `name`, `type`, `default`, `children`, `choices`. That's the surface an agent needs to compose a module the way a UI user drags + fills it in.
434
+
435
+ ### 55 modules verified accessible on this portal
436
+
437
+ **Universal / web-page:**
438
+ `rich_text`, `text`, `header`, `section_header`, `button`, `cta`,
439
+ `divider`, `horizontal_spacer`, `form`, `icon`, `linked_image`,
440
+ `image_grid`, `gallery`, `image_slider_gallery`, `logo`, `logo_grid`,
441
+ `video`, `menu`, `simple_menu`, `language_switcher`, `social_sharing`,
442
+ `social_follow`, `page_footer`, `meetings`, `payments`, `product`,
443
+ `whatsapp_link`
444
+
445
+ **Blog:** `blog_content`, `blog_subscribe`, `blog_comments`,
446
+ `post_filter`, `rss_listing`
447
+
448
+ **System:** `search_input`, `search_results`, `password_prompt`,
449
+ `membership_social_logins`
450
+
451
+ **Email-specific:** `email_header`, `email_cta`, `email_text`,
452
+ `email_section_header`, `email_linked_image`, `email_logo`,
453
+ `email_post_filter`, `email_post_listing`, `email_social_sharing`,
454
+ `email_subscriptions`, `email_subscriptions_confirmation`,
455
+ `email_simple_subscription`, `email_body`, `raw_html_email`,
456
+ `email_can_spam`
457
+
458
+ **Legacy quote templates:** `quote_download`, `quote_payment`,
459
+ `quote_signature`, `line_items`
460
+
461
+ ### 13 modules listed in HubSpot docs but not on this portal
462
+
463
+ Deprecated/renamed or portal-specific-gated:
464
+ `image`, `blog_posts`, `post_listing`, `email_footer` (resolves
465
+ via widget reference even though fields.json 404s), `image_email`,
466
+ `video_email`, `one_line_of_text`, `view_as_web_page`, `whitespace`,
467
+ `spacer`, `follow_me`, `rss_email`, `product_markdown`.
468
+
469
+ ### Render rules (what actually appears where)
470
+
471
+ | Module | Email canvas | Landing/site page | Blog | Notes |
472
+ |---|---|---|---|---|
473
+ | `rich_text` | โœ… | โœ… | โœ… | Universal. Field: `html` (richtext). |
474
+ | `email_footer` | โœ… | โ€” | โ€” | Required CAN-SPAM footer. `email_can_spam` alias resolves to same. |
475
+ | `preview_text` widget | โœ… | โ€” | โ€” | Widget-level, not a module. |
476
+ | `button` | โŒ | โœ… | โœ… | Page-only. In emails, use inline bulletproof `<table>` in rich_text. |
477
+ | `divider` | โŒ | โœ… | โœ… | Page-only. In emails, use `<hr>`. |
478
+ | `header` | โŒ | โœ… | โœ… | Page-only. In emails, wrap `<h1>` in rich_text. |
479
+ | `linked_image` / `email_linked_image` | โš ๏ธ | โœ… | โœ… | In emails: renders only in the webversion preview URL, not the editor iframe (cross-origin image sandbox). The sent email does render the image. |
480
+ | `form` | โŒ (emails can't carry interactive forms by HubSpot policy) | โœ… | โœ… | |
481
+
482
+ ---
483
+
484
+ ## 10. What we can't do (verified blocks)
485
+
486
+ Every row has been probed on 2026-04-23. Full evidence in Appendix C.
487
+
488
+ | Want | Root cause | Evidence |
489
+ |---|---|---|
490
+ | Populate `actions[]` on **v4** workflow | v4 schema internal-only โ€” POST 500 / PATCH 405. **Workaround lives:** use `hscli workflows v3 create` (legacy v3 API accepts full `actions[]`; same workflow appears in v4 + UI canvas). Action creation is NOT blocked by HubSpot โ€” wrong endpoint was being used. |
491
+ | Transition AUTOMATED_DRAFT โ†’ AUTOMATED via PATCH | No state-transition via PATCH | PATCH โ†’ 400; PUT โ†’ 405; use `/publish` endpoint via `hscli marketing emails publish` |
492
+ | Create email in `AUTOMATED` state directly | Explicit API rejection | Error message: *"Creating an email in the published state AUTOMATED is not allowed. Consider using AUTOMATED_DRAFT."* |
493
+ | Transition AUTOMATED_DRAFT โ†’ AUTOMATED via PATCH/PUT | Must use `/publish` | PATCH โ†’ 400; PUT โ†’ 405 |
494
+ | ~~Clone v3 marketing email~~ | UPGRADED 2026-04-23 | Now `hscli marketing emails clone <id>` โ€” endpoint takes id in body, not path. |
495
+ | ~~A/B test / email variant authoring~~ | UPGRADED 2026-04-23 | Now `hscli marketing emails ab-variant --content-id <id> --name 'Variant B'`. |
496
+ | Render body images inside the email editor iframe | Cross-origin iframe sandbox strips external images | Verified across 5 markup variants |
497
+ | Merge-tag chip in stored HTML | Chip is in-edit React overlay only | 5 markup variants tested โ€” none reproduce chip |
498
+ | Connect new domain + TLS | POST to domains is blocked | `POST /cms/v3/domains` โ†’ 405 |
499
+ | Chatflows / chatbot CRUD | No public endpoint | `/conversations/v3/chatflows` โ†’ 404 |
500
+ | Brand kits | No public endpoint | 404 on 3 candidate paths |
501
+ | SLA policies | No public endpoint | 404 on `/conversations/v3/sla-policies`, 400 on `/crm/v3/objects/sla_policies` |
502
+ | E-signature on quote | No public endpoint | `POST /crm/v3/objects/quotes/{id}/esignature` โ†’ 404 |
503
+ | Forecast-category authoring | No public endpoint | 404 on `/crm/v3/forecasts/categories` |
504
+ | Reports v3 API (report authoring) | No public endpoint | 404 on `/reports/v3/reports`, `/reports/v3/report-types`. Analytics DATA is fetchable via `hscli reporting email|content|feedback` + `hscli email-events campaign`; only the UI report-builder is missing. |
505
+ | Personalization token listing | No public endpoint | 404 on `/cms/v3/personalization/tokens` (merge tags still work when typed into HubL) |
506
+
507
+ ---
508
+
509
+ ## 11. Items ๐Ÿšง hscli-side-blocked (quick wins)
510
+
511
+ These are served by HubSpot but hscli's `INVALID_PATH_SCOPE` guard rejects them:
512
+
513
+ | Endpoint | What it unlocks |
514
+ |---|---|
515
+ | `/feedback/v3/*`, `/feedback/v4/*` | Survey definition + submission CRUD |
516
+ | `/goals/v1/*` | Goal CRUD (legacy API, `/crm/v3/objects/goal_targets` is also available) |
517
+ | `/content/tree`, `/content-folders/*` | Folder-tree listing for design manager |
518
+
519
+ Adding these to hscli's allowlist is a one-line-per-path change in the core HTTP client.
520
+
521
+ ---
522
+
523
+ ## 12. Roadmap โ€” hscli-side polish
524
+
525
+ Not HubSpot blocks โ€” things hscli should add/fix:
526
+
527
+ 1. **`cms source-code` path validator** โ€” currently rejects `/`; should accept `@hubspot/*.module/*.json`.
528
+ 2. **`cms source-code list-modules`** โ€” iterates the known-module wordlist + returns inventory as JSON.
529
+ 3. **`marketing emails upload-image`** โ€” wraps `POST /files/v3/files/import-from-url/async` + status polling; returns final HubFS URL.
530
+ 4. **`marketing emails publish <id>`** โ€” surface the `/publish` endpoint as a first-class command (currently only reachable via `api request`).
531
+ 5. **`api request --content-type <type>`** โ€” loosen the default JSON Content-Type to allow template uploads.
532
+ 6. **Allowlist expansion** โ€” add `/feedback/*`, `/goals/v1/*` paths (see ยง11).
533
+ 7. **MCP tool auto-gen from `fields.json`** โ€” every HubSpot module becomes a typed MCP tool with correct input schema.
534
+
535
+ ---
536
+
537
+ ## 13. Undocumented endpoints surfaced from HubSpot's open-source repos
538
+
539
+ A GitHub scan of [HubSpot/hubspot-local-dev-lib](https://github.com/HubSpot/hubspot-local-dev-lib), [HubSpot/hubspot-api-nodejs](https://github.com/HubSpot/hubspot-api-nodejs), and the official `hs` CLI revealed API paths HubSpot's own tooling hits that are **not in developers.hubspot.com** navigation. hscli's allowlist now permits these paths (0.8.7+) โ€” whether they return data depends on your token's scope.
540
+
541
+ | Endpoint family | What it's for | Allowlist status | Scope |
542
+ |---|---|---|---|
543
+ | `/apps-dev/external/public/v3/*` | App-install analytics (test-portal installs, install counts, full portal details) | โœ… allowed | Dev-app token |
544
+ | `/apps-hublets/external/static-token/v3` | Static-token app install | โœ… allowed | Dev-app token |
545
+ | `/dfs/v1/*`, `/dfs/deploy/v1/*`, `/dfs/deploy/v3/*`, `/dfs/logging/v1/*`, `/dfs/migrations/v1/*` | Developer File System โ€” projects upload, deploy, logs, migrations (used by `hs project upload`) | โœ… allowed | Dev-app token |
546
+ | `/project-components-external/v3` | New v3 project upload-with-IR (replaces `dfs/v1/projects/upload/{name}` for apps) | โœ… allowed | Dev-app token |
547
+ | `/file-transport/v1/hubfiles/*` | HubFiles custom-object schema upload (used by `hs hubfiles`) | โœ… allowed | Custom-object scopes |
548
+ | `/localdevauth/v1/*` | Local-dev account linking flow | โœ… allowed | Standard |
549
+ | `/content/filemapper/v1/upload/{urlencoded-dest}` | **The endpoint `hs upload` actually uses** (not `/cms/v3/source-code/*`) for theme/template uploads. Multipart with `file` field. | โœ… (under `content` scope) | Standard |
550
+ | `/crm/v3/lists/{listId}/conversion/*` | List conversion schedule/update/cancel (added Sept 2025, not yet in docs) | โœ… (under `crm` scope) | Standard |
551
+
552
+ ### Multipart endpoints โ€” ALL UNBLOCKED 0.8.8+
553
+
554
+ `src/core/http.ts` now accepts `RequestOptions.multipart` โ€” a field-name โ†’ (string | file) record. Internally it builds a native `FormData` instance and lets Node 20+ `fetch` emit the correct `multipart/form-data; boundary=โ€ฆ` Content-Type (manually setting the header without a boundary was the root cause of our 415s, as also seen in HubSpot's own nodejs SDK).
555
+
556
+ | Endpoint | hscli command | Status |
557
+ |---|---|---|
558
+ | `PUT /cms/v3/source-code/{env}/content/{path}` | `hscli cms source-code upload <env> <destPath> --file <local>` | โœ… verified live |
559
+ | `POST /cms/v3/hubdb/tables/{id}/draft/import` | `hscli cms hubdb import <tableId> --file <path> --config '<json>'` | โœ… transport verified; CSV-import itself tier-gated |
560
+ | `POST /content/filemapper/v1/upload/{dest}` | `hscli cms upload <destPath> --file <local>` | โœ… verified live (mirrors `hs upload`) |
561
+ | `POST /file-transport/v1/hubfiles/object-schemas` | `hscli api request --path /file-transport/v1/hubfiles/object-schemas --method POST --file file=<local>` | โš ๏ธ reachable (raw passthrough); wrapper command pending |
562
+ | `POST /project-components-external/v3/upload/new-api` | `hscli api request --path /project-components-external/v3/upload/new-api --method POST --file projectFilesZip=<zip> --part platformVersion=2026.03 --part uploadRequest='<json>'` | โš ๏ธ reachable via raw passthrough |
563
+
564
+ Also: `hscli api request` now takes `--file <field>=<path>[:<mime>]` (repeatable) and `--part <field>=<value>` (repeatable). So any untyped multipart endpoint is reachable without a dedicated command.
565
+
566
+ ### Additional endpoints documented only in HubSpot's own SDK
567
+
568
+ From [HubSpot/hubspot-api-nodejs codegen](https://github.com/HubSpot/hubspot-api-nodejs):
569
+
570
+ | Endpoint | CLI status |
571
+ |---|---|
572
+ | `POST /marketing/v3/emails/{id}/revisions/{rev}/restore-to-draft` | โœ… `hscli marketing emails revision-restore <id> <rev>` |
573
+ | `POST /marketing/v3/emails/{id}/unpublish` | โœ… `hscli marketing emails unpublish <id>` |
574
+ | `POST /marketing/v3/emails/{id}/draft/reset` | โœ… `hscli marketing emails draft-reset <id>` |
575
+ | `POST /cms/v3/pages/site-pages/ab-test/rerun` (needs `AbTestRerunRequestVNext`) | โœ… (existing `hscli cms site-pages ab-test rerun`) |
576
+ | `POST /crm/v3/lists/{listId}/conversion/{schedule|update|cancel}` (added Sept 2025) | โš ๏ธ Reachable via `hscli api request`; no first-class command yet |
577
+
578
+ ---
579
+
580
+ ## Appendix A โ€” Single-command probes
581
+
582
+ ```bash
583
+ # Every module schema accessible on your portal
584
+ for m in $(cat docs/module-names.txt); do
585
+ hscli api request \
586
+ --path "/cms/v3/source-code/published/content/@hubspot/${m}.module/fields.json" \
587
+ --json | jq -r --arg m "$m" 'if .ok then "โœ“ \($m)" else "โœ— \($m)" end'
588
+ done
589
+
590
+ # Probe all write capabilities on this profile
591
+ hscli doctor --check writes
592
+
593
+ # Every request hscli makes, audited to JSONL
594
+ hscli --telemetry-file ./audit.jsonl <any-command>
595
+
596
+ # Replay a traced session
597
+ hscli trace replay --file ./audit.jsonl --dry-run
598
+ ```
599
+
600
+ ## Appendix B โ€” MCP exposure
601
+
602
+ Every CLI command maps to an MCP tool via:
603
+
604
+ ```bash
605
+ hscli mcp serve # stdio or --transport sse
606
+ ```
607
+
608
+ 1,180+ typed tools covering this capability library. See [MCP.md](MCP.md).
609
+
610
+ ### HubSpot drag-and-drop module library exposed as 3 MCP tools (0.8.8+)
611
+
612
+ Every `@hubspot/*` module's `fields.json` schema is surfaced on demand โ€” not pre-generated as 55 separate tools. Agents get the same "browse โ†’ describe โ†’ fill" flow a UI user has.
613
+
614
+ | Tool | What it does |
615
+ |---|---|
616
+ | `hubspot_module_list` | Enumerate all built-in modules accessible on the caller's portal. Optional `schemas: true` returns full field definitions inline. |
617
+ | `hubspot_module_describe` | Fetch one module's `fields.json` schema: names, types (text, richtext, number, boolean, color, choice, group, image, link, ...), required flags, defaults, choices, nested children. Exactly what a drag-drop user sees when they click a module. |
618
+ | `hubspot_module_compose` | Given a module path + field values, returns a widget body ready to embed in `content.widgets[widgetId]`. Validates values against the schema first โ€” rejects unknown fields and type mismatches with a clear error. No more hand-shaping widget bodies. |
619
+
620
+ Example (agent-driven): "Create a welcome email with a hero image + CTA button" becomes
621
+ 1. `hubspot_module_describe @hubspot/linked_image` โ†’ see what fields the image module takes
622
+ 2. `hubspot_module_describe @hubspot/button` โ†’ see button field shape
623
+ 3. `hubspot_module_compose` ร— 2 โ†’ get validated widget bodies
624
+ 4. `marketing_emails_create` โ†’ paste the composed widgets under `content.widgets` + reference from `flexAreas`
625
+
626
+ This is the hscli-side implementation of the "agent does what a drag-drop human does" value proposition, backed by HubSpot's own module schemas.
627
+
628
+ ## Appendix C โ€” Verification log
629
+
630
+ All status claims in this doc were probed on 2026-04-23 against portal
631
+ 147975758 (EU1). Raw probe logs:
632
+
633
+ - **Tier B retest** (`/tmp/verify-results.txt` during prep): clone/publish/source-code-create/workflow-enable โ€” see exact HTTP codes per entry in ยง10.
634
+ - **Tier C first-probe**: SLA, feedback, playbooks, chatflows, forecasts, brand kits, domains, e-signature, reports, personalization tokens โ€” each entry in ยง10 cites the exact URL + response.
635
+ - **Deep-dive followup** (`/tmp/followup.sh`): retried 415 / 500 / validation errors with cleaner payloads โ€” uncovered that v3 email `/publish` is real (validation-gated), playbook schema is accessible, source-code uploads return 415 (fixable Content-Type issue).
636
+
637
+ No โŒ entry in this library is "claimed from priors." Every block was
638
+ reproduced. Re-run probes before trusting any entry older than the
639
+ date above.