@revfleet/hscli 0.8.7 → 0.8.10

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 (75) hide show
  1. package/CHANGELOG.md +204 -0
  2. package/CONTRIBUTING.md +120 -0
  3. package/README.md +14 -6
  4. package/brand/readme-hero.svg +25 -0
  5. package/dist/cli.js +10 -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 +32 -6
  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/shared.d.ts +1 -0
  22. package/dist/commands/crm/shared.js +3 -4
  23. package/dist/commands/crm/shared.js.map +1 -1
  24. package/dist/commands/events/index.js +7 -8
  25. package/dist/commands/events/index.js.map +1 -1
  26. package/dist/commands/marketing/index.js +3 -4
  27. package/dist/commands/marketing/index.js.map +1 -1
  28. package/dist/commands/settings/index.js +12 -13
  29. package/dist/commands/settings/index.js.map +1 -1
  30. package/dist/core/http.d.ts +27 -0
  31. package/dist/core/http.js +87 -18
  32. package/dist/core/http.js.map +1 -1
  33. package/dist/core/plugins.d.ts +5 -2
  34. package/dist/core/plugins.js +18 -1
  35. package/dist/core/plugins.js.map +1 -1
  36. package/dist/core/telemetry-context.d.ts +13 -0
  37. package/dist/core/telemetry-context.js +30 -0
  38. package/dist/core/telemetry-context.js.map +1 -0
  39. package/dist/mcp/hubspot-modules.d.ts +30 -0
  40. package/dist/mcp/hubspot-modules.js +305 -0
  41. package/dist/mcp/hubspot-modules.js.map +1 -0
  42. package/dist/mcp/server.d.ts +2 -0
  43. package/dist/mcp/server.js +30 -26
  44. package/dist/mcp/server.js.map +1 -1
  45. package/docs/ARCHITECTURE.md +39 -0
  46. package/docs/CAPABILITY_LIBRARY.md +638 -0
  47. package/docs/CMS_SETUP.md +349 -0
  48. package/docs/COMMAND_COMPATIBILITY.md +24 -0
  49. package/docs/COMMAND_TREE.md +183 -0
  50. package/docs/COMMERCE_SETUP.md +400 -0
  51. package/docs/COMPARISON.md +146 -0
  52. package/docs/COOKBOOK.md +800 -0
  53. package/docs/INTEGRATIONS_NOTIFICATIONS_SETUP.md +352 -0
  54. package/docs/MARKETING_SETUP.md +503 -0
  55. package/docs/MCP.md +171 -0
  56. package/docs/OPERATIONAL_PLAYBOOKS.md +322 -0
  57. package/docs/OPERATIONS_SETUP.md +362 -0
  58. package/docs/PLUGIN_GUIDE.md +158 -0
  59. package/docs/POLICY_EXAMPLE.json +57 -0
  60. package/docs/PORTAL_SETUP.md +683 -0
  61. package/docs/PUBLISHING.md +154 -0
  62. package/docs/RELEASE_GOVERNANCE.md +34 -0
  63. package/docs/REPORTING_SETUP.md +310 -0
  64. package/docs/ROADMAP-DATE-BASED-API.md +103 -0
  65. package/docs/ROADMAP_PHASE1_TO_3.md +96 -0
  66. package/docs/SAFETY_MODEL.md +37 -0
  67. package/docs/SALES_SETUP.md +369 -0
  68. package/docs/SERVICE_SETUP.md +403 -0
  69. package/docs/TESTING_PLAN.md +89 -0
  70. package/docs/TIERS.md +320 -0
  71. package/docs/TUTORIALS/audit-portal-writes.md +150 -0
  72. package/docs/TUTORIALS/secure-agent-writes.md +177 -0
  73. package/docs/TUTORIALS/trace-replay-repro.md +147 -0
  74. package/docs/WHY_HOW_WHAT.md +81 -0
  75. package/package.json +7 -2
@@ -0,0 +1,800 @@
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
+
19
+ ### Login via stdin (CI pipelines)
20
+
21
+ ```bash
22
+ echo "$HUBSPOT_TOKEN" | hscli auth login --token-stdin --profile production
23
+ ```
24
+
25
+ ### Switch between profiles
26
+
27
+ ```bash
28
+ hscli auth profiles
29
+ hscli auth whoami --profile staging
30
+ hscli auth profile-show --profile production
31
+ ```
32
+
33
+ ### Inspect token scopes and expiry
34
+
35
+ ```bash
36
+ hscli auth token-info --profile production
37
+ ```
38
+
39
+ ### Lock a profile to read-only
40
+
41
+ ```bash
42
+ hscli auth set-mode production read-only
43
+ ```
44
+
45
+ Re-enable writes:
46
+
47
+ ```bash
48
+ hscli auth set-mode production read-write
49
+ ```
50
+
51
+ ### Encrypt and decrypt the credential vault
52
+
53
+ Requires `HSCLI_VAULT_PASSPHRASE` environment variable.
54
+
55
+ ```bash
56
+ export HSCLI_VAULT_PASSPHRASE="my-secure-passphrase"
57
+ hscli auth encrypt
58
+ hscli auth decrypt
59
+ ```
60
+
61
+ ### Generate an OAuth authorization URL
62
+
63
+ ```bash
64
+ hscli auth oauth-url \
65
+ --client-id "a1b2c3d4-5678-9abc-def0-1234567890ab" \
66
+ --redirect-uri "https://app.example.com/oauth/callback" \
67
+ --scopes "crm.objects.contacts.read,crm.objects.contacts.write"
68
+ ```
69
+
70
+ ### Exchange an OAuth code for a token
71
+
72
+ ```bash
73
+ hscli auth oauth-exchange \
74
+ --client-id "a1b2c3d4-5678-9abc-def0-1234567890ab" \
75
+ --client-secret "secret-value" \
76
+ --code "auth-code-from-redirect" \
77
+ --redirect-uri "https://app.example.com/oauth/callback" \
78
+ --profile oauth-prod
79
+ ```
80
+
81
+ ---
82
+
83
+ ## 2. CRM Operations (Contacts, Companies, Deals, Tickets)
84
+
85
+ All four object types share the same subcommands: `list`, `get`, `search`, `create`, `update`, `delete`, `merge`, `batch-read`, `batch-upsert`, `batch-archive`.
86
+
87
+ ### List contacts with specific properties
88
+
89
+ ```bash
90
+ hscli crm contacts list --limit 20 --properties "firstname,lastname,email,company"
91
+ ```
92
+
93
+ ### Paginate through companies
94
+
95
+ ```bash
96
+ hscli crm companies list --limit 50 --after "NTI1"
97
+ ```
98
+
99
+ ### Get a single deal by ID
100
+
101
+ ```bash
102
+ hscli crm deals get 18294750312 --properties "dealname,amount,dealstage,closedate"
103
+ ```
104
+
105
+ ### Search contacts by name
106
+
107
+ ```bash
108
+ hscli crm contacts search --query "Sarah Chen" --limit 5
109
+ ```
110
+
111
+ ### Create a contact (dry-run first, then execute)
112
+
113
+ ```bash
114
+ # Preview what would be sent
115
+ hscli crm contacts create --dry-run \
116
+ --data '{"properties":{"firstname":"Maria","lastname":"Gonzalez","email":"maria.gonzalez@acmecorp.com","company":"Acme Corp","phone":"+1-415-555-0198"}}'
117
+
118
+ # Execute the create
119
+ hscli crm contacts create --force \
120
+ --data '{"properties":{"firstname":"Maria","lastname":"Gonzalez","email":"maria.gonzalez@acmecorp.com","company":"Acme Corp","phone":"+1-415-555-0198"}}'
121
+ ```
122
+
123
+ ### Update a deal stage
124
+
125
+ ```bash
126
+ hscli crm deals update 18294750312 --dry-run \
127
+ --data '{"properties":{"dealstage":"contractsent","amount":"45000"}}'
128
+
129
+ hscli crm deals update 18294750312 --force \
130
+ --data '{"properties":{"dealstage":"contractsent","amount":"45000"}}'
131
+ ```
132
+
133
+ ### Delete (archive) a ticket
134
+
135
+ ```bash
136
+ hscli crm tickets delete 9871234567 --dry-run
137
+ hscli crm tickets delete 9871234567 --force
138
+ ```
139
+
140
+ ### Merge duplicate contacts
141
+
142
+ ```bash
143
+ hscli crm contacts merge --dry-run \
144
+ --data '{"primaryObjectId":"551","objectIdToMerge":"552"}'
145
+
146
+ hscli crm contacts merge --force \
147
+ --data '{"primaryObjectId":"551","objectIdToMerge":"552"}'
148
+ ```
149
+
150
+ ### Batch read multiple contacts by ID
151
+
152
+ ```bash
153
+ hscli crm contacts batch-read \
154
+ --data '{"inputs":[{"id":"551"},{"id":"552"},{"id":"553"}],"properties":["firstname","lastname","email"]}'
155
+ ```
156
+
157
+ ### Batch upsert companies
158
+
159
+ ```bash
160
+ hscli crm companies batch-upsert --force \
161
+ --data '{"inputs":[{"idProperty":"domain","id":"acmecorp.com","properties":{"name":"Acme Corp","industry":"Technology"}},{"idProperty":"domain","id":"globex.com","properties":{"name":"Globex Inc","industry":"Manufacturing"}}]}'
162
+ ```
163
+
164
+ ### Batch archive deals
165
+
166
+ ```bash
167
+ hscli crm deals batch-archive --dry-run \
168
+ --data '{"inputs":[{"id":"100"},{"id":"101"},{"id":"102"}]}'
169
+ ```
170
+
171
+ ### Include archived records
172
+
173
+ ```bash
174
+ hscli crm contacts list --archived true --limit 10
175
+ ```
176
+
177
+ ---
178
+
179
+ ## 3. Custom Objects
180
+
181
+ ### List all custom object schemas
182
+
183
+ ```bash
184
+ hscli crm custom-objects schemas list
185
+ ```
186
+
187
+ ### Get a specific schema
188
+
189
+ ```bash
190
+ hscli crm custom-objects schemas get vehicles
191
+ ```
192
+
193
+ ### Create a custom object schema
194
+
195
+ ```bash
196
+ hscli crm custom-objects schemas create --dry-run \
197
+ --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"}]}'
198
+
199
+ hscli crm custom-objects schemas create --force \
200
+ --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"}]}'
201
+ ```
202
+
203
+ ### Update a custom object schema
204
+
205
+ ```bash
206
+ hscli crm custom-objects schemas update vehicles --force \
207
+ --data '{"labels":{"singular":"Vehicle","plural":"Vehicles"},"secondaryDisplayProperties":["make","model"]}'
208
+ ```
209
+
210
+ ### List records of a custom object type
211
+
212
+ ```bash
213
+ hscli crm custom-objects records list vehicles --limit 25
214
+ ```
215
+
216
+ ### Create a custom object record
217
+
218
+ ```bash
219
+ hscli crm custom-objects records create vehicles --force \
220
+ --data '{"properties":{"vin":"1HGCM82633A004352","make":"Honda","model":"Accord"}}'
221
+ ```
222
+
223
+ ### Search custom object records
224
+
225
+ ```bash
226
+ hscli crm custom-objects records search vehicles \
227
+ --data '{"query":"Honda","limit":10}'
228
+ ```
229
+
230
+ ### Delete a custom object record
231
+
232
+ ```bash
233
+ hscli crm custom-objects records delete vehicles 29384756 --force
234
+ ```
235
+
236
+ ---
237
+
238
+ ## 4. Engagements (Notes, Calls, Tasks, Emails, Meetings)
239
+
240
+ All engagement types share the same subcommands as standard CRM objects: `list`, `get`, `search`, `create`, `update`, `delete`, `merge`, `batch-read`, `batch-upsert`, `batch-archive`.
241
+
242
+ ### Create a note
243
+
244
+ ```bash
245
+ hscli crm engagements notes create --force \
246
+ --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"}}'
247
+ ```
248
+
249
+ ### List recent calls
250
+
251
+ ```bash
252
+ hscli crm engagements calls list --limit 10 \
253
+ --properties "hs_call_title,hs_call_duration,hs_call_direction,hs_timestamp"
254
+ ```
255
+
256
+ ### Create a task assigned to an owner
257
+
258
+ ```bash
259
+ hscli crm engagements tasks create --dry-run \
260
+ --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"}}'
261
+
262
+ hscli crm engagements tasks create --force \
263
+ --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"}}'
264
+ ```
265
+
266
+ ### Search for meetings
267
+
268
+ ```bash
269
+ hscli crm engagements meetings search --query "product demo" --limit 5
270
+ ```
271
+
272
+ ### Log an email engagement
273
+
274
+ ```bash
275
+ hscli crm engagements emails create --force \
276
+ --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"}}'
277
+ ```
278
+
279
+ ---
280
+
281
+ ## 5. Properties and Associations
282
+
283
+ ### List all properties for contacts
284
+
285
+ ```bash
286
+ hscli crm properties list contacts
287
+ ```
288
+
289
+ ### Get a specific property definition
290
+
291
+ ```bash
292
+ hscli crm properties get deals dealstage
293
+ ```
294
+
295
+ ### Create a custom property
296
+
297
+ ```bash
298
+ hscli crm properties create contacts --dry-run \
299
+ --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"}]}'
300
+
301
+ hscli crm properties create contacts --force \
302
+ --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"}]}'
303
+ ```
304
+
305
+ ### Update a property label
306
+
307
+ ```bash
308
+ hscli crm properties update contacts preferred_language --force \
309
+ --data '{"label":"Preferred Communication Language"}'
310
+ ```
311
+
312
+ ### List associations from a contact to companies
313
+
314
+ ```bash
315
+ hscli crm associations list contacts 551 companies
316
+ ```
317
+
318
+ ### Create an association between a deal and a company
319
+
320
+ ```bash
321
+ hscli crm associations create deals 18294750312 companies 9182736450 --dry-run
322
+ hscli crm associations create deals 18294750312 companies 9182736450 --force
323
+ ```
324
+
325
+ ### Remove an association
326
+
327
+ ```bash
328
+ hscli crm associations remove contacts 551 companies 9182736450 --force
329
+ ```
330
+
331
+ ---
332
+
333
+ ## 6. Pipelines and Owners
334
+
335
+ ### List deal pipelines
336
+
337
+ ```bash
338
+ hscli crm pipelines list deals
339
+ ```
340
+
341
+ ### Get a specific ticket pipeline
342
+
343
+ ```bash
344
+ hscli crm pipelines get tickets 0
345
+ ```
346
+
347
+ ### List owners
348
+
349
+ ```bash
350
+ hscli crm owners list --limit 50
351
+ ```
352
+
353
+ ### Filter owners by email
354
+
355
+ ```bash
356
+ hscli crm owners list --email "sarah.chen@company.com"
357
+ ```
358
+
359
+ ---
360
+
361
+ ## 7. Describe and Validate
362
+
363
+ ### Describe the schema for deals (properties, pipelines, enums)
364
+
365
+ ```bash
366
+ hscli crm describe deals
367
+ ```
368
+
369
+ ### Force a cache refresh
370
+
371
+ ```bash
372
+ hscli crm describe contacts --refresh-cache
373
+ ```
374
+
375
+ ### Use a custom cache TTL
376
+
377
+ ```bash
378
+ hscli crm describe tickets --ttl-hours 4
379
+ ```
380
+
381
+ ### Validate a payload before creating a record
382
+
383
+ ```bash
384
+ hscli crm validate contacts \
385
+ --data '{"properties":{"firstname":"Maria","lastname":"Gonzalez","email":"maria@acmecorp.com"}}'
386
+ ```
387
+
388
+ ### Offline validation (cached schema only)
389
+
390
+ ```bash
391
+ hscli crm validate deals --offline \
392
+ --data '{"properties":{"dealname":"Acme Renewal","amount":"45000","dealstage":"appointmentscheduled"}}'
393
+ ```
394
+
395
+ ---
396
+
397
+ ## 8. Marketing, Forms, Files, CMS, Workflows, Service
398
+
399
+ ### Marketing emails
400
+
401
+ ```bash
402
+ hscli marketing emails list --limit 10
403
+ hscli marketing emails get 87654321
404
+ hscli marketing emails create --dry-run \
405
+ --data '{"name":"March Newsletter","subject":"Your March Product Updates"}'
406
+ ```
407
+
408
+ ### Marketing campaigns
409
+
410
+ ```bash
411
+ hscli marketing campaigns list --limit 5
412
+ hscli marketing campaigns get 12345678
413
+ ```
414
+
415
+ ### Forms
416
+
417
+ ```bash
418
+ hscli forms list --limit 10
419
+ hscli forms get "f47ac10b-58cc-4372-a567-0e02b2c3d479"
420
+
421
+ hscli forms create --dry-run \
422
+ --data '{"name":"Q2 Webinar Signup","formType":"hubspot","configuration":{"language":"en"}}'
423
+
424
+ hscli forms update "f47ac10b-58cc-4372-a567-0e02b2c3d479" --force \
425
+ --data '{"name":"Q2 Webinar Signup (Updated)"}'
426
+ ```
427
+
428
+ ### File assets
429
+
430
+ ```bash
431
+ hscli files assets list --limit 20
432
+ hscli files assets get 48192837465
433
+ hscli files assets update 48192837465 --force \
434
+ --data '{"name":"proposal-final-v2.pdf"}'
435
+ hscli files assets delete 48192837465 --force
436
+ ```
437
+
438
+ ### CMS pages and blog posts
439
+
440
+ ```bash
441
+ hscli cms pages list --limit 10
442
+ hscli cms blogs list --limit 5
443
+ hscli cms blogs get 19283746501
444
+
445
+ hscli cms pages create --dry-run \
446
+ --data '{"name":"Q2 Product Update","slug":"q2-product-update"}'
447
+
448
+ hscli cms blogs delete 19283746501 --force
449
+ ```
450
+
451
+ ### Workflows
452
+
453
+ ```bash
454
+ hscli workflows flows list --limit 10
455
+ hscli workflows flows get 39172845
456
+
457
+ hscli workflows flows create --dry-run \
458
+ --data '{"name":"New Lead Nurture Sequence","type":"PLATFORM_FLOW"}'
459
+ ```
460
+
461
+ ### Service conversations and feedback
462
+
463
+ ```bash
464
+ hscli service conversations list --limit 10
465
+ hscli service feedback list --limit 10
466
+ hscli service feedback get 56789012
467
+
468
+ hscli service feedback create --force \
469
+ --data '{"properties":{"hs_content":"Great onboarding experience.","hs_rating":"5"}}'
470
+ ```
471
+
472
+ ---
473
+
474
+ ## 9. Webhooks
475
+
476
+ ### List webhook subscriptions for an app
477
+
478
+ ```bash
479
+ hscli webhooks list --app-id 12345
480
+ ```
481
+
482
+ ### Create a webhook subscription
483
+
484
+ ```bash
485
+ hscli webhooks subscribe --app-id 12345 --dry-run \
486
+ --data '{"eventType":"contact.creation","propertyName":"email","active":true}'
487
+
488
+ hscli webhooks subscribe --app-id 12345 --force \
489
+ --data '{"eventType":"contact.creation","propertyName":"email","active":true}'
490
+ ```
491
+
492
+ ### Delete a webhook subscription
493
+
494
+ ```bash
495
+ hscli webhooks delete --app-id 12345 --subscription-id 67890 --force
496
+ ```
497
+
498
+ ---
499
+
500
+ ## 10. Imports
501
+
502
+ ### Start an import
503
+
504
+ ```bash
505
+ hscli crm imports create --force \
506
+ --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"}]}}]}'
507
+ ```
508
+
509
+ ### Check import status
510
+
511
+ ```bash
512
+ hscli crm imports list
513
+ hscli crm imports get 84726153
514
+ ```
515
+
516
+ ### View import errors
517
+
518
+ ```bash
519
+ hscli crm imports errors 84726153
520
+ ```
521
+
522
+ ---
523
+
524
+ ## 11. Incremental Sync
525
+
526
+ ### Full pull of all contacts (paginated)
527
+
528
+ ```bash
529
+ hscli crm sync pull contacts --limit 100 --max-pages 10
530
+ ```
531
+
532
+ State is saved to `.hscli-sync-contacts.json` by default. Subsequent runs resume from the last cursor.
533
+
534
+ ### Pull contacts modified since a specific date
535
+
536
+ ```bash
537
+ hscli crm sync pull contacts --since "2026-03-01T00:00:00Z"
538
+ ```
539
+
540
+ ### Custom state file and output file
541
+
542
+ ```bash
543
+ hscli crm sync pull deals \
544
+ --state-file "./sync-state/deals.json" \
545
+ --out-file "./exports/deals-latest.json" \
546
+ --limit 50 \
547
+ --max-pages 20
548
+ ```
549
+
550
+ ### Cron-friendly sync (run periodically, automatically resumes)
551
+
552
+ ```bash
553
+ hscli crm sync pull companies --limit 100 --max-pages 5 --json
554
+ ```
555
+
556
+ ---
557
+
558
+ ## 12. Raw API Requests
559
+
560
+ For endpoints not covered by built-in commands, use `api request`. Write methods go through the same safety controls.
561
+
562
+ ### GET request
563
+
564
+ ```bash
565
+ hscli api request --path "/crm/v3/objects/contacts" --method GET
566
+ ```
567
+
568
+ ### POST search with payload
569
+
570
+ ```bash
571
+ hscli api request --path "/crm/v3/objects/contacts/search" --method POST \
572
+ --data '{"query":"acme","limit":5}'
573
+ ```
574
+
575
+ ### PATCH with safety controls
576
+
577
+ ```bash
578
+ hscli api request --path "/crm/v3/objects/deals/18294750312" --method PATCH --dry-run \
579
+ --data '{"properties":{"dealstage":"closedwon"}}'
580
+
581
+ hscli api request --path "/crm/v3/objects/deals/18294750312" --method PATCH --force \
582
+ --data '{"properties":{"dealstage":"closedwon"}}'
583
+ ```
584
+
585
+ ### DELETE via raw API
586
+
587
+ ```bash
588
+ hscli api request --path "/crm/v3/objects/contacts/551" --method DELETE --force
589
+ ```
590
+
591
+ ### Hit an endpoint not in the CLI (e.g. timeline events)
592
+
593
+ ```bash
594
+ hscli api request --path "/crm/v3/timeline/events" --method POST --force \
595
+ --data '{"eventTemplateId":"12345","objectId":"551","tokens":{"action":"Logged in"}}'
596
+ ```
597
+
598
+ ---
599
+
600
+ ## 13. Safety Controls
601
+
602
+ ### Dry-run (preview without executing)
603
+
604
+ Every write command supports `--dry-run`. It returns the method, path, and body that would be sent, without making the API call.
605
+
606
+ ```bash
607
+ hscli crm contacts create --dry-run \
608
+ --data '{"properties":{"email":"test@example.com"}}'
609
+ ```
610
+
611
+ ### Force (execute the write)
612
+
613
+ Without `--force`, write operations fail with `WRITE_CONFIRMATION_REQUIRED`.
614
+
615
+ ```bash
616
+ hscli crm contacts create --force \
617
+ --data '{"properties":{"email":"test@example.com"}}'
618
+ ```
619
+
620
+ ### Policy file
621
+
622
+ A JSON policy file can restrict writes and deletes per profile. See `docs/POLICY_EXAMPLE.json`.
623
+
624
+ ```bash
625
+ hscli crm contacts delete 551 --force --policy-file ./policy.json
626
+ ```
627
+
628
+ Example policy file:
629
+
630
+ ```json
631
+ {
632
+ "defaults": {
633
+ "allowWrite": true,
634
+ "allowDelete": false,
635
+ "requireChangeTicket": false
636
+ },
637
+ "profiles": {
638
+ "production": {
639
+ "allowDelete": false,
640
+ "requireChangeTicket": true
641
+ }
642
+ },
643
+ "blockedMethodPathPrefixes": {
644
+ "DELETE": ["/crm/v3/schemas"]
645
+ }
646
+ }
647
+ ```
648
+
649
+ ### Change ticket requirement
650
+
651
+ When a policy requires change tickets, all writes must include `--change-ticket`:
652
+
653
+ ```bash
654
+ hscli --profile production crm deals update 18294750312 --force \
655
+ --change-ticket "JIRA-4521" \
656
+ --data '{"properties":{"dealstage":"closedwon"}}'
657
+ ```
658
+
659
+ ### Read-only profile mode
660
+
661
+ Lock a profile so all writes are blocked at the auth layer:
662
+
663
+ ```bash
664
+ hscli auth set-mode production read-only
665
+ ```
666
+
667
+ ### Environment variable for policy
668
+
669
+ The policy file can also be set via environment variable:
670
+
671
+ ```bash
672
+ export HSCLI_POLICY_FILE=./policy.json
673
+ hscli crm contacts create --force \
674
+ --data '{"properties":{"email":"test@example.com"}}'
675
+ ```
676
+
677
+ ---
678
+
679
+ ## 14. MCP Server
680
+
681
+ Run hscli as a Model Context Protocol server over stdio, suitable for integration with AI agents.
682
+
683
+ ```bash
684
+ hscli mcp
685
+ ```
686
+
687
+ Configure in your MCP client (e.g. Claude Desktop `claude_desktop_config.json`):
688
+
689
+ ```json
690
+ {
691
+ "mcpServers": {
692
+ "hubspot": {
693
+ "command": "hscli",
694
+ "args": ["mcp"]
695
+ }
696
+ }
697
+ }
698
+ ```
699
+
700
+ With a specific profile:
701
+
702
+ ```json
703
+ {
704
+ "mcpServers": {
705
+ "hubspot": {
706
+ "command": "hscli",
707
+ "args": ["--profile", "production", "mcp"]
708
+ }
709
+ }
710
+ }
711
+ ```
712
+
713
+ The MCP server exposes the same operations as the CLI with the same safety model (`force: true` required for writes).
714
+
715
+ ---
716
+
717
+ ## 15. Doctor / Diagnostics
718
+
719
+ ### Check hublet configuration consistency
720
+
721
+ Verifies that hscli's detected hublet, token prefix, and `@hubspot/cli` config all agree:
722
+
723
+ ```bash
724
+ hscli doctor hublet-check
725
+ hscli doctor hublet-check --profile production
726
+ ```
727
+
728
+ ### Probe endpoint capabilities
729
+
730
+ Discovers which API endpoints are available for the current portal and caches the results:
731
+
732
+ ```bash
733
+ hscli doctor capabilities
734
+ hscli doctor capabilities --refresh
735
+ hscli doctor capabilities --ttl-hours 12
736
+ ```
737
+
738
+ ### Strict capabilities mode
739
+
740
+ Fail fast when an endpoint's capability status is unknown:
741
+
742
+ ```bash
743
+ hscli --strict-capabilities crm contacts list
744
+ ```
745
+
746
+ ---
747
+
748
+ ## 16. Output Formats
749
+
750
+ All commands support `--format` and `--json` flags.
751
+
752
+ ```bash
753
+ hscli crm contacts list --format json
754
+ hscli crm contacts list --format csv
755
+ hscli crm contacts list --format yaml
756
+ hscli crm contacts list --format table # default
757
+ hscli crm contacts list --json # shorthand for --format json
758
+ ```
759
+
760
+ ### Telemetry logging
761
+
762
+ Append request telemetry to a local JSONL file for auditing:
763
+
764
+ ```bash
765
+ hscli --telemetry-file ./telemetry.jsonl crm contacts list
766
+ hscli --telemetry-file ./telemetry.jsonl crm deals create --force \
767
+ --data '{"properties":{"dealname":"Tracked Deal","pipeline":"default"}}'
768
+ ```
769
+
770
+ ---
771
+
772
+ ## 17. Multi-Profile Workflows
773
+
774
+ ### Manage staging and production side by side
775
+
776
+ ```bash
777
+ hscli auth login --token "pat-na1-staging-token" --profile staging
778
+ hscli auth login --token "pat-eu1-production-token" --profile production
779
+
780
+ # Read from staging
781
+ hscli --profile staging crm contacts search --query "test"
782
+
783
+ # Write to production (with safety)
784
+ hscli --profile production crm contacts create --force \
785
+ --data '{"properties":{"email":"verified@customer.com","firstname":"Verified","lastname":"Customer"}}'
786
+ ```
787
+
788
+ ### Audit which profiles exist
789
+
790
+ ```bash
791
+ hscli auth profiles
792
+ hscli auth profile-show --profile staging
793
+ hscli auth profile-show --profile production
794
+ ```
795
+
796
+ ### Remove a profile
797
+
798
+ ```bash
799
+ hscli auth logout --profile staging
800
+ ```