Nouvel onglet Paramètres > API externe (admin) : état de l'API, adresse, création d'une clé nommée par outil (affichée une seule fois), liste avec dernière utilisation, révocation immédiate. - table external_api_keys (empreinte SHA-256 uniquement), créée par migrations.production.ts et init.sql - l'API accepte les clés de Paramètres et toujours celles de EXTERNAL_API_KEYS ; 503 seulement si aucune clé active - routes /api/external-api/keys (session + admin) - documentation et .env.example mis à jour Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JrRFddV2BaqDCxGY1j52UJ
6.6 KiB
API externe — Rapprochement BL / factures
Permet à un outil tiers (logiciel comptable, n8n, script…) de lire les magasins, les fournisseurs et les livraisons livrées avec leur numéro de BL, puis d'écrire la référence et le montant de la facture, comme dans la page Rapprochement.
Code : server/externalApi.ts. Préfixe : /api/ext/v1.
Activation et authentification
Depuis LogiFlow (recommandé) : Paramètres > API externe (admin). On y
crée une clé par outil (nommée, ex. « n8n comptabilité »), affichée une seule
fois à sa création, avec sa date de dernière utilisation ; une clé se révoque
d'un clic, sans redémarrage. Seule l'empreinte SHA-256 de la clé est stockée
(table external_api_keys). L'onglet s'ouvre directement par
/utilities?tab=api.
Par l'environnement (optionnel) : des clés peuvent aussi être définies, séparées par des virgules, puis le serveur redémarré :
EXTERNAL_API_KEYS=3f9c…a1,7b20…e4
Générer une clé :
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
Aucune clé active (ni dans Paramètres, ni dans l'environnement) : l'API répond
503 (désactivée).
Chaque requête envoie la clé dans l'un de ces en-têtes :
X-API-Key: <clé>
Authorization: Bearer <clé>
Clé absente ou fausse : 401. Une clé donne accès à tous les magasins ;
pour révoquer un outil, retirer sa clé de la liste et redémarrer.
Exposer l'API uniquement en HTTPS (la clé circule dans chaque requête).
Points d'accès
GET /stores — magasins
[{ "id": 1, "name": "Magasin Nancy" }]
GET /suppliers — fournisseurs
[{ "id": 4, "name": "Lactalis", "code": "LAC01", "paymentMethod": "Virement", "automaticReconciliation": false }]
code = code fournisseur (codefou).
GET /deliveries — livraisons à rapprocher
Seules les livraisons livrées sont renvoyées (même périmètre que la page Rapprochement), de la plus récente à la plus ancienne.
| Paramètre | Exemple | Effet |
|---|---|---|
storeId |
1 |
Un seul magasin |
supplierId |
4 |
Un seul fournisseur |
blNumber |
BL-4567 |
N° de BL exact (casse et espaces de bord ignorés) |
reconciled |
false |
true = rapprochées, false = en attente |
hasBl |
true |
Avec / sans numéro de BL |
hasInvoice |
false |
Avec / sans référence facture |
from, to |
2026-10-01 |
Bornes incluses sur la date de livraison (sinon date prévue) |
limit |
100 |
Taille de page, 100 par défaut, 500 maximum |
offset |
0 |
Décalage de pagination |
Paramètre mal formé : 400 avec la liste des paramètres fautifs.
{
"total": 1,
"limit": 100,
"offset": 0,
"items": [
{
"id": 812,
"storeId": 1,
"storeName": "Magasin Nancy",
"supplierId": 4,
"supplierName": "Lactalis",
"supplierCode": "LAC01",
"automaticReconciliation": false,
"status": "delivered",
"scheduledDate": "2026-10-08",
"deliveredDate": "2026-10-08T07:42:00.000Z",
"blNumber": "BL-4567",
"blAmount": 1234.5,
"invoiceReference": null,
"invoiceAmount": null,
"invoiceAmountTTC": null,
"dueDate": null,
"reconciled": false,
"validatedAt": null,
"updatedAt": "2026-10-08T07:42:00.000Z"
}
]
}
Montants en nombres (euros), dates YYYY-MM-DD, horodatages ISO 8601 UTC.
GET /deliveries/:id — une livraison
Même objet qu'un élément de items. Inconnue : 404.
PATCH /deliveries/:id — écrire la facture
Tous les champs sont facultatifs, au moins un est requis ; tout autre champ est refusé.
| Champ | Type | Effet |
|---|---|---|
invoiceReference |
texte (100 car.) / null | Référence facture ; null ou "" l'efface |
invoiceAmount |
nombre / texte / null | Montant HT. Accepte 1234.5, "1234,50", "1 234,50" |
invoiceAmountTTC |
nombre / texte / null | Montant TTC, mêmes formats |
dueDate |
YYYY-MM-DD / null |
Échéance. Si absente et que la référence change, elle est reprise de NocoDB comme dans le webUI |
reconciled |
booléen | true valide le rapprochement, false le dévalide |
curl -X PATCH https://logiflow.example/api/ext/v1/deliveries/812 \
-H "X-API-Key: $LOGIFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"invoiceReference":"FAC-2026-0042","invoiceAmount":"1234,50"}'
Réponse : la livraison mise à jour.
Règles :
- livraison non livrée :
409; - livraison déjà rapprochée : sa facture est figée (
409). Envoyer"reconciled": falsedans la même requête pour la dévalider et la modifier ; - exception, fournisseur en rapprochement automatique
(
automaticReconciliation: true) : la livraison est validée d'office dès la saisie du BL, sa facture (référence, montants, échéance) se complète ensuite directement, sans la dévalider ; elle reste validée ; - corps invalide :
400avec le détail par champ.
Exemple : rapprocher une facture reçue
GET /suppliers→ retrouver l'iddu fournisseur via soncode.GET /deliveries?supplierId=4&blNumber=BL-4567→ récupérer l'idde la livraison.PATCH /deliveries/812avecinvoiceReferenceetinvoiceAmount(ajouter"reconciled": truepour valider directement).
Exemple : compléter la facture d'un fournisseur automatique
Les livraisons d'un fournisseur en rapprochement automatique sont déjà
validées (reconciled: true) ; la facture s'y ajoute sans autre champ :
curl -X PATCH https://logiflow.example/api/ext/v1/deliveries/815 \
-H "X-API-Key: $LOGIFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"invoiceReference":"FAC-2026-0057","invoiceAmount":"842,10","invoiceAmountTTC":"1010,52","dueDate":"2026-11-30"}'
Pour les retrouver : GET /deliveries?supplierId=<id auto>&hasInvoice=false.