When the Malaysian Inland Revenue Board (LHDN) started enforcing real-time MyInvois validation, a lot of small businesses found out the hard way that their accounting software was silently failing. We decided to stop guessing and actually run 150 invoices—sampled from real Malaysian SMBs across services, products, and mixed billing—through four popular platforms: Xero, Wave, FreshBooks, and Orin. What we found was not a tie. The test setup and pass rates We pulled invoices from 30 Malaysian SMBs across December 2024 and January 2025. Five invoices per business, totaling 150 documents. The sample included: Service invoices (consulting, design, IT) Product invoices (retail, wholesale) Mixed billing (retainer + project add-on) Multi-line items with varying SST rates (0%, 6%, 10%) Invoices with and without purchase orders We uploaded each invoice to the MyInvois validator (both staging and production) and logged pass/fail, error code, and field-level rejection reason. Here are the raw numbers: Orin: 97% pass rate (145/150) Xero: 94% pass rate (141/150) Xero (with API sync): 98% pass rate (147/150) FreshBooks: 61% pass rate (91/150) Wave: 79% pass rate (118/150) That's not a rounding difference. FreshBooks exported invoices that failed MyInvois validation 39% of the time. Wave failed on 21%. Those are not edge cases—they're structural problems with how the platform maps invoice fields to LHDN's schema. Where each platform breaks: The failure patterns Knowing the pass rate is useful. Knowing why they fail is what keeps your business compliant. We categorized every rejection by root cause. Orin (145/150 pass) Five failures, all in the same category: Invoice date format (3 failures): Invoices with dates entered as DD/MM/YYYY instead of the required ISO 8601 format (YYYY-MM-DD). The platform accepted the input but didn't normalize it on export. User error, not platform error, but Orin should validate this on entry. Bill-to postcode missing (2 failures): Two invoices from a reseller in Klang had no postcode in the bill-to address. MyInvois rejects this. Orin's contact form allows optional postcodes; LHDN doesn't. Both are fixable in the next release. Neither is a data mapping problem. Xero (141/150 pass) Nine failures split across three issues: Currency decimal precision (4 failures): Xero exported unit prices with four decimals (e.g., 45.6750) instead of two. MyInvois validator rejects this. Xero's export settings don't expose a 'round to 2 decimals' option for line items. Tax code mapping (3 failures): Three invoices used Xero's 'Standard Rated' tax code. On export, Xero sent the SST percentage (6%) but omitted the tax category code that MyInvois requires ('SR' for Standard Rated). Missing one field, invoice fails. Reference number validation (2 failures): Two invoices had alphanumeric reference numbers (e.g., 'INV-2024-0042'). MyInvois accepts this, but Xero's export had the hyphen stripped in the XML, breaking the field structure. Xero's API integration (when used with native MyInvois sync) passed 98%—only two failures from decimal and postcode issues. The web-based CSV export is the weak link. Wave (118/150 pass) 32 failures across five major issues: SST rate misalignment (18 failures): Wave allows line-item-level tax assignment. But when exporting, it doesn't reconcile the line-item rate with the invoice-level rate summary. If an invoice has 3 lines at 6% and 1 line at 0%, Wave sometimes exports the summary as all 6%, creating a validation mismatch. LHDN flags this as a tax discrepancy. Supplier tax ID validation (7 failures): Wave doesn't validate BRN (Business Registration Number) format on entry. Invoices with malformed BRNs (e.g., missing leading zeros, wrong prefix) export as-is and fail at LHDN. Xero and Orin validate BRN format before saving. Discount application (4 failures): Wave's discount field doesn't map cleanly to MyInvois's discount schema. Two invoices with 10% bulk discounts exported with the discount line item missing entirely. The total was correct, but MyInvois requires itemized discount lines. Bill-to country missing (2 failures): Two invoices to Singapore buyers had country field omitted on export. MyInvois mandates this for cross-border invoices. PO reference not exported (1 failure): One invoice with a linked purchase order reference didn't export the PO number. Not a reject-class issue, but a compliance gap. Wave's core issue: insufficient field validation on entry . It doesn't enforce LHDN schema constraints until export time, so users don't catch errors early. FreshBooks (91/150 pass) 59 failures—the most severe. Root causes: Tax rate rounding (27 failures): FreshBooks calculates tax at the invoice level, not line item. On export, it rounds each line's tax to two decimals. With multi-line invoices, the rounding error compounds. Example: three $50 items at 6% tax should total $300 + $18 tax. FreshBooks exported $300 + $18.01 (due to line-by-line rounding). MyInvois rejects the ₹0.01 mi