
quote-to-cash
Build the product catalog, assemble quotes (line items + associations to deals), and track invoices and subscriptions through to revenue.
- Installs
- 1.7K
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/hubspot/agent-cli-skills --skill quote-to-cash- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads quote-to-cash automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Resources
| File | When to use |
|---|---|
resources/q2c-essentials.md | Six-field cheat sheet, association directions, portal caveats for invoices/subscriptions/orders/carts. |
Foundations
Read bulk-operations/SKILL.md first — JSONL piping, batch read, pagination, and the dry-run/digest/confirm flow for destructive ops live there. Reshape recipes (read → write payload) are in bulk-operations/resources/json-patterns.md.
hubspot <command> --help is the source of truth. Object types are plural (products, line_items, quotes, invoices, subscriptions). Never hardcode property tables — hubspot properties list --type <type> is one call away. Verify any enum value the agent is about to write with hubspot properties options-list --type <type> <property> | jq -r '.value'.
Portal note: invoices, subscriptions, orders, carts show an empty objectTypeId in hubspot objects types. They work through objects search/list when the token has the matching scope (invoices-read, subscriptions-read, etc.) and 403 otherwise. CLI-created quotes are always DRAFT; approval routing, share links, PDF generation, and invoice creation usually require the HubSpot UI.
1. Create a product
hubspot objects create --type products \
--property name="Enterprise License" \
--property price=12000 \
--property hs_sku=ENT-001
For a recurring product set recurringbillingfrequency; check the API enum values first with hubspot properties options-list --type products recurringbillingfrequency | jq -r '.value'. Bulk-import a catalog by piping JSONL of {"properties":{...}} to hubspot objects create --type products --dry-run.
2. Build a quote: line items → quote → associations
objects create emits one result line per stdin line, in input order. That lets you build line items, capture their IDs, and associate them to the new quote in three pipes — no per-record shell loop.
DEAL_ID=12345
# 1. Create the line items. items.jsonl holds {"name":..,"qty":..,"price":..,"product_id":..} per line.
jq -c '{properties:{
name:.name, quantity:(.qty|tostring), price:(.price|tostring),
hs_product_id:.product_id, hs_line_item_currency_code:"USD"
}}' items.jsonl \
| hubspot objects create --type line_items > /tmp/lineitems.jsonl
# 2. Create the quote.
QUOTE_ID=$(hubspot objects create --type quotes \
--property hs_title="Acme Corp - 2026" \
--property hs_expiration_date=2026-06-30 \
--property hs_currency=USD \
--format json | jq -r '.data.id // .id')
# 3. Associate every new line item to the quote in one pipe.
jq -r '.id' /tmp/lineitems.jsonl \
| jq -cR --arg q "$QUOTE_ID" '{from:("quotes:" + $q), to:("line_items:" + .)}' \
| hubspot associations create
# 4. Link the quote to the deal.
hubspot associations create --from "deals:$DEAL_ID" --to "quotes:$QUOTE_ID"
Discount handling — discount is the writable percentage (10 = 10% off). hs_total_discount is HubSpot-computed; do not set it. Verify with hubspot properties get --type line_items hs_total_discount (property name is positional; look for modificationMetadata.readOnlyValue:true) before relying on this in a portal you don't own.
Promote a quote out of DRAFT when ready to share. objects update is irreversible — dry-run first, then re-run with the digest and --confirm <quote_id>:
hubspot objects update --type quotes <quote_id> --property hs_status=APPROVAL_NOT_NEEDED --dry-run
hubspot objects update --type quotes <quote_id> --property hs_status=APPROVAL_NOT_NEEDED --digest <hash> --confirm <quote_id>
Verify hs_status enum values for your portal: hubspot properties options-list --type quotes hs_status | jq -r '.value'.
3. Track invoices
The CLI reads invoice data and updates status; creation usually needs HubSpot Commerce + UI. Filter by hs_invoice_status and date.
# All outstanding invoices
hubspot objects search --type invoices \
--filter "hs_invoice_status=OUTSTANDING" \
--properties hs_number,hs_amount_billed,hs_balance,hs_due_date
# Past-due (overdue) invoices, dynamic date
hubspot objects search --type invoices \
--filter "hs_due_date<$(date +%Y-%m-%d) AND hs_invoice_status!=PAID" \
--properties hs_number,hs_due_date,hs_balance
# Invoices billed in the last 30 days
hubspot objects search --type invoices \
--filter "hs_invoice_date>=$(date -v-30d +%Y-%m-%d 2>/dev/null || date -d '30 days ago' +%Y-%m-%d)" \
--properties hs_number,hs_amount_billed,hs_invoice_date
Verify the status enum the same way: hubspot properties options-list --type invoices hs_invoice_status | jq -r '.value'.
4. Track subscriptions
Same shape, filter on hs_subscription_status. Verify the enum values before writing the filter — do not hardcode ACTIVE/CANCELLED/PAST_DUE:
hubspot properties options-list --type subscriptions hs_subscription_status | jq -r '.value'
# Then filter (case matters)
hubspot objects search --type subscriptions \
--filter "hs_subscription_status=<value-from-above>" \
--properties hs_mrr,hs_arr,hs_subscription_status
# Sum MRR across active subs
hubspot objects search --type subscriptions \
--filter "hs_subscription_status=<active-value>" --format json \
| jq '[.data[].properties.hs_mrr | select(. != null and . != "") | tonumber] | add // 0'
Known constraints
invoices,subscriptions,orders,carts,paymentsneed the matching read scope on the active token; 403 means the user OAuth login or private-app token is missing the scope.objects deleteon products/quotes/line_items works under both user OAuth (hubspot auth login, with the object's write scope) and a service key (export HUBSPOT_ACCESS_TOKEN=<token>); a 403 means the active token is missing that write scope. The exception is the--gdprpermanent purge, which requires a service key — the GDPR endpoint does not accept user OAuth tokens. Seebulk-operations/SKILL.mdfor the dry-run → digest → confirm flow before bulk-deleting catalog records.- Quote share links, PDF generation, approval routing, and from-scratch invoice creation are UI-only — the CLI updates records but cannot send a quote to a customer.
hs_total_discounton line items is read-only — setdiscount(percentage) instead.
FAQ
What does the quote-to-cash skill do?
Build the product catalog, assemble quotes (line items + associations to deals), and track invoices and subscriptions through to revenue.
How do I install quote-to-cash?
Run npx skills add https://github.com/hubspot/agent-cli-skills --skill quote-to-cash in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/quote-to-cash/ (personal) or .claude/skills/quote-to-cash/ (project).
Which AI agents can use quote-to-cash?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is quote-to-cash safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains quote-to-cash?
It is published by hubspot in hubspot/agent-cli-skills. It has 1,679 recorded installs.
More from hubspot/agent-cli-skills
ticket-resolution
hubspot/agent-cli-skills
Create, triage, advance, and close HubSpot support tickets — pipeline discovery, contact/company association, priority queues, bulk stage moves, resolution close-out.
crm-lookup
hubspot/agent-cli-skills
Find a specific CRM record by ID, email, domain, or name fragment, and traverse associations for the full account picture.
bulk-operations
hubspot/agent-cli-skills
Foundation patterns for the hubspot CLI — JSONL piping, batch read, pagination, dry-run/digest/confirm for destructive ops, and hubspot history for recovery. Every other skill builds on this one.
crm-data-quality
hubspot/agent-cli-skills
Find incomplete records, normalize field values in bulk, dedupe with hubspot objects merge, and audit custom properties. Builds on bulk-operations for JSONL piping and dry-run/digest/confirm.
workflow-automation
hubspot/agent-cli-skills
List, inspect, create, update, and delete HubSpot workflows (v4 flows API) from the hubspot agent CLI, not the hs developer CLI. Classic v3 contact-based workflows are not covered.
deal-management
hubspot/agent-cli-skills
Run the full deal lifecycle from CLI — discover pipelines/stages, qualify MQLs into deals with associations, advance/reassign in bulk, hunt stalled deals, and close.
Popular other skills
hyperframes-cli
heygen-com/hyperframes
The HyperFrames CLI by job - scaffold, check, look at frames, edit the timeline, preview, render locally or in the cloud, publish, project history - plus reading its JSON and recovering from build or render failures.
triage
mattpocock/skills
Move issues and external PRs through a state machine of triage roles, categorise, verify, grill if needed, and write agent-ready briefs.
ask-matt
mattpocock/skills
Ask which skill or flow fits your situation. A router over the skills in this repo.
to-questionnaire
mattpocock/skills
Turn a decision you can't fully answer into a questionnaire for someone else to fill in.
loop-me
mattpocock/skills
Grill me about specs for the workflows I want to build, within this workspace.