Pour les éditeurs de LGO, de contrôle de remises et de SaaS pharmacie
L'optimisation des achats génériques Margen, dans votre logiciel.
Envoyez vos achats, vos RSF et vos remises arrière. Recevez la meilleure répartition par labo et par CIP, l'économie chiffrée, et les volumes prévus pour l'année. Sandbox gratuite, puis 290 € HT par mois avec 30 officines actives incluses.
Vous êtes un groupement et vous n'éditez pas de logiciel ? Utilisez l'application web →
POST /v1/optimize
Quels CIP acheter, chez quel labo, pour payer le moins cher net de remises. Économie chiffrée par groupe générique et par labo.
Volumes prévus inclus
Pour l'année en cours ou la suivante, le résultat donne aussi les volumes prévus mois par mois, sur lesquels la recommandation est calculée.
En bref. URL de base https://public-api.margen.fr, JSON en entrée et en sortie,
clé dans l'en-tête Authorization: Bearer mgn_test_…. Le prix (PFHT), les groupes génériques
et les ruptures viennent du référentiel Margen : vous n'envoyez que vos achats et vos conditions commerciales.
1 Obtenir une clé
- Créez votre compte dans la console et confirmez votre e-mail.
- Activation sous 24 h ouvrées : la console indique quand c'est fait.
- Une fois validé, créez une clé de test
mgn_test_…. Elle n'est affichée qu'une fois : copiez-la.
Vérifiez qu'elle fonctionne : la réponse indique votre offre et le quota restant.
export MARGEN_API_KEY=mgn_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
curl -sS https://public-api.margen.fr/v1/usage -H "Authorization: Bearer $MARGEN_API_KEY"2 Vérifier vos CIP et trouver les labo_id
Facultatif mais recommandé avant le premier appel. Ces deux requêtes sont gratuites (hors quota).
# Vos CIP sont-ils connus ? (groupe générique, labo, PFHT en vigueur)
curl -sS "https://public-api.margen.fr/v1/reference/generics?cip=3400930000014,3400930000021" \
-H "Authorization: Bearer $MARGEN_API_KEY"
# Identifiants des labos (labo_id), pour vos RSF et remises arrière
curl -sS https://public-api.margen.fr/v1/reference/labos -H "Authorization: Bearer $MARGEN_API_KEY"{
"object": "list",
"data": [
{
"cip": "3400930000014",
"label": "…",
"gen_group_id": "…",
"labo_id": 12,
"labo": "…",
"is_generic": true,
"pfht_eur": 2.41
}
],
"not_found": ["3400930000021"]
}3 Préparer la requête
Le minimum : vos achats. Ajoutez vos RSF pour un résultat réaliste. Enregistrez ce fichier sous optimize.json.
{
"year": 2026,
"purchases": [
{ "finess": "750000010", "cip": "3400930000014", "month": "2026-01", "qty": 120 },
{ "finess": "750000010", "cip": "3400930000014", "month": "2026-02", "qty": 98 },
{ "finess": "750000028", "cip": "3400930000021", "month": "2026-01", "qty": 40 }
],
"rsf": [
{ "cip": "3400930000014", "rate_pct": 30 },
{ "cip": "3400930000021", "rate_pct": 22.5 },
{ "labo_id": 12, "rate_pct": 17 }
]
}| Champ | Description |
|---|---|
purchases requis | Une ligne par officine × CIP × mois : finess (9 chiffres), cip (CIP13), month (« AAAA-MM »), qty (boîtes nettes). |
rsf | Remises sur facture négociées, en % (voir ci-dessous). Sans RSF, le taux est 0 %. |
remises_arrieres | Programmes de remises arrière par labo, avec leurs paliers. |
year | Année analysée. Par défaut : l'année en cours (l'année passée en backtest, la suivante en forecast_next). |
mode | current_year (défaut), backtest (rejouer une année passée) ou forecast_next (année suivante). |
scope | groupement (défaut, achats mutualisés) ou per_officine (un calcul par FINESS). |
Les RSF : par CIP, par labo, groupement ou officine
- •
cip+rate_pct: le taux négocié pour ce CIP. C'est le cas courant. - •
labo_idsanscip: taux par défaut pour tous les autres CIP de ce labo. - • Sans
finess, le taux vaut pour tout le groupement. Avecfiness, il ne vaut que pour cette officine (avec"scope": "per_officine"). - • Si plusieurs taux s'appliquent, le plus précis gagne : officine + CIP, puis officine + labo, puis CIP, puis labo, sinon 0 %.
- • Taux variables dans l'année : ajoutez
valid_from/valid_to(« AAAA-MM-JJ »).
Les remises arrière (facultatif)
Un programme par labo. Ici : 3 % jusqu'à 50 000 € d'achats (PFHT), 6 % au-delà. Ajoutez ce bloc au même niveau que purchases. Le plafond légal (RSF + remise arrière, art. L.138-9 CSS : 40 % pour les génériques
en 2026, suivi année par année) est appliqué automatiquement.
"remises_arrieres": [
{
"labo_id": 12,
"type": "threshold_bands",
"tiers": [
{ "min_eur": 0, "max_eur": 50000, "rate_pct": 3 },
{ "min_eur": 50000, "rate_pct": 6 }
]
}
]Vous avez déjà les lignes de facture ?
Contrôle de remises, réception financière, coffre-fort de factures : vous tenez déjà une ligne par facture et par CIP, avec la quantité et la remise réellement appliquée. C'est l'entrée de l'optimiseur. Trois règles d'agrégation suffisent.
1. Le mapping
| Colonne de facture | Champ API | Règle |
|---|---|---|
| FINESS de l'officine | purchases[].finess | Tel quel (9 chiffres). |
| Code CIP (13 ou 7) | purchases[].cip | Tel quel. |
| Date de facture | purchases[].month | Tronquée au mois, « AAAA-MM ». |
| Quantité (avoirs en négatif) | purchases[].qty | Somme par officine × CIP × mois. |
| Remise sur facture appliquée (%) | rsf[].rate_pct | Par CIP : le taux le plus fréquent de l'année, pondéré par les boîtes. Avec finess en per_officine. |
| Prix unitaire, net HT, fournisseur | — | Non envoyés : le PFHT, le labo et le groupe générique viennent du référentiel Margen. |
Factures avec le montant de la remise seulement : taux = remise ÷ (quantité × prix unitaire facturé).
2. Un exemple
Quatre lignes de facture d'une officine, dont un avoir…
FINESS Date CIP Quantité Remise %
130001233 2026-01-05 3400937290494 80 30
130001233 2026-01-19 3400937290494 56 30
130001233 2026-02-25 3400937290494 -2 30 ← avoir
130001233 2026-01-05 3400937199155 34 25…deviennent trois achats mensuels et deux taux de RSF :
{
"scope": "per_officine",
"purchases": [
{ "finess": "130001233", "cip": "3400937290494", "month": "2026-01", "qty": 136 },
{ "finess": "130001233", "cip": "3400937290494", "month": "2026-02", "qty": 0 },
{ "finess": "130001233", "cip": "3400937199155", "month": "2026-01", "qty": 34 }
],
"rsf": [
{ "finess": "130001233", "cip": "3400937290494", "rate_pct": 30 },
{ "finess": "130001233", "cip": "3400937199155", "rate_pct": 25 }
]
}3. Ce que vous récupérez
summary.savings_eur- Ce que l'officine aurait payé en moins sur l'année en achetant chaque groupe générique au bon labo.
to_buy[]- Le plan d'achat par CIP pour les mois restants, prêt à alimenter votre export de prix nets vers le LGO.
Le résultat repose sur les remises telles qu'elles ont été facturées, pas telles qu'elles ont été promises. Un script de conversion CSV → requête est fourni sur demande à contact@margen.fr.
4 Lancer l'optimisation
Prefer: wait=60 demande d'attendre le résultat jusqu'à 60 secondes. Idempotency-Key évite d'être décompté deux fois si vous renvoyez la même requête.
200 — c'est fini
Le résultat est dans la réponse.
202 — encore en cours
Interrogez GET /v1/jobs/{id} toutes les 5 s ; le résultat est dans result.
curl -sS https://public-api.margen.fr/v1/optimize \
-H "Authorization: Bearer $MARGEN_API_KEY" \
-H "Content-Type: application/json" \
-H "Prefer: wait=60" \
-H "Idempotency-Key: $(uuidgen)" \
-d @optimize.json
# Réponse 202 ? Le calcul continue : interrogez le job jusqu'à "status": "succeeded"
curl -sS https://public-api.margen.fr/v1/jobs/JOB_ID -H "Authorization: Bearer $MARGEN_API_KEY"5 Lire le résultat
Les montants sont en euros, nets de RSF et de remises arrière. Les valeurs ci-dessous sont illustratives.
{
"object": "optimize_result",
"year": 2026,
"scope": "groupement",
"summary": {
"hist_effective_eur": 18240.50,
"opt_effective_eur": 16912.10,
"savings_eur": 1328.40,
"savings_rate": 0.0728
},
"units": [
{
"finess": null,
"by_gen_group": [
{
"gen_group_id": "…",
"label": "…",
"delta_eur": -412.30,
"current": [ { "cip": "3400930000021", "labo_id": 52, "qty": 1400, … } ],
"recommended": [ { "cip": "3400930000014", "labo_id": 12, "qty": 1400, … } ]
}
],
"by_labo": [ … ]
}
],
"warnings": []
}summary.savings_eur- Économie totale par rapport aux achats tels qu'ils ont été faits (net de RSF et remises arrière).
units[]- Un élément pour le groupement, ou un par officine en scope per_officine (finess renseigné).
by_gen_group[].to_buy- Ce qu'il faut acheter à partir de maintenant : CIP, labo et boîtes, pour les mois restants (année en cours) ou toute l'année (année suivante).
by_gen_group[].recommended- La répartition optimale sur l'année entière (mois déjà achetés inclus tels qu'achetés) ; current = les achats réels.
by_labo[]- Montants par labo, palier de remise arrière atteint et reste à acheter pour le palier suivant.
warnings[]- Points d'attention (CIP inconnus, lignes ignorées, plafond légal dépassé…).
Les résultats restent disponibles 7 jours sur GET /v1/jobs/{id} ; DELETE /v1/jobs/{id} les efface tout de suite.
Pour le montrer à un pharmacien : le générateur de rapport transforme un résultat en page imprimable par officine, à votre nom, dans le navigateur.
6 Optimiser l'année en cours ou la suivante
Le même appel POST /v1/optimize couvre trois cas, choisis avec mode.
Quand l'année n'est pas terminée, Margen prévoit les volumes des mois restants à partir de votre historique
et optimise sur l'année complète.
current_year | Défaut. L'année en cours : achats déjà faits + volumes prévus jusqu'en décembre. |
forecast_next | L'année suivante, entièrement à partir des volumes prévus. Envoyez l'historique jusqu'à aujourd'hui. |
backtest | Une année passée complète, rejouée : aucune prévision, tout est réel. |
Chaque groupe générique indique alors ce qui est déjà acheté (purchased_qty), ce qui est prévu
(forecast_qty) et le détail par mois (forecast_months) : qty = purchased_qty + forecast_qty. to_buy donne les CIP à acheter
pour ces mois restants (toute l'année en forecast_next). Une prévision marquée "forecast_confidence": "limited" repose sur un historique court (moins de 14 mois) :
envoyez 24 mois d'historique quand c'est possible.
"units": [
{
"last_data_month": 9,
"forecast_from": "2026-10",
"by_gen_group": [
{
"gen_group_id": "…",
"qty": 1480,
"purchased_qty": 1110,
"forecast_qty": 370,
"forecast_confidence": "standard",
"forecast_months": [
{ "month": "2026-10", "qty": 124 },
{ "month": "2026-11", "qty": 121 },
{ "month": "2026-12", "qty": 125 }
],
"to_buy": [
{ "cip": "3400930000014", "labo_id": 12, "qty": 370, "months": [10, 11, 12], … }
],
"recommended": [ … ]
}
]
}
]Erreurs
Toujours le même format : { "error": { "type", "code", "message", "rows" }, "request_id" }.
Donnez le request_id au support si besoin.
| HTTP | code | Que faire |
|---|---|---|
| 400 | finess_required_live | Avec une clé live, chaque ligne d'achat doit porter le FINESS de l'officine (la facturation compte les officines actives). |
| 400 | invalid_rows | Lignes invalides : chacune est listée dans error.rows avec son chemin (ex. purchases[3].cip). |
| 413 | too_many_rows | Requête trop grosse pour votre offre (aussi too_many_officines) : découpez-la. |
| 401 | invalid_api_key | Clé inconnue. Variantes : missing_api_key (en-tête absent), api_key_revoked (clé révoquée). |
| 402 | quota_exceeded | Quota mensuel épuisé (Sandbox) ; il se renouvelle le 1er du mois. Passez en Partner pour lever la limite. |
| 403 | account_pending | Compte en attente de validation par l'équipe Margen. |
| 429 | rate_limited | Trop de requêtes : attendez la durée indiquée par Retry-After. |
| 503 | free_capacity_reached | Capacité Sandbox du jour atteinte : réessayez après minuit UTC (Retry-After), ou passez en Partner. |
Liste complète dans la référence de l'API (openapi.yaml).
Unités et limites
Une optimisation = un calcul (un par officine en per_officine).
Les calculs en échec ou annulés ne sont pas décomptés. En Sandbox : 20 optimisations
par mois, 10 officines par requête, 2 calculs en parallèle.
Les clés de test gardent ces limites sur toutes les offres ; les clés live suivent celles de votre offre
(tarifs).
Vos données
- • Les achats envoyés sont traités en mémoire et jamais stockés.
- • Les résultats sont conservés 7 jours, puis supprimés.
- • Hébergement dans l'Union européenne. Margen agit en sous-traitant (article 28 du RGPD) : conditions et DPA.
Construire ou intégrer ?
Avec un assistant de code, le solveur s'écrit en quelques jours. Ce qui ne se génère pas : la vingtaine de règles commerciales et légales qu'il faut connaître avant d'écrire la première ligne, le référentiel reconstruit chaque nuit, et la preuve que le chiffre est juste avant de le montrer à un pharmacien. Le détail, et le calcul coût interne contre API →
Nos engagements envers les éditeurs partenaires
- • Votre marque, votre prix. Le résultat est le vôtre ; Margen n'apparaît que si vous le souhaitez.
- • Vos clients restent vos clients. Margen ne démarche pas les officines équipées par un partenaire, pendant toute la durée du partenariat. Pour les groupements, nous co-vendons avec vous plutôt que contre vous.
- • Un pilote avant tout engagement. Backtest gratuit sur un échantillon de vos officines, chiffre par officine sous une semaine, puis pilote sans frais.
- • Pas de rétention. Vos données ne sont jamais stockées ; si vous arrêtez, il n'y a rien à récupérer chez nous.
Pour en parler : Clément Lefèvre, fondateur de margen, gérant de timeit srl, contact@margen.fr.
Tarifs de l'API
Prix hors taxes, sans engagement, résiliable chaque mois. Une officine active est un FINESS présent dans au moins une optimisation réussie avec une clé live au cours du mois civil : une officine optimisée dix fois dans le mois est comptée une fois. Les clés de test ne sont jamais facturées.
Intégrer et tester
API Sandbox
0 €
sans carte bancaire
- Clés de test mgn_test_
- 20 optimisations / mois
- 10 officines et 50 000 lignes par requête
- 10 requêtes / minute
Éditeurs de LGO et SaaS pharmacie
API Partner
290 €
HT / mois · 30 officines actives incluses
| 31 – 200 | 9 € |
| 201 – 1 000 | 7 € |
| > 1 000 | 5 € |
- Clés live, facturation à l'officine active
- Jusqu'à 5 000 officines et 2 000 000 lignes par requête
- 120 requêtes / minute, 5 calculs en parallèle
- Webhooks signés
- Souscription en ligne, facture mensuelle
Grands réseaux, au-delà de 5 000 officines
API Enterprise
Sur devis
contrat annuel
- Prix dégressif négocié
- Instance dédiée, SLA et support prioritaire
- Marque blanche
- Accord de traitement des données sur mesure
Prêt à commencer ?
Créez votre compte développeur et une clé de test : la Sandbox est gratuite, sans carte bancaire. Passez en Partner depuis la console quand vous êtes prêt.
Obtenir une clé