Your team just created 47 invoices. Three weeks later, LHDN rejects 12 of them. The reason? Malformed tax IDs. NPWP digits transposed. UEN missing a check digit. BRN in the wrong format. MyInvois doesn't tell you this until after submission—and by then, your cash flow and compliance clock are both ticking. This is not a data quality problem you can solve with reminders. It's an architecture problem. You need validation gates that fire at invoice creation time, not days later. That means real-time format checking, optional API validation, and a quarantine queue for edge cases. Here's how to build it. Why tax ID validation fails in most platforms Most invoicing tools treat tax ID as a text field. Xero does some format checking. Wave does almost none. FreshBooks assumes the user got it right. The problem: tax ID formats are strict and country-specific, and they're validated by government systems (LHDN in Indonesia, ACRA in Singapore, SPR in Malaysia) that reject malformed entries on submission. By the time you find out the tax ID is wrong, the invoice is already in your GL, your cash flow forecast assumes payment, and your accountant is chasing rejections instead of reconciling. The fix is simple: validate before you create the invoice, not after. Build a three-tier validation layer Tier 1: Format validation (regex or pattern matching) This is the fastest and most reliable check. Tax ID formats are rigid: NPWP (Indonesia): 15 digits, format XX.XXX.XXX.X-XXX.XXX. Regex: ^\d{2}\.\d{3}\.\d{3}\.\d{1}-\d{3}\.\d{3}$ UEN (Singapore): 9 characters, format XXXXXXXXC (8 digits + 1 check letter). Regex: ^\d{8}[A-Z]$ BRN (Malaysia): 12 digits, no separators. Regex: ^\d{12}$ Reject any invoice where the tax ID doesn't match the country's format. This catches ~90% of common mistakes: missing digits, wrong separators, transposed characters. Run this check before the invoice is saved to your database. In Orin's invoicing module , you can layer this into the invoice template or use automations to flag non-conforming tax IDs before creation. Tier 2: Check digit validation (NPWP only) NPWP has a built-in check digit (the last digit before the final group). This allows you to mathematically verify that the tax ID is not just formatted correctly, but also arithmetically valid. NPWP check digit algorithm: Take the first 14 digits of the NPWP. Multiply each digit by a weight: 15, 12, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14. Sum the products. Divide by 11; the remainder is subtracted from 11. If result is 10, use 0. Compare to the 15th digit. If the check digit doesn't match, the NPWP is either fake or corrupted. Reject it. This adds a second barrier without calling any external APIs. Tier 3: Live API validation (optional, for high-risk invoices) For invoices above a certain threshold (e.g., > ₹500,000 or > SGD 5,000), call LHDN's test environment or a third-party validator to confirm that the tax ID is registered and active. LHDN test environment: LHDN provides a sandbox API for e-Faktur validation. You can submit a test invoice and receive validation results in real time. This is slower than regex (~2–5 seconds per invoice), but it catches registered tax IDs that have been suspended or that are registered under a different business name. Stripe tax ID validator: Stripe has a public API endpoint that validates tax IDs across multiple countries, including Indonesia (NPWP), Singapore (UEN), and Malaysia (BRN). Hit their endpoint before invoice creation. If validation fails, add the invoice to a quarantine queue (see below). Example Stripe call: POST /v1/tax_ids with type=id_ntr (for NPWP) and value=15.123.456.7-890.123. Response: either { valid: true } or { valid: false, error: "Invalid NPWP format" }. Layer this into your invoicing workflow as an optional, async call. Don't block invoice creation on it—that introduces latency and frustration. Instead, flag high-risk invoices and route them to a quarantine queue. Implement a quarantine queue and manual escalation Not all tax ID validation failures are hard rejects. Some are edge cases: A newly registered NPWP that hasn't yet synced with LHDN's live database. A UEN registered to a holding company; the invoice is to a subsidiary that operates under the same tax ID. A BRN that's valid but in a format variant your regex doesn't recognize (e.g., with spaces instead of hyphens). Build a quarantine queue in your invoicing system. When Tier 1 or Tier 2 validation fails, move the invoice to this queue instead of rejecting it outright. Assign it to your finance or compliance team with a red flag and a link to the customer record. They can then: Contact the customer to confirm the tax ID. Update it if it was a typo. Override the validation if it's a known edge case (e.g., new NPWP not yet in LHDN's DB). Add a note to the customer's file for future invoices. Quarantine queue best practices: Visibility: Show quarantine queue metrics in your finance dashboard. Track how many invoices are stuck, why