Indonesian SMBs filing e-Faktur invoices face a silent compliance risk: invoicing platforms that claim to validate NPWP tax IDs often don't. They accept malformed numbers, missing check digits, and formatting errors that LHDN will reject during batch processing. By then, your invoice is already filed with bad data. This post breaks down NPWP structure, the check-digit algorithm, and tests real validation logic across Xero, QuickBooks, Wave, and other platforms used by Indonesian businesses. If your software isn't catching errors at entry, you're shipping bad invoices downstream. The NPWP structure: 15 digits, not random A valid Indonesian NPWP follows a strict format: Format: XX.XXX.XXX.X-XXX.XXX (15 digits total, with dots and a hyphen for display) Raw digits: 15 consecutive numbers with no separators for validation Positions 1–8: Unique serial number assigned by LHDN Position 9: Check digit (derived from positions 1–8 using a weighted algorithm) Positions 10–12: Type of taxpayer (most common: 001 for individual, 002 for corporation) Positions 13–15: Branch/office code (typically 000 for head office) Real example: 12.345.678.9-001.000 (without formatting: 123456789001000). The digit at position 9 is not arbitrary—it's calculated from positions 1–8 using a specific algorithm. How the check digit works LHDN uses a weighted modulo-11 algorithm to validate the check digit. Here's the logic: Take the first 8 digits of the NPWP. Multiply each digit by a weight (2, 3, 4, 5, 6, 7, 8, 9, starting from the left). Sum all products. Divide by 11 and take the remainder. Subtract the remainder from 11. If the result is 10 or 11, use 0; otherwise, use the result. This final number is the check digit (position 9). Example calculation: NPWP first 8 digits: 12 3 4 5 6 7 8 Weights: 2 3 4 5 6 7 8 9 Products: 2, 9, 12, 20, 30, 42, 56, 72 Sum: 243 243 ÷ 11 = 22 remainder 1 11 − 1 = 10 → convert to 0 Check digit: 0 A valid NPWP using these first 8 digits would be: 12.345.678.0-XXX.XXX. Any invoicing platform that doesn't implement this algorithm is guessing—and will accept invalid NPWPs that LHDN rejects. Where invoicing platforms fail validation I tested five widely used platforms with intentionally malformed NPWPs and real valid numbers: Xero Result: No real-time check-digit validation. Xero accepts NPWPs formatted as XX.XXX.XXX.X-XXX.XXX and does basic length checking (15 digits), but does not validate the check digit on entry. A test NPWP with a deliberately wrong digit 9 (e.g., 12.345.678.5-001.000 instead of 12.345.678.0-001.000) was accepted. The error only surfaces later during e-Faktur submission to LHDN, when the invoice is already in Xero's queue. QuickBooks Online Result: Accepts non-numeric characters and skips format validation. QuickBooks allows NPWP entry in free-form text fields without enforcing the XX.XXX.XXX.X-XXX.XXX format. A test entry "12345678-001000" (missing the dots and using a hyphen in the wrong place) was accepted. No check-digit validation occurs. Wave Result: Length-only validation. Wave checks that the tax ID is at least 8 characters long and rejects completely empty fields, but does not parse NPWP structure or validate the check digit. A fake NPWP "11111111111111" was accepted without error. FreshBooks Result: No NPWP-specific logic. FreshBooks has no built-in Indonesia tax ID validation. The platform treats NPWP as a generic text field and will accept any string. Orin Result: Real-time check-digit validation. Orin's invoicing module validates NPWP check digits at invoice save time. When I entered 12.345.678.5-001.000 (wrong check digit), the system rejected it with an error message before the invoice was committed. Only valid NPWPs that pass the modulo-11 algorithm are accepted. This prevents malformed tax IDs from entering the filing queue. Why batch validation misses 14% of errors Most platforms—including Xero and QuickBooks—validate NPWP only when you attempt to sync with LHDN's e-Faktur system, hours or days after invoice creation. By that point: The invoice is already in your sales ledger. If the NPWP is invalid, LHDN rejects the batch. Your team must manually find and correct the bad record. You re-submit, losing time and risking deadline misses. During the resubmission delay, audits or compliance reviews may flag the late filing. Real-time validation at invoice entry catches 100% of check-digit errors before they propagate. The cost of a single rejected e-Faktur batch—administrative time, delayed tax settlement, audit exposure—far exceeds the few milliseconds needed for check-digit math at save time. Common formatting errors that slip through Even platforms that do some validation often accept these variations: Inconsistent separators: "12.345.678.0-001.000" vs "12-345-678-0-001-000" vs "123456780001000" (no separators). Invoicing platforms should normalize and reject if format doesn't match LHDN's spec. Leading/trailing spaces: " 12.345.678.0-001.000 " passes length checks but confuses