This is a story about a product I didn’t plan to build.
The plan, at the start of December 2025, was a small Cliniko add-on. Sell a gift voucher inside the add-on, redeem it inside the add-on, the add-on updates and keeps track of the vouchers inside Cliniko.
A tidy weekend script that solved a real problem for one shop.
It worked so well that I thought I could maybe build something for other Cliniko users who I knew are out there in user groups asking about gift voucher integration.
Then I started building it properly. And the more I built, the clearer it became that gift vouchers were not a Cliniko feature. They were their own system.
The itch: vouchers were living in the wrong place
Cliniko is excellent at what it was built for: appointments, clients, practitioners, invoices, clinical workflows. It is clean, reliable, and widely trusted by allied health and service businesses for good reason. Indeed, my wife and I have been using it in our clinic, Water Lily House, since 2015.
But gift vouchers are a different kind of object. A voucher is not just a product - it has a lifecycle. It is created, sold, gifted, partially redeemed, checked, possibly reissued, eventually fully redeemed or expired. It carries a balance, it has an audit trail, it creates a liability, it has varying GST consequences, and it has expiry rules under Australian Consumer Law. Trying to make all of that live inside a product record in Cliniko was where the trouble started.
At Water Lily House, the workaround was familiar: a mix of Cliniko products, notes, spreadsheets, memory, and end-of-quarter reconstruction. It worked while the volume was low and while the same person remembered the system. It became painful the moment vouchers started behaving like real vouchers - partial redemptions, old balances, expiry questions, and customers asking how much was left.
That was the itch. Not "Cliniko is bad", but more like: I was asking a practice-management system to be a voucher ledger, a compliance register, and an accounting subledger at the same time.
Water Lily Vouchers: the original plan
The first version of what became VoucherGrid was called Water Lily Vouchers, named after the business it was built for. The original idea was simple: create a voucher in a small external tool, sync it to Cliniko as a product, redeem it through Cliniko, keep both systems aligned, and generate a report when the accountant needed one.
In my head, the architecture was tidy. Cliniko remained the centre of the workflow and Water Lily Vouchers was just a thin voucher layer beside it. A voucher created in Water Lily Vouchers would appear in Cliniko. A redemption in Cliniko would update Water Lily Vouchers. Everything stayed in sync.
It sounded neat. It lasted about a week.
The framing I started with
>
"Cliniko already has the customers. Cliniko already has the workflow. The smallest useful thing I can build is a voucher add-on that lives beside it."
>
The first two sentences were true. The conclusion was wrong.
The four-week realisation
Once I started building, the same realisation kept appearing in different forms: VoucherGrid needed to be the system of record.
Partial redemptions needed a proper balance ledger with full history, not a field that could be overwritten. GST classification needed to live with the voucher product from the moment it was created, not be inferred later from a product code.
The ACCC three-year minimum expiry needed to be enforced at issue, not remembered as a policy. Online voucher sales needed a branded storefront, payment processing, delivery emails, voucher rendering, and redemption codes - not just an invoice line or an entry in the client's record. Accounting reports needed liability snapshots, redemption histories, audit trails, and deferred revenue totals that an accountant could actually use.
The more I realised I needed, the more difficult it became to cram it all into Cliniko. Besides, none of that belonged inside Cliniko's product records. Not because Cliniko had failed - because that is not what product records are for.
By the end of that month, Water Lily Vouchers was renamed VoucherGrid, and had stopped being a Cliniko add-on in any meaningful sense. It had become a complete voucher workflow: create, sell, deliver, redeem, partially redeem, expire, void, report, and reconcile. The integration was no longer the product. The voucher system was the product.
Why I walked away from the sync
At that point I had a choice. I could keep pushing toward the original plan - build a bidirectional Cliniko sync, make VoucherGrid depend on Cliniko product records, and sell it mainly to Cliniko users. Or I could accept what the build had already shown me: VoucherGrid needed to stand on its own.
I chose standalone. Here is why.
Two-way sync adds complexity in exactly the wrong place. Keeping two systems aligned sounds simple until you list the edge cases. What happens if a product is edited directly in Cliniko? What if a partial redemption is recorded in one system while a sync is running? What if a sync fails halfway through? What if the two systems show different balances and a customer is standing at the counter? That complexity would not help the person redeeming the voucher. It would just create a new class of support problems.
Voucher state should have one source of truth. A voucher balance is not casual data - it is what the customer can still claim, what the business still owes, and what the accountant needs to reconcile. That record should live in one place, with an audit trail, and every other system should treat it as the source of truth.
The real value was not Cliniko-specific. The GST logic, ACCC expiry enforcement, partial redemption ledger, liability reporting, Xero journals, QuickBooks journals, and breakage reporting - none of that only matters to Cliniko users. It matters to massage clinics, physios, salons, day spas, restaurants, fitness studios, tutors, golf clubs, accommodation businesses, and any service business selling vouchers.
The market was bigger without the dependency. A Cliniko-only product would have served one slice of the service market. A standalone VoucherGrid can serve businesses using Cliniko, Halaxy, Nookal, Carepatron, Splose, Fresha, Lightspeed, SwiftPOS, or businesses with no booking platform at all.
The question stopped being "How do I make vouchers sync with Cliniko?" It became "What does a proper voucher system need to own?" The answer was: the voucher.
A note to Cliniko users
If you use Cliniko and found this because you are looking for a better way to sell gift vouchers, you are still exactly who I built this for. The only thing that changed is that VoucherGrid does not need to live inside Cliniko to be useful.
Cliniko remains your appointment, client, practitioner, and invoicing system. VoucherGrid sits beside it as your voucher system. You sell vouchers through your branded VoucherGrid storefront, and when a customer comes in to redeem, your staff open VoucherGrid or use the handy Chrome or Safari extension, scan or enter the voucher code, redeem the right amount, and continue with the appointment as usual. Nothing about your Cliniko booking workflow needs to change.
The difference is that the voucher now has a proper home. It has a balance, an expiry, a redemption history, GST treatment, a liability report, and an audit trail. And if a Cliniko integration comes later, it will be optional. It will not be the foundation the whole product depends on.
What this changed about integrations
I still believe integrations matter. Good integrations save time, reduce double entry, and make the product feel like it belongs in the business. VoucherGrid already treats Xero, QuickBooks and Stripe as important parts of the workflow.
But the Cliniko pivot taught me a rule I now trust: integrations should extend the product. They should not define nor restrict it.
VoucherGrid should own voucher state. Accounting systems should receive clean journal entries. Payment systems should process payments and send money directly to the merchant. Practice-management systems may eventually provide useful context - customers, appointments, locations - but they should not be responsible for deciding whether a voucher is valid, expired, partially redeemed, or still holding value.
That boundary matters. It means integrations can be added, removed, improved, or replaced without breaking the voucher record. It also means VoucherGrid can work for businesses that do not use Cliniko at all.
The integration shape I trust now
The pattern is simple:
| Direction | Allowed | Why |
|---|---|---|
| VoucherGrid → Xero / QuickBooks | Yes, one-way | Journal entries should flow out cleanly |
| Stripe → VoucherGrid | Yes, webhook | Payment events create voucher events |
| Practice system → VoucherGrid | Maybe, read-only | Customer or appointment context can be useful |
| Practice system ↔ VoucherGrid | Avoid | Bidirectional voucher state creates drift |
The important part is not the specific systems - it is the boundary. VoucherGrid owns the voucher. Other systems can receive events or provide context. They do not become the voucher ledger.
The lesson
The lesson is not "do not build integrations." The lesson is: build the product first, then let the integration strategy follow the product's real value.
I started out thinking the value was in bolting voucher tracking onto Cliniko. Four weeks of building taught me the value was underneath that - the GST logic, the deferred revenue tracking, the balance ledger, the audit trail, the expiry enforcement, and the accountant-ready reports. That value is useful to Cliniko users. It is also useful to every other Australian service business selling gift vouchers.
So Water Lily Vouchers became VoucherGrid. A weekend script became a platform. And a planned Cliniko integration became an optional future add-on, not the thing holding the product together.
I am glad I walked away from the sync. Not because Cliniko stopped mattering - because the voucher finally had somewhere better to live.