« sendToPhone » à la création, ou POST /send avec channel « whatsapp » : le PDF part dans la conversation du client, au nom du commerçant.
Votre logiciel facture. Fatora s’occupe du reste.
Votre SaaS, votre CRM ou votre application métier n’a pas de module de facturation marocaine ? Un bouton chez vous, un appel HTTP chez nous : Fatora émet la facture ou le devis dans la numérotation du commerçant, avec son cachet, son logo et toutes les mentions de l’article 145 CGI — PDF à l’appui, remis par WhatsApp, par email ou par QR code.
- Factures et devis conformes DGI : ICE, IF, TVA ventilée, montant en toutes lettres, séquence continue
- Remise au choix : WhatsApp, email, ou QR code à imprimer — le client scanne et télécharge
- Modification en langage libre : écrivez le changement, l’IA l’applique
- Logo, cachet et informations société pilotables par API
Obtenir sa clé API
- 1Le commerçant ouvre sa conversation WhatsApp Fatora-Bot
- 2Il écrit simplement « api »
- 3Le bot répond avec sa clé personnelle (fk_…) — à coller dans votre application
La clé est propre à chaque commerçant et incluse dans son abonnement, dès l’essai gratuit. « api reset » la régénère à tout moment (l’ancienne est révoquée). Les factures émises par l’API consomment le quota du plan ; les devis sont gratuits et illimités.
Démarrage en 5 minutes
Une seule requête suffit pour émettre un document. Le prix est hors taxe par défaut ; passez « priceIsTtc »: true si vos montants sont TTC — Fatora reconstitue la base.
curl -X POST https://bot.swiviq.com/v1/documents \
-H "Authorization: Bearer fk_votre_cle" \
-H "Content-Type: application/json" \
-d '{
"type": "invoice",
"client": { "name": "ATLAS DIGITAL SARL", "ice": "001122334455667", "type": "company" },
"items": [
{ "description": "Abonnement CRM — pack annuel", "quantity": 1, "unitPrice": 4800 },
{ "description": "Formation équipe (2 jours)", "quantity": 2, "unitPrice": 1500 }
],
"sendToEmail": "client@exemple.ma"
}'{
"number": "FAT-2026-0042",
"type": "invoice",
"status": "issued",
"issueDate": "2026-08-15",
"client": { "name": "ATLAS DIGITAL SARL", "ice": "001122334455667", "type": "company" },
"items": [
{ "description": "Abonnement CRM — pack annuel", "quantity": 1, "unitPrice": 4800, "vatRate": 20 },
{ "description": "Formation équipe (2 jours)", "quantity": 2, "unitPrice": 1500, "vatRate": 20 }
],
"totals": { "ht": 7800, "vat": 1560, "ttc": 9360, "currency": "MAD" },
"pdfUrl": "https://bot.swiviq.com/f/a1b2c3d4e5",
"qrcodeUrl": "https://bot.swiviq.com/qr/a1b2c3d4e5.png",
"whatsapp": { "owner": "sent", "client": "skipped" },
"email": { "client": "sent" }
}La modification en langage libre
Aucun schéma de patch à apprendre. Votre utilisateur tape sa correction dans un champ texte, vous nous la transmettez telle quelle — le même moteur d’IA qui comprend les commerçants en darija sur WhatsApp la décode et l’applique.
curl -X POST https://bot.swiviq.com/v1/documents/FAT-2026-0042/modify \
-H "Authorization: Bearer fk_votre_cle" \
-H "Content-Type: application/json" \
-d '{
"instruction": "le client est en fait STE ATLAS DIGITAL MAROC SARL,
et remplace la formation par 3 jours à 1200 dh le jour"
}'{
"number": "FAT-2026-0042",
"client": { "name": "STE ATLAS DIGITAL MAROC SARL", "ice": "001122334455667", "type": "company" },
"items": [
{ "description": "Abonnement CRM — pack annuel", "quantity": 1, "unitPrice": 4800, "vatRate": 20 },
{ "description": "Formation équipe", "quantity": 3, "unitPrice": 1200, "vatRate": 20 }
],
"totals": { "ht": 8400, "vat": 1680, "ttc": 10080, "currency": "MAD" },
"pdfUrl": "https://bot.swiviq.com/f/a1b2c3d4e5",
"applied": "le client est en fait STE ATLAS DIGITAL MAROC SARL, et remplace…"
}Le document garde son numéro (aucun trou dans la séquence), le PDF est régénéré, les totaux recalculés. Si l’instruction est incompréhensible, l’API répond 422 avec une explication — jamais de modification hasardeuse.
Remise au client : WhatsApp, email ou QR code
Émettre ne suffit pas — il faut que le client final reçoive son document. Trois canaux, cumulables, réutilisables à volonté : une facture perdue se renvoie en un appel.
« sendToEmail » à la création, ou channel « email » : le client reçoit un message soigné avec la facture en pièce jointe — le même gabarit que le bot.
QR code
Chaque document expose « qrcodeUrl » : un PNG à afficher en caisse, imprimer sur un ticket ou intégrer dans votre interface. Le client scanne, la facture se télécharge.
curl -X POST https://bot.swiviq.com/v1/documents/FAT-2026-0042/send \
-H "Authorization: Bearer fk_votre_cle" \
-H "Content-Type: application/json" \
-d '{ "channel": "email", "to": "client@exemple.ma" }'{ "ok": true, "number": "FAT-2026-0042",
"channel": "email", "to": "client@exemple.ma", "status": "sent" }Référence des endpoints
✓ Chaque exemple ci-dessous a été rejoué tel quel contre l’API de production le 15/08/2026 — les réponses affichées sont les vraies.
/v1/documentsÉmettre une facture ou un devis
« type »: « invoice » (défaut) ou « quote ». Options : « priceIsTtc », « vatRate » par ligne ou global, « sendToPhone » et « sendToEmail » pour la remise immédiate au client final, « notify »: false pour ne pas prévenir le commerçant. Réponse 201 avec numéro, totaux, lien PDF et QR code.
Voir l’exemple testé
curl -X POST https://bot.swiviq.com/v1/documents \
-H "Authorization: Bearer fk_votre_cle" \
-H "Content-Type: application/json" \
-d '{
"type": "invoice",
"client": { "name": "ATLAS DIGITAL SARL", "ice": "001122334455667", "type": "company" },
"items": [
{ "description": "Abonnement CRM — pack annuel", "quantity": 1, "unitPrice": 4800 },
{ "description": "Formation équipe (2 jours)", "quantity": 2, "unitPrice": 1500 }
],
"sendToEmail": "client@exemple.ma"
}'{
"number": "FAT-2026-0042",
"type": "invoice",
"status": "issued",
"issueDate": "2026-08-15",
"client": { "name": "ATLAS DIGITAL SARL", "ice": "001122334455667", "type": "company" },
"items": [
{ "description": "Abonnement CRM — pack annuel", "quantity": 1, "unitPrice": 4800, "vatRate": 20 },
{ "description": "Formation équipe (2 jours)", "quantity": 2, "unitPrice": 1500, "vatRate": 20 }
],
"totals": { "ht": 7800, "vat": 1560, "ttc": 9360, "currency": "MAD" },
"pdfUrl": "https://bot.swiviq.com/f/a1b2c3d4e5",
"qrcodeUrl": "https://bot.swiviq.com/qr/a1b2c3d4e5.png",
"whatsapp": { "owner": "sent", "client": "skipped" },
"email": { "client": "sent" }
}/v1/documents/{number}/modifyModifier en langage libre
Le corps ne contient qu’une « instruction » en texte libre (français, darija ou anglais). Même numéro, PDF régénéré, champ « applied » qui confirme l’instruction comprise.
Voir l’exemple testé
curl -X POST https://bot.swiviq.com/v1/documents/FAT-2026-0042/modify \
-H "Authorization: Bearer fk_votre_cle" \
-H "Content-Type: application/json" \
-d '{
"instruction": "le client est en fait STE ATLAS DIGITAL MAROC SARL,
et remplace la formation par 3 jours à 1200 dh le jour"
}'{
"number": "FAT-2026-0042",
"client": { "name": "STE ATLAS DIGITAL MAROC SARL", "ice": "001122334455667", "type": "company" },
"items": [
{ "description": "Abonnement CRM — pack annuel", "quantity": 1, "unitPrice": 4800, "vatRate": 20 },
{ "description": "Formation équipe", "quantity": 3, "unitPrice": 1200, "vatRate": 20 }
],
"totals": { "ht": 8400, "vat": 1680, "ttc": 10080, "currency": "MAD" },
"pdfUrl": "https://bot.swiviq.com/f/a1b2c3d4e5",
"applied": "le client est en fait STE ATLAS DIGITAL MAROC SARL, et remplace…"
}/v1/documents/{number}/sendRemettre ou renvoyer un document
{ « channel »: « whatsapp » | « email », « to »: numéro ou adresse }. Le PDF est régénéré s’il a disparu — réutilisable autant de fois que nécessaire.
Voir l’exemple testé
curl -X POST https://bot.swiviq.com/v1/documents/FAT-2026-0042/send \
-H "Authorization: Bearer fk_votre_cle" \
-H "Content-Type: application/json" \
-d '{ "channel": "email", "to": "client@exemple.ma" }'{ "ok": true, "number": "FAT-2026-0042",
"channel": "email", "to": "client@exemple.ma", "status": "sent" }/qr/{token}.pngQR code de téléchargement (public)
Le PNG du QR pointant vers le PDF. Sans authentification : le jeton est le secret. À intégrer directement dans une balise <img> ou à imprimer sur un ticket de caisse.
Voir l’exemple testé
<!-- directement dans votre page --> <img src="https://bot.swiviq.com/qr/a1b2c3d4e5.png" width="180" alt="QR facture"> # ou en téléchargement curl -o facture-qr.png https://bot.swiviq.com/qr/a1b2c3d4e5.png
HTTP 200 — image/png, 600 × 600 px Cache-Control: public, max-age=86400, immutable
/v1/documentsLister les documents
Les derniers documents émis, du plus récent au plus ancien. « limit » jusqu’à 50, « type » pour filtrer factures (« invoice ») ou devis (« quote »).
Voir l’exemple testé
curl -H "Authorization: Bearer fk_votre_cle" \ "https://bot.swiviq.com/v1/documents?limit=5&type=invoice"
[
{
"number": "FAT-2026-0042",
"type": "invoice",
"status": "issued",
"issueDate": "2026-08-15",
"client": { "name": "STE ATLAS DIGITAL MAROC SARL", "ice": "001122334455667" },
"totals": { "ht": 8400, "vat": 1680, "ttc": 10080, "currency": "MAD" },
"pdfUrl": "https://bot.swiviq.com/f/a1b2c3d4e5",
"qrcodeUrl": "https://bot.swiviq.com/qr/a1b2c3d4e5.png"
},
{ "number": "FAT-2026-0041", "...": "..." }
]/v1/documents/{number}Lire un document
Lignes, totaux, lien PDF, QR code — pratique pour afficher l’état dans votre interface ou vérifier une modification.
Voir l’exemple testé
curl -H "Authorization: Bearer fk_votre_cle" \ https://bot.swiviq.com/v1/documents/FAT-2026-0042
{
"number": "FAT-2026-0042",
"type": "invoice",
"status": "issued",
"issueDate": "2026-08-15",
"client": { "name": "STE ATLAS DIGITAL MAROC SARL", "ice": "001122334455667", "type": "company" },
"items": [
{ "description": "Abonnement CRM — pack annuel", "quantity": 1, "unitPrice": 4800, "vatRate": 20 },
{ "description": "Formation équipe", "quantity": 3, "unitPrice": 1200, "vatRate": 20 }
],
"totals": { "ht": 8400, "vat": 1680, "ttc": 10080, "currency": "MAD" },
"pdfUrl": "https://bot.swiviq.com/f/a1b2c3d4e5",
"qrcodeUrl": "https://bot.swiviq.com/qr/a1b2c3d4e5.png"
}/v1/accountCompte et quota
Profil société, plan actif, quota consommé/restant. C’est aussi le moyen le plus simple de tester qu’une clé est valide.
Voir l’exemple testé
curl -H "Authorization: Bearer fk_votre_cle" \ https://bot.swiviq.com/v1/account
{
"company": {
"name": "ATLAS SERVICES SARL", "ice": "002233445566778",
"address": "Agdal, Rabat", "defaultVatRate": 20,
"taxRegime": "normal", "hasLogo": true, "hasStamp": true
},
"plan": { "key": "p100", "label": "100 factures / mois", "priceMAD": 90 },
"quota": { "used": 12, "limit": 100, "remaining": 88, "ok": true }
}/v1/companyMettre à jour la société
Champs acceptés : companyName, ice, if, taxePro, rc, address, email, defaultVatRate, paymentTerms. Seuls les champs envoyés sont modifiés.
Voir l’exemple testé
curl -X PUT https://bot.swiviq.com/v1/company \
-H "Authorization: Bearer fk_votre_cle" \
-H "Content-Type: application/json" \
-d '{
"address": "12 rue Oued Fès, Agdal, Rabat",
"paymentTerms": "Virement à 30 jours"
}'{
"ok": true,
"company": {
"name": "ATLAS SERVICES SARL", "ice": "002233445566778",
"address": "12 rue Oued Fès, Agdal, Rabat", "defaultVatRate": 20
}
}/v1/company/logoEnvoyer le logo
Corps : { « image »: « <base64 ou data-URI png/jpeg> » } (6 Mo max). Le logo est nettoyé et recadré automatiquement, puis apposé sur les prochains PDF.
Voir l’exemple testé
curl -X POST https://bot.swiviq.com/v1/company/logo \
-H "Authorization: Bearer fk_votre_cle" \
-H "Content-Type: application/json" \
-d "{ \"image\": \"data:image/png;base64,$(base64 -w0 logo.png)\" }"{ "ok": true, "logo": "saved",
"appliesTo": "toutes les prochaines factures" }/v1/company/stampEnvoyer le cachet
Même format que le logo. Le fond est supprimé par extraction d’encre (une photo du cachet sur papier suffit), puis le cachet est apposé sur chaque PDF.
Voir l’exemple testé
curl -X POST https://bot.swiviq.com/v1/company/stamp \
-H "Authorization: Bearer fk_votre_cle" \
-H "Content-Type: application/json" \
-d "{ \"image\": \"data:image/png;base64,$(base64 -w0 cachet.jpg)\" }"{ "ok": true, "stamp": "saved",
"appliesTo": "toutes les prochaines factures" }Codes d’erreur
Toute erreur renvoie un JSON à deux champs constants : « error » (code machine stable, à tester dans votre code) et « message » (explication en clair, affichable telle quelle). Le 402 ajoute « used », « limit » et « reason » pour construire votre propre écran de quota.
400 | Requête invalide | Codes : invalid_json (corps illisible), empty_body (corps vide — vérifiez qu’aucun retour à la ligne ne casse vos en-têtes), missing_client, missing_items, invalid_channel, invalid_phone, invalid_email, invalid_image. Le message dit exactement quel champ corriger. |
401 | Clé absente ou invalide | missing_api_key : ajoutez l’en-tête Authorization: Bearer fk_… · invalid_api_key : clé inconnue ou révoquée par « api reset » — redemandez-la au commerçant. |
402 | Quota du plan atteint | quota_exceeded : la réponse contient used/limit/reason. Les devis ne comptent pas. Le commerçant passe au plan supérieur en deux messages WhatsApp. |
403 | Compte suspendu | account_suspended : le compte du commerçant est suspendu — contactez contact@swiviq.com. |
404 | Document introuvable | not_found : aucun document à ce numéro pour CE compte — chaque clé ne voit que ses propres documents. |
409 | Document annulé | cancelled : le document a été annulé (avoir émis) — il ne peut plus être modifié ni renvoyé. Émettez-en un nouveau. |
413 | Corps trop volumineux | body_too_large : 8 Mo maximum — compressez le logo ou le cachet avant l’envoi. |
422 | Instruction incomprise | instruction_not_understood : l’IA n’a pas pu appliquer la modification sans risque — reformulez plus précisément. Rien n’a été modifié. |
429 | Trop de requêtes | rate_limited : 60 requêtes/minute par clé — espacez ou mettez en file d’attente, puis réessayez. |
500 | Erreur interne | internal : réessayez ; si l’erreur persiste, écrivez à contact@swiviq.com avec le corps de la réponse. |
HTTP 402
{
"error": "quota_exceeded",
"reason": "trial",
"used": 2,
"limit": 2,
"message": "Quota d'essai atteint (2 factures). Le commerçant peut passer
au plan supérieur depuis son WhatsApp Fatora."
}Questions d’intégration
Combien coûte l’API ?
Rien de plus que l’abonnement Fatora du commerçant, dès l’essai gratuit. Les factures API comptent dans le quota du plan comme celles dictées sur WhatsApp ; les devis sont gratuits et illimités.
Qui détient la clé : moi (l’éditeur) ou mon utilisateur ?
Chaque commerçant a sa propre clé, liée à son compte et à sa numérotation. Votre application stocke la clé que l’utilisateur colle — aucun compte central à gérer, chaque client paie son propre abonnement.
Les montants que j’envoie sont TTC — comment faire ?
Ajoutez « priceIsTtc »: true. Fatora reconstitue la base hors taxe en divisant par un plus le taux, ligne par ligne.
Le commerçant est auto-entrepreneur, sans TVA ?
Son régime fiscal est enregistré dans son compte et s’impose à l’API : quoi que votre application envoie, ses documents sortent sans TVA, avec la mention adaptée.
Que se passe-t-il quand le quota est atteint ?
L’API répond 402 avec used, limit et un message prêt à afficher. Le commerçant change de plan en deux messages WhatsApp.