Skip to main content

Egypt ETA E-Invoice & E-Receipt

The ECOSIRE Egypt ETA module is a country pack that connects Odoo to the Egyptian Tax Authority (ETA) e-invoicing and e-receipt system. Egypt operates a direct government API model: your Odoo instance calls the ETA REST API directly (no Peppol relay, no third-party ASP) using OAuth2 client_credentials to obtain a short-lived JWT, then submits signed JSON documents asynchronously.

This module sits on top of the GCC E-Invoicing | Core Engine and adds everything Egypt-specific: the ETA state machine (draft → built → submitted → cleared / rejected), submission UUID and document UUID tracking, cancel/reject within the ETA time window, EGS/GS1 product code management, notification polling, a per-submission audit log, and a clear preprod-first onboarding flow.

Compatibility: Odoo 17 / 18 / 19 (Community or Enterprise) Price: $349 (one-time) — requires GCC E-Invoicing Core ($499) installed alongside License: Up to 3 domain activations Category: Accounting / Localizations / EDI ETA authority: Egyptian Tax Authority — sdk.invoicing.eta.gov.eg

Live demo

The GCC E-Invoicing suite is live at zatca.demo.ecosire.com — log in with admin / admin. The KSA pack is active on the demo; Egypt pack configuration requires your own ETA preprod sandbox credentials.

Overview

Egypt's ETA mandate covers B2B e-invoicing (Invoice, Credit Note, Debit Note, and Export variants) and B2C e-receipt (POS). The mandate has been rolling out in phases: large taxpayers first, then mid-size, then small taxpayers and B2C eReceipt. Check the ETA portal to verify your filing obligation.

What this module does:

  • OAuth2 token management — acquires and caches a 60-minute Bearer token from the ETA Identity Service (id.eta.gov.eg / id.preprod.eta.gov.eg). Tokens are cached for the full lifetime; the module never acquires a new token on every API call.
  • Document builder — assembles a JSON document skeleton from an Odoo account.move: issuer TIN/RIN, receiver identity, document type and version, line items with EGS item codes and unit types, tax breakdown, and totals.
  • Async submission — posts the document to POST /api/v1.0/documentsubmissions (HTTP 202 = accepted for processing, not final clearance). The module stores the ETA-assigned submissionUUID and, once assigned, documentUUID (26 chars) and longId (42 chars, for ETA PDF retrieval).
  • Submission lifecycle state machine — seven states: draft → built → submitted → cleared / rejected / pending_retry / dead_letter. Every state change is chatter-logged.
  • Cancel / reject within ETA windowPUT /api/v1.0/documents/state/{UUID}/state for issuers (cancel) and recipients (reject), within the ETA-configured time window.
  • Poll submission statusGET /api/v1.0/documentsubmissions/{submissionUUID} to reconcile state after the async 202.
  • Document type / schema retrievalGET /api/v1.0/documenttypes and version schema endpoint (returns Base64 JSON/XML schema) for diagnostic use.
  • ETA notification pollingGET /api/v1.0/notifications/taxpayer with date/type/language filters.
  • EGS / GS1 product code management — register taxpayer internal codes (POST /api/v1.0/codetypes/requests/codes) and search published codes.
  • Automatic retry cron — a scheduled job retries pending_retry submissions (transient 429/503 failures). After five consecutive failures, a submission moves to dead_letter for manual review.
  • Per-submission audit log (eta.audit.log) — every API attempt is recorded with HTTP method, target URL, environment, ETA error code, and a truncated response excerpt. Secrets are never written.
  • Per-company credential scope — credentials live on res.company and are company-scoped, supporting multi-company deployments.
  • Environment switch — preprod sandbox vs production, per company.

Important constraints (sandbox-gated): The exact JSON document schema (field names, casing, required sub-objects) is published by ETA only via the preprod sandbox Get Document Type Version endpoint. The X.509 eSeal signing algorithm and CanonicalJSON serialization rules live in the ETA integration toolkit (Docker/NuGet/CLI), not in public documentation. The eReceipt submission endpoint path was unavailable on the SDK portal at contract-verification time. These three areas raise a clear UserError directing you to complete preprod sandbox onboarding before using them in production. No endpoints are fabricated — only contract-verified paths are implemented.

Requirements

RequirementDetail
Odoo17.0, 18.0, or 19.0 (Community or Enterprise)
Required moduleecosire_einvoice_core (GCC E-Invoicing Core Engine)
Required moduleecosire_license_client (ECOSIRE License Client)
Python packagesrequests
ECOSIRE licenseActive license for ecosire_einvoice_eg
ETA preprod credentialsOAuth2 client_id + client_secret from the ETA preprod portal — required before any submission
X.509 eSeal certificateUSB hardware security token or HSM from an ETA-accredited certification authority — required for production submissions

Installation

  1. Download ECOSIRE GCC E-Invoicing Core and ECOSIRE Egypt ETA E-Invoice ZIPs from your ECOSIRE Dashboard.
  2. Extract both to your Odoo addons directory:
    unzip ecosire-einvoice-core-*.zip -d /opt/odoo/addons/
    unzip ecosire-einvoice-eg-*.zip -d /opt/odoo/addons/
  3. Install the Python dependency:
    pip install requests
  4. Restart the Odoo service:
    sudo systemctl restart odoo
  5. In Odoo, go to Apps, click Update Apps List.
  6. Search for ECOSIRE E-Invoicing | Egypt ETA and click Install (the core engine installs automatically as a dependency).
  7. Enter your ECOSIRE license key when prompted.

After installation an ETA E-Invoicing menu appears under Accounting.

Configuration & Credentials

Step 1: Activate your ECOSIRE license

Navigate to Settings → ECOSIRE License and enter the license key you received. The license must be active before building or submitting documents — all transmission entry points are license-gated.

Step 2: Obtain ETA credentials from the preprod portal

Before configuring Odoo, complete taxpayer-system registration on the ETA preprod portal:

  1. Go to profile.preprod.eta.gov.eg and register your organization.
  2. Under the taxpayer-system registration section, create a new system integration and note your Client ID and Client Secret.
  3. Install the ETA Root CA certificate on your development machine (preprod only — do not install the preprod certificate on production systems). Admin rights are required on Windows.
  4. Download the ETA Postman collection and environment files from the SDK portal FAQ page to verify your credentials manually before wiring them into Odoo.
  5. Obtain your Taxpayer Registration/Identification Number (RIN/TIN) — this appears as the issuer identity on every submitted document.
  6. Procure an X.509 eSeal certificate from an ETA-accredited certification authority (USB token or HSM) — required before signing live production documents. Preprod uses document version v0.9, which disables signature validation for testing.

Step 3: Enter credentials in Odoo

  1. Go to Settings → Companies and open your company record.
  2. Open the ETA E-Invoicing tab (added by this module).
  3. Fill in the following fields:
FieldWhere it comes from
ETA EnvironmentChoose Preprod Sandbox first; switch to Production only after successful sandbox tests
ETA Client IDOAuth2 client_id from the ETA portal system registration
ETA Client SecretOAuth2 client_secret from the ETA portal system registration — stored masked
ETA Registration Number (RIN/TIN)Your taxpayer registration/identification number
On-Behalf-Of (Intermediary)Leave empty for direct submission; set to the taxpayer RIN only if this ERP acts as an intermediary on behalf of another registered entity
ETA Document Versionv1.0 for production (signature validation active); v0.9 for transition/testing only (signature validation disabled)
  1. Save the company record. Credentials are stored per company — in a multi-company setup, configure each company independently.

Step 4: Verify the connection (preprod)

Open an ETA Submission record (Accounting → ETA E-Invoicing → Submissions → New), select a posted invoice, set Document Type to Invoice, and click Build Document. If credentials and the RIN are correct, the document JSON is assembled and the state advances to Built. Review the JSON in the Document JSON field — this is the contract-shaped skeleton. Full schema conformance and eSeal signing require completing the preprod sandbox integration toolkit setup (see the ETA SDK portal at sdk.invoicing.eta.gov.eg).

Sandbox vs production

ItemPreprod SandboxProduction
Identity serviceid.preprod.eta.gov.egid.eta.gov.eg
API base URLapi.preprod.invoicing.eta.gov.egapi.invoicing.eta.gov.eg
Root CAInstall ETA preprod Root CA (dev machine only)Standard trusted CA
Document versionv0.9 (signature validation off)v1.0 (signature required)
SigningNot required (v0.9)X.509 eSeal certificate required

Switch the ETA Environment field on the company to Production only after you have validated the full flow — schema-exact document assembly and eSeal signing — in the preprod sandbox.

Usage

The submission workflow

Each ETA document starts as an eta.submission record linked to an Odoo invoice (account.move). The workflow is:

  1. Create a submission — go to Accounting → ETA E-Invoicing → Submissions and click New. Select the posted invoice and choose the document type (Invoice, Credit Note, Debit Note, Export Invoice, Export Credit Note, or Export Debit Note).
  2. Build document — click Build Document. The module assembles the JSON payload from the invoice (issuer, receiver, line items, taxes, totals) and stores it on the record. State moves to Built.
  3. Submit to ETA — click Submit. The module posts the payload to POST /api/v1.0/documentsubmissions. ETA returns HTTP 202 (accepted for async processing) with a submissionUUID. State moves to Submitted.
  4. Poll status — click Poll Status to query GET /api/v1.0/documentsubmissions/{submissionUUID}. When ETA finishes processing, the state advances to Cleared (valid) or Rejected.
  5. Cancel or reject (if needed) — within the ETA-configured time window, use Cancel (issuer) or Reject (recipient) to send a PUT state-change request. After the window expires, issue a credit note instead.

Submission states

StateMeaning
DraftRecord created; no document built yet
BuiltJSON document assembled; not yet submitted
SubmittedAccepted by ETA (HTTP 202); awaiting async processing
ClearedETA confirmed the document is valid
RejectedETA rejected the document (see audit log for error code)
Pending RetryTransient failure (429/503) — automatic retry cron will re-attempt
Dead LetterFive consecutive failures — manual review required

Automatic retry

A scheduled cron job (_cron_retry_pending) runs on the interval configured in Settings → Technical → Automation → Scheduled Actions and re-attempts all pending_retry submissions. After five failures, the submission moves to dead_letter. The retry cron silently skips execution if the ECOSIRE license is not active.

Audit log

Every API interaction is recorded in eta.audit.log (Accounting → ETA E-Invoicing → Audit Log): HTTP method, target URL, environment (preprod/production), outcome, ETA error code, and a truncated response excerpt. Credentials and secrets are never written to the audit log.

ETA notification polling

Go to Accounting → ETA E-Invoicing → Notifications and use Poll Notifications to query GET /api/v1.0/notifications/taxpayer. You can filter by date range, notification type (1–9), and language (Arabic or English).

EGS product code management

If your products use internal EGS codes, register them with ETA via Accounting → ETA E-Invoicing → EGS Codes → Register Code. ETA employee approval is required before the code can be used in submissions. Use Search Codes to browse published GS1 and EGS codes.

Troubleshooting / FAQ

IssueCause and fix
"ETA credentials missing"The company's ETA Client ID or Client Secret field is empty. Go to Settings → Companies → ETA E-Invoicing tab and fill both fields.
"Set ETA Registration Number before building"The company RIN/TIN field is empty. Set ETA Registration Number (RIN/TIN) on the company.
License not activeThe ECOSIRE license for ecosire_einvoice_eg is missing or expired. Go to Settings → ECOSIRE License and verify the key.
HTTP 400 BadStructureThe document payload does not match the ETA JSON schema. This occurs before you have completed the schema-exact assembly via the ETA integration toolkit. Verify the document JSON against the schema retrieved from the sandbox Get Document Type Version endpoint.
HTTP 400 MaximumSizeExceededThe submission payload is too large. Split into smaller batches.
HTTP 403 IncorrectSubmitterThe authenticated client_id does not match the issuer TIN. Confirm the credentials belong to the same taxpayer system registration as the RIN on the company.
HTTP 422 DuplicateSubmissionAn identical document was submitted within the last 10 minutes. Wait and check whether the original was accepted.
HTTP 429 / submission in Pending RetryRate limit exceeded. The automatic retry cron handles this. ETA recommends following the Retry-After header.
HTTP 503 / submission in Pending RetryETA system overload. Retry after 1–3 seconds; the cron handles this automatically.
"X.509 eSeal signing algorithm — sandbox required"The document signing step is gated. Complete the ETA preprod sandbox onboarding using the ETA integration toolkit (Docker/NuGet/CLI).
"eReceipt endpoint path is not verified"The eReceipt submission path was unavailable in the SDK portal at contract-verification time. Complete preprod sandbox access to obtain the verified path before using eReceipt submission.
State stays at SubmittedETA processing is asynchronous. Click Poll Status a few minutes after submission. Use the ETA invoicing portal (invoicing.eta.gov.eg) to confirm document status independently.
Rejection after time windowYou can no longer cancel. Issue a credit note in Odoo and submit it as a Credit Note document type.
Preprod SSL errorsYou have not installed the ETA preprod Root CA certificate. Follow the instructions at sdk.invoicing.eta.gov.eg/faq/ — admin rights are required on Windows. Do not install the preprod cert on production machines.

Why does the document say production_ready: false?

The document builder produces a skeleton whose top-level shape is grounded in the ETA contract (issuer, receiver, type, lines, totals). The schema-exact field names and eSeal signature are added by the ETA integration toolkit during the preprod phase. The _ecosire_meta.production_ready: false flag in the built JSON is a safety marker that tells you the skeleton is ready for review but must pass through the toolkit signing step before live production submission.

Can I use this module without the GCC E-Invoicing Core?

No. ecosire_einvoice_core is a required dependency and must be installed first.

Does this module support eReceipt (B2C POS)?

The eReceipt submission endpoint paths were unavailable in the ETA SDK portal at the time the API contract was verified (June 2026 — detail pages returned 404). The POS submission path is stubbed with a clear error message. Once the paths are confirmed via preprod sandbox access, they will be implemented. eInvoicing (B2B documents) is fully wired.

What is the ETA document version?

v1.0 is the production version (signature validation active). v0.9 has signature validation disabled and is a transition/testing version only. Always use v1.0 for production submissions.

Support