Skip to content

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

  1. System NetSuite
  2. Step Summarise per account
  3. Step Derive signals
  4. System Salesforce
Also Alert on combination

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. 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. 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. 3

    Signals are derived from the raw figures

    Days overdue, average days to pay, payment method risk, trend against the last two quarters.

  4. 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. 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. 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. 1

    Set up and decide what actually needs to cross

    Most billing to CRM projects fail by copying too much.

    Headless skills build-workflow

    Use 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. 2

    Summarise per account, and keep it read-only

    The rule that stops the CRM becoming a second ledger.

    Headless skills build-workflow

    Use 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. 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. 4

    Match the cadence to the data, and handle the edges

    Because syncing everything hourly hides the change that mattered.

    Headless skills tray-gotchas

    Use 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. 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. 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)

Last reviewed September 2026.