Skip to main content

E-Invoicing | Jordan JoFotara (ISTD)

The ECOSIRE Jordan JoFotara module connects Odoo to Jordan's JoFotara (Arabic: فوترتي, "My Invoice") national e-invoicing system, operated by the Income and Sales Tax Department (ISTD) under the Ministry of Finance. JoFotara is a direct-API, real-time Continuous Transaction Control (CTC) platform: your Odoo instance submits a Jordan-profile UBL 2.1 XML invoice directly to ISTD, which validates, clears, and returns a UUID and QR code synchronously. The QR is printed on the issued invoice PDF and constitutes the legal proof of clearance.

JoFotara is already mandatory for GST-registered taxpayers in Jordan — phased in since 2021 for large taxpayers, 2022 for medium, and ongoing rollout to all registered businesses. This is not a future mandate; Jordan Odoo users are currently out of compliance without it.

Compatibility: Odoo 17 / 18 / 19 (Community or Enterprise) Price: $299 (one-time) + $499 for the GCC E-Invoicing Core Engine License: Up to 3 domain activations Category: Accounting / Localizations / EDI

Sandbox-verify before production

Jordan JoFotara is the newest and least-documented GCC e-invoicing regime. Validate the full document structure, authentication field names, response shape, and QR format against the ISTD sandbox (sandbox.jofotara.gov.jo) before any production go-live. The live-transmission path in this module is explicitly gated: production submission is refused unless the company environment mode is set to Production and credentials are configured.

Overview

How it works

Odoo invoice (account.move)

│ Jordan-profile UBL 2.1 XML (built by this module)

ISTD JoFotara API ──── real-time clearance ────► UUID + QR code returned

(ISTD retains the invoice; UUID + QR stored on Odoo record; QR printed on PDF)

This architecture is distinct from:

  • UAE / Peppol — no mandatory third-party ASP relay
  • KSA ZATCA — no dual-phase HSM signing device, no cryptographic stamp before submission

What the module does

  • OAuth2 client_credentials authentication — uses a client_id and secret_key issued by the JoFotara portal after Jordan TIN registration; stored on res.company with admin-only visibility, never printed or logged.
  • Jordan-profile UBL 2.1 document builder — 16% GST (Jordan calls it General Sales Tax, not VAT), JOD (Jordanian Dinar) at 3-decimal precision, B2B standard invoices with buyer TIN, B2C simplified invoices without buyer TIN, and credit notes with a billing reference to the original cleared UUID.
  • Real-time clearance submissionPOST /api/invoice; ISTD validates in real time and returns a UUID and QR code string on success.
  • Submission state machine — draft / submitted / cleared / rejected / pending_retry; every state transition is tracked.
  • Per-attempt audit log — each HTTP call to ISTD is recorded with HTTP status, message, and a response excerpt for traceability.
  • Exponential-backoff retry queue — a scheduled cron retries 5xx server errors automatically (up to 5 attempts, backoff: 2^n minutes); the stored ISTD UUID is the at-most-once idempotency guard so a cleared invoice is never re-submitted.
  • Status queryGET /api/invoice/{uuid} lets you poll ISTD for the latest clearance status of a submitted invoice.
  • Sandbox / production environment switch — base URLs are configurable on res.company; defaults point to the reported ISTD URLs. Production submissions are refused if the company environment is not explicitly set to Production.

Endpoints implemented

EndpointMethodPurpose
/api/get_tokenPOSTObtain a Bearer token using client_id + secret_key
/api/invoicePOSTSubmit an invoice or credit note for real-time clearance
/api/invoice/{uuid}GETQuery clearance status by ISTD-assigned UUID

Features intentionally not implemented (pending ISTD sandbox verification)

The following are stubbed and return a UserError with a clear explanation rather than fabricated behavior:

  • GET /api/taxpayer — endpoint path and response schema unverified
  • Seller-side XML digital signing (JoFotara Phase 2+) — signing algorithm and ISTD PKI CA are unknown; Phase 1 uses ISTD server-side clearance
  • Local QR code generation — the JoFotara QR string is supplied by ISTD in the clearance response; the Jordan-specific content format is unverified and is never self-generated

Prerequisites

  • Odoo 17, 18, or 19 (Community or Enterprise edition)
  • ecosire_einvoice_core — the ECOSIRE GCC E-Invoicing Core Engine must be installed first
  • An active ECOSIRE license for ecosire_einvoice_jo
  • Python packages: lxml, requests
  • A valid Jordan TIN (15-digit) registered with the ISTD
  • JoFotara portal credentials (client_id and secret_key) — obtained from jofotara.gov.jo after TIN registration
  • Sandbox credentials for pre-production testing — registered separately at sandbox.jofotara.gov.jo; sandbox registration also requires a Jordan TIN

Installation

  1. Install the GCC E-Invoicing Core Engine first — this country pack depends on it.
  2. Download the Jordan JoFotara module ZIP from your ECOSIRE Dashboard.
  3. Extract it to your Odoo addons directory alongside the core engine:
    unzip ecosire-einvoice-jo-*.zip -d /opt/odoo/addons/
  4. Install the required Python packages into the same environment that runs Odoo:
    pip install lxml requests
  5. Restart the Odoo service:
    sudo systemctl restart odoo
  6. In Odoo go to Apps, click Update Apps List.
  7. Search for ECOSIRE E-Invoicing | Jordan JoFotara and click Install.
  8. Activate your ECOSIRE license when prompted (see below).

After installation a JoFotara submenu appears under Accounting → JoFotara.

Configuration and Credentials

Step 1: Activate your ECOSIRE license

  1. Navigate to Settings → ECOSIRE License.
  2. Enter the license key you received from ECOSIRE.
  3. Click Activate. The module refuses to submit invoices until the license is active.

If activation returns an error, verify the key is for ecosire_einvoice_jo and that the domain matches your Odoo instance URL. Contact [email protected] if the problem persists.

Step 2: Obtain JoFotara API credentials

  1. Register or log in to the JoFotara portal at jofotara.gov.jo using your Jordan TIN.
  2. Navigate to the developer / API access section and apply for API credentials.
  3. ISTD issues a Client ID (client_id) and a Secret Key (secret_key).

For sandbox testing, register separately at sandbox.jofotara.gov.jo. Sandbox credentials are issued independently and do not affect live fiscal records.

Credential field names

The JoFotara API uses secret_key (not the OAuth2 standard client_secret). This is consistent with ISTD integrator references. Confirm the exact field names against the official ISTD API documentation when you access the developer portal, and adjust the configuration accordingly.

Step 3: Configure company settings

  1. Go to Settings → Companies (or Settings → General Settings → Companies) and open your company record.
  2. Navigate to the JoFotara / E-Invoicing tab.
  3. Enter your credentials:
    • JoFotara Client ID (jo_jofotara_client_id) — from the ISTD portal
    • JoFotara Secret Key (jo_jofotara_secret_key) — from the ISTD portal; stored with admin-only visibility, never displayed in logs
  4. Verify the base URLs (pre-filled with reported ISTD defaults):
    • Sandbox Base URLhttps://sandbox.jofotara.gov.jo (verify against ISTD developer docs before use)
    • Production Base URLhttps://backend.jofotara.gov.jo (verify against ISTD developer docs before use)
  5. Set Company E-Invoice Environment to Sandbox during testing. Switch to Production only after successful sandbox verification.

Step 4: Configure GST tax mapping

Jordan uses General Sales Tax (GST) at a standard rate of 16%, not VAT. Ensure your Odoo tax configuration reflects this:

  • Standard rate: 16% GST (tax category code S)
  • Zero-rated: 0% (exports and certain exempted goods, category Z)
  • Exempt: healthcare, education, and basic food items (category E)

Map these to the appropriate Odoo tax records via Accounting → Configuration → Taxes. The UBL builder reads the tax category from the invoice line tax records.

Step 5: Configure JOD currency precision

JOD (Jordanian Dinar) uses 3 decimal places (fils). Verify that the JOD currency in Odoo is set to 3 decimal places under Settings → Technical → Currencies. The UBL builder enforces 3dp on all monetary amounts.

Usage

Submitting an invoice for clearance

  1. Create and confirm a customer invoice in Accounting → Customers → Invoices.
  2. The module automatically detects Jordan invoices (based on company country) and creates a JoFotara submission record in Draft state.
  3. Open the invoice and click Submit to JoFotara (or navigate to Accounting → JoFotara → Submissions and open the submission record).
  4. Click Submit Now.
  5. The module:
    • Validates mandatory fields (seller TIN, invoice number, line items, GST amounts)
    • Builds the Jordan-profile UBL 2.1 XML
    • Authenticates with ISTD (POST /api/get_token)
    • Submits the XML (POST /api/invoice)
  6. On success, ISTD returns a UUID and QR code string. These are stored on the submission record and written back to the invoice. The state transitions to Cleared.
  7. The QR code is embedded in the invoice PDF. The invoice is legally valid only after clearance (UUID and QR issued by ISTD).

Submission states

StateMeaning
DraftCreated, not yet submitted to ISTD
SubmittedSent to ISTD, awaiting outcome
ClearedISTD cleared the invoice; UUID and QR code stored
RejectedISTD rejected the invoice (see the Attempts tab for error details)
Pending RetryTransient failure (5xx); will be retried automatically by the cron

Credit notes

Credit notes follow the same flow. The UBL builder automatically includes a BillingReference element pointing to the original invoice's ISTD UUID. The original invoice must be cleared (have a UUID) before you can clear a credit note referencing it.

Simplified invoices (B2C)

For B2C invoices, the module creates a Simplified submission (no buyer TIN required). The system determines the subtype from the partner type on the invoice. Individual / consumer partners trigger the simplified path.

Retry queue

If ISTD returns a 5xx server error, the submission moves to Pending Retry. A scheduled cron job checks pending submissions every few minutes and retries them with an exponential backoff (2, 4, 8, 16, 32 minutes). After 5 failed attempts the submission stays in Rejected for manual review. The stored UUID acts as the idempotency guard — a submission with an existing UUID is never re-submitted.

Manual status query

If a submission was sent but the response was unclear, open the submission record and click Query ISTD Status. The module calls GET /api/invoice/{uuid} and updates the state based on ISTD's response.

API Details

FieldValue
Auth methodOAuth2 client_credentials (Bearer token)
Auth endpointPOST /api/get_token at https://backend.jofotara.gov.jo (reported — verify)
Submit endpointPOST /api/invoice
Status endpointGET /api/invoice/{uuid}
Sandbox base URLhttps://sandbox.jofotara.gov.jo (reported — verify)
Production base URLhttps://backend.jofotara.gov.jo (reported — verify)
Document formatUBL 2.1 XML, Jordan ISTD profile
Key config fieldsjo_jofotara_client_id, jo_jofotara_secret_key, jo_jofotara_sandbox_base_url, jo_jofotara_prod_base_url
Reported URLs

The ISTD API base URLs above are widely cited in Jordan integrator references but could not be verified from primary sources at time of publication (jofotara.gov.jo requires in-country network access). Confirm the exact base URLs and endpoint paths against the official ISTD developer documentation before production go-live. Both the sandbox and production base URLs are configurable on the company record so you can correct them without a code change.

Troubleshooting

IssueSolution
License not activeGo to Settings → ECOSIRE License and verify the license key is entered and activated for ecosire_einvoice_jo
"Refusing production submission" errorGo to the company settings and confirm the Company E-Invoice Environment is set to Production; only change this after successful sandbox testing
Authentication failed (401)Verify client_id and secret_key on the company record; confirm field names against ISTD developer documentation
Connection error / ECONNREFUSEDThe ISTD API may be temporarily unavailable; check the base URLs on the company record against ISTD developer documentation
Submission rejected (400)Open the submission's Attempts tab; the error message from ISTD (field-level validation failures) appears in the response excerpt; correct the invoice data and retry
Submission rejected (422)Likely a business rule violation — duplicate invoice number or a credit note referencing an uncleared original; verify invoice number uniqueness and original UUID
QR code not printing on PDFThe QR string is stored on the submission record's ISTD QR Code field only after clearance; the PDF template reads it from the linked submission; verify the invoice is in Cleared state
Credit note missing billing referenceThe original invoice must be cleared (have an ISTD UUID) before the credit note can reference it; clear the original first
"No ISTD UUID" on status queryThe invoice has not been submitted yet; use Submit Now first
Cron not retrying pending submissionsCheck Settings → Technical → Scheduled Actions and confirm the JoFotara Retry Pending Submissions cron is enabled and its interval is set
Base URL needs updatingISTD may have changed the API endpoint; update the Sandbox Base URL or Production Base URL on the company record to match the current ISTD developer documentation

FAQ

Does this module require the GCC E-Invoicing Core Engine? Yes. ecosire_einvoice_jo is a country pack that depends on ecosire_einvoice_core. Install the core engine first.

Can I test without a real Jordan TIN? No. ISTD sandbox registration requires a valid Jordan TIN. You must have a Jordan TIN to obtain sandbox credentials.

Is seller-side XML digital signing required? For Phase 1 of JoFotara, ISTD performs server-side signing during the clearance response (returning the UUID and QR). Seller-side digital signing has been reported as a possible Phase 2+ requirement, but the algorithm and ISTD PKI specification are not confirmed. The module does not implement seller-side signing for Phase 1; if ISTD introduces this requirement, it will be added in a future version.

What happens if ISTD returns 5xx errors during peak periods? The submission moves to Pending Retry and the exponential-backoff cron retries it automatically. You can also click Retry Now on the submission record to force an immediate retry.

Can I submit invoices in foreign currencies? Jordan GST must be computed and reported in JOD even for foreign-currency invoices, using the exchange rate on the invoice date. Set the correct exchange rate in Odoo before confirming the invoice. The exact foreign-currency exchange rate field name in the JoFotara UBL profile requires confirmation from the ISTD XSD specification.

Is Point of Sale (POS) supported? POS e-invoicing is not included in this release. The module covers account.move invoices, credit notes, and debit notes.

How long must e-invoices be archived? Jordan GST law requires a 5-year archiving period (reported — verify the specific e-invoice archiving format and retrieval obligation from ISTD official circulars). Odoo stores all submission records and UBL XML on the jofotara.submission model indefinitely unless explicitly purged.

Support