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.

Example
{
  "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 failed status. See Responses.

Authentication

CodeHTTPMeaningRetry
MISSING_AUTH401No Authorization: Bearer header.No
INVALID_API_KEY401API key unknown, revoked, or malformed.No

Company profile & quotas

CodeHTTPMeaningRetry
PROFILE_INCOMPLETE403Production EGS or live API key requires complete company profile (VAT, CR, Saudi address).No
LEGAL_ENTITY_LIMIT_REACHED402Organization has reached its legal entity quota (dashboard Companies page).No

EGS

CodeHTTPMeaningRetry
EGS_UNIT_REQUIRED400egs_unit_id missing from the body.No
EGS_UNIT_NOT_FOUND400Unit does not exist for this tenant.No
EGS_UNIT_ENV_MISMATCH400API key environment does not match the EGS unit.No
EGS_NOT_READY400Onboarding not active — wait until status is active.No
EGS_INVOICE_TYPE_MISMATCH400Unit invoice_type cannot issue this document kind.No
CERTIFICATE_EXPIRED400CSID 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.

CodeHTTPMeaningRetry
VALIDATION_ERROR400Unknown or invalid field. See error.details.No
EMPTY_LINE_ITEMS400line_items must contain at least one line.No
INVALID_QUANTITY400quantity must be greater than 0.No
INVALID_PRICE400unit_price must be ≥ 0.No
INVALID_VAT_CATEGORY400vat_category must be S, Z, E, or O (we use it to compute 15% vs 0%). Omit to default to S.No
MISSING_SELLER_DATA400Seller name required.No
INVALID_SELLER_VAT400Seller VAT must be 15 digits starting and ending with 3.No
SELLER_VAT_MISMATCH400seller.vat_number must match the company profile VAT when the profile has one.No
SELLER_CRN_REQUIRED400A Commercial Registration Number is required on the invoice or company profile (presence only — not format).No
MISSING_SELLER_ADDRESS400No address on the invoice and no usable company-profile address.No
MISSING_BUYER_DATA400Buyer address required for standard (B2B) invoices.No
INVALID_BUYER_VAT400Buyer VAT shape invalid or missing for B2B.No
UNSUPPORTED_CURRENCY400Only SAR is supported.No

Notes & lookups

CodeHTTPMeaningRetry
ORIGINAL_INVOICE_NOT_FOUND404Credit/debit note original UUID not found.No
ORIGINAL_INVOICE_NOT_READY400Original invoice not yet reported/cleared.No
CREDIT_NOTE_TOTAL_EXCEEDS_ORIGINAL400Credit note total exceeds the original invoice.No
INVOICE_NOT_FOUND404GET/list target invoice missing for this tenant.No
IDEMPOTENCY_KEY_MISMATCH409Same 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; see last_error and 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.

Related: Responses · Invoices