Integration · Revenue operations
How to build a billing to CRM sync
A rep opens a renewal conversation with a customer who is ninety days overdue and nobody told them. Below is the model behind billing data reaching the account team, the prompts that build it, and the parts that only bite once it is live.
Built with Tray Headless
- System NetSuite
- Step Summarise per account
- Step Derive signals
- System Salesforce
One direction only. Billing is the source of truth and the CRM displays a read-only summary.
The short answer
What is a billing to CRM sync?
A billing to CRM sync is four parts: a one-way flow that treats billing as the source of truth, a summary on the account instead of every transaction copied across, derived signals like days overdue and payment behaviour instead of raw balances, and a refresh cadence matched to how fast the data actually changes. What sinks most attempts is copying everything. A CRM holding every invoice line becomes a second billing system that disagrees with the first one within a month.
What matters here
- Billing is the source of truth and the CRM is a reader. Two-way sync on financial data produces two versions of the balance.
- Summarise, not copy. Total outstanding, oldest invoice age and payment behaviour beat a list of every transaction.
- Derive the signals people act on. Days overdue and average days to pay change a renewal conversation; a balance figure does not.
- Match the cadence to the data. Payment state changes daily, contract terms change quarterly, and syncing both hourly is waste.
- Never let the CRM write back to billing. A rep adjusting an invoice from an opportunity screen is how the ledger goes wrong.
Who this is for
You run revenue operations or customer success systems. Renewal and expansion conversations happen without any visibility of whether the customer pays on time, and finding out means asking finance.
How it works in practice
The path from an invoice changing state to a rep knowing about it.
- 1
Billing events are read on a schedule that fits
Payment state daily, contract terms weekly. Not everything at the same interval because one thing needed it.
- 2
The data is summarised per account, not copied
One roll-up per account, not a transaction table the CRM was never designed to hold.
- 3
Signals are derived from the raw figures
Days overdue, average days to pay, payment method risk, trend against the last two quarters.
- 4
The summary is written to the account, read-only
Visible on the record where renewal and expansion conversations happen, and not editable there.
- 5
Thresholds raise a flag, not a number
Ninety days overdue on a renewal in the next quarter is an alert, not a field somebody might notice.
- 6
Nothing flows back to billing
The CRM reads. A correction happens in the billing system by somebody who is allowed to make it.
What the sync is made of
One direction, one summary, and the discipline not to rebuild billing inside the CRM.
A one-way flow
Billing is authoritative. The CRM displays. Two-way financial sync produces two balances and an argument about which is right.
A summary, not a copy
Outstanding total, oldest invoice, last payment, next invoice date. Not every line item ever raised.
Derived signals
Days overdue, average days to pay, whether payment behaviour is worsening. The figures a rep can actually act on.
A cadence per data type
Payment state changes daily. Contract terms do not. Syncing both on the same schedule wastes calls and hides the change that mattered.
The Tray Headless prompts
Paste these into Claude Code or Codex with the Tray Headless plugin installed. Each stage runs on its own. The systems named in them are the worked example rather than a requirement, and every prompt says so.
Once per project, run
/tray-workflows:set-workspace
to pick the workspace these build in. Point it at a sandbox first.
- 1
Set up and decide what actually needs to cross
Most billing to CRM projects fail by copying too much.
Headless skills
build-workflowUse build-workflow. The systems in play are NetSuite and Salesforce, or whatever we run in those seats. From NetSuite I need Invoice, CustomerPayment and CreditMemo, plus the subscription terms on the Customer record. From Salesforce I need Account and whichever custom fields already hold financial data, because there are usually two of them and they disagree. Then help me decide what genuinely needs to cross. The default should be nothing, and each field has to earn its place by changing a conversation somebody actually has.
- 2
Summarise per account, and keep it read-only
The rule that stops the CRM becoming a second ledger.
Headless skills
build-workflowUse build-workflow. Compute one summary per account rather than copying transactions: Total outstanding, and how much of it is overdue Oldest unpaid invoice and its age in days Last payment amount and date Next invoice date and amount Average days to pay over the last four invoices Current subscription value and term end Write these to read-only fields on the Account. Set field-level security so nobody can edit them in the CRM, because a rep correcting a balance in Salesforce creates a number that disagrees with the ledger and is believed by the next person who reads it.
- 3
Derive the signals people act on
A balance is data. Days overdue is a reason to pick up the phone.
Raw figures do not change behaviour. Derive: Payment health: on time, occasionally late, consistently late, currently overdue. Computed over the last four invoices, not one. Trend: is average days to pay improving or worsening against the previous two quarters. Renewal risk overlay: an account overdue beyond a threshold with a renewal inside the next quarter. That combination is the single most useful thing this sync produces. Payment method risk: a card expiring before the next invoice date, which is a preventable failure and nobody looks for it. Put payment health on the account as a labelled state, not a number. A rep scanning a list reads a label; they skip a figure.
The renewal risk overlay is the reason to build this. Everything else is context; that one changes who gets called this week.
- 4
Match the cadence to the data, and handle the edges
Because syncing everything hourly hides the change that mattered.
Headless skills
tray-gotchasUse tray-gotchas, then set cadences separately: Payment and invoice state daily Subscription terms weekly Anything overdue crossing a threshold immediately Handle these explicitly: A credit note that clears a balance should clear the overdue flag in the same run, not the next one. A disputed invoice is not the same as an unpaid one. Read the dispute flag and label it differently, because calling a customer overdue on an invoice they have queried damages the relationship. Partial payments reduce the outstanding figure without clearing the age of the oldest invoice. An account with no billing record at all is a state, not an error. Show it as not yet billed instead of as zero outstanding.
- 5
Alert on the combination, not the field
Nobody reads a field. People read an alert about a deal.
Write no alert for a number changing. Alert on combinations that mean something: Overdue beyond the threshold with a renewal in the next quarter Payment health moving from on time to consistently late A failed payment on an account with an open expansion opportunity A card expiring before the next invoice on an account above a value Send each to the account owner and to customer success, not to a shared finance channel where the account team never looks. Then report monthly: how often a renewal was worked on an account with an overdue balance nobody had flagged. That number is what this sync exists to reduce.
- 6
Validate, then hand the thresholds over
Because what counts as overdue is a commercial policy.
Run the per-step schema checks and the whole-workflow audit before this touches production. Then open the same workflow in Tray Build so revenue operations can adjust the overdue thresholds, the payment health bands and the alert rules in the visual canvas. Those are commercial policy, and they change.
What it connects to
One system holds the money, another holds the relationship, and the flow runs one way.
NetSuite
Read invoices, payments, credit notes and subscription terms. The source of truth, and never written to by this workflow.
Reads
Salesforce
Write the read-only account summary and the derived payment health label where the account team works.
Writes
Stripe
Read payment method state and failures where collection runs outside the ERP, including cards expiring before the next invoice.
Reads
Slack
Alert the account owner on the combinations that matter, rather than posting balances to a finance channel.
Writes
Snowflake
Land the payment history, so payment behaviour by segment is analysable rather than anecdotal.
Writes
Same build, other stacks
The design does not change if you run something else in one of these seats. The same prompts build it against Microsoft Dynamics 365, SAP S/4HANA, Google BigQuery, Microsoft Teams, HubSpot or Oracle.
Named systems are the ones most teams run, not the only ones that work. Each is an authentication in your Tray workspace, referenced by name, so the workflow never holds a credential. Where we have a connector page, the name links to it.
Running it in production
This puts financial data in front of the commercial team. Accuracy and direction both matter.
The platform runs it, not a laptop under a desk
Daily and weekly cadences run independently on the same engine, so a slow billing export does not delay the payment state everybody reads.
The direction is enforced, not only intended
Read from billing, write to the CRM, never the reverse. That constraint is what keeps one balance, not two.
Managed credentials, not secrets in a config file
The billing credential is read-only by design and lives in your workspace. This workflow should be incapable of changing a ledger.
RevOps owns the thresholds
Overdue bands, payment health definitions and alert rules open in Tray Build, because they are commercial policy instead of engineering settings.
Staleness is visible
Stamp the last successful sync on the account. A payment health label that silently stopped updating is worse than no label.
Questions people ask
Why one-way, not bidirectional?
Because two-way sync on financial data produces two versions of the balance, and the CRM version gets believed. Billing is the source of truth and the CRM is a reader.
Why summarise instead of copying every invoice?
Because a CRM holding every transaction becomes a second billing system that disagrees with the first within a month. A roll-up per account carries what a rep needs and nothing they will misread.
What is the most useful signal?
An account overdue beyond the threshold with a renewal inside the next quarter. That combination is the reason to build this; everything else is context.
How often should it sync?
By data type. Payment state daily, subscription terms weekly, and anything crossing an overdue threshold immediately. One interval for everything wastes calls and delays the thing that mattered.
Should a rep be able to correct a balance in the CRM?
No. Set field-level security so the summary is read-only. A corrected figure in Salesforce disagrees with the ledger and is believed by whoever reads it next.
Vibe-coding app guides
Vibe-code an entire app with Helix
This moves the data between systems. It does not give anybody a screen to work in. Build that app in Claude Code, Codex or Cursor, then deploy and run it governed on Tray Helix. Same kind of guide, same kind of prompts.
How to build a renewal tracker (opens helix.tray.ai in a new tab)
Related guides
Revenue operations
How to build an order-to-cash integration
Closed-won to sales order to invoice to cash applied, as a CRM to ERP integration. Idempotent writes, a reconciliation loop, and the Headless prompts that build it.
Revenue operations
How to build pipeline hygiene automation
Detect the staleness that matters, nudge the owner rather than the report, escalate on the deals that count, and measure whether it worked. The prompts that build it.
Platform engineering
How to build webhook fan-out
Acknowledge before you fan out, verify the signature first, retry per consumer, and make replay possible. The Headless prompts that build it.
Last reviewed September 2026.