Indonesia's MyInvois mandate arrives in Q2 2025, and most invoicing platforms either don't know it's coming or are pretending the problem is smaller than it is. We tested four: FreshBooks, Xero, Wave, and Orin. Real invoices. Real LHDN submission. Real validation rules. Three of them fail in ways your accountant won't catch until the audit does. What MyInvois actually requires—and why most platforms miss it MyInvois is Indonesia's e-invoicing mandate. Every invoice issued after the enforcement date must validate against the LHDN (Direktorat Jenderal Pajak) API in real time. No batch uploads. No "we'll fix it later." The invoice must authenticate, contain a valid NPWP (tax ID), match the business entity, and serialize a valid JSON structure that LHDN will accept or reject on submission. Here's what invoicing platforms struggle with: NPWP format and digit check: NPWP is 15 digits. Most platforms store it as text and don't validate the check digit. LHDN does. Business entity matching: Your invoices must link to a registered NPWP. If your invoice is issued by Entity A but the NPWP belongs to Entity B, LHDN rejects it. Tax calculation and rounding: If your platform rounds tax to 2 decimals but LHDN expects 0, the submission hash fails. Timestamp and serialization: The JSON structure must match LHDN's schema exactly. A missing field or a string where a number is expected kills the whole submission. Most platforms build invoicing for the West—Australia, UK, US. They bolt on "international" features without understanding that MyInvois is not an optional checkbox. It's mandatory, it's real-time, and it validates before your invoice is legally issued. FreshBooks: Silent failure on NPWP validation FreshBooks lets you store a tax ID field. We entered a valid NPWP and issued an invoice. The invoice generated cleanly. No errors. No warnings. Then we submitted the JSON to LHDN's test API. Rejected: invalid tax ID format. We checked FreshBooks' field validation. It stores the NPWP as a text string. It does not validate the 15-digit format. It does not calculate the check digit. It does not flag when the NPWP doesn't match the business entity. Worse: FreshBooks' export shows the NPWP in the invoice JSON, but the value is not padded or formatted to LHDN spec. When LHDN's parser tries to read it, the check digit fails, and the entire submission is rejected. This is a silent failure. Your accountant sees a valid-looking invoice in FreshBooks. They don't know it will fail LHDN validation until they try to submit it—after the enforcement date. FreshBooks does not validate NPWP format or check digit. Invoices with invalid NPWP will pass FreshBooks but fail LHDN submission. Xero: Passes validation but creates confusion in the audit trail Xero validates the NPWP format and matches it against the business entity. The invoice submitted cleanly to LHDN's test API. However, Xero's audit trail is muddied. When you update the NPWP on a contact, Xero does not retroactively update prior invoices. If you correct an NPWP mid-month, invoices issued before the correction still carry the old (possibly invalid) NPWP. You must manually reissue the invoice to update the LHDN submission. Xero also doesn't warn you when an invoice fails LHDN submission. It shows "invoice issued" and assumes the LHDN submission was successful. If the submission failed (due to a timeout, network error, or schema mismatch), Xero doesn't retry or alert you. Your accountant must manually check the LHDN portal to confirm. The platform passes the validation test. The operational risk is in the handoff between Xero and LHDN. Wave: Strips tax IDs and routes around the problem Wave doesn't have a dedicated NPWP field in its invoicing module. We added the NPWP as a custom field, thinking we could populate it on export. When we exported the invoice as JSON, Wave's export did not include the custom field. The tax ID was missing from the serialized invoice. LHDN rejected it immediately: required field missing. Wave's workaround is to route all tax ID data through the invoice line items (as memo text). This is fragile, manually intensive, and not auditable. If a user deletes the memo, the tax ID is lost. If the tax rate changes, the memo becomes outdated. For MyInvois compliance, Wave requires manual post-processing before submission. This scales badly and introduces error. Orin: Validates, submits, and logs the audit trail Orin validates NPWP format and check digit at invoice creation. If the NPWP is invalid, the invoice draft is blocked until you correct it. On submission, Orin submits the invoice JSON to LHDN's API and logs the response (pass or fail) in the audit trail. If LHDN rejects the submission, Orin flags the invoice as "LHDN submission failed" and displays the specific error. Your team knows immediately. Because Orin integrates WhatsApp and email messaging natively , you can alert customers about invoice status without switching tools. If an invoice fails LHDN validati