@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,896 @@
1
+ # hscli Cookbook
2
+
3
+ Practical examples for common HubSpot CRM operations using `hscli`.
4
+
5
+ All write operations are **dry-run by default**. Omit flags to see the safety error, use `--dry-run` to preview, and `--force` to execute.
6
+
7
+ ---
8
+
9
+ ## 1. Auth and Setup
10
+
11
+ ### Login with a private app token
12
+
13
+ ```bash
14
+ hscli auth login --token "pat-eu1-a1b2c3d4-5678-9abc-def0-1234567890ab"
15
+ ```
16
+
17
+ Hublet is auto-detected from the token prefix (e.g. `pat-eu1-...` routes to `api-eu1.hubapi.com`).
18
+ If the token does not expose enough metadata, force routing explicitly:
19
+
20
+ ```bash
21
+ hscli auth login --profile live --token-stdin --hublet eu1
22
+ hscli auth set-hublet live eu1
23
+ hscli --hublet eu1 --profile live account info
24
+ ```
25
+
26
+ ### Login via stdin (CI pipelines)
27
+
28
+ ```bash
29
+ echo "$HUBSPOT_TOKEN" | hscli auth login --token-stdin --profile production
30
+ ```
31
+
32
+ ### Switch between profiles
33
+
34
+ ```bash
35
+ hscli auth profiles
36
+ hscli auth whoami --profile staging
37
+ hscli auth profile-show --profile production
38
+ ```
39
+
40
+ ### Inspect token scopes and expiry
41
+
42
+ ```bash
43
+ hscli auth token-info --profile production
44
+ hscli doctor scopes list --filter "crm.objects"
45
+ hscli --profile production doctor scopes diff --required real-mirror-read
46
+ hscli doctor scopes explain sales-email-read
47
+ ```
48
+
49
+ ### Lock a profile to read-only
50
+
51
+ ```bash
52
+ hscli auth set-mode production read-only
53
+ ```
54
+
55
+ Re-enable writes:
56
+
57
+ ```bash
58
+ hscli auth set-mode production read-write
59
+ ```
60
+
61
+ ### Encrypt and decrypt the credential vault
62
+
63
+ Requires `HSCLI_VAULT_PASSPHRASE` environment variable.
64
+
65
+ ```bash
66
+ export HSCLI_VAULT_PASSPHRASE="my-secure-passphrase"
67
+ hscli auth encrypt
68
+ hscli auth decrypt
69
+ ```
70
+
71
+ ### Generate an OAuth authorization URL
72
+
73
+ ```bash
74
+ hscli auth oauth-url \
75
+ --client-id "a1b2c3d4-5678-9abc-def0-1234567890ab" \
76
+ --redirect-uri "https://app.example.com/oauth/callback" \
77
+ --scopes "crm.objects.contacts.read,crm.objects.contacts.write"
78
+ ```
79
+
80
+ ### Exchange an OAuth code for a token
81
+
82
+ ```bash
83
+ hscli auth oauth-exchange \
84
+ --client-id "a1b2c3d4-5678-9abc-def0-1234567890ab" \
85
+ --client-secret "secret-value" \
86
+ --code "auth-code-from-redirect" \
87
+ --redirect-uri "https://app.example.com/oauth/callback" \
88
+ --profile oauth-prod
89
+ ```
90
+
91
+ ---
92
+
93
+ ## 2. CRM Operations (Contacts, Companies, Deals, Tickets)
94
+
95
+ All four object types share the same subcommands: `list`, `get`, `search`, `create`, `update`, `delete`, `merge`, `batch-read`, `batch-upsert`, `batch-archive`.
96
+
97
+ ### List contacts with specific properties
98
+
99
+ ```bash
100
+ hscli crm contacts list --limit 20 --properties "firstname,lastname,email,company"
101
+ ```
102
+
103
+ ### Paginate through companies
104
+
105
+ ```bash
106
+ hscli crm companies list --limit 50 --after "NTI1"
107
+ ```
108
+
109
+ ### Get a single deal by ID
110
+
111
+ ```bash
112
+ hscli crm deals get 18294750312 --properties "dealname,amount,dealstage,closedate"
113
+ ```
114
+
115
+ ### Search contacts by name
116
+
117
+ ```bash
118
+ hscli crm contacts search --query "Sarah Chen" --limit 5
119
+ ```
120
+
121
+ ### Create a contact (dry-run first, then execute)
122
+
123
+ ```bash
124
+ # Preview what would be sent
125
+ hscli crm contacts create --dry-run \
126
+ --data '{"properties":{"firstname":"Maria","lastname":"Gonzalez","email":"maria.gonzalez@acmecorp.com","company":"Acme Corp","phone":"+1-415-555-0198"}}'
127
+
128
+ # Execute the create
129
+ hscli crm contacts create --force \
130
+ --data '{"properties":{"firstname":"Maria","lastname":"Gonzalez","email":"maria.gonzalez@acmecorp.com","company":"Acme Corp","phone":"+1-415-555-0198"}}'
131
+ ```
132
+
133
+ ### Update a deal stage
134
+
135
+ ```bash
136
+ hscli crm deals update 18294750312 --dry-run \
137
+ --data '{"properties":{"dealstage":"contractsent","amount":"45000"}}'
138
+
139
+ hscli crm deals update 18294750312 --force \
140
+ --data '{"properties":{"dealstage":"contractsent","amount":"45000"}}'
141
+ ```
142
+
143
+ ### Delete (archive) a ticket
144
+
145
+ ```bash
146
+ hscli crm tickets delete 9871234567 --dry-run
147
+ hscli crm tickets delete 9871234567 --force
148
+ ```
149
+
150
+ ### Merge duplicate contacts
151
+
152
+ ```bash
153
+ hscli crm contacts merge --dry-run \
154
+ --data '{"primaryObjectId":"551","objectIdToMerge":"552"}'
155
+
156
+ hscli crm contacts merge --force \
157
+ --data '{"primaryObjectId":"551","objectIdToMerge":"552"}'
158
+ ```
159
+
160
+ ### Batch read multiple contacts by ID
161
+
162
+ ```bash
163
+ hscli crm contacts batch-read \
164
+ --data '{"inputs":[{"id":"551"},{"id":"552"},{"id":"553"}],"properties":["firstname","lastname","email"]}'
165
+ ```
166
+
167
+ ### Batch upsert companies
168
+
169
+ ```bash
170
+ hscli crm companies batch-upsert --force \
171
+ --data '{"inputs":[{"idProperty":"domain","id":"acmecorp.com","properties":{"name":"Acme Corp","industry":"Technology"}},{"idProperty":"domain","id":"globex.com","properties":{"name":"Globex Inc","industry":"Manufacturing"}}]}'
172
+ ```
173
+
174
+ ### Batch archive deals
175
+
176
+ ```bash
177
+ hscli crm deals batch-archive --dry-run \
178
+ --data '{"inputs":[{"id":"100"},{"id":"101"},{"id":"102"}]}'
179
+ ```
180
+
181
+ ### Include archived records
182
+
183
+ ```bash
184
+ hscli crm contacts list --archived true --limit 10
185
+ ```
186
+
187
+ ---
188
+
189
+ ## 3. Custom Objects
190
+
191
+ ### List all custom object schemas
192
+
193
+ ```bash
194
+ hscli crm custom-objects schemas list
195
+ ```
196
+
197
+ ### Get a specific schema
198
+
199
+ ```bash
200
+ hscli crm custom-objects schemas get vehicles
201
+ ```
202
+
203
+ ### Create a custom object schema
204
+
205
+ ```bash
206
+ hscli crm custom-objects schemas create --dry-run \
207
+ --data '{"name":"vehicles","labels":{"singular":"Vehicle","plural":"Vehicles"},"primaryDisplayProperty":"vin","properties":[{"name":"vin","label":"VIN","type":"string","fieldType":"text"},{"name":"make","label":"Make","type":"string","fieldType":"text"},{"name":"model","label":"Model","type":"string","fieldType":"text"}]}'
208
+
209
+ hscli crm custom-objects schemas create --force \
210
+ --data '{"name":"vehicles","labels":{"singular":"Vehicle","plural":"Vehicles"},"primaryDisplayProperty":"vin","properties":[{"name":"vin","label":"VIN","type":"string","fieldType":"text"},{"name":"make","label":"Make","type":"string","fieldType":"text"},{"name":"model","label":"Model","type":"string","fieldType":"text"}]}'
211
+ ```
212
+
213
+ ### Update a custom object schema
214
+
215
+ ```bash
216
+ hscli crm custom-objects schemas update vehicles --force \
217
+ --data '{"labels":{"singular":"Vehicle","plural":"Vehicles"},"secondaryDisplayProperties":["make","model"]}'
218
+ ```
219
+
220
+ ### List records of a custom object type
221
+
222
+ ```bash
223
+ hscli crm custom-objects records list vehicles --limit 25
224
+ ```
225
+
226
+ ### Create a custom object record
227
+
228
+ ```bash
229
+ hscli crm custom-objects records create vehicles --force \
230
+ --data '{"properties":{"vin":"1HGCM82633A004352","make":"Honda","model":"Accord"}}'
231
+ ```
232
+
233
+ ### Search custom object records
234
+
235
+ ```bash
236
+ hscli crm custom-objects records search vehicles \
237
+ --data '{"query":"Honda","limit":10}'
238
+ ```
239
+
240
+ ### Delete a custom object record
241
+
242
+ ```bash
243
+ hscli crm custom-objects records delete vehicles 29384756 --force
244
+ ```
245
+
246
+ ---
247
+
248
+ ## 4. Engagements (Notes, Calls, Tasks, Emails, Meetings)
249
+
250
+ All engagement types share the same subcommands as standard CRM objects: `list`, `get`, `search`, `create`, `update`, `delete`, `merge`, `batch-read`, `batch-upsert`, `batch-archive`.
251
+
252
+ ### Create a note
253
+
254
+ ```bash
255
+ hscli crm engagements notes create --force \
256
+ --data '{"properties":{"hs_note_body":"Spoke with Maria about Q2 renewal. She requested a discount proposal by Friday.","hs_timestamp":"2026-03-14T10:30:00Z"}}'
257
+ ```
258
+
259
+ ### List recent calls
260
+
261
+ ```bash
262
+ hscli crm engagements calls list --limit 10 \
263
+ --properties "hs_call_title,hs_call_duration,hs_call_direction,hs_timestamp"
264
+ ```
265
+
266
+ ### Create a task assigned to an owner
267
+
268
+ ```bash
269
+ hscli crm engagements tasks create --dry-run \
270
+ --data '{"properties":{"hs_task_subject":"Follow up on Acme Corp proposal","hs_task_body":"Send revised pricing deck and schedule demo.","hs_task_status":"NOT_STARTED","hs_task_priority":"HIGH","hs_timestamp":"2026-03-18T09:00:00Z","hubspot_owner_id":"284719503"}}'
271
+
272
+ hscli crm engagements tasks create --force \
273
+ --data '{"properties":{"hs_task_subject":"Follow up on Acme Corp proposal","hs_task_body":"Send revised pricing deck and schedule demo.","hs_task_status":"NOT_STARTED","hs_task_priority":"HIGH","hs_timestamp":"2026-03-18T09:00:00Z","hubspot_owner_id":"284719503"}}'
274
+ ```
275
+
276
+ ### Search for meetings
277
+
278
+ ```bash
279
+ hscli crm engagements meetings search --query "product demo" --limit 5
280
+ ```
281
+
282
+ ### Log an email engagement
283
+
284
+ ```bash
285
+ hscli crm engagements emails create --force \
286
+ --data '{"properties":{"hs_email_subject":"Re: Acme Corp Renewal Pricing","hs_email_text":"Hi Maria, attached is the revised pricing.","hs_email_direction":"EMAIL","hs_timestamp":"2026-03-14T14:00:00Z"}}'
287
+ ```
288
+
289
+ ---
290
+
291
+ ## 5. Properties and Associations
292
+
293
+ ### Start with a guided migration workflow
294
+
295
+ ```bash
296
+ hscli guide
297
+
298
+ hscli guide --goal portal-migration
299
+ ```
300
+
301
+ ### Export portal migration metadata
302
+
303
+ ```bash
304
+ hscli crm migration export-metadata --out migration-metadata.json
305
+
306
+ hscli crm migration export-metadata \
307
+ --association-pairs contacts:companies,companies:contacts,2-123456:contacts \
308
+ --out migration-metadata.json
309
+ ```
310
+
311
+ This captures property groups with their real labels/displayOrder, property definitions, deal/ticket pipelines with per-stage detail, custom object schemas, owners, teams, business units, currencies, and standard association labels. Use it before building replay payloads so pipeline IDs/stage IDs and owner/team mappings are explicit.
312
+
313
+ ### Export recoverable record activities
314
+
315
+ ```bash
316
+ hscli crm activities export contacts 12345 --out contact-12345-activities.json
317
+
318
+ hscli crm activities export contacts 12345 \
319
+ --engagement-types notes,emails,calls,tasks,meetings \
320
+ --history-properties createdate,lifecyclestage,hubspot_owner_id,hs_analytics_source \
321
+ --out contact-12345-activities.json
322
+ ```
323
+
324
+ This exports associated notes/emails/calls/tasks/meetings, current segment/list memberships with first/last-added timestamps, hydrated list details, and selected property history. HubSpot does not expose every UI activity-feed card as a replayable public API event, so “created from…” and “moved to…” cards are reconstructed from available properties/history.
325
+
326
+ ### List all properties for contacts
327
+
328
+ ```bash
329
+ hscli crm properties list contacts
330
+ ```
331
+
332
+ ### Get a specific property definition
333
+
334
+ ```bash
335
+ hscli crm properties get deals dealstage
336
+ ```
337
+
338
+ ### Create a custom property
339
+
340
+ ```bash
341
+ hscli crm properties create contacts --dry-run \
342
+ --data '{"name":"preferred_language","label":"Preferred Language","type":"enumeration","fieldType":"select","groupName":"contactinformation","options":[{"label":"English","value":"en"},{"label":"Spanish","value":"es"},{"label":"French","value":"fr"}]}'
343
+
344
+ hscli crm properties create contacts --force \
345
+ --data '{"name":"preferred_language","label":"Preferred Language","type":"enumeration","fieldType":"select","groupName":"contactinformation","options":[{"label":"English","value":"en"},{"label":"Spanish","value":"es"},{"label":"French","value":"fr"}]}'
346
+ ```
347
+
348
+ ### Batch-create properties from a sandbox export
349
+
350
+ Property groups have their own labels and display order. Export/recreate groups from the source portal before property batch-create; do not derive group labels from `groupName`.
351
+
352
+ ```bash
353
+ hscli --json crm properties list contacts > contacts-properties.json
354
+
355
+ hscli --dry-run crm properties batch-create contacts \
356
+ --skip-existing \
357
+ --skip-label-collisions \
358
+ --data @contacts-properties.json
359
+
360
+ hscli --force crm properties batch-create contacts \
361
+ --skip-existing \
362
+ --skip-label-collisions \
363
+ --data @contacts-properties.json
364
+ ```
365
+
366
+ `batch-create` skips `hs_*` reserved names, HubSpot-defined/read-only properties, and empty enumerations by default. It also removes enum options with blank labels/values before sending. If you prefer to keep a property whose enum options cannot be recovered, demote it to a free-text property:
367
+
368
+ ```bash
369
+ hscli --dry-run crm properties batch-create contacts \
370
+ --empty-enum demote \
371
+ --data @contacts-properties.json
372
+ ```
373
+
374
+ For custom objects, pass the object type ID directly:
375
+
376
+ ```bash
377
+ hscli --force crm properties batch-create 2-123456 \
378
+ --data '{"inputs":[{"name":"migration_region","label":"Migration Region","type":"string","fieldType":"text","groupName":"customobjectinformation"}]}'
379
+ ```
380
+
381
+ ### Update a property label
382
+
383
+ ```bash
384
+ hscli crm properties update contacts preferred_language --force \
385
+ --data '{"label":"Preferred Communication Language"}'
386
+ ```
387
+
388
+ ### List associations from a contact to companies
389
+
390
+ ```bash
391
+ hscli crm associations list contacts 551 companies
392
+ ```
393
+
394
+ ### Create an association between a deal and a company
395
+
396
+ ```bash
397
+ hscli crm associations create deals 18294750312 companies 9182736450 --dry-run
398
+ hscli crm associations create deals 18294750312 companies 9182736450 --force
399
+ ```
400
+
401
+ ### Remove an association
402
+
403
+ ```bash
404
+ hscli crm associations remove contacts 551 companies 9182736450 --force
405
+ ```
406
+
407
+ ---
408
+
409
+ ## 6. Pipelines and Owners
410
+
411
+ ### List deal pipelines
412
+
413
+ ```bash
414
+ hscli crm pipelines list deals
415
+ ```
416
+
417
+ ### Get a specific ticket pipeline
418
+
419
+ ```bash
420
+ hscli crm pipelines get tickets 0
421
+ ```
422
+
423
+ ### List owners
424
+
425
+ ```bash
426
+ hscli crm owners list --limit 50
427
+ ```
428
+
429
+ ### Filter owners by email
430
+
431
+ ```bash
432
+ hscli crm owners list --email "sarah.chen@company.com"
433
+ ```
434
+
435
+ ---
436
+
437
+ ## 7. Describe and Validate
438
+
439
+ ### Describe the schema for deals (properties, pipelines, enums)
440
+
441
+ ```bash
442
+ hscli crm describe deals
443
+ ```
444
+
445
+ ### Force a cache refresh
446
+
447
+ ```bash
448
+ hscli crm describe contacts --refresh-cache
449
+ ```
450
+
451
+ ### Use a custom cache TTL
452
+
453
+ ```bash
454
+ hscli crm describe tickets --ttl-hours 4
455
+ ```
456
+
457
+ ### Validate a payload before creating a record
458
+
459
+ ```bash
460
+ hscli crm validate contacts \
461
+ --data '{"properties":{"firstname":"Maria","lastname":"Gonzalez","email":"maria@acmecorp.com"}}'
462
+ ```
463
+
464
+ ### Offline validation (cached schema only)
465
+
466
+ ```bash
467
+ hscli crm validate deals --offline \
468
+ --data '{"properties":{"dealname":"Acme Renewal","amount":"45000","dealstage":"appointmentscheduled"}}'
469
+ ```
470
+
471
+ ---
472
+
473
+ ## 8. Marketing, Forms, Files, CMS, Workflows, Service
474
+
475
+ ### Marketing emails
476
+
477
+ ```bash
478
+ hscli marketing emails list --limit 10
479
+ hscli marketing emails get 87654321
480
+ hscli marketing emails create --dry-run \
481
+ --data '{"name":"March Newsletter","subject":"Your March Product Updates"}'
482
+ ```
483
+
484
+ ### Marketing campaigns
485
+
486
+ ```bash
487
+ hscli marketing campaigns list --limit 5
488
+ hscli marketing campaigns get 12345678
489
+ ```
490
+
491
+ ### Forms
492
+
493
+ ```bash
494
+ hscli forms list --limit 10
495
+ hscli forms get "f47ac10b-58cc-4372-a567-0e02b2c3d479"
496
+
497
+ hscli forms create --dry-run \
498
+ --data '{"name":"Q2 Webinar Signup","formType":"hubspot","configuration":{"language":"en"}}'
499
+
500
+ hscli forms create --dry-run --source-format v2 \
501
+ --data '{"name":"Legacy Webinar Signup","submitText":"Register","formFieldGroups":[{"fields":[{"name":"email","label":"Email","fieldType":"email","required":true}]}]}'
502
+
503
+ hscli forms create --source-format v2 --strict --dry-run \
504
+ --data '{"name":"Legacy Webinar Signup","formFieldGroups":[{"fields":[{"name":"email","label":"Email","fieldType":"email","required":true}]}]}'
505
+
506
+ hscli forms translate-v2 --data '{"name":"Legacy Webinar Signup","submitText":"Register","formFieldGroups":[{"fields":[{"name":"email","label":"Email","fieldType":"email","required":true}]}]}'
507
+
508
+ hscli forms update "f47ac10b-58cc-4372-a567-0e02b2c3d479" --force \
509
+ --data '{"name":"Q2 Webinar Signup (Updated)"}'
510
+ ```
511
+
512
+ ### File assets
513
+
514
+ ```bash
515
+ hscli files assets list --limit 20
516
+ hscli files assets get 48192837465
517
+ hscli files assets update 48192837465 --force \
518
+ --data '{"name":"proposal-final-v2.pdf"}'
519
+ hscli files assets delete 48192837465 --force
520
+ ```
521
+
522
+ ### CMS pages and blog posts
523
+
524
+ ```bash
525
+ hscli cms pages list --limit 10
526
+ hscli cms blogs list --limit 5
527
+ hscli cms blogs get 19283746501
528
+
529
+ hscli cms pages create --dry-run \
530
+ --data '{"name":"Q2 Product Update","slug":"q2-product-update"}'
531
+
532
+ hscli cms blogs delete 19283746501 --force
533
+ ```
534
+
535
+ ### Workflows
536
+
537
+ ```bash
538
+ hscli workflows flows list --limit 10
539
+ hscli workflows flows get 39172845
540
+
541
+ hscli workflows flows create --dry-run \
542
+ --data '{"name":"New Lead Nurture Sequence","type":"PLATFORM_FLOW"}'
543
+ ```
544
+
545
+ ### Service conversations and feedback
546
+
547
+ ```bash
548
+ hscli service conversations list --limit 10
549
+ hscli service feedback list --limit 10
550
+ hscli service feedback get 56789012
551
+
552
+ hscli service feedback create --force \
553
+ --data '{"properties":{"hs_content":"Great onboarding experience.","hs_rating":"5"}}'
554
+ ```
555
+
556
+ ---
557
+
558
+ ## 9. Webhooks
559
+
560
+ ### List webhook subscriptions for an app
561
+
562
+ ```bash
563
+ hscli webhooks list --app-id 12345
564
+ ```
565
+
566
+ ### Create a webhook subscription
567
+
568
+ ```bash
569
+ hscli webhooks subscribe --app-id 12345 --dry-run \
570
+ --data '{"eventType":"contact.creation","propertyName":"email","active":true}'
571
+
572
+ hscli webhooks subscribe --app-id 12345 --force \
573
+ --data '{"eventType":"contact.creation","propertyName":"email","active":true}'
574
+ ```
575
+
576
+ ### Delete a webhook subscription
577
+
578
+ ```bash
579
+ hscli webhooks delete --app-id 12345 --subscription-id 67890 --force
580
+ ```
581
+
582
+ ---
583
+
584
+ ## 10. Imports
585
+
586
+ ### Start an import
587
+
588
+ ```bash
589
+ hscli crm imports create --force \
590
+ --data '{"name":"Q1 Lead List","importOperations":{"0":"CREATE"},"dateFormat":"YEAR_MONTH_DAY","files":[{"fileName":"q1-leads.csv","fileFormat":"CSV","fileImportPage":{"hasHeader":true,"columnMappings":[{"columnObjectTypeId":"0-1","columnName":"Email","propertyName":"email"},{"columnObjectTypeId":"0-1","columnName":"First Name","propertyName":"firstname"}]}}]}'
591
+ ```
592
+
593
+ ### Check import status
594
+
595
+ ```bash
596
+ hscli crm imports list
597
+ hscli crm imports get 84726153
598
+ ```
599
+
600
+ ### View import errors
601
+
602
+ ```bash
603
+ hscli crm imports errors 84726153
604
+ ```
605
+
606
+ ---
607
+
608
+ ## 11. Incremental Sync
609
+
610
+ ### Full pull of all contacts (paginated)
611
+
612
+ ```bash
613
+ hscli crm sync pull contacts --limit 100 --max-pages 10
614
+ ```
615
+
616
+ State is saved to `.hscli-sync-contacts.json` by default. Subsequent runs resume from the last cursor.
617
+
618
+ ### Pull contacts modified since a specific date
619
+
620
+ ```bash
621
+ hscli crm sync pull contacts --since "2026-03-01T00:00:00Z"
622
+ ```
623
+
624
+ ### Custom state file and output file
625
+
626
+ ```bash
627
+ hscli crm sync pull deals \
628
+ --state-file "./sync-state/deals.json" \
629
+ --out-file "./exports/deals-latest.json" \
630
+ --limit 50 \
631
+ --max-pages 20
632
+ ```
633
+
634
+ ### Cron-friendly sync (run periodically, automatically resumes)
635
+
636
+ ```bash
637
+ hscli crm sync pull companies --limit 100 --max-pages 5 --json
638
+ ```
639
+
640
+ ---
641
+
642
+ ## 12. Raw API Requests
643
+
644
+ For endpoints not covered by built-in commands, use `api request`. Write methods go through the same safety controls.
645
+
646
+ ### GET request
647
+
648
+ ```bash
649
+ hscli api request --path "/crm/v3/objects/contacts" --method GET
650
+ ```
651
+
652
+ ### POST search with payload
653
+
654
+ ```bash
655
+ hscli api request --path "/crm/v3/objects/contacts/search" --method POST \
656
+ --data '{"query":"acme","limit":5}'
657
+ ```
658
+
659
+ ### PATCH with safety controls
660
+
661
+ ```bash
662
+ hscli api request --path "/crm/v3/objects/deals/18294750312" --method PATCH --dry-run \
663
+ --data '{"properties":{"dealstage":"closedwon"}}'
664
+
665
+ hscli api request --path "/crm/v3/objects/deals/18294750312" --method PATCH --force \
666
+ --data '{"properties":{"dealstage":"closedwon"}}'
667
+ ```
668
+
669
+ ### DELETE via raw API
670
+
671
+ ```bash
672
+ hscli api request --path "/crm/v3/objects/contacts/551" --method DELETE --force
673
+ ```
674
+
675
+ ### Hit an endpoint not in the CLI (e.g. timeline events)
676
+
677
+ ```bash
678
+ hscli api request --path "/crm/v3/timeline/events" --method POST --force \
679
+ --data '{"eventTemplateId":"12345","objectId":"551","tokens":{"action":"Logged in"}}'
680
+ ```
681
+
682
+ ---
683
+
684
+ ## 13. Safety Controls
685
+
686
+ ### Dry-run (preview without executing)
687
+
688
+ Every write command supports `--dry-run`. It returns the method, path, and body that would be sent, without making the API call.
689
+
690
+ ```bash
691
+ hscli crm contacts create --dry-run \
692
+ --data '{"properties":{"email":"test@example.com"}}'
693
+ ```
694
+
695
+ ### Force (execute the write)
696
+
697
+ Without `--force`, write operations fail with `WRITE_CONFIRMATION_REQUIRED`.
698
+
699
+ ```bash
700
+ hscli crm contacts create --force \
701
+ --data '{"properties":{"email":"test@example.com"}}'
702
+ ```
703
+
704
+ ### Policy file
705
+
706
+ A JSON policy file can restrict writes and deletes per profile. See `docs/POLICY_EXAMPLE.json`.
707
+
708
+ ```bash
709
+ hscli crm contacts delete 551 --force --policy-file ./policy.json
710
+ ```
711
+
712
+ Example policy file:
713
+
714
+ ```json
715
+ {
716
+ "defaults": {
717
+ "allowWrite": true,
718
+ "allowDelete": false,
719
+ "requireChangeTicket": false
720
+ },
721
+ "profiles": {
722
+ "production": {
723
+ "allowDelete": false,
724
+ "requireChangeTicket": true
725
+ }
726
+ },
727
+ "blockedMethodPathPrefixes": {
728
+ "DELETE": ["/crm/v3/schemas"]
729
+ }
730
+ }
731
+ ```
732
+
733
+ ### Change ticket requirement
734
+
735
+ When a policy requires change tickets, all writes must include `--change-ticket`:
736
+
737
+ ```bash
738
+ hscli --profile production crm deals update 18294750312 --force \
739
+ --change-ticket "JIRA-4521" \
740
+ --data '{"properties":{"dealstage":"closedwon"}}'
741
+ ```
742
+
743
+ ### Read-only profile mode
744
+
745
+ Lock a profile so all writes are blocked at the auth layer:
746
+
747
+ ```bash
748
+ hscli auth set-mode production read-only
749
+ ```
750
+
751
+ ### Environment variable for policy
752
+
753
+ The policy file can also be set via environment variable:
754
+
755
+ ```bash
756
+ export HSCLI_POLICY_FILE=./policy.json
757
+ hscli crm contacts create --force \
758
+ --data '{"properties":{"email":"test@example.com"}}'
759
+ ```
760
+
761
+ ---
762
+
763
+ ## 14. MCP Server
764
+
765
+ Run hscli as a Model Context Protocol server over stdio, suitable for integration with AI agents.
766
+
767
+ ```bash
768
+ hscli mcp
769
+ ```
770
+
771
+ Configure in your MCP client (e.g. Claude Desktop `claude_desktop_config.json`):
772
+
773
+ ```json
774
+ {
775
+ "mcpServers": {
776
+ "hubspot": {
777
+ "command": "hscli",
778
+ "args": ["mcp"]
779
+ }
780
+ }
781
+ }
782
+ ```
783
+
784
+ With a specific profile:
785
+
786
+ ```json
787
+ {
788
+ "mcpServers": {
789
+ "hubspot": {
790
+ "command": "hscli",
791
+ "args": ["--profile", "production", "mcp"]
792
+ }
793
+ }
794
+ }
795
+ ```
796
+
797
+ The MCP server exposes the same operations as the CLI with the same safety model (`force: true` required for writes).
798
+
799
+ ---
800
+
801
+ ## 15. Doctor / Diagnostics
802
+
803
+ ### Start from an operator workflow
804
+
805
+ Use Claude-style slash commands when you want the CLI to tell you the next safe sequence:
806
+
807
+ ```bash
808
+ hscli /setup
809
+ hscli /migration
810
+ hscli /read
811
+ hscli /write
812
+ hscli /guardrails
813
+ ```
814
+
815
+ ### Check hublet configuration consistency
816
+
817
+ Verifies that hscli's detected hublet, token prefix, and `@hubspot/cli` config all agree:
818
+
819
+ ```bash
820
+ hscli doctor hublet-check
821
+ hscli doctor hublet-check --profile production
822
+ ```
823
+
824
+ ### Probe endpoint capabilities
825
+
826
+ Discovers which API endpoints are available for the current portal and caches the results:
827
+
828
+ ```bash
829
+ hscli doctor capabilities
830
+ hscli doctor capabilities --refresh
831
+ hscli doctor capabilities --ttl-hours 12
832
+ ```
833
+
834
+ ### Strict capabilities mode
835
+
836
+ Fail fast when an endpoint's capability status is unknown:
837
+
838
+ ```bash
839
+ hscli --strict-capabilities crm contacts list
840
+ ```
841
+
842
+ ---
843
+
844
+ ## 16. Output Formats
845
+
846
+ All commands support `--format` and `--json` flags.
847
+
848
+ ```bash
849
+ hscli crm contacts list --format json
850
+ hscli crm contacts list --format csv
851
+ hscli crm contacts list --format yaml
852
+ hscli crm contacts list --format table # default
853
+ hscli crm contacts list --json # shorthand for --format json
854
+ ```
855
+
856
+ ### Telemetry logging
857
+
858
+ Append request telemetry to a local JSONL file for auditing:
859
+
860
+ ```bash
861
+ hscli --telemetry-file ./telemetry.jsonl crm contacts list
862
+ hscli --telemetry-file ./telemetry.jsonl crm deals create --force \
863
+ --data '{"properties":{"dealname":"Tracked Deal","pipeline":"default"}}'
864
+ ```
865
+
866
+ ---
867
+
868
+ ## 17. Multi-Profile Workflows
869
+
870
+ ### Manage staging and production side by side
871
+
872
+ ```bash
873
+ hscli auth login --token "pat-na1-staging-token" --profile staging
874
+ hscli auth login --token "pat-eu1-production-token" --profile production
875
+
876
+ # Read from staging
877
+ hscli --profile staging crm contacts search --query "test"
878
+
879
+ # Write to production (with safety)
880
+ hscli --profile production crm contacts create --force \
881
+ --data '{"properties":{"email":"verified@customer.com","firstname":"Verified","lastname":"Customer"}}'
882
+ ```
883
+
884
+ ### Audit which profiles exist
885
+
886
+ ```bash
887
+ hscli auth profiles
888
+ hscli auth profile-show --profile staging
889
+ hscli auth profile-show --profile production
890
+ ```
891
+
892
+ ### Remove a profile
893
+
894
+ ```bash
895
+ hscli auth logout --profile staging
896
+ ```