SDK Python : bientôt disponible officiellement. Cette documentation présente l'API telle qu'elle sera disponible ; la publication officielle est en cours de finalisation.
Simulateur DGI: la plateforme nationale d'e-facturation de la DGI n'est pas encore ouverte aux intégrations. La clairance (statuts ACCEPTED / REJECTED, référence, QR code) est aujourd'hui assurée par notre simulateur, qui reproduit le flux officiel. Le basculement vers la plateforme officielle se fera sans changement côté client. En savoir plus
SDK officiel EFact pour Python ≥ 3.9, typé avec Pydantic v2. Toutes les opérations sur les factures sont exposées via efact.invoices.*.
En bref
Le SDK Python officiel d'EFact (efact) permet de créer et suivre des factures électroniques conformes DGI depuis Python. Installez-le avec pip install efact, initialisez le client avec votre clé secrète efact_sk_ chargée depuis l'environnement, puis créez vos factures : le SDK gère la génération UBL 2.1, la signature XAdES et la transmission côté serveur.
Installation
pip install efactInitialisation
Basique
import os
from efact import EFact
# La clé secrète identifie ET authentifie votre organisation.
# Ne la committez jamais : chargez-la depuis l'environnement.
efact = EFact(os.environ["EFACT_SECRET_KEY"])efact.invoices.create(data)
Signature
efact.invoices.create(data: CreateInvoiceRequest | dict) -> InvoiceResponseExemple complet
invoice = efact.invoices.create({
"invoiceNumber": "INV-2026-001",
"invoiceDate": "2026-06-24",
"currency": "MAD",
"paymentMethod": "BANK_TRANSFER",
"buyerIce": "001234567890123",
"buyerName": "Client SARL",
"buyerAddress": "Casablanca",
"lines": [
{
"lineNumber": 1,
"description": "Prestation de service",
"quantity": 1,
"unitPrice": 1000,
"vatRate": 20,
},
],
})
print(invoice.id, invoice.status)efact.invoices.retrieve(invoice_id)
invoice = efact.invoices.retrieve("550e8400-e29b-41d4-a716-446655440000")
print(invoice.status, invoice.invoice_number)Lève EFactNotFoundError (HTTP 404) si la facture n’existe pas ou n’appartient pas au tenant.
efact.invoices.retrieve_status(invoice_id)
status = efact.invoices.retrieve_status("550e8400-e29b-41d4-a716-446655440000")
print(status.status, status.dgi_reference)efact.invoices.list(...)
page = efact.invoices.list(page=0, size=20, status="ACCEPTED")
for inv in page.content:
print(inv.invoice_number, inv.status)Pagination par page/size, pas par curseur.
efact.invoices.update(invoice_id, data)
# Uniquement pour une facture au statut PENDING - sinon 409
updated = efact.invoices.update("550e8400-e29b-41d4-a716-446655440000", {
"dueDate": "2026-07-31",
"buyerAddress": "Nouvelle adresse, Casablanca",
})efact.invoices.cancel(invoice_id)
# Uniquement pour une facture au statut PENDING
cancelled = efact.invoices.cancel("550e8400-e29b-41d4-a716-446655440000")
print(cancelled.status) # 'CANCELLED'Gestion des erreurs
Le SDK lève des erreurs typées, toutes héritées de EFactError. Toujours envelopper les appels dans un try/except :
from efact import (
EFactApiError,
EFactAuthError,
EFactValidationError,
EFactNotFoundError,
EFactConflictError,
EFactConnectionError,
EFactTimeoutError,
)
try:
efact.invoices.create(data)
except EFactValidationError as e:
print("Champs invalides :", e.errors)
except EFactAuthError:
print("Clé API manquante ou invalide.")
except EFactConflictError:
print("Facture non modifiable (statut ≠ PENDING).")
except EFactApiError as e:
print(e.code, e.http_status, e)
except EFactTimeoutError:
print("Délai dépassé.")
except EFactConnectionError:
print("Échec réseau.")Hiérarchie des erreurs
| Classe | Code HTTP | Quand |
|---|---|---|
EFactConfigError | - | Mauvaise configuration (avant tout appel réseau) |
EFactAuthError | 401 / 403 | Clé API manquante ou invalide |
EFactNotFoundError | 404 | Ressource introuvable (y compris hors tenant) |
EFactValidationError | 400 / 422 | Payload invalide |
EFactConflictError | 409 | Ex. modification/annulation d’une facture non PENDING |
EFactApiError | 5xx | Erreur côté EFact |
EFactTimeoutError | - | Délai dépassé avant réponse |
EFactConnectionError | - | Échec réseau |
Les requêtes GET, PUT et DELETE sont rejouées automatiquement (back-off exponentiel) sur timeout, erreur réseau, ou statuts HTTP 408/425/429/500/502/503/504, jusqu’à max_retries fois. POST (création) n’est jamais rejoué.
Intégration Django
# views.py
import os
from django.http import JsonResponse
from django.views.decorators.http import require_POST
from efact import EFact
efact = EFact(os.environ["EFACT_SECRET_KEY"])
@require_POST
def create_invoice(request):
import json
body = json.loads(request.body)
invoice = efact.invoices.create({
"invoiceNumber": body["invoiceNumber"],
"invoiceDate": body["invoiceDate"],
"currency": "MAD",
"paymentMethod": "BANK_TRANSFER",
"buyerIce": body.get("buyerIce"),
"buyerName": body.get("buyerName"),
"buyerAddress": body.get("buyerAddress"),
"lines": body["lines"],
})
return JsonResponse({"id": invoice.id, "status": invoice.status})Statuts de facture
Le statut reflète le cycle de vie complet, aligné avec le backend :
| Statut | Signification |
|---|---|
PENDING | Créée, modifiable, pas encore transmise |
SIGNED | Signée (XAdES), en attente de transmission |
TRANSMITTED | Envoyée à la plateforme DGI, en attente de clairance |
ACCEPTED | Validée par la DGI - référence et QR code disponibles |
REJECTED | Rejetée par la DGI - voir errorCode / errorMessage |
FAILED | Échec technique de traitement |
CANCELLED | Annulée (uniquement possible depuis PENDING) |
Questions fréquentes
Comment installer le SDK Python d'EFact ?
Installez le paquet officiel depuis PyPI avec pip install efact, puis importez le client (from efact import EFact). Initialisez-le avec votre clé secrète chargée depuis l'environnement, puis créez et suivez vos factures via ses méthodes. Le SDK gère la génération UBL 2.1, la signature et la transmission côté serveur EFact.
Le SDK Python EFact est-il compatible avec les frameworks web ?
Oui. Le SDK Python s'utilise dans n'importe quelle application, y compris les frameworks web comme Django ou FastAPI : instanciez le client au démarrage, chargez la clé API depuis une variable d'environnement, et appelez ses méthodes depuis vos vues ou tâches de fond pour créer et suivre les factures.
Comment suivre le statut d'une facture avec le SDK Python ?
Après la création, interrogez le statut de la facture via la méthode dédiée du client, avec un intervalle de polling de 2 à 5 secondes. Une fois le statut ACCEPTED, vous récupérez la référence DGI et les artefacts. En production, les webhooks remplaceront le polling pour être notifié du statut final.