API eFacture Connect
Intégrez la facture électronique tunisienne dans votre ERP en quelques minutes. Envoyez du JSON, recevez un XML TEIF v1.8.8 signé (XAdES) et un PDF avec QR code, prêts à être déposés chez TunisieTradeNet.
https://efacturetn.com/api/v1Premier appel en 30 secondes
Copiez la commande à droite dans votre terminal pour tester l'API en mode sandbox. Remplacez sk_test_xxx par votre clé reçue par email après inscription.
Vous recevrez en retour un XML réellement signé (environnement sandbox) et un PDF, exactement comme en production. Aucun crédit n'est consommé en mode test.
Authentification
L'API utilise des clés API passées dans le header X-Api-Key. Chaque requête doit inclure une clé valide.
| Préfixe | Mode | Usage |
|---|---|---|
sk_test_ |
Test | Signature réelle sur l'environnement sandbox, dépôt TTN de test, aucun crédit consommé. Pour l'intégration. |
sk_live_ |
Production | Signature XAdES réelle, dépôt TTN effectif, 1 crédit déduit par signature. |
Comptes et clients
Un compte développeur peut gérer plusieurs clients (une intégration par entreprise finale). Vous créez et configurez vos clients depuis votre espace développeur, section « Mes clients ».
| Notion | Description |
|---|---|
| Clés par client | Chaque client possède sa propre paire de clés ck_test_ / ck_live_ (clé de client), distinctes de votre clé de développeur sk_test_ / sk_live_ qui sert à la gestion. Une requête d'émission est toujours rattachée au client dont vous utilisez la clé. La clé développeur ne peut pas émettre de factures : /einvoices/prepare et /einvoices/process répondent 403 DEVELOPER_KEY_NOT_ALLOWED, utilisez la clé du client concerné. |
| Portefeuille partagé | Les crédits sont achetés au niveau du compte développeur et partagés entre tous vos clients. |
| Plafond par client | Vous pouvez fixer un plafond de crédits par client. Le client se bloque à son plafond sans affecter les autres ni le reste du portefeuille. Vous suivez la consommation par client. |
| Canal de dépôt | Chaque client dépose à TTN par SOAP (synchrone) ou SFTP (asynchrone), selon la configuration de son compte TTN. En SFTP, la facture passe par le statut submitted_ttn puis la validation arrive par webhook ou par polling. |
| Méthode de signature | Configurée par client : cachet serveur (automatique), clé USB (signature locale) ou signature à distance. Sans incidence sur le format des requêtes. |
Test vs Production
Passer en production ne nécessite aucun changement de code : remplacez simplement sk_test_xxx par sk_live_xxx.
signing_url de /einvoices/prepare pointe vers la vraie page de signature (sandbox), où le signataire signe avec un certificat de test. Le compte de signature sandbox du client doit donc être configuré.| Critère | Test | Production |
|---|---|---|
| Signature | XAdES réelle (environnement sandbox) | XAdES réelle (production) |
| Dépôt TTN | Plateforme TTN de test | Plateforme TTN de production |
| Crédits consommés | Aucun | 1 par signature |
| Cachet/Certificat | Requis (sandbox) | Requis (production) |
SEAL vs DigiGo
Deux modes de signature selon votre cas d'usage. Vous pouvez basculer à la volée via le champ method dans la requête.
| SEAL | DigiGo | |
|---|---|---|
| Synchrone ? | Oui (~5s) | Non (signature manuelle) |
| Interaction | Aucune | PIN + OTP utilisateur |
| Endpoint | POST /einvoices/process | POST /einvoices/prepare |
| Cas d'usage | ERP back-office, volumes élevés | Signature personnelle, petits volumes |
| Récup résultat | Direct dans la réponse | Polling /einvoices/{id} ou webhook |
Gestion des erreurs
L'API utilise les codes HTTP standards et retourne un payload JSON normalisé. Toutes les erreurs ont la même forme :
| Code | HTTP | Description |
|---|---|---|
AUTH_INVALID_KEY | 401 | Clé API invalide, inactive ou non autorisée |
VALIDATION_FAILED | 422 | Champs requis manquants : voir error.details |
INVALID_JSON | 400 | Corps de requête non JSON valide |
INSUFFICIENT_CREDITS | 402 | Portefeuille épuisé ou plafond du client atteint (live uniquement) |
SEAL_NOT_CONFIGURED | 412 | Cachet électronique SEAL non provisionné pour ce client sur l'environnement de la clé (sandbox ou production) |
SIGNER_NOT_CONFIGURED | 412 | Service de signature DigiGo/USB non configuré pour ce client |
SIGNER_EMAIL_MISSING | 412 | Signature à distance sans signer_email renseigné sur le client. Renseignez-le (API ou portail) : c'est lui qui reçoit la demande de signature |
DEVELOPER_KEY_NOT_ALLOWED | 403 | Clé développeur (sk_) utilisée sur /einvoices/prepare ou /process : l'émission passe obligatoirement par la clé du client concerné (ck_) |
PERMISSION_DENIED | 403 | Le signing_id consulté appartient à un autre compte. Seuls le client propriétaire et son développeur parent peuvent le consulter |
TTN_DEPOSIT_FAILED | - | Présent dans ttn.error de l'objet einvoice : la facture est signée mais le dépôt TTN a échoué (ex. identifiants TTN invalides). Corrigez la configuration TTN du client puis ré-émettez la facture |
SIGNER_UNAVAILABLE | 400 | Méthode de signature inconnue (method doit être seal, digigo ou usb) |
SIGNER_CIRCUIT_OPEN | 503 | Service de signature en panne répétée : circuit breaker activé. Réessayer dans 30-60 sec |
RATE_LIMIT | 429 | Limite de requêtes par minute dépassée |
SIGNING_FAILED | 503 | Échec technique du service de signature (timeout, 5xx provider, etc.) |
USER_CANCELLED | - | (DigiGo) Le client final a annulé la signature. Présent dans error de l'objet einvoice au statut rejected |
Debug en mode test (sk_test_ / ck_test_)
En mode test uniquement, les erreurs SIGNING_FAILED retournent un champ error.details.debug
contenant le message technique sous-jacent, et GET /einvoices/{id} inclut un bloc debug
(état de la signature, erreur de vérification éventuelle) tant que la facture est en cours.
Ces champs ne sont jamais présents en mode production (clés live), pour éviter toute fuite d'information.
{
"success": false,
"data": null,
"error": {
"code": "SIGNING_FAILED",
"message": "La signature électronique a échoué. Veuillez réessayer.",
"details": {
"debug": "HTTP 401 Unauthorized"
}
}
}
Tableau de résolution des erreurs SIGNING_FAILED
Si vous rencontrez un SIGNING_FAILED, consultez ci-dessous le contenu de error.details.debug pour identifier la cause :
Message dans debug | Cause probable | Action recommandée |
|---|---|---|
HTTP 401ou Unauthorized |
Le jeton de signature configuré pour votre compte est invalide ou expiré. | Contactez le support pour faire renouveler votre jeton de signature. |
HTTP 402ou Payment Required |
Compte de signature sans crédit ou plan expiré. | Contactez le support pour réactiver le service. |
HTTP 403ou Forbidden |
L'organisation associée à votre compte n'est pas autorisée pour cet endpoint. | Vérifier la method envoyée. Contacter le support si problème persistant. |
HTTP 500 ou HTTP 502Bad Gateway |
Le service de signature est temporairement indisponible ou en surcharge. | Réessayer dans 1 à 2 minutes. Implémentez un retry avec backoff exponentiel côté client. |
HTTP 504Gateway Timeout |
Le service de signature met trop de temps à répondre. | Réessayer immédiatement. Si récurrent, contacter le support. |
Connection timed outou Could not resolve host |
Problème réseau côté serveur (souvent une route bloquée par un pare-feu sortant). | Réessayer dans quelques minutes. Si persistant, alerter le support. |
Idle timeout reachedou timed out after |
Le service de signature met plus de 30 secondes à répondre (charge serveur). | Réessayer après 1 minute. Le mode seal est plus rapide que digigo pour les volumes élevés. |
Email signataire non configuré |
L'email du signataire associé à votre compte est manquant. | Contactez le support pour compléter votre configuration. |
Passphrase manquanteou required for seal |
Le mode seal exige une passphrase configurée pour votre compte. |
Soit basculez vers method: "digigo", soit demandez au support de configurer la passphrase SEAL. |
Invoice not foundou Locked invoice 50010 |
Tentative de re-signer une facture déjà en cours de signature. | Récupérez l'état actuel via GET /einvoices/{id}. Si rejected, créez une nouvelle facture avec un invoice_number différent. |
Invalid TEIF formatou erreur de validation XML |
Les données envoyées ne respectent pas le format TEIF v1.8.8. | Vérifiez vos données : matricule fiscal (8 chiffres + lettre + 3 chars), TVA dans [0, 7, 13, 19], champs requis. |
aucune transaction UUID retournée |
Réponse anormale du service de signature. | Réessayer. Si persistant, contacter le support avec votre invoice_number. |
| Autre message non listé | Erreur non répertoriée - possiblement nouvelle. | Contactez le support avec : debug complet, invoice_number, horodatage, et votre Client ID API. |
- Implémentez un retry avec backoff exponentiel pour les erreurs 5xx et timeouts (3 tentatives max : 1s, 3s, 10s)
- Ne retentez jamais automatiquement les erreurs 4xx (sauf 429 RATE_LIMIT et 412 SIGNER_NOT_CONFIGURED)
- Loguez le
request_idde chaque requête pour faciliter le support en cas de problème - Configurez un webhook pour éviter d'avoir à poller en cas de signature DigiGo (asynchrone)
Valider un payload
Valide la structure du payload sans signer ni déposer chez TTN. Idéal pour debugger votre intégration. Aucun crédit consommé même en mode live.
Paramètres requis
| Champ | Type | Description |
|---|---|---|
| invoice_numberrequis | string | Numéro de facture côté ERP. |
| daterequis | date YYYY-MM-DD | Date d'émission. |
| sellerrequis | object | name, tax_id, address. |
| buyerrequis | object | name, tax_id. |
| itemsrequis | array | Au moins 1 ligne. Voir Objet Invoice. |
| pdf_base64optionnel | string | Votre PDF de facture encodé en base64. Voir PDF de la facture. |
Signer + déposer (mode SEAL)
Synchrone (~5 secondes). Signature automatique via cachet électronique serveur, dépôt immédiat chez TTN. La réponse contient directement le XML signé (base64), le PDF avec QR code (base64) et la référence TTN. Clé requise : celle du client concerné (ck_) - une clé développeur reçoit 403 DEVELOPER_KEY_NOT_ALLOWED.
Codes de réponse
| HTTP | Signification |
|---|---|
| 200 | Facture signée et déposée. Réponse complète. |
| 412 | Cachet non provisionné (live). Contactez le support. |
| 402 | Crédits insuffisants. |
| 422 | Validation échouée. Voir error.details. |
Préparer une signature (mode DigiGo)
Asynchrone. Génère le TEIF, crée une transaction de signature et retourne une signing_url vers laquelle vous redirigez le client final (signature à distance ou clé USB locale). Celui-ci signe, puis est redirigé vers votre return_url. Clé requise : celle du client concerné (ck_) - une clé développeur reçoit 403 DEVELOPER_KEY_NOT_ALLOWED. Le signing_id retourné (format sg_...) sert au suivi via GET /einvoices/{signing_id}.
Récupérez le résultat final via :
- Polling :
GET /einvoices/{signing_id}jusqu'àstatus: validated - Webhook (recommandé) : nous appelons votre serveur dès que la signature est validée
Paramètres spécifiques DigiGo
| Champ | Type | Description |
|---|---|---|
| methodoptionnel | enum | seal, digigo, usb. Défaut : type configuré sur la clé. |
| return_urlrequis pour DigiGo | URL HTTPS | URL de votre ERP où le client est redirigé après signature. Doit être en HTTPS (les URL http:// sont rejetées). Vos propres paramètres de query sont préservés. |
return_url sert uniquement à ramener l'utilisateur dans votre interface. C'est une redirection navigateur : ne considérez jamais une facture comme signée parce que le navigateur est revenu sur cette URL - elle pourrait être appelée directement.
Pour confirmer le statut réel, utilisez toujours un canal authentifié serveur-à-serveur :
- Polling :
GET /einvoices/{signing_id}avec votre clé API (headerX-Api-Key). - Webhook : nous signons l'événement en HMAC-SHA256 (
X-Efacture-Signature) - vérifiez la signature.
?efacture_invoice={invoice_number}&signing_id={signing_id} à votre return_url. Le signing_id (format sg_...) est celui à utiliser avec GET /einvoices/{signing_id}. Utilisez ces paramètres seulement pour retrouver la facture concernée, jamais comme preuve de signature.
Récupérer une e-facture
Retourne le statut et les fichiers d'une e-facture. Utilisé principalement pour le polling après POST /einvoices/prepare. Seuls le client propriétaire de la facture et son développeur parent peuvent la consulter : toute autre clé reçoit 403 PERMISSION_DENIED.
Cycle de vie
draft → teif_generated → pending_signature → signed → submitted_ttn → validated
↘ rejected
| Statut | Description |
|---|---|
pending_signature | En attente que le client signe sur signing_url |
signed | Signature reçue, dépôt TTN en cours |
submitted_ttn | Déposé, attente validation TTN |
validated | TTN a accepté : xml_base64 + pdf_base64 disponibles |
rejected | Annulé ou rejeté : voir les blocs signature et ttn pour savoir quel étage a échoué |
Deux étages décrits séparément : signature et ttn
Le champ status est la synthèse globale du cycle. Un rejected peut signifier deux choses très différentes : signature refusée, ou facture signée mais dépôt TTN refusé. La réponse contient donc deux blocs dédiés :
{
"status": "rejected",
"signature": {
"status": "signed", // pending | signed | rejected
"signed_xml_available": true
},
"ttn": {
"status": "rejected", // not_reached | submitted | validated | rejected
"reference": null,
"error": { "code": "TTN_DEPOSIT_FAILED", "message": "Erreur TTN: ..." }
}
}
| Scénario | status | signature.status | ttn.status |
|---|---|---|---|
| En attente du signataire | pending_signature | pending | not_reached |
| Signature refusée / annulée | rejected | rejected | not_reached |
| Signée, dépôt TTN refusé | rejected | signed | rejected + error |
| Signée, déposée (SFTP), réponse TTN en attente | submitted_ttn | signed | submitted |
| Validée | validated | signed | validated + reference |
En cas de dépôt refusé (ttn.status: rejected) : le XML signé reste disponible, corrigez la cause (ex. identifiants TTN du client) puis ré-émettez la facture (nouveau /prepare ou /process). Un rejet est final pour ce signing_id.
Solde de crédits
Retourne le solde courant de crédits, le total utilisé et le total acheté.
Gestion des clients (API)
Un compte développeur peut gérer ses clients directement depuis son ERP, via l'API. Chaque client possède sa configuration TTN (sandbox et production), sa méthode de signature, son plafond de crédits et ses propres clés API.
Confidentialité des secrets
Les mots de passe TTN et SFTP ne sont jamais renvoyés en clair. En lecture, ils sont masqués par des astérisques dont le nombre correspond à la longueur enregistrée (ex. "password": "********"). Vous pouvez les écrire (création / modification) mais jamais les relire.
Champs d'un client
| Champ | Type | Description |
|---|---|---|
name | string | Nom du client (obligatoire a la creation) |
matricule | string | Matricule fiscal (identifiant TTN) |
signer_method | string | seal (cachet serveur), usb (cle locale) ou digigo (a distance) |
signer_email | string | Email du signataire : il reçoit les demandes de signature à distance. Obligatoire pour la méthode digigo (erreur SIGNER_EMAIL_MISSING, HTTP 412, sinon). Vous pouvez y mettre votre propre adresse si vous signez vous-même. Transmis automatiquement au service de signature à la création et à chaque modification. |
usb_signing_tool_url | string | Lecture seule. Lien de téléchargement direct de l'outil de signature USB (Windows) à installer sur le poste du signataire. Distribuez-le à vos clients depuis votre ERP. |
submission_channel | string | soap (synchrone) ou sftp (asynchrone) |
credit_cap | int / null | Plafond de credits du client. null = illimite (dans la limite du portefeuille) |
ttn.sandbox / ttn.prod | objet | login + password du compte TTN par environnement |
sftp.sandbox / sftp.prod | objet | host, port, username, password, in_dir, out_dir (canal SFTP) |
provision | string | Optionnel (création / modification). sandbox, production ou both : crée ou met à jour le compte de signature du client (méthode cachet serveur). L'opération est idempotente (création la première fois, mise à jour ensuite). Le résultat, y compris le message d'erreur éventuel du service, est renvoyé dans provisioning. Sans provision, tout PATCH met à jour automatiquement les environnements déjà connectés (raison sociale, matricule, accès TTN, email du signataire). |
En lecture, chaque client renvoie aussi son suivi : credits (cap, used, remaining) et stats (total, validated, rejected). De quoi afficher un mini tableau de bord par client dans votre ERP.
Creer un client
Crée un client et retourne ses clés API (ck_test_ / ck_live_). Ces clés restent récupérables à tout moment via GET /clients/{id}. Ajoutez "provision": "sandbox" (ou production / both) pour créer en même temps le compte de signature du client.
POST /api/v1/clients
X-Api-Key: sk_live_VOTRE_CLE_DEVELOPPEUR
Content-Type: application/json
{
"name": "Societe ABC",
"matricule": "1234567AAM000",
"signer_method": "seal",
"signer_email": "signataire@societe-abc.tn",
"submission_channel": "soap",
"credit_cap": 500,
"ttn": {
"sandbox": { "login": "abc_test", "password": "secret1" },
"prod": { "login": "abc_prod", "password": "secret2" }
}
}
Reponse (201) :
{
"success": true,
"data": {
"id": "018f...-....",
"name": "Societe ABC",
"matricule": "1234567AAM000",
"signer_method": "seal",
"signer_email": "signataire@societe-abc.tn",
"submission_channel": "soap",
"active": true,
"live_enabled": true,
"credits": { "cap": 500, "used": 0, "remaining": 500 },
"stats": { "total": 0, "validated": 0, "rejected": 0 },
"ttn": {
"sandbox": { "login": "abc_test", "password": "*******" },
"prod": { "login": "abc_prod", "password": "*******" }
},
"keys": { "test": "ck_test_...", "live": "ck_live_..." }
}
}
Si vous avez demandé un provision, la réponse contient un bloc provisioning par environnement :
"provisioning": {
"sandbox": { "success": true, "message": "Compte de signature cree (environnement test)." },
"production": { "success": false, "message": "L'organisation existe deja chez le prestataire..." }
}
La création du client réussit même si le provisioning échoue : corrigez les accès puis relancez via PATCH avec provision. Utilisez ensuite la clé du client (keys.live / keys.test) pour émettre ses e-factures via /einvoices/process ou /einvoices/prepare.
Lister les clients
Retourne tous vos clients (secrets masqués) avec leurs crédits et statistiques, plus le solde de votre portefeuille partagé.
{
"success": true,
"data": {
"clients": [
{ "id": "...", "name": "Societe ABC",
"credits": { "cap": 500, "used": 180, "remaining": 320 },
"stats": { "total": 200, "validated": 190, "rejected": 10 }, ... }
],
"wallet": { "balance": 4200, "total_purchased": 5000 }
}
}
Lire un client
Retourne un client : configuration, crédits, statistiques et ses clés API (keys.test / keys.live, préfixe ck_). Les mots de passe TTN/SFTP restent masqués, mais les clés API du client sont renvoyées en clair pour vous permettre de les récupérer à tout moment.
Modifier un client
Mise à jour partielle : seuls les champs envoyés sont modifiés. Envoyez uniquement un mot de passe TTN/SFTP pour le remplacer ; omettez-le pour le conserver. Ajoutez "provision" pour recréer ou mettre à jour le compte de signature.
PATCH /api/v1/clients/018f...
X-Api-Key: sk_live_VOTRE_CLE_DEVELOPPEUR
{ "credit_cap": 800, "submission_channel": "sftp",
"sftp": { "prod": { "host": "sftp.ttn.tn", "port": 22, "username": "abc",
"password": "xxx", "in_dir": "/in", "out_dir": "/out" } } }
Supprimer un client • Régénérer les clés
Supprime le client.
Régénère les clés API du client (les anciennes cessent immédiatement de fonctionner). Les nouvelles clés sont retournées, et restent récupérables via GET /clients/{id}.
Webhooks
Configurez une URL HTTPS et nous vous notifions dès qu'une e-facture passe à validated ou rejected. Évite le polling.
Événements envoyés : einvoice.validated, einvoice.rejected, et pour le canal SFTP l'événement intermédiaire einvoice.submitted (facture déposée, en attente de la réponse TTN).
Vérification HMAC
Chaque webhook inclut un header X-Efacture-Signature au format sha256=<hex>. Calculez l'HMAC-SHA256 du body brut avec votre webhook secret et comparez avec le header.
Politique de retry
- Livraison asynchrone, jusqu'à 3 nouvelles tentatives avec backoff exponentiel en cas d'échec
- Considéré réussi si vous répondez
2xx(tout autre code déclenche un retry) - Timeout de 10 s par tentative ; répondez vite et traitez en tâche de fond si besoin
- Idempotence : le même
signing_idpeut être notifié plusieurs fois
Rate limits
Par défaut : 60 requêtes par minute par clé API. Sliding window, comptage atomique. Configurable sur demande pour les volumes élevés.
En cas de dépassement : réponse 429 RATE_LIMIT. Implémentez un backoff exponentiel côté client.
Objet Invoice
| Champ | Type | Description |
|---|---|---|
| invoice_numberrequis | string | Numéro de facture côté ERP. |
| daterequis | date | Date d'émission YYYY-MM-DD. |
| due_dateoptionnel | date | Date d'échéance. |
| currencyoptionnel | string | Devise ISO 4217. Défaut TND (3 décimales). Pour les factures offshore/export : EUR, USD… (2 décimales) - conservées telles quelles, aucune conversion. En devise étrangère : ni TVA, ni timbre fiscal (régime export), le montant est en TTC = HT. |
| seller.namerequis | string | Raison sociale du vendeur. |
| seller.tax_idrequis | string | Matricule fiscal (8 chiffres + lettre + 3 chars). |
| seller.addressrequis | string | Adresse (rue). Aussi : address_line_2, postal_code, city, governorate, country, phone, email. |
| buyer.namerequis | string | Raison sociale / nom du client. |
| buyer.tax_idrequis* | string | MF du client. *À défaut, id_number (CIN/passeport pour un particulier). |
| buyer.addressoptionnel | string | Adresse (rue) du client. |
| buyer.address_line_2optionnel | string | Complément d'adresse. |
| buyer.postal_codeoptionnel | string | Code postal. |
| buyer.cityoptionnel | string | Ville. |
| buyer.governorateoptionnel | string | Gouvernorat. |
| buyer.countryoptionnel | string | Pays (code ISO, défaut TN). |
| buyer.phone / buyer.emailoptionnel | string | Téléphone / e-mail du client. |
| items[].descriptionrequis | string | Description de la ligne. |
| items[].quantityrequis | number | Quantité. |
| items[].unit_pricerequis | number | Prix unitaire HT. |
| items[].vat_raterequis* | enum | 0, 7, 13, 19. Alias : tva_rate, tax_rate. *Requis sauf si default_vat_rate (facture) est défini ou si la ligne est exonerated. Aucune valeur n'est supposée par défaut : un taux manquant renvoie une erreur de validation. (Ignoré en devise étrangère : pas de TVA.) |
| items[].discount_percentoptionnel | number | Remise sur la ligne, en % (0–100). Le Total HT de la ligne est diminué d'autant, et la TVA est calculée sur le HT après remise. Alias : remise, remise_percent, discount. |
| items[].exoneratedoptionnel | boolean | Ligne exonérée de TVA (taux 0 %). Équivaut à vat_rate: 0. Alias : vat_exempt. |
| items[].fodecoptionnel | boolean | FODEC 1 % sur la ligne (produits assujettis). Calculé sur le HT après remise, et la TVA de la ligne est calculée sur HT + FODEC (règle tunisienne). Apparaît en ligne « FODEC (1%) » dans les totaux du PDF et en taxe I-1603 dans le TEIF. Alias : fodec_applicable, is_fodec. (Ignoré en devise étrangère.) |
| default_vat_rateoptionnel | enum | Taux TVA par défaut de la facture (0, 7, 13, 19), appliqué aux lignes sans vat_rate. Évite de répéter le taux sur chaque ligne. |
| stamp_dutyoptionnel | boolean | number | Timbre fiscal. Présent par défaut (1,000 TND) - mettre false pour le désactiver, ou un montant numérique pour le personnaliser. Alias : timbre, fiscal_stamp. |
| withholding_tax_rateoptionnel | number | Retenue à la source (ex. 1.5, 3, 10, 15, 20). Base = TTC hors timbre (HT + TVA). Montant déduit du Net à payer. |
| brand_coloroptionnel | string | Couleur de marque du PDF généré (hex, ex. #1d4ed8). Défaut : #dc2626. Ignoré si vous fournissez pdf_base64. |
| payment_methodoptionnel | string | Mode de règlement affiché sur le PDF (texte libre, ex. Virement bancaire - RIB 12345678901234567890, Chèque, Espèces). Max 255 caractères. Rendu sur le PDF généré (mode B). |
| custom_noteoptionnel | object | Note libre positionnable (mentions légales, conditions, paragraphe…). Objet { "text": string (max 1000), "position": "top_left" | "bottom_left" | "bottom_center" | "bottom_right" }. Défaut position : bottom_left. Rendu sur le PDF généré (mode B). |
| invoice_objectoptionnel | string | Objet de la facture, affiché « Objet : … » (ex. Prestation de conseil - janvier 2026). Max 255 caractères. Rendu sur le PDF généré (mode B). |
| termsoptionnel | string | Conditions générales / conditions de paiement / mentions, affichées dans un bloc « Conditions générales » (ex. Paiement à 30 jours. Pénalité de 1,5%/mois en cas de retard.). Max 1000 caractères. Rendu sur le PDF généré (mode B). |
| referencesoptionnel | string | Référence libre affichée « Référence » (ex. Bon de commande N° 1234 du 05/01/2026). Max 100 caractères. Rendu sur le PDF généré (mode B). |
| bank_detailsoptionnel | string | Coordonnées bancaires affichées « Coordonnées bancaires : … » (ex. RIB 12345678901234567890 - Banque XYZ). Max 255 caractères. Rendu sur le PDF généré (mode B). |
| pdf_base64optionnel | string | Votre PDF de facture encodé en base64. Voir PDF de la facture. |
Exemple complet (tous les champs)
Payload de référence regroupant l'ensemble des champs supportés : coordonnées structurées vendeur/client (MF, adresse, ville, code postal, gouvernorat, pays, téléphone, e-mail), TVA multi-taux par ligne, taux par défaut, ligne exonérée, timbre fiscal, retenue à la source et couleur du PDF. Ce payload passe la validation sans erreur.
Notes :
method:sealpour/einvoices/process(signature automatique),digigopour/einvoices/prepare(signature par le client).- Particulier : remplacez
buyer.tax_idparbuyer.id_number(CIN/passeport) → le PDF affiche « CIN » au lieu de « MF ». default_vat_rates'applique aux lignes sansvat_rate; chaque ligne peut le surcharger (TVA différente par ligne). Un récap TVA par taux est généré automatiquement.stamp_dutyest présent par défaut (1,000 TND) - mettezfalsepour le retirer.brand_coloret les coordonnées ne servent au rendu que pour le PDF généré (mode B). En mode A (pdf_base64), c'est votre PDF qui fait foi.- Validez d'abord via
POST /einvoices/validate(0 crédit) : tout champ manquant/invalide est retourné danserror.details. - Alias de champs acceptés (vendeur/client) :
name=nom/raison_sociale,tax_id=matricule_fiscal/mf,address=adresse/rue,postal_code=code_postal/cp,city=ville,governorate=gouvernorat,country=pays,phone=tel. L'addresspeut aussi être un objet{ street, city, postal_code }.
Récap TVA produit pour cet exemple :
| Taux | Base HT | Montant TVA |
|---|---|---|
| 0 % (exonéré) | 500,000 | 0,000 |
| 7 % | 100,000 | 7,000 |
| 13 % | 500,000 | 65,000 |
| 19 % | 1 000,000 | 190,000 |
| TOTAL | 2 100,000 | 262,000 |
Retenue à la source (RS)
La retenue à la source est l'impôt que l'acheteur retient sur le paiement et reverse à l'État pour le compte du vendeur. Elle ne modifie ni le HT, ni la TVA, ni le Total TTC : elle réduit seulement le Net à payer.
- Optionnelle : envoyez
withholding_tax_rateuniquement quand il y a une retenue. Omettez le champ (ou mettez0) pour ne pas en appliquer - la ligne « Retenue à la source » n'apparaît alors pas et le Net à payer = Total TTC. Aucun autre indicateur n'est requis. - Base de calcul = TTC hors timbre (HT + TVA).
- Taux courants :
1.5(achats biens/services > 1000 DT TTC),3(honoraires régime réel),10(honoraires/loyers/commissions),15,20…
Exemple 1 - avec retenue à la source (1,5 %)
| Ligne | Montant | Calcul |
|---|---|---|
| Total HT | 125,000 | 1 × 125,000 |
| TVA (7 %) | 8,750 | 7 % du HT |
| Timbre fiscal | 1,000 | fixe |
| Total TTC | 134,750 | HT + TVA + timbre |
| Retenue à la source 1,5 % | − 2,006 | 1,5 % × (HT + TVA) = 1,5 % × 133,750 |
| NET À PAYER | 132,744 | TTC − RS |
Exemple 2 - sans retenue à la source
Il suffit de ne pas envoyer withholding_tax_rate (ou de mettre 0) :
| Ligne | Montant | Calcul |
|---|---|---|
| Total HT | 125,000 | 1 × 125,000 |
| TVA (7 %) | 8,750 | 7 % du HT |
| Timbre fiscal | 1,000 | fixe |
| NET À PAYER (= Total TTC) | 134,750 | aucune ligne RS affichée |
PDF de la facture
Le PDF est le document visuel présenté au signataire et archivé après signature (le QR de signature y est apposé automatiquement). Deux modes sont possibles :
| Mode | Quand | Résultat |
|---|---|---|
| A - Vous fournissez le PDF recommandé | Vous envoyez le champ pdf_base64 (votre PDF déjà mis en page : logo, couleurs, mentions de votre ERP). |
Votre PDF est signé tel quel. C'est votre document qui fait foi. |
| B - Génération automatique | Vous omettez pdf_base64. |
Nous générons un PDF neutre mais valide à partir des données de la facture (vendeur, client, lignes, totaux). Sans votre logo. |
Recommandation : si votre ERP produit déjà des factures PDF, envoyez-les via
pdf_base64 pour conserver votre charte graphique. Contraintes :
- Encodage base64 du contenu binaire du PDF (préfixe
data:application/pdf;base64,toléré mais optionnel). - Doit être un PDF valide (commence par
%PDF). - Taille maximale : 10 Mo (avant encodage).
- Si le PDF fourni est invalide ou absent, le mode B (génération) prend automatiquement le relais - aucun échec de signature.
Objet Error
Format normalisé pour toutes les erreurs :
Payload Webhook
Envoyé par notre serveur à votre URL configurée lorsqu'une e-facture change de statut final :
Header de signature : X-Efacture-Signature: sha256=<hex> calculé en HMAC-SHA256 du body brut avec votre webhook secret.
Une question technique ? Contactez l'équipe ou consultez la référence interactive Swagger.