Read bulk-operations/SKILL.md first — JSONL piping, batch read, pagination, dry-run/digest/confirm, and hubspot history recovery live there. hubspot <command> --help is authoritative. Tickets use the tickets object type (plural, e.g. tickets:45123).
1. Discover pipeline + stages (portal-specific, run every session)
Stage IDs differ in every portal — never hard-code them.
The stage table prints each stage's ID and Label ("New", "Waiting on contact", "Closed", etc.). pipelines list/get also return each pipeline's full stages array in jsonl/json, so one call is enough to map a hs_pipeline_stage value to its label.
2. Verify enum option values for THIS portal
hs_ticket_priority, hs_ticket_category, and hs_resolution are all enumeration properties — option values are portal-configurable. List the allowed options directly with properties options-list (the old objects update … --property hs_resolution=__probe__ probe no longer works — updates are digest-gated now). properties get returns the same options array inline if you want values and labels together:
Do NOT assume HubSpot defaults — read the portal.
3. Create a ticket and associate it
subject is the only practically-required property. Skipping hs_pipeline/hs_pipeline_stage lands the ticket in the default pipeline's first stage.
Bulk intake from a JSONL queue (see bulk-operations/resources/json-patterns.md for reshape patterns):
4. Triage queries
Filter by owner with hubspot_owner_id=<id> (find IDs via hubspot owners list --format table).
5. Advance tickets through stages (bulk update from search)
objects update is irreversible, so re-pipe the same search with the --digest/--confirm lifted from the preview line — required at every row count, not just >100 (confirm = the row count for a batch). See the --digest/--confirm flow in bulk-operations/SKILL.md ("Safe destructive workflow"). Reassign in bulk works identically with {hubspot_owner_id:"<new>"}.
6. Log a resolution note
Activity creation lives in sales-execution/SKILL.md (notes/calls/meetings/tasks). After creating the note there, link it: hubspot associations create --from notes:<note_id> --to tickets:<ticket_id>.
7. Close the ticket
hs_resolution is an enumeration — pass an allowed option value from Step 2, not free text. HubSpot then computes hs_is_closed=true, closed_date, and time_to_close.
objects update is irreversible — dry-run first, then re-run with the digest and --confirm <ticket_id>:
Known limitations
- Enum options: list them with
hubspot properties options-list --type tickets <property>(fallback: read live records). - Chat/inbox:
hubspot conversationsreads inboxes, channels, threads, and messages — e.g.hubspot conversations threads list --inbox-id <id> --associated-ticket-id <ticket_id>pulls the chat thread behind a ticket. Runhubspot conversations --helpfor the full surface.

