← for real estate agencies

VAULTRE → XERO + PORTALS · TECHNICAL

Settled sales that invoice their own commission

The owner-facing version of this lives here. This is the breakdown for whoever in the agency actually runs the software — the approach, the data we touch, the real shape of the mapping, and the line we draw at the trust account.

technical · 8 min read · VaultRE REST API + Xero Accounting API

The problem, stated precisely

VaultRE already holds everything about a sale: the property, the sale price, the agents on it, the commission structure, the buyer and vendor contacts. The moment a sale settles, all of that is sitting there, perfectly structured. And yet the commission invoice gets rebuilt by hand in Xero — sale price re-typed, the agency's percentage re-calculated, splits and referral fees worked out in a spreadsheet, GST added on top. It's the kind of job that's wrong roughly as often as it's late.

The same shape of problem repeats at the other end: a listing entered in VaultRE is re-entered for realestate.com.au and Domain, and a managed property's owner is re-keyed into the PM platform. Different data, identical waste.

What "fixed" looks like

A sale is marked settled in VaultRE. Within seconds, a draft commission invoice exists in Xero against the right contact — gross commission as one line, each deduction (referral, conjunctional split, franchise fee) as its own, GST applied correctly, and the VaultRE sale ID stamped on the reference so the two systems can always be reconciled back to each other. A bookkeeper approves it. Nobody re-typed a number.

How we'd connect it

VaultRE exposes a REST API over the agency's data — listings, sales, contacts and enquiries. Where VaultRE can notify us of a change we subscribe to it; where it can't, we poll on a schedule and track what we've already seen. Either way the pattern is the same: detect a settled sale, read the full record, translate it into Xero's shape, and write a draft invoice.

VaultRE sale settled read full sale + splits map to commission invoice Xero (draft)

Three pieces are where the real work is, and where a generic connector falls over: authenticating to VaultRE and reading the sale reliably, mapping commission, splits and GST correctly, and knowing what not to touch.

1. Authenticate and detect the settled sale

We authenticate to the VaultRE API with the agency's credentials and either receive a change notification or poll the sales endpoint for status changes. We record every sale ID we've processed, so a re-notification or an overlapping poll never produces a second invoice. The detection step is deliberately boring and idempotent — boring is what you want touching the books.

detect-settled.js
// poll (or receive a webhook) → only act on a clean transition to settled
async function onSaleChanged(saleId){
  if (await alreadyProcessed(saleId)) return;   // idempotent
  const sale = await vault.get(`/sales/` + saleId);
  if (sale.status !== "settled") return;        // ignore drafts / fall-throughs

  await withRetry(() => createCommissionInvoice(sale));
  await markProcessed(saleId);
}

2. Map the sale to a commission invoice

This is the part that earns the fee. A residential sale is rarely "one agency, one percentage." There are split agents, conjunctional agencies, referral fees, and — for franchise offices — a franchise fee off the top. Each of those is a separate line with its own account code, and GST applies to the commission, not to the sale price. We model the commission explicitly rather than collapsing it to a single number, so the invoice your bookkeeper sees matches the agreement the vendor signed.

map-commission.js — illustrative shape, mapped to your real commission rules
function toXeroInvoice(sale){
  const gross = sale.commission.grossExGst;   // agency commission, ex-GST
  return {
    Type: "ACCREC",
    Status: "DRAFT",                       // a human approves before it's live
    Contact: { Name: sale.vendor.displayName },
    Reference: `VaultRE sale #` + sale.id,
    Date: sale.settlementDate,
    LineAmountTypes: "Exclusive",
    LineItems: [
      { Description: `Commission — ` + sale.address,
        Quantity: 1, UnitAmount: gross,
        AccountCode: "200", TaxType: "OUTPUT" },     // GST on commission
      ...sale.deductions.map(d => ({              // referral, conjunctional, franchise
        Description: d.label, Quantity: 1,
        UnitAmount: -d.amountExGst,
        AccountCode: d.accountCode, TaxType: d.taxType }))
    ]
  };
}

Then it's a single authenticated call to Xero's Accounting API to create the invoice as a draft. We default to draft on purpose: the first thing an agency principal asks is "so a robot is writing invoices?" — and the honest answer is no, the robot writes the draft and a person clicks approve, until you trust it enough to change that.

3. Push a listing once (the other half)

The same VaultRE read pattern feeds the portals. A listing entered in VaultRE is mapped to the realestate.com.au and Domain schemas — which disagree on property types, features and media rules — and pushed, so price and copy can't drift between the two. This typically uses the portals' standard listing feed rather than ad-hoc posting, and it's scoped as its own piece because the schema-mapping is fiddly enough to deserve its own testing.

The line we don't cross

// trust accounting

An agency runs two financial worlds: the agency's own books (Xero, fair game) and the trust account (PropertyMe, Property Tree, Console — regulated under state agents' legislation, audited, and not ours to write to). We read from and report on the trust platform where it helps — outstanding rent, owner statements, reconciliations to check — but we never post a transaction into a trust ledger. We move data, not money. This isn't caution for its own sake; writing to a trust account is a compliance boundary, and respecting it is part of the build.

The edge cases that bite

The happy path is a clean single-agency sale. The reason this is real work and not a Zapier zap is everything below.

// what we build for, that a generic connector doesn't
  • Commission splits and conjunctionals. Two agencies on one sale, internal agent splits, and referrer fees each land as their own line against the right account — not buried in one lump.
  • GST on commission, not on price. The taxable amount is the agency's commission, with the right Xero tax type — so the BAS is right the first time.
  • Fall-through and re-settlement. Sales collapse and re-list. We act only on a genuine transition to settled, and never invoice a deal that fell over.
  • Adjusted or amended sales. A corrected sale price after settlement becomes a credit note or adjustment with an audit trail, not a quiet overwrite.
  • Duplicate notifications. Webhook retries and overlapping polls are de-duplicated by sale ID — a sale is invoiced exactly once.
  • Portal schema drift. REA and Domain model property types, features and media differently; the mapping is explicit and validated before anything goes live to the public.
  • When a system is down. Failed pushes land in a retry queue with alerting. You hear about a problem from us, not from your auditor.

What it'd take for you

The VaultRE → Xero commission piece on its own typically lands in the $6k–$12k range and takes a couple of weeks, depending on how layered your commission and franchise structure is. Adding the listing-to-portals push, or read-only reporting off your PM platform, scopes as its own stage. You'd watch it produce draft invoices against real settled sales before it touches anything you rely on.

Sound like your settlement process?

tell us what's not talking to what · 20-min fit call

Book a fit call