Files
Apiflow/API_DOCUMENTATION.md
T

23 KiB

Documentation API Foirfouille

Base URL : https://api.ffnancy.fr Format : JSON Méthode : GET uniquement (API lecture seule) Données : Synchronisées depuis SQL Server chaque nuit à 3h00


Santé

GET /api/health
{ "status": "ok", "database": "foirfouille", "server": "postgres" }

Articles

Liste avec filtres

GET /api/articles
Paramètre Type Description Défaut
search string Recherche dans libellé —
codein string Code interne (partiel) —
ean string EAN / GTIN —
codefou string Code fournisseur (partiel) —
actif 1/0 1 = actif, 0 = suspendu —
page int Numéro de page 1
limit int Lignes par page (max 500) 50

Réponse :

{
  "page": 1,
  "limit": 50,
  "articles": [
    {
      "no_id": 12345,
      "codein": "ABC123",
      "libelle1": "MON ARTICLE",
      "libelle2": "SOUS-LIBELLE",
      "lib_ticket": "MON ART",
      "tax_code": "A",
      "ach_code": "X",
      "utilisable": "O",
      "actif": "O",
      "suspendu": null,
      "suividatecreation": "2020-01-15T00:00:00.000Z",
      "suividatemodif": "2024-06-01T00:00:00.000Z",
      "prix_vente_mini": 15.00,
      "prix_vente_maxi": 25.00,
      "eco_ttc": 0.10,
      "on_web": "O",
      "interdit_remise": null,
      "nomphoto": "ABC123.jpg",
      "datedebvente": null,
      "datefinvente": null,
      "pa": 10.50,
      "gtin": "3760000000001",
      "codefou_principal": "FOU01",
      "nom_fou_principal": "MON FOURNISSEUR",
      "ref_fou_principale": "REF-FOU-001",
      "pcb_principal": 6
    }
  ]
}

Détail d'un article

GET /api/articles/:id

Paramètre : id = no_id de l'article

Réponse :

{
  "article": { "no_id": 12345, "codein": "...", "libelle1": "...", "pa": 10.50, "..." : "..." },
  "gtins": [
    { "gtin": "3760000000001", "preferentiel": 1 }
  ],
  "stock": [
    { "site": "001", "qte": 12, "prmp": 10.20, "valstock": 122.40, "pv": 18.50, "stockdispo": 10 }
  ],
  "prix": [
    { "site": "001", "pv": 18.50 }
  ],
  "fournisseurs": [
    {
      "codefou": "FOU01", "nom_fou": "MON FOURNISSEUR",
      "reference": "REF-001", "ean13": "3760000000001",
      "pcb": 6, "delai": 7, "preference": 1,
      "prixachat": 10.50, "remise_promotion": 5.00
    }
  ]
}

Fiche complète (référentiel)

GET /api/articles/:id/referentiel

Retourne toutes les informations consolidées de l'article :

{
  "article": {
    "no_id": 12345, "codein": "ABC123", "libelle1": "MON ARTICLE",
    "prix_vente_mini": 15.00, "prix_vente_maxi": 25.00,
    "eco_ht": 0.08, "eco_ttc": 0.10,
    "on_web": "O", "pv_conseille": 19.90,
    "nom_code": "RAY01", "nom_libelle": "RAYON MAISON", "nom_niveau": 1
  },
  "gtins": [ { "gtin": "3760000000001", "preferentiel": 1 } ],
  "gammes": [
    { "gamme_code": "ETE2024", "gamme_libelle": "ÉTÉ 2024", "saison_code": "S24", "saison_libelle": "SAISON 2024" }
  ],
  "stock": [
    { "site": "001", "qte": 12, "prmp": 10.20, "valstock": 122.40, "pv": 18.50, "stockdispo": 10 }
  ],
  "stock_remballe": [],
  "prix": {
    "achat": 10.50,
    "vente_par_site": [ { "site": "001", "pv": 18.50 } ]
  },
  "fournisseurs": [
    { "codefou": "FOU01", "nom_fou": "MON FOURNISSEUR", "ref_fou": "REF-001", "pcb": 6, "prixachat": 10.50 }
  ],
  "performance": {
    "derniere_entree": "2024-05-10T00:00:00.000Z",
    "derniere_vente": "2024-06-15T00:00:00.000Z",
    "qte_totale_vendue": 248,
    "ca_ttc_total": 4588.00,
    "marge_totale": 1020.50
  },
  "notes": []
}

Mouvements d'un article

GET /api/articles/:id/mouvements
Paramètre Type Description Défaut
dateDebut date Date début YYYY-MM-DD 2000-01-01
dateFin date Date fin YYYY-MM-DD 2099-12-31
site string Filtrer par site (partiel) —
page int Numéro de page 1
limit int Lignes par page (max 1000) 100

Réponse :

{
  "page": 1, "limit": 100,
  "mouvements": [
    {
      "datmvt": "2024-06-15T00:00:00.000Z",
      "site": "001",
      "libmvt": "VENTE",
      "genremvt": 3,
      "qtemvt": 2,
      "mntmvtttc": 37.00,
      "margemvt": 8.20,
      "qtestock": 10
    }
  ]
}

Valeurs GenreMvt : 1 = entrée stock, 3 = vente


Fournisseurs

Liste des fournisseurs

GET /api/fournisseurs?search=
Paramètre Type Description
search string Recherche sur code/nom

Réponse :

{
  "count": 142,
  "fournisseurs": [
    {
      "codefou": "FOU01",
      "nom": "MON FOURNISSEUR SARL",
      "adresse": "1 RUE DE LA PAIX",
      "telephone": "0383000000",
      "email": "contact@fournisseur.fr",
      "nb_articles": 320,
      "nb_actifs": 285,
      "nb_suspendus": 35
    }
  ]
}

Articles d'un fournisseur

GET /api/fournisseurs/:code/articles?page=&limit=

Réponse :

{
  "code": "FOU01",
  "page": 1, "limit": 50,
  "articles": [
    {
      "no_id": 12345, "codein": "ABC123", "libelle1": "MON ARTICLE",
      "ref_fou": "REF-FOU-001", "ean13": "3760000000001",
      "pcb": 6, "delai": 7, "suspendu": null,
      "prixachat": 10.50, "remise_promotion": 5.00,
      "pa": 10.50, "pv_central": 18.50
    }
  ]
}

Commandes en cours d'un fournisseur

GET /api/fournisseurs/:code/commandes
Paramètre Type Description Défaut
dateDebut date Date début YYYY-MM-DD 2020-01-01
dateFin date Date fin YYYY-MM-DD 2099-12-31
page int Numéro de page 1
limit int Max 1000 100

Stock

Stock global

GET /api/stock?site=&page=&limit=
Paramètre Type Description Défaut
site string Filtrer par site tous
page int Numéro de page 1
limit int Max 1000 100

Stock d'un article (tous sites)

GET /api/stock/article/:id

Réponse :

{
  "artnoid": 12345,
  "stock": [
    {
      "site": "001",
      "qte": 12,
      "prmp": 10.20,
      "valstock": 122.40,
      "pv": 18.50,
      "stockdispo": 10,
      "stockmort": 0,
      "stockcolis": 2,
      "dernierevente": "2024-06-15T00:00:00.000Z",
      "dernierereception": "2024-05-10T00:00:00.000Z",
      "nbjoursdernierevente": 5,
      "interditachat": null,
      "codefou": "FOU01"
    }
  ]
}

Stock d'un article à une date précise

GET /api/stock/article/:id/historique?date=&site=

Retourne le stock tel qu'il était à une date donnée, en utilisant le champ QteStock enregistré dans chaque mouvement (valeur du stock au moment exact du mouvement).

Paramètre Type Description Défaut
date date Date cible YYYY-MM-DD aujourd'hui
site string Filtrer par site (partiel) tous

Réponse :

{
  "artNoId": "12345",
  "date": "2025-12-31",
  "stock": [
    {
      "site": "001",
      "qte": 28,
      "prmp": 10.20,
      "date_dernier_mouvement": "2025-12-29T00:00:00.000Z",
      "libelle_dernier_mouvement": "VENTE"
    }
  ]
}

Principe : on prend le dernier mouvement enregistré avant ou à la date demandée. Si aucun mouvement n'existe avant cette date, le site ne figure pas dans la réponse.


Stock + ventes d'un article sur une période

GET /api/stock/article/:id/periode?dateDebut=&dateFin=&site=

Endpoint principal pour analyser un article sur une période passée. Retourne en une seule requête : stock de début, stock de fin, ventes et réceptions.

Paramètre Type Description Défaut
dateDebut date Date début YYYY-MM-DD 1er du mois
dateFin date Date fin YYYY-MM-DD aujourd'hui
site string Filtrer par site (partiel) tous

Réponse :

{
  "artNoId": "12345",
  "dateDebut": "2025-12-01",
  "dateFin": "2025-12-31",
  "data": [
    {
      "site": "001",
      "stock_debut": {
        "qte": 45,
        "prmp": 10.20,
        "au": "2025-11-30T00:00:00.000Z"
      },
      "stock_fin": {
        "qte": 28,
        "prmp": 10.20,
        "au": "2025-12-29T00:00:00.000Z"
      },
      "ventes": {
        "site": "001",
        "nb_passages": 18,
        "qte_vendue": 17,
        "ca_ht": 274.00,
        "ca_ttc": 315.10,
        "marge": 72.00,
        "taux_marge": 22.86,
        "premiere_vente": "2025-12-02T00:00:00.000Z",
        "derniere_vente": "2025-12-29T00:00:00.000Z"
      },
      "receptions": {
        "site": "001",
        "nb_receptions": 1,
        "qte_recue": 0
      }
    }
  ]
}

Lecture : stock_debut = dernier mouvement avant dateDebut / stock_fin = dernier mouvement à ou avant dateFin. Les champs ventes et receptions sont null si aucun mouvement sur la période.


Stock d'un site (tous articles)

GET /api/stock/site/:site?page=&limit=

Valorisation du stock par site

GET /api/stock/valorisation

Réponse :

{
  "valorisation": [
    {
      "site": "001",
      "nb_articles": 4200,
      "qte_totale": 85000,
      "val_stock": 420000.00,
      "val_pv_theorique": 890000.00,
      "prmp_moyen": 12.50
    }
  ]
}

Commandes

Commandes en cours

GET /api/commandes
Paramètre Type Description Défaut
dateDebut date Date début YYYY-MM-DD 2020-01-01
dateFin date Date fin YYYY-MM-DD 2099-12-31
codefou string Filtrer par fournisseur —
page int Numéro de page 1
limit int Max 1000 100

Réponse :

{
  "page": 1, "limit": 100,
  "commandes": [
    {
      "no_commande": 98765,
      "codefou": "FOU01",
      "codein": "ABC123",
      "libelle": "MON ARTICLE",
      "ref_fou": "REF-001",
      "qte_cde": 24,
      "prix_brut": 12.00,
      "remise": 5.00,
      "prix_net": 11.40,
      "montant": 273.60,
      "qte_acceptee": 24,
      "qte_annulee": 0,
      "qte_attente": 0,
      "qte_reliquat": 0,
      "date_livraison_cible": "2024-07-01T00:00:00.000Z",
      "date_commande": "2024-06-01T00:00:00.000Z"
    }
  ]
}

Détail d'une commande

GET /api/commandes/:noCommande

Réponse :

{
  "noCommande": "98765",
  "nbLignes": 15,
  "montantTotal": 4250.80,
  "lignes": [ { "..." : "..." } ]
}

Liste des réceptions

GET /api/commandes/receptions/liste
Paramètre Type Description Défaut
dateDebut date Date début YYYY-MM-DD 2020-01-01
dateFin date Date fin YYYY-MM-DD 2099-12-31
page int Numéro de page 1
limit int Max 1000 100

Mouvements

Types de mouvements disponibles

GET /api/mouvements/types

Retourne tous les codes GenreMvt et libellés présents dans la base, avec leur nombre d'occurrences. À appeler en premier pour connaître les codes de régularisation propres à votre magasin.

{
  "types": [
    { "genremvt": 1, "libmvt": "RECEPTION",      "nb_occurrences": "142580" },
    { "genremvt": 3, "libmvt": "VENTE",           "nb_occurrences": "2130137" },
    { "genremvt": 2, "libmvt": "RETOUR CLIENT",   "nb_occurrences": "8420" },
    { "genremvt": 5, "libmvt": "REGULARISATION",  "nb_occurrences": "3210" },
    { "genremvt": 6, "libmvt": "INVENTAIRE",      "nb_occurrences": "1850" }
  ]
}

Les codes exacts dépendent de votre paramétrage Mercalys. Consultez cet endpoint pour connaître la liste réelle.


Mouvements articles (tous types)

GET /api/mouvements/articles
Paramètre Type Description Défaut
dateDebut date Date début YYYY-MM-DD 2024-01-01
dateFin date Date fin YYYY-MM-DD 2099-12-31
site string Filtrer par site —
codefou string Filtrer par fournisseur —
genremvt int Filtrer par type (ex: 1, 3, 5...) tous
page int Numéro de page 1
limit int Max 1000 100

Types principaux GenreMvt :

Code Type
1 Entrée stock
3 Vente
autres Régularisations (voir /api/mouvements/types)

Entrées en stock

GET /api/mouvements/entrees

Toutes les réceptions / entrées en stock (GenreMvt = 1). Inclut la date de création de l'article pour retrouver la première entrée.

Paramètre Type Description Défaut
dateDebut date Date début YYYY-MM-DD 2024-01-01
dateFin date Date fin YYYY-MM-DD 2099-12-31
site string Filtrer par site —
artNoId int Filtrer sur un article précis —
page int Numéro de page 1
limit int Max 1000 100

Réponse :

{
  "page": 1, "limit": 100,
  "entrees": [
    {
      "date_entree": "2025-12-10T00:00:00.000Z",
      "site": "001",
      "artnoid": 12345,
      "codein": "ABC123",
      "libelle1": "MON ARTICLE",
      "date_creation_article": "2020-03-15T00:00:00.000Z",
      "libelle_mouvement": "RECEPTION",
      "qte_entree": 24,
      "prmp": 10.20,
      "stock_apres_entree": 36,
      "codefou": "FOU01"
    }
  ]
}

Pour trouver la première entrée d'un article : filtrez par artNoId avec dateDebut=2000-01-01 et triez par date croissante (la première ligne = première réception).


Régularisations de stock

GET /api/mouvements/regularisations

Tous les mouvements hors ventes et hors réceptions : inventaires, corrections, démarques, transferts, retours, etc.

Paramètre Type Description Défaut
dateDebut date Date début YYYY-MM-DD 2024-01-01
dateFin date Date fin YYYY-MM-DD 2099-12-31
site string Filtrer par site —
artNoId int Filtrer sur un article précis —
page int Numéro de page 1
limit int Max 1000 100

Réponse :

{
  "page": 1, "limit": 100,
  "regularisations": [
    {
      "date_mouvement": "2025-12-05T00:00:00.000Z",
      "site": "001",
      "artnoid": 12345,
      "codein": "ABC123",
      "libelle1": "MON ARTICLE",
      "genremvt": 6,
      "libelle_mouvement": "INVENTAIRE",
      "qte": -3,
      "valeur": -30.60,
      "stock_apres": 42,
      "prmp": 10.20
    }
  ]
}

Une qte négative = sortie de stock (correction à la baisse, démarque…). Une qte positive = entrée hors réception (correction à la hausse, retour…).


Synthèse par jour et site

GET /api/mouvements/synthese?dateDebut=&dateFin=&site=

Réponse :

{
  "synthese": [
    {
      "jour": "2024-06-15",
      "site": "001",
      "genremvt": 3,
      "nb_mvt": 152,
      "qte_totale": 312,
      "mnt_ht": 4200.00,
      "mnt_ttc": 4830.00,
      "marge": 1050.00
    }
  ]
}

Performance

Chiffre d'affaires

GET /api/performance/ca
Paramètre Type Description Défaut
dateDebut date Date début YYYY-MM-DD 2024-01-01
dateFin date Date fin YYYY-MM-DD 2099-12-31
site string Filtrer par site tous
groupBy jour / mois Granularité jour

Réponse :

{
  "groupBy": "mois",
  "dateDebut": "2024-01-01",
  "dateFin": "2024-12-31",
  "site": "tous",
  "ca": [
    {
      "periode": "2024-06",
      "site": "001",
      "nb_ventes": 4820,
      "qte_vendue": 9640,
      "ca_ht": 85200.00,
      "ca_ttc": 97980.00,
      "marge": 21300.00,
      "taux_marge": 21.74
    }
  ]
}

Hit-parade articles

GET /api/performance/hitparade
Paramètre Type Description Défaut
dateDebut date Date début YYYY-MM-DD 2024-01-01
dateFin date Date fin YYYY-MM-DD 2099-12-31
site string Filtrer par site tous
limit int Nombre d'articles (max 500) 50
groupBy ca / qte / marge Critère de classement ca

Réponse :

{
  "classementPar": "ca",
  "hitparade": [
    {
      "codein": "ABC123",
      "libelle1": "MON ARTICLE",
      "site": "001",
      "nb_passages": 320,
      "qte_vendue": 640,
      "ca_ht": 5760.00,
      "ca_ttc": 6624.00,
      "marge": 1440.00,
      "taux_marge": 21.74,
      "derniere_vente": "2024-06-15T00:00:00.000Z"
    }
  ]
}

CA par nomenclature (rayon)

GET /api/performance/ca/nomenclature?dateDebut=&dateFin=&site=&niveau=1
Paramètre Type Description
niveau int Niveau de nomenclature (1 = racine)

Réponse :

{
  "ca_par_nomenclature": [
    {
      "code_nomen": "RAY01",
      "libelle": "RAYON MAISON",
      "niveau": 1,
      "nb_articles": 420,
      "qte_vendue": 8400,
      "ca_ht": 95000.00,
      "ca_ttc": 109250.00,
      "marge": 23750.00
    }
  ]
}

CA par gamme

GET /api/performance/ca/gamme?dateDebut=&dateFin=&site=

Réponse :

{
  "ca_par_gamme": [
    {
      "gamme": "ETE2024",
      "libelle_gamme": "ÉTÉ 2024",
      "nb_articles": 85,
      "qte_vendue": 1700,
      "ca_ttc": 28900.00,
      "marge": 6450.00
    }
  ]
}

Synchronisation

État de la sync

GET /api/sync/status

Réponse :

{
  "sync": [
    {
      "table_name": "articles",
      "last_sync": "2026-03-18T03:00:00.000Z",
      "rows_synced": 42062,
      "status": "ok",
      "error_msg": null
    }
  ]
}

Tables synchronisées :

Table Mode Fréquence
articles Delta (SUIVIDATEMODIF) Nuit
article_infosup Delta Nuit
art_gtin Upsert complet Nuit
artfou1 Delta Nuit
artfou2 Upsert complet Nuit
fouadr1 Refresh complet Nuit
cube_stock Refresh complet Nuit
cube_pa Refresh complet Nuit
cube_pv Refresh complet Nuit
mvtart Append (DatMvt >= hier) Nuit
nomenclature Refresh complet Nuit
gammes Refresh complet Nuit
art_gamme_saison Refresh complet Nuit
saisons Refresh complet Nuit
cdefou_vivant Refresh complet Nuit
cdefou_reception Delta Nuit
cdefou_receplig Delta Nuit

Exemples d'intégration JavaScript

const API_BASE = 'https://api.ffnancy.fr';

// Rechercher des articles
async function rechercherArticles(search, page = 1) {
  const params = new URLSearchParams({ search, page, limit: 50 });
  const res = await fetch(`${API_BASE}/api/articles?${params}`);
  return res.json();
}

// Fiche complète d'un article
async function getFicheArticle(id) {
  const res = await fetch(`${API_BASE}/api/articles/${id}/referentiel`);
  return res.json();
}

// CA du mois en cours par jour
async function getCaMoisEnCours() {
  const now = new Date();
  const debut = new Date(now.getFullYear(), now.getMonth(), 1).toISOString().slice(0, 10);
  const fin   = new Date(now.getFullYear(), now.getMonth() + 1, 0).toISOString().slice(0, 10);
  const params = new URLSearchParams({ dateDebut: debut, dateFin: fin, groupBy: 'jour' });
  const res = await fetch(`${API_BASE}/api/performance/ca?${params}`);
  return res.json();
}

// Top 10 articles par CA sur 30 jours
async function getTop10() {
  const fin   = new Date().toISOString().slice(0, 10);
  const debut = new Date(Date.now() - 30 * 86400000).toISOString().slice(0, 10);
  const params = new URLSearchParams({ dateDebut: debut, dateFin: fin, limit: 10, groupBy: 'ca' });
  const res = await fetch(`${API_BASE}/api/performance/hitparade?${params}`);
  return res.json();
}

// Stock d'un article
async function getStock(artNoId) {
  const res = await fetch(`${API_BASE}/api/stock/article/${artNoId}`);
  return res.json();
}

// Valorisation globale du stock
async function getValorisationStock() {
  const res = await fetch(`${API_BASE}/api/stock/valorisation`);
  return res.json();
}

// Commandes en cours d'un fournisseur
async function getCommandesFournisseur(codeFou) {
  const res = await fetch(`${API_BASE}/api/fournisseurs/${codeFou}/commandes`);
  return res.json();
}

Codes d'erreur HTTP

Code Description
200 Succès
404 Ressource introuvable (article, commande…)
500 Erreur serveur (détail dans le champ error)

Format erreur :

{ "error": "Article introuvable" }

Notes importantes

  • Les données sont en lecture seule — aucun endpoint d'écriture
  • Les données sont décalées d'au plus 24h (sync à 3h00)
  • Les champs dates sont au format ISO 8601 UTC
  • La pagination commence à page=1
  • Le champ no_id est l'identifiant interne SQL Server de l'article
  • Les codes sites (001, 002…) correspondent aux différents points de vente