I'm implementing it · 6 min read
Decide before you configure
The decision is made, or nearly, and you need the order things go in and what to sign before anyone configures anything.
If you have five minutes
- Seven decisions with named owners, signed before configuration. The first is which system is the receivables ledger of record. The signed memo is also the artifact that carries the CFO's buy-in.
- Term of record and billing migration are two different projects that share a name. The first is reversible and has no parallel run. The second is set per contract at creation, never changed, and needs one full billing cycle and one period close before cutover.
- Product library first, then contract structure, then billing schedule, then quote rules, then the reporting spec. Six records carry one sale; know which number on each you can trust.
Decide before you configure
The intuitive order is discover, build, train, test, get buy-in. For a system that issues financial documents that order is wrong three ways: buy-in happens at different moments for different people, testing cannot be a single phase, and the people who catch errors have to be trained before the people who create volume. So the engagement starts with a signed set of decisions, each with a named owner.
| Decision | Owner | What it costs to get it late |
|---|---|---|
| Which system is the receivables ledger of record | CFO or controller | Two ledgers and a reconciliation that grows monthly |
| Where HubSpot stops and recognition begins | Controller | Audit exposure and lost credibility |
| Commission on bookings, billings or collections | Sales leadership with finance | A comp dispute at go-live |
| What constitutes one contract | Finance with RevOps | Every downstream report wrong; not editable after create |
| Who may create products and price books | RevOps | Catalog sprawl within a quarter |
| Who authorises credit memos and refunds | Controller | An audit finding |
| What lands on unshipped capability, and what happens to it | RevOps with whoever owns the outcome | A workaround built into the foundation that has to be unwound |
The chain, object by object
Six records carry one sale from the quote to the cash. Each one has a job, and the reporting mistakes come from asking one of them a question that belongs to another.
| Object | What it is for | The number on it you can trust |
|---|---|---|
| Deal | The sales process. It ends when the customer commits | Four rollups computed from the line items. The headline amount is a number someone typed |
| Quote | The offer, and where the contract's clock starts | Total contract value on the quote; the headline switches between contract value and first payment depending on a setting |
| Contract | The agreement: committed revenue, term, renewal, every change since. Locks at creation | Committed value, recurring revenue, the change history. This is the bookings ledger |
| Order | The event. On every accepted change HubSpot creates one carrying the difference | Its total is typed, not computed. Read the order as an event, not a total |
| Invoice | The billing document, immutable once issued. Corrected by credit memo or void | Its subtotal is a real sum of its own line items, for one billing period |
| Payment | The cash event | What actually landed, and when |
| Subscription | Recurring billing execution, running under the contract | Total recurring revenue as a rollup; check what is associated before trusting it |
Six properties nobody sees and everyone lives with
- Billing enabled, set at birth
- Whether HubSpot bills a contract is decided when the contract is created and cannot be changed afterward. Term of record or billing migration is a create-time choice, not a switch you flip later.
- The effective date, immutable
- Decided on the quote, arrives on the contract, never moves. A wrong convention means reloading the agreements. Billing start and recognition start can legitimately differ from it, which is a design choice the platform supports, not a workaround.
- Term as a number of payments
- A three-year agreement is thirty-six monthly or three annual payments on the recurring line. A text field on a deal saying three years drives nothing and will disagree with the line within a quarter. A line left to renew automatically with no count is evergreen, and it never reaches completed on its own.
- The annual figure caps at twelve months
- Annual recurring revenue on a line is the monthly figure times the term, capped at twelve. A six-month contract reports six months of it, not an annualised run rate; a three-year contract reports twelve while total contract value keeps counting.
- One line item, many copies
- A line item is copied at every hop, the quote, the subscription, each invoice, each payment, except one: the deal and the order share the same record. Sum the object without a filter and one ordinary six-month sale counts two and a half times. Report on the container's rollup, never the raw line items.
- Percentage discounts only, on a contract line
- A contract line accepts a percentage off list and refuses a flat amount. Concessions are negotiated in dollars, so you convert. It reads as an annoyance and it is a position: the discount is stored as a relationship to list, so it can be reported and rolled off at renewal.
One honest gap
The contract object carries over a hundred native properties and the public write path to it is still a beta. Everything above comes from HubSpot's documentation, a production migration and a validated live run, not from a property-by-property audit. Where a claim matters to your build, read your own portal's schema before you rely on it.
The order the design goes in
- Product library and price books first. Everything downstream inherits it, and the pricing model per product is the hardest thing in the build to reverse.
- Contract structure: grain, term handling, renewal treatment, what a change looks like.
- Billing schedule design, only if HubSpot bills: dates, frequencies, consolidation, staggered terms.
- Quote templates, rules and approvals last, because the thresholds depend on the product structure.
- The reporting spec, written before the build. It is the top of the derivation chain and it is how you verify the build was right.
Five things a real migration taught me
From moving about four hundred agreements onto the contract record in a production portal. Two of these contradict HubSpot's own migration guide.
- Reading contracts is not writing them. Prove the write path with one throwaway record before building a pipeline. Bulk import runs through the interface, by a person with a Revenue Hub seat.
- One contract per agreement, and take the term from the original deal, not the subscription. A chain of annual subscriptions is one agreement plus renewals, not three agreements.
- The import wants the contract's fields on every line-item row, not the first row only. The guide says otherwise; the importer does not agree.
- A failed import burns its unique id. Retrying with the same id fails as "already exists" on an empty portal. Fresh id every attempt, and a ledger of attempts.
- Import line items as custom lines. Hydrating them from products fails even when the product exists.
Check your own portal first
Before any of this, nine questions tell you whether the agreement record can even represent your book: evergreen terms, chained multi-years, one-time lines that will need changing, whose ledger the money lives in. It runs in the browser, nothing is captured, and the result is yours.
Where to next
Where this comes from
- Ryan's order of operations and engagement plan. phases 0 to 9, the decision gate, the two modes; authored 2026-08-16 and 2026-08-29
- HubSpot's Contracts API, 2026-09 beta, and Quotes API, 2026-03. immutable fields, change types, the effective-date bridge; read 2026-08-23
- A production migration of about four hundred agreements, August 2026. the five traps and the two places HubSpot's own guide is wrong; anonymised
- The Line Item Series research, verified 2026-08-02. one sale, fifteen line items; the rollups that are real and the one that is typed
- A validated live run, 2026-08-23. a buyer-initiated change quote accepted end to end; the platform minted the order and voided the stale invoice
What we do not know yet
- The Contract object carries over a hundred native properties and has not been audited property by property; every claim here traces to documentation, a migration or a live run, not to a full schema read.
- The Contracts API is a beta that already moved an endpoint once mid-flight. Anything built on it pins the doc revision it was built against.
- Whether every path that creates an order reuses the deal's line item the same way has been observed on eight cases, all through two creation paths.
Mid-way through a quote-to-cash build, or stuck on one?
Come walk through it on the show and we will work it out on air, weekday mornings.

