How do you handle tax API errors?
TaxBridge normalizes errors into one vocabulary. Validation problems (400) list the exact fields; duplicates (409) mean the invoice was already approved; quota (402) means upgrade or renew; rejections (422) carry the authority message; timeouts (502/504) should be retried with the same idempotency key.
The full table
| HTTP | Meaning | What your code does |
|---|---|---|
201 | Approved by the authority | Print qrCode, store submissionId |
200 | Idempotent replay (duplicate:true) | Treat like the original — no quota consumed |
400 INVALID_INVOICE | Normalizer rejected it; details[] lists every problem | Fix and resubmit — no quota consumed |
402 QUOTA_EXCEEDED | Plan limit hit or subscription expired | Upgrade or renew |
409 DUPLICATE_INVOICE | Invoice number already approved for this authority + environment | Do not resubmit |
422 | Authority rejected it (status:"REJECTED") | Read authorityMessage, fix the data |
429 | Rate limit or sandbox soft cap | Honour Retry-After |
502 / 504 | Authority errored or timed out | Retry with the same Idempotency-Key |
Fixing INVALID_INVOICE (400)
The normalizer rejected the payload before any authority call, so no quota was consumed. The details[] array names every problem — missing customer name, a bad HS code, totals that do not add up. Fix the listed fields and resubmit.
Handling DUPLICATE_INVOICE (409) vs replay (200)
A 409 means this invoice number was already approved for this authority and environment — do not resubmit. A 200 with duplicate:true is an idempotent replay of your own earlier call; treat it exactly like the original result, no quota consumed.
Retrying 502/504 safely
These mean the authority errored or timed out. Retry with the same Idempotency-Key; a completed key replays the stored response and never double-files. Never retry without one.