@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,683 @@
1
+ # Portal Setup Guide
2
+
3
+ How to set up a new HubSpot portal from scratch for use with hscli, in the correct order. Each phase builds on the previous one — skip nothing, follow the sequence.
4
+
5
+ Use the **Setup Checklist** at the bottom to audit an existing portal and find what's missing.
6
+
7
+ ### Related Setup Guides
8
+
9
+ This guide covers the portal foundation. For hub-specific configuration, see:
10
+
11
+ | Guide | Covers |
12
+ |-------|--------|
13
+ | [MARKETING_SETUP.md](MARKETING_SETUP.md) | Email, campaigns, forms, ads, social, SEO, lead scoring, ABM |
14
+ | [SALES_SETUP.md](SALES_SETUP.md) | Pipelines, quotes, meetings, sequences, playbooks, forecasting |
15
+ | [SERVICE_SETUP.md](SERVICE_SETUP.md) | Tickets, knowledge base, customer portal, SLAs, feedback surveys |
16
+ | [COMMERCE_SETUP.md](COMMERCE_SETUP.md) | Products, payments, invoices, subscriptions, tax |
17
+ | [CMS_SETUP.md](CMS_SETUP.md) | Domains, templates, blog, pages, file manager, developer tools |
18
+ | [OPERATIONS_SETUP.md](OPERATIONS_SETUP.md) | Data sync, data quality, datasets, custom objects, imports |
19
+ | [REPORTING_SETUP.md](REPORTING_SETUP.md) | Dashboards, custom reports, attribution, analytics, goals |
20
+ | [INTEGRATIONS_NOTIFICATIONS_SETUP.md](INTEGRATIONS_NOTIFICATIONS_SETUP.md) | Marketplace apps, webhooks, notifications, security, account defaults |
21
+
22
+ > Also see: [COMMAND_TREE.md](COMMAND_TREE.md) for CLI commands to automate portal setup
23
+
24
+ ---
25
+
26
+ ## Phase 1: Account Foundation (UI only)
27
+
28
+ These settings affect everything downstream. Get them right first.
29
+
30
+ ### 1.1 Account Defaults
31
+
32
+ **Where:** Settings > Account Management > Account Defaults > General
33
+
34
+ | Setting | What to configure | Why it matters |
35
+ |---------|-------------------|----------------|
36
+ | Account name | Your company or project name | Appears in emails, quotes, reports |
37
+ | Time zone | Your primary business timezone | Affects workflow triggers, email send times, reporting windows |
38
+ | Fiscal year | Start month (e.g., January–December) | Affects goal tracking, forecasting, fiscal-period reports |
39
+ | Company name | Legal entity name | Used in email footers (CAN-SPAM), quotes, invoices |
40
+ | Company address | Full physical address | Required for email compliance (CAN-SPAM/GDPR) |
41
+ | Company domain | Your main website domain | Used as default for tracking and branding |
42
+
43
+ > **API:** Read-only (`GET /account-info/v3/details`). These must be set in the UI.
44
+
45
+ ### 1.2 Currency
46
+
47
+ **Where:** Settings > Account Defaults > Currency
48
+
49
+ Set your company (home) currency. Add additional currencies if you sell internationally.
50
+
51
+ | Setting | What to configure |
52
+ |---------|-------------------|
53
+ | Company currency | Your primary currency (e.g., USD, EUR, GBP) |
54
+ | Additional currencies | Any secondary currencies + exchange rates |
55
+ | Number format | Regional format (e.g., 1,234.56 vs 1 234,56) |
56
+
57
+ > **API:** `settings.currencies.read/write` scopes. Currencies can be read and managed via API after initial setup.
58
+ >
59
+ > **Important:** Company currency cannot be changed once set. Choose carefully.
60
+
61
+ ### 1.3 Branding
62
+
63
+ **Where:** Settings > Account Defaults > Branding (if available on your plan)
64
+
65
+ | Setting | What to configure |
66
+ |---------|-------------------|
67
+ | Logo | Company logo (used in emails, quotes, chat widget) |
68
+ | Favicon | Browser tab icon for hosted pages |
69
+ | Brand colors | Primary and secondary colors |
70
+ | Fonts | Default fonts for emails and pages |
71
+
72
+ > **API:** UI only. No public API for branding settings.
73
+
74
+ ### 1.4 Privacy & Consent
75
+
76
+ **Where:** Settings > Privacy & Consent
77
+
78
+ | Setting | What to configure |
79
+ |---------|-------------------|
80
+ | GDPR toggle | Enable if you process EU personal data |
81
+ | Consent types | Define legal basis types (legitimate interest, consent, etc.) |
82
+ | Cookie banner | Configure consent banner for tracking |
83
+ | Subscription types | Email opt-in/out categories |
84
+
85
+ > **API:** Partial. Consent properties can be set via API; GDPR mode itself is UI-only.
86
+ >
87
+ > **Why now:** Enabling GDPR after data exists creates retroactive compliance problems. Set it before any data enters the portal.
88
+
89
+ ---
90
+
91
+ ## Phase 2: Domain & Email Setup (UI + DNS)
92
+
93
+ ### 2.1 Connect Your Domain
94
+
95
+ **Where:** Settings > Content > Domains (or via the domain setup wizard)
96
+
97
+ | Domain type | Purpose | Example |
98
+ |-------------|---------|---------|
99
+ | Website domain | Landing pages, website pages | `www.yourcompany.com` |
100
+ | Email sending domain | Authenticated email delivery | `yourcompany.com` |
101
+ | Blog domain | Blog hosting | `blog.yourcompany.com` |
102
+ | Knowledge base | Help center hosting | `help.yourcompany.com` |
103
+
104
+ **Process:**
105
+ 1. Add the domain in HubSpot
106
+ 2. HubSpot provides DNS records (CNAME, TXT)
107
+ 3. Add records at your DNS registrar
108
+ 4. Wait for verification (can take up to 48h, usually minutes)
109
+
110
+ > **API:** Read-only (`GET /cms/v3/domains`). Domain connection requires the UI + DNS configuration.
111
+
112
+ ### 2.2 Email Authentication (DKIM, SPF)
113
+
114
+ **Where:** Settings > Marketing > Email > Configuration
115
+
116
+ | Record | Purpose |
117
+ |--------|---------|
118
+ | CNAME (DKIM) | Proves emails are from your domain, not spoofed |
119
+ | TXT (SPF) | Authorizes HubSpot to send email on your behalf |
120
+ | DMARC | Policy for handling failed authentication (set at your DNS) |
121
+
122
+ HubSpot provides the specific DNS records. Add them at your registrar and verify.
123
+
124
+ > **Why now:** Without email authentication, marketing and transactional emails may land in spam. Must be done before sending any emails.
125
+
126
+ ### 2.3 Tracking Code
127
+
128
+ **Where:** Settings > Tracking & Analytics > Tracking Code
129
+
130
+ Install the HubSpot tracking code on your website:
131
+ - **HubSpot-hosted pages:** Automatic, no action needed
132
+ - **External website:** Copy the JavaScript snippet and add it to your site's `<head>` tag
133
+
134
+ > **API:** The tracking code API can push events, but installing the snippet is manual.
135
+
136
+ ---
137
+
138
+ ## Phase 3: Users & Teams (UI + API)
139
+
140
+ ### 3.1 Invite Users
141
+
142
+ **Where:** Settings > Account Management > Users & Teams > Add users
143
+
144
+ | Setting | What to configure |
145
+ |---------|-------------------|
146
+ | Email addresses | Invite by email |
147
+ | Seats | Assign seat types (Core, Sales, Service, etc.) |
148
+ | Permission set | Super Admin, Admin, or custom permission sets |
149
+
150
+ **Process:**
151
+ 1. Click **Add users** and enter email addresses
152
+ 2. Assign a seat type (determines which tools they access)
153
+ 3. Assign a permission set (determines what they can do)
154
+ 4. Users receive an email invitation and must accept
155
+
156
+ > **API:** Yes — `settings.users.read/write` scopes. The User Provisioning API (`/settings/v3/users`) supports inviting and managing users.
157
+
158
+ ### 3.2 Create Teams
159
+
160
+ **Where:** Settings > Users & Teams > Teams tab
161
+
162
+ Teams enable:
163
+ - Record ownership segmentation (e.g., "Sales East" vs "Sales West")
164
+ - Team-based reporting and dashboards
165
+ - Permission hierarchies
166
+
167
+ > **API:** Teams are readable via API (`GET /settings/v3/users/teams`). Creation is done in the UI.
168
+
169
+ ### 3.3 Verify Owners
170
+
171
+ Users who can own CRM records appear as "owners." After inviting users, verify they show up:
172
+
173
+ ```bash
174
+ # List all owners in the portal
175
+ hscli crm owners list
176
+
177
+ # Filter by email
178
+ hscli crm owners list --email "user@yourcompany.com"
179
+ ```
180
+
181
+ > **Important:** Note owner IDs — you'll need them for record creation, imports, and bulk operations.
182
+
183
+ ---
184
+
185
+ ## Phase 4: Private App & CLI Authentication (UI + CLI)
186
+
187
+ ### 4.1 Create a Private App
188
+
189
+ **Where:** Settings > Integrations > Private Apps (or Legacy Apps)
190
+
191
+ 1. Click **Create legacy app** (or **Create a private app**)
192
+ 2. Name it (e.g., `hscli`)
193
+ 3. Grant the required scopes:
194
+
195
+ **Minimum scopes for full hscli functionality:**
196
+
197
+ | Category | Scopes |
198
+ |----------|--------|
199
+ | **CRM Objects** | `crm.objects.contacts.read/write`, `crm.objects.companies.read/write`, `crm.objects.deals.read/write`, `crm.objects.deals.sensitive.read` |
200
+ | **CRM Schemas** | `crm.schemas.contacts.read/write`, `crm.schemas.companies.read/write`, `crm.schemas.deals.read/write` |
201
+ | **Tickets** | `tickets`, `tickets.sensitive` |
202
+ | **Pipelines** | `crm.pipelines.orders.read/write` |
203
+ | **Owners** | `crm.objects.owners.read` |
204
+ | **Lists** | `crm.lists.read/write` |
205
+ | **Custom Objects** | `crm.objects.custom.sensitive.read/write` |
206
+ | **Imports** | `crm.import` |
207
+ | **Marketing** | `marketing-email`, `marketing.campaigns.read/write` |
208
+ | **Forms** | `forms` |
209
+ | **Files** | `files` |
210
+ | **CMS** | `content` |
211
+ | **Workflows** | `automation` |
212
+ | **Conversations** | `conversations.read/write` |
213
+ | **Settings** | `settings.users.read/write`, `settings.currencies.read/write` |
214
+
215
+ 4. Click **Create app** and copy the access token
216
+
217
+ **Token format by hublet:**
218
+ - US: `pat-na1-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX`
219
+ - EU: `pat-eu1-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX`
220
+
221
+ ### 4.2 Authenticate hscli
222
+
223
+ ```bash
224
+ # Build hscli (first time only)
225
+ cd hscli-main && npm install && npm run build
226
+
227
+ # Authenticate (pipe to avoid token in shell history)
228
+ printf '%s' 'pat-eu1-XXXX' | hscli auth login --token-stdin
229
+
230
+ # Verify
231
+ hscli auth whoami
232
+ hscli auth token-info
233
+
234
+ # Check capabilities
235
+ hscli doctor capabilities --refresh
236
+ ```
237
+
238
+ **Expected `auth whoami` output:** Portal ID, hublet, uiDomain, authenticated user email.
239
+
240
+ ---
241
+
242
+ ## Phase 5: Data Model — Properties (CLI)
243
+
244
+ Properties define the fields on each CRM object. Standard properties exist by default; add custom properties before importing any data.
245
+
246
+ ### 5.1 Review existing properties
247
+
248
+ ```bash
249
+ # List properties per object type
250
+ hscli crm properties list contacts
251
+ hscli crm properties list companies
252
+ hscli crm properties list deals
253
+ hscli crm properties list tickets
254
+
255
+ # Full schema introspection (includes metadata)
256
+ hscli crm describe contacts
257
+ hscli crm describe deals
258
+ ```
259
+
260
+ ### 5.2 Create custom properties
261
+
262
+ ```bash
263
+ # Example: dropdown property on contacts
264
+ hscli crm properties create contacts --data '{
265
+ "name": "lead_source_detail",
266
+ "label": "Lead Source Detail",
267
+ "type": "enumeration",
268
+ "fieldType": "select",
269
+ "groupName": "contactinformation",
270
+ "options": [
271
+ {"label": "Organic Search", "value": "organic_search", "displayOrder": 0},
272
+ {"label": "Paid Ads", "value": "paid_ads", "displayOrder": 1},
273
+ {"label": "Referral", "value": "referral", "displayOrder": 2}
274
+ ]
275
+ }' --force
276
+
277
+ # Example: number property on deals
278
+ hscli crm properties create deals --data '{
279
+ "name": "mrr",
280
+ "label": "Monthly Recurring Revenue",
281
+ "type": "number",
282
+ "fieldType": "number",
283
+ "groupName": "dealinformation"
284
+ }' --force
285
+ ```
286
+
287
+ > Default behavior is `--dry-run`. Always dry-run first, then add `--force` to commit.
288
+
289
+ ### 5.3 Update existing properties
290
+
291
+ ```bash
292
+ hscli crm properties update contacts --data '{
293
+ "name": "lead_source_detail",
294
+ "label": "Lead Source (Detailed)",
295
+ "options": [
296
+ {"label": "Organic Search", "value": "organic_search", "displayOrder": 0},
297
+ {"label": "Paid Ads", "value": "paid_ads", "displayOrder": 1},
298
+ {"label": "Referral", "value": "referral", "displayOrder": 2},
299
+ {"label": "Partner", "value": "partner", "displayOrder": 3}
300
+ ]
301
+ }' --force
302
+ ```
303
+
304
+ ---
305
+
306
+ ## Phase 6: Data Model — Pipelines (UI + CLI)
307
+
308
+ Pipelines define how deals and tickets flow through your process.
309
+
310
+ ### 6.1 Configure Deal Pipeline
311
+
312
+ **Where:** Settings > Objects > Deals > Pipelines tab
313
+
314
+ Design your stages with probabilities:
315
+
316
+ | Stage | Probability | Meaning |
317
+ |-------|-------------|---------|
318
+ | Prospect | 10% | Initial contact, not yet qualified |
319
+ | Qualification | 30% | Evaluating fit and budget |
320
+ | Proposal | 60% | Proposal sent, awaiting decision |
321
+ | Negotiation | 80% | Terms being discussed |
322
+ | Won | 100% | Deal closed successfully |
323
+ | Lost | 0% | Deal did not close |
324
+
325
+ ### 6.2 Configure Ticket Pipeline
326
+
327
+ **Where:** Settings > Objects > Tickets > Pipelines tab
328
+
329
+ Design your statuses:
330
+
331
+ | Status | Open/Closed |
332
+ |--------|-------------|
333
+ | New | Open |
334
+ | Waiting on contact | Open |
335
+ | Waiting on us | Open |
336
+ | Closed | Closed |
337
+
338
+ ### 6.3 Verify via CLI
339
+
340
+ ```bash
341
+ # List pipelines and their stages
342
+ hscli crm pipelines list deals
343
+ hscli crm pipelines list tickets
344
+
345
+ # Get detailed pipeline info (stage IDs, probabilities)
346
+ hscli crm pipelines get deals
347
+ hscli crm pipelines get tickets
348
+ ```
349
+
350
+ > **Note:** The Pipelines API (`/crm/v3/pipelines`) supports full CRUD. Pipelines can also be created via API if you have the `crm.pipelines.orders.read/write` scope.
351
+
352
+ ---
353
+
354
+ ## Phase 7: Data Model — Custom Objects (CLI, if needed)
355
+
356
+ Custom objects extend the CRM beyond contacts, companies, deals, and tickets.
357
+
358
+ ### 7.1 List existing schemas
359
+
360
+ ```bash
361
+ hscli crm custom-objects schemas list
362
+ ```
363
+
364
+ ### 7.2 Create a custom object
365
+
366
+ ```bash
367
+ hscli crm custom-objects schemas create --data '{
368
+ "name": "project",
369
+ "labels": {"singular": "Project", "plural": "Projects"},
370
+ "primaryDisplayProperty": "project_name",
371
+ "requiredProperties": ["project_name"],
372
+ "properties": [
373
+ {"name": "project_name", "label": "Project Name", "type": "string", "fieldType": "text"},
374
+ {"name": "status", "label": "Status", "type": "enumeration", "fieldType": "select",
375
+ "options": [
376
+ {"label": "Planning", "value": "planning"},
377
+ {"label": "Active", "value": "active"},
378
+ {"label": "Complete", "value": "complete"}
379
+ ]},
380
+ {"name": "budget", "label": "Budget", "type": "number", "fieldType": "number"}
381
+ ],
382
+ "associatedObjects": ["CONTACT", "COMPANY", "DEAL"]
383
+ }' --force
384
+ ```
385
+
386
+ ---
387
+
388
+ ## Phase 8: Test & Validate (CLI)
389
+
390
+ Before importing data at scale, create one record of each type to verify the data model.
391
+
392
+ ### 8.1 Create a test contact
393
+
394
+ ```bash
395
+ # Dry-run first
396
+ hscli crm contacts create --data '{
397
+ "properties": {
398
+ "email": "setup-test@example.com",
399
+ "firstname": "Setup",
400
+ "lastname": "Test",
401
+ "hubspot_owner_id": "<OWNER_ID>"
402
+ }
403
+ }'
404
+
405
+ # Execute
406
+ hscli crm contacts create --data '{
407
+ "properties": {
408
+ "email": "setup-test@example.com",
409
+ "firstname": "Setup",
410
+ "lastname": "Test",
411
+ "hubspot_owner_id": "<OWNER_ID>"
412
+ }
413
+ }' --force
414
+ ```
415
+
416
+ ### 8.2 Create and associate records
417
+
418
+ ```bash
419
+ # Create a company
420
+ hscli crm companies create --data '{
421
+ "properties": {"name": "Test Company", "domain": "testco.com"}
422
+ }' --force
423
+
424
+ # Associate contact → company
425
+ hscli crm associations create contacts <contactId> companies <companyId> --force
426
+
427
+ # Create a deal in the pipeline
428
+ hscli crm deals create --data '{
429
+ "properties": {
430
+ "dealname": "Test Deal",
431
+ "pipeline": "<pipelineId>",
432
+ "dealstage": "<stageId>",
433
+ "amount": "10000",
434
+ "hubspot_owner_id": "<OWNER_ID>"
435
+ }
436
+ }' --force
437
+
438
+ # Associate deal → contact and deal → company
439
+ hscli crm associations create deals <dealId> contacts <contactId> --force
440
+ hscli crm associations create deals <dealId> companies <companyId> --force
441
+ ```
442
+
443
+ ### 8.3 Validate data
444
+
445
+ ```bash
446
+ # Validate a payload against the schema before creating
447
+ hscli crm validate contacts --data '{
448
+ "properties": {"email": "test@example.com", "firstname": "Test"}
449
+ }'
450
+ ```
451
+
452
+ ---
453
+
454
+ ## Phase 9: Data Import (CLI)
455
+
456
+ Once the data model is validated, import your data.
457
+
458
+ ### 9.1 Single records
459
+
460
+ ```bash
461
+ hscli crm contacts create --data '{...}' --force
462
+ hscli crm companies create --data '{...}' --force
463
+ ```
464
+
465
+ ### 9.2 Batch operations
466
+
467
+ ```bash
468
+ hscli crm contacts batch-upsert --data '{
469
+ "inputs": [
470
+ {"properties": {"email": "alice@example.com", "firstname": "Alice"}, "idProperty": "email"},
471
+ {"properties": {"email": "bob@example.com", "firstname": "Bob"}, "idProperty": "email"}
472
+ ]
473
+ }' --force
474
+ ```
475
+
476
+ ### 9.3 CSV imports
477
+
478
+ ```bash
479
+ hscli crm imports create --data '<import-payload>' --force
480
+
481
+ # Check import status
482
+ hscli crm imports list
483
+ hscli crm imports get <importId>
484
+ hscli crm imports errors <importId>
485
+ ```
486
+
487
+ ### Import safety rules
488
+
489
+ - **Validate first:** Create a single test record before bulk operations
490
+ - **5-error hard stop:** If >5 errors on the same endpoint, stop and diagnose
491
+ - **Rate limits:** ~100 requests/10s for private apps. Use sequential processing with 1-2s pauses per 5 records
492
+ - **Idempotent re-runs:** Check for existing records before creating duplicates
493
+ - **Always assign owners:** Never import records without an owner
494
+
495
+ ---
496
+
497
+ ## Phase 10: Engagement Tools (UI + CLI)
498
+
499
+ ### 10.1 Email Configuration
500
+
501
+ **Where:** Settings > Marketing > Email
502
+
503
+ | Setting | What to configure |
504
+ |---------|-------------------|
505
+ | Subscription types | Define email categories (Marketing, Sales, Newsletter, etc.) |
506
+ | Email footer | Company name, address (required by CAN-SPAM) |
507
+ | Default "from" address | noreply@, marketing@, etc. |
508
+
509
+ ### 10.2 Forms
510
+
511
+ ```bash
512
+ # List existing forms
513
+ hscli forms list
514
+
515
+ # Create a form
516
+ hscli forms create --data '{...}' --force
517
+ ```
518
+
519
+ ### 10.3 Workflows
520
+
521
+ **Where:** Automation > Workflows (UI only for building; `automation` scope for custom actions)
522
+
523
+ ```bash
524
+ # List workflows
525
+ hscli workflows flows list
526
+ ```
527
+
528
+ ---
529
+
530
+ ## Setup Checklist
531
+
532
+ Use this to verify a new portal or audit an existing one. Items are in dependency order.
533
+
534
+ ### Phase 1 — Account Foundation (UI)
535
+ ```
536
+ [ ] Account name set
537
+ [ ] Time zone configured
538
+ [ ] Fiscal year set
539
+ [ ] Company name and address filled in (email compliance)
540
+ [ ] Company currency set (cannot be changed later)
541
+ [ ] Additional currencies added (if multi-currency)
542
+ [ ] Branding configured (logo, colors, favicon)
543
+ [ ] Privacy & consent settings enabled (GDPR if applicable)
544
+ ```
545
+
546
+ ### Phase 2 — Domains & Email (UI + DNS)
547
+ ```
548
+ [ ] Website domain connected and verified
549
+ [ ] Email sending domain authenticated (DKIM + SPF)
550
+ [ ] DMARC record configured at DNS registrar
551
+ [ ] Tracking code installed on external website
552
+ ```
553
+
554
+ ### Phase 3 — Users & Teams (UI)
555
+ ```
556
+ [ ] Users invited with correct seats and permissions
557
+ [ ] Teams created (if using team-based segmentation)
558
+ [ ] Owners verified: hscli crm owners list
559
+ ```
560
+
561
+ ### Phase 4 — CLI Authentication
562
+ ```
563
+ [ ] Private App created with required scopes
564
+ [ ] hscli authenticated: hscli auth whoami
565
+ [ ] Token info verified: hscli auth token-info
566
+ [ ] Capabilities checked: hscli doctor capabilities --refresh
567
+ ```
568
+
569
+ ### Phase 5 — Properties (CLI)
570
+ ```
571
+ [ ] Contact properties reviewed/created
572
+ [ ] Company properties reviewed/created
573
+ [ ] Deal properties reviewed/created
574
+ [ ] Ticket properties reviewed/created
575
+ ```
576
+
577
+ ### Phase 6 — Pipelines (UI, verified via CLI)
578
+ ```
579
+ [ ] Deal pipeline stages configured with probabilities
580
+ [ ] Ticket pipeline statuses configured (open/closed)
581
+ [ ] Pipelines verified: hscli crm pipelines list deals
582
+ ```
583
+
584
+ ### Phase 7 — Custom Objects (CLI, if needed)
585
+ ```
586
+ [ ] Custom object schemas created
587
+ [ ] Custom object properties defined
588
+ [ ] Associations configured
589
+ ```
590
+
591
+ ### Phase 8 — Validation (CLI)
592
+ ```
593
+ [ ] Test contact created and verified
594
+ [ ] Test company created and associated
595
+ [ ] Test deal created in correct pipeline/stage
596
+ [ ] Associations verified between objects
597
+ ```
598
+
599
+ ### Phase 9 — Data Import (CLI)
600
+ ```
601
+ [ ] Data imported (contacts, companies, deals, tickets)
602
+ [ ] Import errors reviewed and resolved
603
+ [ ] Owner assignment verified on imported records
604
+ ```
605
+
606
+ ### Phase 10 — Engagement Tools (UI + CLI)
607
+ ```
608
+ [ ] Email subscription types configured
609
+ [ ] Email footer set (company address)
610
+ [ ] Forms created (if needed)
611
+ [ ] Workflows built (if needed)
612
+ ```
613
+
614
+ ---
615
+
616
+ ## Quick Audit Script
617
+
618
+ Run this to quickly assess what's configured in an existing portal:
619
+
620
+ ```bash
621
+ #!/bin/bash
622
+ echo "=== Auth & Connectivity ==="
623
+ hscli auth whoami
624
+ hscli doctor capabilities --refresh
625
+
626
+ echo "=== Owners ==="
627
+ hscli crm owners list
628
+
629
+ echo "=== Pipelines ==="
630
+ hscli crm pipelines list deals
631
+ hscli crm pipelines list tickets
632
+
633
+ echo "=== Property Counts ==="
634
+ hscli crm properties list contacts --json 2>/dev/null | grep -c '"name"' || echo "contacts: error"
635
+ hscli crm properties list companies --json 2>/dev/null | grep -c '"name"' || echo "companies: error"
636
+ hscli crm properties list deals --json 2>/dev/null | grep -c '"name"' || echo "deals: error"
637
+ hscli crm properties list tickets --json 2>/dev/null | grep -c '"name"' || echo "tickets: error"
638
+
639
+ echo "=== Custom Objects ==="
640
+ hscli crm custom-objects schemas list
641
+
642
+ echo "=== Record Counts ==="
643
+ hscli crm contacts search --data '{"filterGroups":[], "limit": 1}' --json 2>/dev/null
644
+ hscli crm companies search --data '{"filterGroups":[], "limit": 1}' --json 2>/dev/null
645
+ hscli crm deals search --data '{"filterGroups":[], "limit": 1}' --json 2>/dev/null
646
+ ```
647
+
648
+ ---
649
+
650
+ ## API vs UI Reference
651
+
652
+ | Step | What | API support | hscli command |
653
+ |------|------|-------------|----------------|
654
+ | Account defaults | Name, timezone, currency | Read-only | — |
655
+ | Branding | Logo, colors, fonts | None | — |
656
+ | Domains | Website, email sending | Read-only | — |
657
+ | Email auth | DKIM, SPF | None (DNS manual) | — |
658
+ | Tracking code | JS snippet | Push events only | — |
659
+ | Privacy/consent | GDPR, cookie banner | Partial | — |
660
+ | Users | Invite, permissions | Full CRUD | — |
661
+ | Owners | List portal owners | Read | `hscli crm owners list` |
662
+ | Properties | Object fields | Full CRUD | `hscli crm properties list/create/update` |
663
+ | Pipelines | Deal/ticket stages | Full CRUD | `hscli crm pipelines list/get` |
664
+ | Custom objects | Schema + records | Full CRUD | `hscli crm custom-objects schemas list/create` |
665
+ | Data import | Bulk CSV | Full | `hscli crm imports create` |
666
+ | Records | CRUD + search | Full | `hscli crm <object> list/get/create/update/delete` |
667
+ | Associations | Record linking | Full | `hscli crm associations create/list/remove` |
668
+ | Forms | Lead capture | Full CRUD | `hscli forms list/create` |
669
+ | Workflows | Automation | Limited | `hscli workflows flows list` |
670
+ | Marketing | Email, campaigns | Partial | `hscli marketing emails/campaigns list` |
671
+
672
+ ---
673
+
674
+ ## Hublet Reference
675
+
676
+ hscli auto-detects the hublet from the token prefix and routes API calls to the correct endpoint.
677
+
678
+ | Hublet | Token prefix | API base URL | UI domain |
679
+ |--------|-------------|-------------|-----------|
680
+ | US | `pat-na1-*` | `https://api.hubapi.com` | `app.hubspot.com` |
681
+ | EU | `pat-eu1-*` | `https://api-eu1.hubapi.com` | `app-eu1.hubspot.com` |
682
+
683
+ Never hardcode `api.hubapi.com` — it defaults to US and will fail for EU portals.