Certifier une facture
Certifie une facture de façon synchrone : la réponse HTTP contient directement la signature, le QR code et l’horodatage. Aucun callback ni polling.
Authentification : clé API — voir Authentification.
Endpoint
URL : POST /api/v1/invoices/certify
Hôte : votre TCC Server (ex. http://localhost:23109 en local, ou https://<votre-serveur> via reverse proxy en production)
POST http://localhost:23109/api/v1/invoices/certify
Content-Type: application/json
Authorization: ApiKey ak_votre_cle_iciCorps de la requête
Les champs sont en camelCase (ex.
invoiceId,recipientType).
Identification de la facture
| Champ | Type | Obligatoire | Contraintes / Description |
|---|---|---|---|
invoiceId | string | ✅ | Max 23 caractères, unique. Un ID déjà certifié est rejeté (409). |
invoiceType | string | ✅ | salesInvoice ou creditNote. |
invoiceSubject | string | ❌ | Objet de la facture. |
invoiceDueDate | string | ❌ | Format YYYY-MM-DD. |
referenceInvoiceId | string | Conditionnel | Max 23. Obligatoire si invoiceType = creditNote (facture d’origine). |
Destinataire
| Champ | Type | Obligatoire | Contraintes |
|---|---|---|---|
recipientType | string | ✅ | individual, business, government, foreign (détermine les champs obligatoires). |
recipientName | string | Conditionnel | Nom ou raison sociale. |
recipientNiu | string | Conditionnel | Exactement 16 ou 17 caractères. |
recipientAddress | string | Conditionnel | Max 250. |
recipientPhone | string | Conditionnel | Format Congo ou E.164. |
recipientEmail | string | Conditionnel | Email valide. |
isRecipientTaxable | boolean | ✅ | true / false. |
Montants
Tous de type number (décimal, précision 15, échelle 2) et obligatoires — envoyez 0 si non applicable.
| Champ | Description |
|---|---|
subtotal | Sous-total HT (= somme des netAmount des items). |
totalTaxTAmount | TVA au taux normal [T] (18%). |
totalTaxRAmount | TVA au taux réduit [R] (5%). |
totalExemptAmount | Montant total exonéré. |
totalTaxAmount | Total de la TVA. |
discountAmount | Escompte — remise globale (niveau facture). |
totalLineDiscountAmount | Somme des remises de tous les items (Σ items[].discountAmount). |
additionalCentTax | Taxe additionnelle (centimes). |
electronicStampDuty | Droit de timbre électronique — doit être 0 (non calculé par le contribuable). |
totalAmount | Montant total TTC. |
amountDue | Montant restant dû. |
discountAmount (Escompte) et totalLineDiscountAmount (Total Remises) sont deux remises distinctes, affichées sur deux lignes séparées de la facture. totalLineDiscountAmount doit être la somme des remises de tous les items (Σ items[].discountAmount), pas celle d’un seul item.
Paiement
| Champ | Type | Obligatoire | Contraintes |
|---|---|---|---|
currency | string | ✅ | XAF, USD ou EUR. |
paymentMethod | string | ✅ | bank_transfer, card, cash, mobile_money, cheque. |
paymentReference | string | ❌ | Max 100. |
paymentDate | string | ❌ | Format YYYY-MM-DDTHH:mm:ss. |
Vendeur & références (optionnels)
sellerAddress, sellerTaxRegime, sellerBankIban, sellerBankRib, cashierName, logoImg, sciet, externalCreditNoteNumber, originalSfecInvoiceNumber, notes.
Lignes (items) — minimum 1
| Champ | Type | Obligatoire | Contraintes |
|---|---|---|---|
designation | string | ✅ | Max 500. |
classificationCode | string | ❌ | Max 20. |
type | string | ✅ | product ou service. |
unitPrice | number | ✅ | ≥ 0.01. |
quantity | number | ✅ | ≥ 0.001 (3 décimales max). |
subtotal | number | ✅ | = unitPrice × quantity. |
discountAmount | number | ✅ | ≥ 0. |
discountType | string | ✅ | fixed ou percentage. |
netAmount | number | ✅ | = subtotal − discountAmount. |
taxRate | string | ✅ | Max 10 (ex. "19.25", "0" pour exonéré). |
taxAmount | number | ✅ | Montant de la taxe calculée. |
totalAmount | number | ✅ | = netAmount + taxAmount. |
Taxes additionnelles (additionalTaxes, optionnel)
| Champ | Type | Obligatoire |
|---|---|---|
taxCode | string | ✅ |
taxLabel | string | ❌ |
taxAmount | number | ✅ |
taxRate | number | ❌ |
Validation
Champs destinataire obligatoires par type
| Champ | individual | business | government | foreign |
|---|---|---|---|---|
recipientName | Optionnel | Obligatoire | Obligatoire | Obligatoire |
recipientNiu | Optionnel | Obligatoire | Obligatoire | Optionnel |
recipientPhone | Optionnel | Obligatoire | Obligatoire | Obligatoire |
recipientEmail | Optionnel | Obligatoire | Obligatoire | Obligatoire |
recipientAddress | Optionnel | Obligatoire | Obligatoire | Obligatoire |
Même optionnel, un champ fourni doit respecter son format. NIU : 16–17 caractères · Téléphone Congo : +242 0[4-6]XXXXXXX ou 0[4-6]XXXXXXX · International : E.164 · Montants : précision 15, échelle 2 · Quantités : précision 10, échelle 3.
Énumérations
invoiceType:salesInvoice,creditNoterecipientType:individual,business,government,foreignpaymentMethod:bank_transfer,card,cash,mobile_money,chequetype(items) :product,servicediscountType:fixed,percentage
Réponse — 200 OK
{
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"invoiceId": "FAC-2026-001234",
"certificationStatus": "certified",
"certificationDate": "2026-04-24T14:30:45.123",
"certificationSignature": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
"certificationShortSignature": "A1B2C3D4E5F6A1B2C3D4",
"certificationQrCode": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...",
"message": "Invoice certified successfully"
}| Champ | Description |
|---|---|
id | UUID interne attribué par le TCC Server. |
certificationSignature | Signature complète (64 hexadécimaux, HMAC-SHA256). |
certificationShortSignature | Signature abrégée (20 hexadécimaux) — à imprimer. |
certificationQrCode | QR code (Data URL PNG 200×200) — à imprimer. |
certificationDate | Horodatage NTP (ISO 8601) — à imprimer. |
À imprimer sur la facture : certificationShortSignature, certificationQrCode et certificationDate.
Codes d’erreur
| Code | error | Signification |
|---|---|---|
200 | — | Certification réussie. |
400 | validation_error | Données invalides (détails dans errors[]). |
400 | invalid_request | Corps de requête mal formé. |
401 | unauthorized | Clé API absente ou invalide. |
404 | not_found | Facture introuvable. |
409 | duplicate | Facture déjà certifiée — ne pas re-soumettre (émettre un avoir). |
500 | internal_error | Erreur interne — réessayer après quelques secondes. |
Exemple d’erreur de validation :
{
"error": "validation_error",
"message": "Validation failed",
"errors": [
{ "field": "invoiceId", "message": "Invoice ID is required" },
{ "field": "items[0].subtotal", "message": "Item subtotal is incoherent" }
]
}Exemple — vente à une entreprise
curl -X POST http://localhost:23109/api/v1/invoices/certify \
-H "Content-Type: application/json" \
-H "Authorization: ApiKey ak_votre_cle_ici" \
-d '{
"invoiceId": "FAC-2026-001234",
"invoiceType": "salesInvoice",
"recipientType": "business",
"recipientName": "Société XYZ SARL",
"recipientNiu": "M202600001234567",
"recipientAddress": "123 Avenue de la Paix, Brazzaville",
"recipientPhone": "+24206XXXXXXX",
"recipientEmail": "comptabilite@xyz-sarl.cg",
"isRecipientTaxable": true,
"subtotal": 1000000.00,
"totalTaxTAmount": 192500.00,
"totalTaxRAmount": 0.00,
"totalExemptAmount": 0.00,
"totalTaxAmount": 192500.00,
"discountAmount": 0.00,
"totalLineDiscountAmount": 0.00,
"additionalCentTax": 0.00,
"electronicStampDuty": 0.00,
"totalAmount": 1192500.00,
"amountDue": 1192500.00,
"currency": "XAF",
"paymentMethod": "bank_transfer",
"items": [
{
"designation": "Ramettes de papier A4 (carton de 5)",
"type": "product",
"unitPrice": 25000.00,
"quantity": 20.000,
"subtotal": 500000.00,
"discountAmount": 0.00,
"discountType": "fixed",
"netAmount": 500000.00,
"taxRate": "19.25",
"taxAmount": 96250.00,
"totalAmount": 596250.00
}
]
}'Étape suivante → Consulter les factures