Errors
Esnad uses a single error object for request failures (HTTP 4xx). ZATCA content warnings on an accepted invoice are not errors — they appear on 200 responses as zatca_warnings.
Error object
Failed requests return JSON with an error object. Check retryable before automatic retries.
{
"error": {
"code": "SELLER_VAT_MISMATCH",
"message": "seller.vat_number must match the company profile VAT (3…). Received: \"3999…\"",
"retryable": false
}
}Two lanes
- Esnad 4xx — we cannot safely build or attribute the invoice (auth, EGS, money math, identity). Listed below.
- Fatoora / ZATCA — content rules (building digits, CRN shape, VATEX, …). We call Fatoora; you get warnings on HTTP 200 or a later
failedstatus. See Responses.
Authentication
| Code | HTTP | Meaning | Retry |
|---|---|---|---|
| MISSING_AUTH | 401 | No Authorization: Bearer header. | No |
| INVALID_API_KEY | 401 | API key unknown, revoked, or malformed. | No |
Company profile & quotas
| Code | HTTP | Meaning | Retry |
|---|---|---|---|
| PROFILE_INCOMPLETE | 403 | Production EGS or live API key requires complete company profile (VAT, CR, Saudi address). | No |
| LEGAL_ENTITY_LIMIT_REACHED | 402 | Organization has reached its legal entity quota (dashboard Companies page). | No |
EGS
| Code | HTTP | Meaning | Retry |
|---|---|---|---|
| EGS_UNIT_REQUIRED | 400 | egs_unit_id missing from the body. | No |
| EGS_UNIT_NOT_FOUND | 400 | Unit does not exist for this tenant. | No |
| EGS_UNIT_ENV_MISMATCH | 400 | API key environment does not match the EGS unit. | No |
| EGS_NOT_READY | 400 | Onboarding not active — wait until status is active. | No |
| EGS_INVOICE_TYPE_MISMATCH | 400 | Unit invoice_type cannot issue this document kind. | No |
| CERTIFICATE_EXPIRED | 400 | CSID expired — renew the unit. | No |
Invoice structure & identity
These are required so we can price, sign, and attribute the UBL. ZATCA format rules (4-digit building, CRN≠VAT, VATEX codelist) are not API validation errors.
| Code | HTTP | Meaning | Retry |
|---|---|---|---|
| VALIDATION_ERROR | 400 | Unknown or invalid field. See error.details. | No |
| EMPTY_LINE_ITEMS | 400 | line_items must contain at least one line. | No |
| INVALID_QUANTITY | 400 | quantity must be greater than 0. | No |
| INVALID_PRICE | 400 | unit_price must be ≥ 0. | No |
| INVALID_VAT_CATEGORY | 400 | vat_category must be S, Z, E, or O (we use it to compute 15% vs 0%). Omit to default to S. | No |
| MISSING_SELLER_DATA | 400 | Seller name required. | No |
| INVALID_SELLER_VAT | 400 | Seller VAT must be 15 digits starting and ending with 3. | No |
| SELLER_VAT_MISMATCH | 400 | seller.vat_number must match the company profile VAT when the profile has one. | No |
| SELLER_CRN_REQUIRED | 400 | A Commercial Registration Number is required on the invoice or company profile (presence only — not format). | No |
| MISSING_SELLER_ADDRESS | 400 | No address on the invoice and no usable company-profile address. | No |
| MISSING_BUYER_DATA | 400 | Buyer address required for standard (B2B) invoices. | No |
| INVALID_BUYER_VAT | 400 | Buyer VAT shape invalid or missing for B2B. | No |
| UNSUPPORTED_CURRENCY | 400 | Only SAR is supported. | No |
Notes & lookups
| Code | HTTP | Meaning | Retry |
|---|---|---|---|
| ORIGINAL_INVOICE_NOT_FOUND | 404 | Credit/debit note original UUID not found. | No |
| ORIGINAL_INVOICE_NOT_READY | 400 | Original invoice not yet reported/cleared. | No |
| CREDIT_NOTE_TOTAL_EXCEEDS_ORIGINAL | 400 | Credit note total exceeds the original invoice. | No |
| INVOICE_NOT_FOUND | 404 | GET/list target invoice missing for this tenant. | No |
| IDEMPOTENCY_KEY_MISMATCH | 409 | Same Idempotency-Key with a different body than the first request. | No |
Fatoora / ZATCA (not API validation errors)
Wrong building digits, VAT-shaped CRN, missing VATEX on zero-rated lines, and similar rules are enforced by Fatoora. Typical outcomes:
- Accept with warnings — HTTP 200,
zatca_compliant: false,resubmit: false,zatca_warnings[]with codes like BR-KSA-37, BR-KSA-69, BR-KSA-F-08. - Hard reject after submit — invoice may move to
failed; seelast_errorand invoice.failed.
BR-KSA codes (e.g. BR-KSA-37, BR-KSA-69) appear in zatca_warnings on accepted invoices. Esnad does not re-implement that full catalog as API validation errors — fix the underlying data on your next document and read warnings via Responses or webhooks. Contact support if you need help interpreting a specific code.