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.

Base URLToutes les requêtes utilisent https://efacturetn.com/api/v1

Premier 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éfixeModeUsage
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.
Ne partagez jamais votre cléLes clés API donnent un accès complet à votre compte. Stockez-les comme des secrets (variables d'environnement, gestionnaire de secrets).

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 ».

NotionDescription
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.
INSUFFICIENT_CREDITSCette erreur (402) est renvoyée lorsque le portefeuille du compte développeur est vide OU lorsque le plafond de crédits du client concerné est atteint.

Test vs Production

Passer en production ne nécessite aucun changement de code : remplacez simplement sk_test_xxx par sk_live_xxx.

Sandbox = environnement réel de testAucune simulation : en mode test, la signature et le dépôt s'exécutent réellement sur les environnements de TEST du service de signature et de TTN. La 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èreTestProduction
SignatureXAdES réelle (environnement sandbox)XAdES réelle (production)
Dépôt TTNPlateforme TTN de testPlateforme TTN de production
Crédits consommésAucun1 par signature
Cachet/CertificatRequis (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.

SEALDigiGo
Synchrone ?Oui (~5s)Non (signature manuelle)
InteractionAucunePIN + OTP utilisateur
EndpointPOST /einvoices/processPOST /einvoices/prepare
Cas d'usageERP back-office, volumes élevésSignature personnelle, petits volumes
Récup résultatDirect dans la réponsePolling /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 :

CodeHTTPDescription
AUTH_INVALID_KEY401Clé API invalide, inactive ou non autorisée
VALIDATION_FAILED422Champs requis manquants : voir error.details
INVALID_JSON400Corps de requête non JSON valide
INSUFFICIENT_CREDITS402Portefeuille épuisé ou plafond du client atteint (live uniquement)
SEAL_NOT_CONFIGURED412Cachet électronique SEAL non provisionné pour ce client sur l'environnement de la clé (sandbox ou production)
SIGNER_NOT_CONFIGURED412Service de signature DigiGo/USB non configuré pour ce client
SIGNER_EMAIL_MISSING412Signature à 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_ALLOWED403Clé développeur (sk_) utilisée sur /einvoices/prepare ou /process : l'émission passe obligatoirement par la clé du client concerné (ck_)
PERMISSION_DENIED403Le 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_UNAVAILABLE400Méthode de signature inconnue (method doit être seal, digigo ou usb)
SIGNER_CIRCUIT_OPEN503Service de signature en panne répétée : circuit breaker activé. Réessayer dans 30-60 sec
RATE_LIMIT429Limite de requêtes par minute dépassée
SIGNING_FAILED503É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.

Exemple de réponse SIGNING_FAILED en mode test
{
  "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 debugCause probableAction recommandée
HTTP 401
ou Unauthorized
Le jeton de signature configuré pour votre compte est invalide ou expiré. Contactez le support pour faire renouveler votre jeton de signature.
HTTP 402
ou Payment Required
Compte de signature sans crédit ou plan expiré. Contactez le support pour réactiver le service.
HTTP 403
ou 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 502
Bad 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 504
Gateway Timeout
Le service de signature met trop de temps à répondre. Réessayer immédiatement. Si récurrent, contacter le support.
Connection timed out
ou 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 reached
ou 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 manquante
ou 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 found
ou 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 format
ou 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.
Bonnes pratiques en production
  • 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_id de 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

POST /api/v1/einvoices/validate

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

ChampTypeDescription
invoice_numberrequisstringNuméro de facture côté ERP.
daterequisdate YYYY-MM-DDDate d'émission.
sellerrequisobjectname, tax_id, address.
buyerrequisobjectname, tax_id.
itemsrequisarrayAu moins 1 ligne. Voir Objet Invoice.
pdf_base64optionnelstringVotre PDF de facture encodé en base64. Voir PDF de la facture.

Signer + déposer (mode SEAL)

POST /api/v1/einvoices/process

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.

Cas d'usage recommandéERP back-office, batch quotidien, volumes élevés. Aucune interaction utilisateur.

Codes de réponse

HTTPSignification
200Facture signée et déposée. Réponse complète.
412Cachet non provisionné (live). Contactez le support.
402Crédits insuffisants.
422Validation échouée. Voir error.details.

Préparer une signature (mode DigiGo)

POST /api/v1/einvoices/prepare

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

ChampTypeDescription
methodoptionnelenumseal, digigo, usb. Défaut : type configuré sur la clé.
return_urlrequis pour DigiGoURL HTTPSURL 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.
Sécurité de la redirection (à lire) Le 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 (header X-Api-Key).
  • Webhook : nous signons l'événement en HMAC-SHA256 (X-Efacture-Signature) - vérifiez la signature.
Pour vous aider à corréler le retour, nous ajoutons automatiquement ?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

GET /api/v1/einvoices/{id}

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
StatutDescription
pending_signatureEn attente que le client signe sur signing_url
signedSignature reçue, dépôt TTN en cours
submitted_ttnDéposé, attente validation TTN
validatedTTN a accepté : xml_base64 + pdf_base64 disponibles
rejectedAnnulé 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énariostatussignature.statusttn.status
En attente du signatairepending_signaturependingnot_reached
Signature refusée / annuléerejectedrejectednot_reached
Signée, dépôt TTN refusérejectedsignedrejected + error
Signée, déposée (SFTP), réponse TTN en attentesubmitted_ttnsignedsubmitted
Validéevalidatedsignedvalidated + 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.

Stratégie de pollingBackoff exponentiel recommandé : 5s, 10s, 20s, 30s, 60s... avec timeout total de 30 minutes. Préférez les webhooks pour éviter les requêtes inutiles.

Solde de crédits

GET /api/v1/credits/balance

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.

AuthentificationCes endpoints utilisent la clé de votre compte développeur (pas la clé d'un client). Ils opèrent sur vos clients rattachés. Une clé de client est refusée (403).

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

ChampTypeDescription
namestringNom du client (obligatoire a la creation)
matriculestringMatricule fiscal (identifiant TTN)
signer_methodstringseal (cachet serveur), usb (cle locale) ou digigo (a distance)
signer_emailstringEmail 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_urlstringLecture 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_channelstringsoap (synchrone) ou sftp (asynchrone)
credit_capint / nullPlafond de credits du client. null = illimite (dans la limite du portefeuille)
ttn.sandbox / ttn.prodobjetlogin + password du compte TTN par environnement
sftp.sandbox / sftp.prodobjethost, port, username, password, in_dir, out_dir (canal SFTP)
provisionstringOptionnel (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

POST /api/v1/clients

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

GET /api/v1/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

GET /api/v1/clients/{id}

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

PATCH /api/v1/clients/{id}

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

DELETE /api/v1/clients/{id}

Supprime le client.

POST /api/v1/clients/{id}/keys

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_id peut ê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

ChampTypeDescription
invoice_numberrequisstringNuméro de facture côté ERP.
daterequisdateDate d'émission YYYY-MM-DD.
due_dateoptionneldateDate d'échéance.
currencyoptionnelstringDevise 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.namerequisstringRaison sociale du vendeur.
seller.tax_idrequisstringMatricule fiscal (8 chiffres + lettre + 3 chars).
seller.addressrequisstringAdresse (rue). Aussi : address_line_2, postal_code, city, governorate, country, phone, email.
buyer.namerequisstringRaison sociale / nom du client.
buyer.tax_idrequis*stringMF du client. *À défaut, id_number (CIN/passeport pour un particulier).
buyer.addressoptionnelstringAdresse (rue) du client.
buyer.address_line_2optionnelstringComplément d'adresse.
buyer.postal_codeoptionnelstringCode postal.
buyer.cityoptionnelstringVille.
buyer.governorateoptionnelstringGouvernorat.
buyer.countryoptionnelstringPays (code ISO, défaut TN).
buyer.phone / buyer.emailoptionnelstringTéléphone / e-mail du client.
items[].descriptionrequisstringDescription de la ligne.
items[].quantityrequisnumberQuantité.
items[].unit_pricerequisnumberPrix unitaire HT.
items[].vat_raterequis*enum0, 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_percentoptionnelnumberRemise 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[].exoneratedoptionnelbooleanLigne exonérée de TVA (taux 0 %). Équivaut à vat_rate: 0. Alias : vat_exempt.
items[].fodecoptionnelbooleanFODEC 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_rateoptionnelenumTaux 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_dutyoptionnelboolean | numberTimbre 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_rateoptionnelnumberRetenue à la source (ex. 1.5, 3, 10, 15, 20). Base = TTC hors timbre (HT + TVA). Montant déduit du Net à payer.
brand_coloroptionnelstringCouleur de marque du PDF généré (hex, ex. #1d4ed8). Défaut : #dc2626. Ignoré si vous fournissez pdf_base64.
payment_methodoptionnelstringMode 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_noteoptionnelobjectNote 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_objectoptionnelstringObjet de la facture, affiché « Objet : … » (ex. Prestation de conseil - janvier 2026). Max 255 caractères. Rendu sur le PDF généré (mode B).
termsoptionnelstringConditions 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).
referencesoptionnelstringRé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_detailsoptionnelstringCoordonné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_base64optionnelstringVotre 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.

{ "method": "seal", "invoice_number": "F-2026-00042", "date": "2026-06-26", "due_date": "2026-07-26", "default_vat_rate": 19, "stamp_duty": true, "withholding_tax_rate": 1.5, "brand_color": "#1d4ed8", "payment_method": "Virement bancaire - RIB 12345678901234567890", "invoice_object": "Prestation de conseil - janvier 2026", "terms": "Paiement à 30 jours. Pénalité de 1,5%/mois en cas de retard (art. 5 CGV).", "references": "Bon de commande N° 1234 du 05/01/2026", "bank_details": "RIB 12345678901234567890 - Banque XYZ", "custom_note": { "text": "Facture soumise à la TVA. En cas de retard de paiement, une pénalité de 1,5% par mois sera appliquée (art. 5 des CGV).", "position": "bottom_left" }, "seller": { "name": "Mon Entreprise SARL", "tax_id": "1234567ABM000", "address": "Avenue Habib Bourguiba", "address_line_2": "Immeuble El Amen, 3e etage", "postal_code": "1000", "city": "Tunis", "governorate": "Tunis", "country": "TN", "phone": "71234567", "email": "contact@mon-entreprise.tn" }, "buyer": { "name": "Client Demo SARL", "tax_id": "7654321ABM000", "address": "Rue de la Liberte", "postal_code": "3000", "city": "Sfax", "governorate": "Sfax", "country": "TN", "phone": "74111222", "email": "facturation@client-demo.tn" }, "items": [ { "description": "Prestation de conseil", "quantity": 1, "unit_price": 1000.000, "vat_rate": 19 }, { "description": "Licence logicielle annuelle", "quantity": 2, "unit_price": 250.000, "vat_rate": 13 }, { "description": "Produit de premiere necessite","quantity": 5, "unit_price": 20.000, "vat_rate": 7 }, { "description": "Service a l'export", "quantity": 1, "unit_price": 500.000, "exonerated": true } ], "return_url": "https://votre-erp.tn/factures/retour" }

Notes :

  • method : seal pour /einvoices/process (signature automatique), digigo pour /einvoices/prepare (signature par le client).
  • Particulier : remplacez buyer.tax_id par buyer.id_number (CIN/passeport) → le PDF affiche « CIN » au lieu de « MF ».
  • default_vat_rate s'applique aux lignes sans vat_rate ; chaque ligne peut le surcharger (TVA différente par ligne). Un récap TVA par taux est généré automatiquement.
  • stamp_duty est présent par défaut (1,000 TND) - mettez false pour le retirer.
  • brand_color et 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é dans error.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'address peut aussi être un objet { street, city, postal_code }.

Récap TVA produit pour cet exemple :

TauxBase HTMontant TVA
0 % (exonéré)500,0000,000
7 %100,0007,000
13 %500,00065,000
19 %1 000,000190,000
TOTAL2 100,000262,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_rate uniquement quand il y a une retenue. Omettez le champ (ou mettez 0) 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 %)

{ "invoice_number": "F-2026-00051", "date": "2026-06-27", "stamp_duty": true, "withholding_tax_rate": 1.5, "seller": { "name": "Mon Entreprise SARL", "tax_id": "1234567ABM000", "address": "Tunis" }, "buyer": { "name": "Client Public", "tax_id": "7654321ABM000", "address": "Sfax" }, "items": [ { "description": "Location bus", "quantity": 1, "unit_price": 125.000, "vat_rate": 7 } ] }
LigneMontantCalcul
Total HT125,0001 × 125,000
TVA (7 %)8,7507 % du HT
Timbre fiscal1,000fixe
Total TTC134,750HT + TVA + timbre
Retenue à la source 1,5 %− 2,0061,5 % × (HT + TVA) = 1,5 % × 133,750
NET À PAYER132,744TTC − RS

Exemple 2 - sans retenue à la source

Il suffit de ne pas envoyer withholding_tax_rate (ou de mettre 0) :

{ "invoice_number": "F-2026-00052", "date": "2026-06-27", "stamp_duty": true, "seller": { "name": "Mon Entreprise SARL", "tax_id": "1234567ABM000", "address": "Tunis" }, "buyer": { "name": "Client Prive", "tax_id": "7654321ABM000", "address": "Sfax" }, "items": [ { "description": "Location bus", "quantity": 1, "unit_price": 125.000, "vat_rate": 7 } ] }
LigneMontantCalcul
Total HT125,0001 × 125,000
TVA (7 %)8,7507 % du HT
Timbre fiscal1,000fixe
NET À PAYER (= Total TTC)134,750aucune 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 :

ModeQuandRé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 :

{ "success": false, "data": null, "error": { "code": "VALIDATION_FAILED", "message": "Invoice validation failed.", "details": [ "seller.address is required.", "buyer.tax_id or buyer.id_number is required.", "item 1: vat_rate is required (set the line vat_rate, a document default_vat_rate, or \"exonerated\": true)." ] } }

Payload Webhook

Envoyé par notre serveur à votre URL configurée lorsqu'une e-facture change de statut final :

{ "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" }

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.