DGI Clearance Architecture & Pipeline
One API call in, a normalized, signed, and cleared invoice out. Here is everything that happens in between.
In short
EFact orchestrates an end-to-end pipeline: data normalization into XML UBL 2.1, XAdES electronic signature with your qualified certificate, and transmission to the DGI for clearance and fiscal validation (visa fiscal). Each step maps directly to an invoice status. Once signed, the invoice is locked, recorded in an immutable audit trail, and stored under 10-year legal archiving.
DGI Integration Status
The national DGI e-invoicing platform is not yet open to external integrations. The "DGI" step described on this page is currently handled by our DGI simulator, which replicates the official clearance workflow end-to-end (submission, signature validation, fiscal reference, QR code, callbacks). The ACCEPTED / REJECTED statuses reflect the simulator's decision, not yet that of the tax authority. The transition to the official platform will take place without any client-side changes.
Overview
SDKs, ERPs, and the dashboard all enter through the same edge. Authentication resolves the organization before the pipeline ever touches the invoice.
- Client
- Edge
- Authentication
- Pipeline
- DGI
- Clients
- Official SDKs (Node.js, Python), ERPs and SaaS via direct REST, and the dashboard for humans.
- Edge
- TLS, security filter chains, rate limiting at 300 requests/minute per key.
- Authentication
- Hashed API keys for the invoicing API; JWTs validated against the identity provider (OIDC) for the dashboard.
- Pipeline
- Validates, normalizes, signs, and transmits - then writes to the system of record and the audit trail.
- DGI
- mTLS transmission; clearance callbacks return signed via HMAC. Today: the DGI simulator (see notice above).
- Persistence
- Relational database as system of record, UUID keys, versioned migrations.
Edge and Gateway
Every request passes through the same hardened edge.
- TLS
- HTTPS termination only.
- Separate filters
- Dashboard routes receive the JWT validator; the invoicing API authenticates its own keys. Anything not explicitly declared is rejected by default.
- Rate limiting
- 300 requests/minute per key (token-bucket), returning a structured
429and aRetry-Afterheader when exceeded. - Uniform envelope
- Every response, success or failure, follows
{ code, message, data, errors }. SDKs unpackdataand throw typed errors otherwise.
Authentication
Two planes, isolated by design. Full details on the Security page.
| Plane | Principal | Identifier | Validation |
|---|---|---|---|
| Invoicing API | Servers (SDK, ERP) | efact_sk_... | SHA-256 hash, organization resolved from key |
| Dashboard API | Humans | JWT (OIDC) | Signature, issuer, expiration; role from claims |
Invoicing Pipeline
POST /v1/invoices executes a synchronous, transactional pipeline: the returned invoice is already signed and routed toward the DGI.
- Validate
- Normalize
- Sign
- Transmit
- Clear
- Validate
- Schema and business rules: ICE, currency, line items.
- Normalize
- Mapping to XML UBL 2.1, validation against official XSD, canonicalization, and SHA-256 hash.
- Sign
- XAdES signature using the organization's PKCS#12 certificate (RSA/SHA-256).
- Transmit
- mTLS submission (to the DGI simulator currently).
- Clear
- The clearance platform validates, then assigns a fiscal reference and QR code.
- All-or-nothing
- Validation, normalization, and signing share a single transaction. If any step fails, the entire operation rolls back: no half-processed invoice ever exists.
- Server-computed totals
- Pre-tax (HT), VAT (TVA), and total with tax (TTC) are calculated server-side from line items. The backend is the single source of truth, not the caller.
- Immutability
- Once an invoice moves beyond
PENDING, its content is locked. Any modification or cancellation attempt returns409.
Invoice Lifecycle
Integrators poll GET /v1/invoices/{id}/status: a lightweight object containing status, DGI reference, QR payload, and any structured error details.
PENDINGCreated, awaiting processing.
SIGNEDNormalized to UBL 2.1 and digitally signed.
TRANSMITTEDSubmitted to the DGI, awaiting clearance.
ACCEPTEDCleared - DGI reference and QR code assigned.
REJECTEDRejected by the DGI (structured error code and message).
FAILEDUnrecoverable processing or submission error.
CANCELLEDCancelled by caller before signature.
The nominal flow is PENDING → SIGNED → TRANSMITTED → ACCEPTED or REJECTED. An invoice can be cancelled while in PENDING, and an unrecoverable submission error moves it to FAILED.
Resilience and Self-Healing
The platform assumes the government platform can be slow, unavailable, or drop messages, and guarantees that no invoice is ever silently lost.
- Catch-up worker
- Resubmits
SIGNEDinvoices older than 2 minutes: covers crashes between commit and submission, as well as transient DGI errors. - Fallback polling
- Repolls the DGI for invoices stuck in
TRANSMITTEDfor more than 5 minutes: covers lost callbacks. - Idempotent callbacks
- Every DGI event is deduplicated by identifier: retries and replays can never apply a state transition twice.
- SDK client-side
- Official SDKs retry safe calls with exponential backoff and jitter, honor
Retry-After, and never retrycreate.
Invoice Artifacts
Artifacts are preserved throughout the 10-year legal archiving period.
| Artifact | Endpoint | Content |
|---|---|---|
| Signed XML | GET /v1/invoices/{id}/xml | The XAdES-signed UBL 2.1 document, the legal original |
GET /v1/invoices/{id}/pdf | Human-readable rendered invoice | |
| QR code | GET /v1/invoices/{id}/qr | The DGI clearance QR code |
Audit Trail
Every status transition - triggered by the API, a DGI callback, a scheduler, or an administrator - writes an immutable row: previous status, new status, actor, reason code, reason, and metadata. The log is append-only and queryable via the API (permission AUDIT_READ).
Monitoring and Operations
- Health checks
- Health probes with dedicated indicators: can we reach the clearance platform, and are invoices getting stuck?
- Metrics
- Request metrics and business counters (submissions, callback results, polling fallbacks) collected continuously.
- Redacted logs
- Signatures, QR payloads, passwords, and private keys are pattern-redacted at the logging layer before any write occurs.
Data Layer
- Relational database
- Transactional system of record.
- UUID keys
- Everywhere: no enumerable identifiers.
- Migrations
- Versioned and immutable. Schema history is itself an audit trail: migrations are never edited, only appended.
- Sensitive columns
- Encrypted with AES-256-GCM. See Security.
Environments
The built-in DGI simulator replicates the clearance workflow end-to-end - submission, signature verification, HMAC-signed callbacks, accept/reject scenarios - to test the entire lifecycle before the national platform goes live.
| Environment | Target | DGI Backend |
|---|---|---|
| Production | https://api.efact.ma | DGI production (mTLS) - sandboxed simulator until official integration opens |
| Local / Integrator | Override SDK baseUrl | DGI simulator (full lifecycle, including signature and callbacks) |
API Contract
The API is defined by a versioned OpenAPI contract; official SDKs are generated from this live contract and remain continuously aligned with the API. The platform is built on open standards: UBL 2.1, XAdES, OAuth2/OIDC.
Frequently asked questions
How does EFact transform an invoice into a DGI-compliant document?
EFact orchestrates a pipeline: normalizing data into UBL 2.1 XML, applying an XAdES electronic signature with your qualified certificate, and transmitting it to the DGI for clearance and tax validation (visa fiscal). Each step maps to an invoice status, and the signed document and its artifacts are archived.
What is the EFact DGI simulator?
Because the national DGI platform is not yet open to integrations in July 2026, EFact uses a simulator that replicates the official clearance flow: submission, signature validation, reference assignment, QR code generation, and callbacks. Switching to the official platform requires no client-side changes.
How does EFact guarantee invoice integrity?
Once signed or transmitted, an invoice is locked and its content cannot be altered. Every status transition is written to an append-only audit log, and documents are archived in immutable storage for 10 years, ensuring a reliable audit trail compliant with Moroccan tax requirements.