Guide d'intégration

eFacture Connect : du JSON à la facture signée et déposée chez TTN

Voir Swagger →

1. Choisir le bon mode de signature

Deux modes disponibles selon votre cas d'usage. Vous pouvez basculer de l'un à l'autre par requête via le champ method.

🔵 DigiGo : PIN + OTP

Endpoint : POST /einvoices/prepare

  • Asynchrone (signature manuelle utilisateur)
  • Redirection vers page sécurisée (PIN + OTP SMS)
  • Récupération via polling ou webhook
  • Idéal pour signature personnelle / petits volumes
  • Pas de cachet à provisionner : certificat utilisateur

2. Authentification

Toutes les requêtes nécessitent un header X-Api-Key.

X-Api-Key: sk_test_xxxxxxxxxxxxxxxxxxxxxxxx

Deux types de clés :

  • sk_test_xxx en mode test : signature mockée, ttn_reference au format TTN-TEST-XXXXX, aucun crédit consommé. Idéal pour intégration.
  • sk_live_xxx en production : signature réelle, dépôt TTN réel, 1 crédit déduit par signature.

3. Flux SEAL : synchrone, automatique

3.1 Diagramme de séquence

sequenceDiagram autonumber participant ERP as Votre ERP participant API as eFacture Connect participant SIG as Service signature participant TTN as TunisieTradeNet ERP->>API: POST /einvoices/process (JSON) API->>API: Validation payload API->>SIG: Génération TEIF + signature SEAL SIG-->>API: XML signé API->>TTN: Dépôt facture signée TTN-->>API: ttn_reference API-->>ERP: 200 OK { xml_base64, pdf_base64, ttn_reference }

3.2 Requête

POST https://efacturetn.com/api/v1/einvoices/process
X-Api-Key: sk_test_xxxxxxxxxxxx
Content-Type: application/json

{
  "invoice_number": "F-2026-001",
  "date": "2026-06-13",
  "seller": {
    "name": "Mon Entreprise SARL",
    "tax_id": "1234567MAM000",
    "address": "Tunis"
  },
  "buyer": {
    "name": "Client SARL",
    "tax_id": "7654321XAM000"
  },
  "items": [
    { "description": "Service de conseil", "quantity": 1, "unit_price": 500, "vat_rate": 19 }
  ]
}

3.3 Réponse (succès)

{
  "success": true,
  "data": {
    "status": "signed",
    "invoice_number": "F-2026-001",
    "ttn_reference": "TTN-2026-XXXXX",
    "xml_base64": "PD94bWwgdmVyc2lvbj0iMS4wIi...",
    "pdf_base64": "JVBERi0xLjQKJaqrrK0K...",
    "test_mode": true,
    "credits_remaining": null
  },
  "error": null
}

3.4 Exemple cURL

curl -X POST https://efacturetn.com/api/v1/einvoices/process \
  -H "X-Api-Key: sk_test_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d @facture.json

4. Flux DigiGo : asynchrone, signature utilisateur

4.1 Diagramme : version polling

sequenceDiagram autonumber participant ERP as Votre ERP participant USER as Client final participant API as eFacture Connect participant SIG as Page signature participant TTN as TunisieTradeNet ERP->>API: POST /einvoices/prepare (method=digigo, return_url) API-->>ERP: 200 { signing_id, signing_url } ERP-->>USER: Redirection vers signing_url USER->>SIG: Saisie PIN + OTP SMS SIG->>API: Signature OK API->>TTN: Dépôt facture signée SIG-->>USER: Redirection vers return_url loop Polling toutes les 5-30s ERP->>API: GET /einvoices/{signing_id} API-->>ERP: { status: "pending_signature" | "signed" | "validated" } end API-->>ERP: { status: "validated", xml_base64, pdf_base64, ttn_reference }

4.2 Diagramme : version webhook (recommandé)

sequenceDiagram autonumber participant ERP as Votre ERP participant USER as Client final participant API as eFacture Connect participant SIG as Page signature participant TTN as TunisieTradeNet ERP->>API: POST /einvoices/prepare (method=digigo, return_url) API-->>ERP: 200 { signing_id, signing_url } ERP-->>USER: Redirection vers signing_url USER->>SIG: Saisie PIN + OTP SMS SIG->>API: Signature OK API->>TTN: Dépôt facture signée SIG-->>USER: Redirection vers return_url API->>ERP: POST webhook { signing_id, status: validated, ttn_reference } Note over ERP,API: Header X-Efacture-Signature (HMAC-SHA256) ERP-->>API: 200 OK

4.3 Étape 1 : Préparer la signature

POST https://efacturetn.com/api/v1/einvoices/prepare
X-Api-Key: sk_test_xxxxxxxxxxxx
Content-Type: application/json

{
  "invoice_number": "F-2026-001",
  "date": "2026-06-13",
  "seller": { ... },
  "buyer": { ... },
  "items": [ ... ],
  "method": "digigo",
  "return_url": "https://votre-erp.tn/factures/F-2026-001/retour-signature"
}

Réponse :

{
  "success": true,
  "data": {
    "status": "pending_signature",
    "signing_id": "sg_a7f9c21b3e4d8f6a9b2c1d4e",
    "signing_url": "https://signature-securisee.tn/sign/xa7f9c21",
    "method": "digigo",
    "invoice_number": "F-2026-001"
  },
  "error": null
}

4.4 Étape 2 : Rediriger le client

HTTP/1.1 302 Found
Location: https://signature-securisee.tn/sign/xa7f9c21

4.5 Étape 3a : Polling (option simple)

Backoff exponentiel recommandé : 5s, 10s, 20s, 30s, 60s... Timeout total : 30 minutes.

GET https://efacturetn.com/api/v1/einvoices/sg_a7f9c21b3e4d8f6a9b2c1d4e
X-Api-Key: sk_test_xxxxxxxxxxxx

Quand status: "validated", la réponse contient xml_base64 + pdf_base64 + ttn_reference.

4.6 Étape 3b : Webhook (option recommandée)

Configurez votre URL HTTPS avec notre support. Vous recevrez un POST quand la signature passe à validated ou rejected.

Voir section 5. Webhook pour les détails de vérification HMAC.

5. Webhook : détails techniques

5.1 Payload reçu

POST https://votre-erp.tn/webhooks/efacture
X-Efacture-Signature: sha256=a3f1b2...
Content-Type: application/json

{
  "event": "einvoice.validated",
  "signing_id": "sg_a7f9c21b3e4d8f6a9b2c1d4e",
  "invoice_number": "F-2026-001",
  "status": "validated",
  "ttn_reference": "TTN-2026-XXXXX",
  "timestamp": "2026-06-13T14:30:00Z"
}

5.2 Vérification de la signature HMAC (PHP)

$rawBody = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_EFACTURE_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $webhookSecret);

if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    exit('Invalid signature');
}

$payload = json_decode($rawBody, true);
// Traiter selon $payload['event'] et $payload['status']
http_response_code(200);

5.3 Politique de retry

  • 3 tentatives : immédiat, +1 min, +5 min
  • Succès si vous renvoyez 2xx
  • Échec persistant : pas de re-essai automatique : vous pouvez récupérer via GET /einvoices/{signing_id}
Idempotence : le même signing_id peut être notifié plusieurs fois (retry, transitions de statut). Vérifiez dans votre base si déjà traité avant de re-traiter.

6. Codes d'erreur

CodeHTTPDescriptionAction recommandée
AUTH_INVALID_KEY401Clé API invalide ou inactiveVérifier la clé
RATE_LIMIT429Trop de requêtesBackoff exponentiel, lire X-RateLimit-*
INVALID_JSON400Corps non JSONCorriger le payload
VALIDATION_FAILED422Champs requis manquantsLire error.details
INSUFFICIENT_CREDITS402Solde épuiséAcheter des crédits
SEAL_NOT_CONFIGURED412Cachet non provisionnéContacter le support
SIGNING_FAILED503Service signature downRéessayer dans 1-2 min

6.1 Format de réponse d'erreur

{
  "success": false,
  "data": null,
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "Invoice validation failed.",
    "details": [
      "Field \"buyer.tax_id\" is required.",
      "Item 0: vat_rate must be one of 0, 7, 13, 19."
    ]
  }
}

7. Passer de Test à Production

CritèreTest (sk_test_)Production (sk_live_)
SignatureMockée (TEIF placeholder)XAdES réelle
Dépôt TTNAucun (référence fictive)Dépôt réel
ttn_referenceTTN-TEST-XXXXXTTN-2026-XXXXX
Crédits consommésAucun1 par signature
Cachet/Certificat requisNonOui (SEAL ou DigiGo)
Pour passer en production : provisionnez votre cachet (SEAL) ou votre certificat DigiGo via le support. Aucun code à changer côté ERP : il suffit de remplacer la clé sk_test_ par sk_live_.