@fiscapi-node/sdk
v1.1.0
Published
SDK officiel Node.js/TypeScript pour l'API FiscAPI - Facturation e-MECeF au Bénin
Maintainers
Readme
FiscAPI SDK pour Node.js
SDK officiel pour l'intégration de la facturation e-MECeF (DGI Bénin) avec FiscAPI.
✨ Nouveautés v1.1.0
- ✅ Support complet des avoirs (FA/EA)
- ✅ Endpoint de normalisation des brouillons
- ✅ Authentification via header
x-api-key - ✅ Support des réponses paginées
- ✅ Calcul TVA côté client
📦 Installation
npm install @fiscapi-node/sdk
# ou
yarn add @fiscapi-node/sdk🔐 Sécurité - IMPORTANT
⚠️ NE JAMAIS exposer votre clé API côté client
// ❌ DANGEREUX - La clé est visible dans le code source
const fiscapi = new FiscApi('sk_live_xxx'); // Dans le navigateur = FUITE✅ Utilisez TOUJOURS le SDK côté serveur
| Architecture | Sécurité | Recommandation | |--------------|----------|----------------| | Node.js / Backend | ✅ Sécurisé | ✅ Recommandé | | Serverless (Vercel, Netlify) | ✅ Sécurisé | ✅ Recommandé | | Frontend (React, Vue, etc.) | ❌ Dangereux | ❌ À éviter | | Mobile (React Native, Flutter) | ❌ Dangereux | ❌ À éviter |
Architecture recommandée
┌─────────────────┐ ┌─────────────────┐ ┌────────────────┐
│ Votre Frontend │ --> │ Votre Backend │ --> │ FiscAPI v1 │
│ (React, Vue) │ │ (Node, Python) │ │ (clé API ici) │
└─────────────────┘ └─────────────────┘ └────────────────┘
▲ │
│ │
Sans clé Clé API en
(session) variable envVariables d'environnement
# .env (jamais commité)
FISCAPI_API_KEY=sk_live_xxx
# .env.example (à committer)
FISCAPI_API_KEY=// Charger la clé depuis l'environnement
const fiscapi = new FiscApi(process.env.FISCAPI_API_KEY!);🚀 Démarrage rapide
import { FiscApi } from '@fiscapi-node/sdk';
// Initialiser avec votre clé API (côté serveur uniquement)
const fiscapi = new FiscApi(process.env.FISCAPI_API_KEY!);
// Créer et normaliser une facture
const invoice = await fiscapi.invoices.create({
type: 'FV', // FV = Facture de Vente
items: [
{
name: 'Consultation',
price: 50000, // Prix TTC
quantity: 1,
taxGroup: 'B' // B = TVA 18%
}
],
client: {
name: 'SARL Example',
ifu: '0101010101010' // Optionnel
}
});
// Récupérer les données de sécurité DGI
console.log(invoice.status); // 'CONFIRMED'
console.log(invoice.security?.codeMECeFDGI); // 'TEST-XXXX-YYYY-ZZZZ'
console.log(invoice.security?.qrCode); // QR code à imprimer
console.log(invoice.security?.nim); // NIM de la machine
console.log(invoice.totals.total); // 50000
console.log(invoice.totals.totalTVA); // 7627📋 Format de requête (Format DGI)
interface CreateInvoicePayload {
// Type de facture
type: 'FV' | 'FA' | 'EV' | 'EA'; // FV=Vente, FA=Avoir, EV=Export, EA=Avoir Export
// AIB (Acompte Impôt Bénéfice)
aib?: 'A' | 'B' | null; // A=1%, B=5%, null=pas d'AIB
// Client (optionnel pour vente au comptoir)
client?: {
name: string; // Nom (min 5 caractères)
ifu?: string; // IFU 13 chiffres
contact?: string; // Téléphone
address?: string; // Adresse
};
// Articles
items: Array<{
name: string; // Désignation
price: number; // Prix unitaire
quantity: number; // Quantité
taxGroup: 'A'|'B'|'C'|'D'|'E'|'F';
taxSpecific?: number; // Taxe spécifique par unité
}>;
// Paiements
payment?: Array<{
name: 'ESPECES' | 'VIREMENT' | 'CARTEBANCAIRE' | 'MOBILEMONEY';
amount: number;
}>;
// Options
pricingMode?: 'HT' | 'TTC'; // Défaut: TTC
autoNormalize?: boolean; // Défaut: true
reference?: string; // Pour avoirs FA/EA
}📊 Groupes de taxes
| Code | Nom | Taux | Description |
|------|-----|------|-------------|
| A | Exonéré | 0% | Produits exonérés de TVA |
| B | Taxable | 18% | TVA standard |
| C | Exportation | 0% | Vente à l'export |
| D | Exception | 0% | Régime d'exception |
| E | TPS | 0% | Taxe Professionnelle Synthétique |
| F | Spécifique | 0% | Taxe spécifique uniquement |
📝 Exemples
Facture simple (FV)
const invoice = await fiscapi.invoices.create({
type: 'FV',
client: { name: 'Client Simple' },
items: [
{ name: 'Consultation', price: 50000, quantity: 1, taxGroup: 'B' }
]
});
console.log(invoice.status); // 'CONFIRMED'
console.log(invoice.security?.codeMECeFDGI); // 'TEST-XXXX-...'Facture multi-lignes
const invoice = await fiscapi.invoices.create({
type: 'FV',
client: {
name: 'Entreprise ABC',
ifu: '0101010101010',
contact: '+229 97 00 00 00',
address: 'Cotonou, Bénin'
},
items: [
{ name: 'Ordinateur portable', price: 350000, quantity: 2, taxGroup: 'B' },
{ name: 'Souris sans fil', price: 15000, quantity: 5, taxGroup: 'B' },
{ name: 'Câble HDMI', price: 5000, quantity: 3, taxGroup: 'A' } // Exonéré
]
});Facture avec AIB
const invoice = await fiscapi.invoices.create({
type: 'FV',
aib: 'A', // 1% du montant
client: {
name: 'Client avec AIB',
ifu: '0202020202020'
},
items: [
{ name: 'Prestation de services', price: 100000, quantity: 1, taxGroup: 'B' }
]
});
console.log(invoice.totals.aib); // Montant AIB (1000 FCFA)Facture d'exportation (EV)
const invoice = await fiscapi.invoices.create({
type: 'EV',
client: {
name: 'Client Export International',
address: 'Paris, France'
},
items: [
{ name: 'Noix de cajou (export)', price: 500000, quantity: 10, taxGroup: 'C' },
{ name: 'Karité brut (export)', price: 250000, quantity: 5, taxGroup: 'C' }
]
});
console.log(invoice.totals.totalTVA); // 0 (pas de TVA à l'export)Mode HT (prix hors taxes)
const invoice = await fiscapi.invoices.create({
type: 'FV',
pricingMode: 'HT', // Prix hors taxes
client: { name: 'Client HT' },
items: [
{ name: 'Service', price: 10000, quantity: 1, taxGroup: 'B' }
]
});
// Le SDK calcule automatiquement la TVA
console.log(invoice.totals.totalHT); // 10000
console.log(invoice.totals.totalTVA); // 1800
console.log(invoice.totals.total); // 11800💳 Avoirs (Remboursements)
Avoir total (remboursement complet)
// Créer d'abord une facture
const invoice = await fiscapi.invoices.create({
type: 'FV',
client: { name: 'Client à rembourser' },
items: [
{ name: 'Produit', price: 30000, quantity: 1, taxGroup: 'B' }
]
});
// Attendre 4 secondes pour la prise en compte DGI
await new Promise(resolve => setTimeout(resolve, 4000));
// Créer l'avoir total
const creditNote = await fiscapi.invoices.refund(invoice.uid, 'Annulation commande');
console.log(creditNote.type); // 'FA'
console.log(creditNote.status); // 'CONFIRMED'
console.log(creditNote.security?.codeMECeFDGI); // Code de l'avoirAvoir partiel (remboursement sélectif)
// Rembourser 2 unités de la ligne 1
const creditNote = await fiscapi.invoices.refundPartial('clx123abc', {
lines: [
{ position: 1, quantity: 2 }, // Ligne 1, 2 unités
{ position: 3 }, // Ligne 3 entière
],
reason: 'Retour produit défectueux'
});📄 Brouillons
Créer un brouillon (sans normaliser)
const draft = await fiscapi.invoices.createDraft({
type: 'FV',
items: [{ name: 'Test', price: 25000, quantity: 2, taxGroup: 'B' }],
client: { name: 'Client Draft' }
});
console.log(draft.status); // 'DRAFT'Normaliser le brouillon plus tard
const confirmed = await fiscapi.invoices.normalize(draft.uid);
console.log(confirmed.status); // 'CONFIRMED'
console.log(confirmed.security?.codeMECeFDGI); // Code MECeF⚠️ Gestion des erreurs
import { FiscApiError } from '@fiscapi-node/sdk';
try {
const invoice = await fiscapi.invoices.create({ ... });
} catch (error) {
if (error instanceof FiscApiError) {
console.error('Code:', error.code); // 'VALIDATION_ERROR'
console.error('Message:', error.message);
console.error('Status:', error.status); // 422
console.error('Details:', error.details);
// Codes d'erreur possibles
switch (error.code) {
case 'VALIDATION_ERROR':
// Payload invalide
break;
case 'INSUFFICIENT_CREDITS':
// Pas assez de crédits
break;
case 'NORMALIZATION_ERROR':
// Erreur e-MCF (rejet DGI)
break;
case 'UNAUTHORIZED':
// Clé API invalide
break;
}
}
}🛠 Utilitaires
Calculer la TVA (synchrone)
// Calculer à partir du TTC
const result = fiscapi.taxGroups.calculateVat(11800, 'B', 'TTC');
console.log(result); // { ht: 10000, tax: 1800, ttc: 11800 }
// Calculer à partir du HT
const result2 = fiscapi.taxGroups.calculateVat(10000, 'B', 'HT');
console.log(result2); // { ht: 10000, tax: 1800, ttc: 11800 }
// Exonéré
const result3 = fiscapi.taxGroups.calculateVat(50000, 'A', 'TTC');
console.log(result3); // { ht: 50000, tax: 0, ttc: 50000 }Vérifier les crédits
const balance = await fiscapi.credits.getBalance();
console.log(`Crédits: ${balance.available}/${balance.total}`);
if (balance.isLow) {
console.warn('Solde bas ! Rechargez vos crédits.');
}
// Vérifier avant un batch
const canProcess = await fiscapi.credits.hasSufficientBalance(100);Vérifier la connexion
const isHealthy = await fiscapi.ping();
if (!isHealthy) {
console.error('API FiscAPI indisponible');
}Lister les factures avec pagination
const { data: invoices, count } = await fiscapi.invoices.list({
limit: 20,
status: 'CONFIRMED'
});
console.log(`${count} factures trouvées`);
invoices.forEach(inv => console.log(inv.uid, inv.status));⚙️ Configuration avancée
const fiscapi = new FiscApi({
apiKey: process.env.FISCAPI_API_KEY!,
baseUrl: 'https://api.fiscapi.com', // Optionnel
timeout: 30000, // Optionnel (ms)
});🔄 Polling (attente de confirmation)
// Attendre qu'une facture soit confirmée
const confirmed = await fiscapi.invoices.waitForConfirmation('clx123abc', {
maxAttempts: 30, // Défaut: 30
intervalMs: 1000, // Défaut: 1000ms
});📚 API Reference
fiscapi.invoices
| Méthode | Description |
|---------|-------------|
| create(payload) | Créer et normaliser une facture |
| createDraft(payload) | Créer un brouillon |
| get(id) | Récupérer une facture |
| list(filters?) | Lister les factures (paginé) |
| normalize(id) | Normaliser un brouillon |
| refund(id, reason?) | Avoir total |
| refundPartial(id, options) | Avoir partiel |
| isConfirmed(id) | Vérifier si confirmée |
| waitForConfirmation(id, options?) | Polling |
| getPdfUrl(id) | URL du PDF |
fiscapi.credits
| Méthode | Description |
|---------|-------------|
| getBalance() | Solde de crédits |
| hasSufficientBalance(n) | Vérifier solde suffisant |
| listPacks() | Packs disponibles |
fiscapi.fiscalProfiles
| Méthode | Description |
|---------|-------------|
| list() | Lister les profils |
| get(id) | Récupérer un profil |
| hasValidToken(id) | Token e-MCF valide ? |
fiscapi.taxGroups
| Méthode | Description |
|---------|-------------|
| list() | Tous les groupes |
| get(code) | Infos d'un groupe |
| calculateVat(amount, taxGroup, mode) | Calculer TVA |
🧪 Tests effectués
Le SDK a été testé avec succès pour :
- ✅ Facture de Vente simple (FV)
- ✅ Facture multi-lignes avec TVA mixte
- ✅ Facture avec AIB (1% et 5%)
- ✅ Facture d'Exportation (EV)
- ✅ Création et normalisation de brouillons
- ✅ Avoir total (FA) avec code MECeF
- ✅ Mode de tarification HT et TTC
- ✅ Calculs TVA synchrones
🆘 Support
- 📖 Documentation: https://fiscapi.com/developers
- 📧 Email: [email protected]
- 🖥️ Dashboard: https://fiscapi.com/dashboard
📄 Licence
MIT
