Comment lire les chiffres d'une officine avec l'API Artemis ?
Mis à jour le 14/10/2026
L'API Artemis donne, en lecture seule, les chiffres d'une officine : ventes mois par mois, stock, marges, laboratoires, familles. Une clé ouvre les données d'une seule officine, celle du titulaire qui l'a créée, produit par produit, sans aucune donnée patient. Elle s'appelle depuis un serveur, jamais depuis une page web.
Que faut-il pour commencer ?
- L'adresse : https://artemis.sydera.ai/api/v1.
- Le contrat OpenAPI 3.1, public et sans clé : artemis.sydera.ai/api/v1/openapi.json. Il donne le niveau de chaque route et de chaque champ réservé (x-niveau).
- Une clé : le titulaire la crée dans Artemis, onglet API, avec un abonnement à Artemis (ou à PriceCraft, qui le comprend), un essai en cours ou un accès offert. Elle commence par sk_art_ et porte un niveau d'accès, choisi à sa création.
Que ne fait pas l'API ?
- Aucune recommandation de prix : elle ne calcule ni ne propose aucun prix.
- Aucune donnée de marché : aucun prix d'une autre pharmacie, d'un site en ligne ou d'une zone.
- Aucune écriture : elle ne modifie aucune donnée de prix ou de stock de l'officine. Toutes les routes sont en GET.
L'API donne à voir les chiffres de l'officine ; PriceCraft les fait agir.
Quel niveau de clé choisir ?
Le titulaire choisit le niveau à la création de la clé, et il ne se modifie pas : pour en changer, il crée une nouvelle clé et retire l'ancienne. Le niveau proposé par défaut est ventes.
| Niveau | Ce qu'il ouvre | Routes |
|---|---|---|
| catalogue | produits, prix de vente, stock ; ni ventes, ni prix d'achat | /officine, /recherche, /fiche, /liste, /produits, /stock |
| ventes | le catalogue, plus les ventes mensuelles, les palmarès, la saison, le stock dormant et la couverture ; ni prix d'achat, ni marge | les précédentes, plus /top-ventes, /palmares, /laboratoires, /gamme, /ventes-du-mois, /stock-dormant, /couverture, /ventes |
| complet | tout : prix d'achat (PAMP), valeur du stock au PAMP, marges, bilan | toutes, /bilan compris |
- Une route au-dessus du niveau de la clé répond 403 niveau_insuffisant, avec niveau_requis et niveau_de_la_cle. Rien n'est lu.
- Dans une route ouverte, un champ d'un niveau plus haut n'est jamais rendu : une clé ventes lit /top-ventes sans pamp_ht ni marge_eur. Prévoyez qu'il manque.
- Choisissez le niveau le plus bas qui suffit. Le niveau complet donne les prix d'achat et les marges de l'officine : ne le confiez qu'à un outil que vous maîtrisez.
- Les clés créées avant l'arrivée des niveaux sont de niveau complet.
Pourquoi appeler depuis un serveur ?
La clé donne accès aux ventes et aux marges de l'officine. Placée dans une page web ou une application qui tourne dans le navigateur, n'importe quel visiteur peut la lire. L'API refuse donc les appels venus d'un navigateur (aucun en-tête CORS) : appelez-la depuis votre serveur ou une fonction serveur, gardez la clé dans un secret, et ne renvoyez au navigateur que ce qu'il affiche.
Comment s'authentifier ?
curl -H "Authorization: Bearer sk_art_…" "https://artemis.sydera.ai/api/v1/officine"L'en-tête X-Api-Key: sk_art_… fonctionne aussi. L'officine lue est toujours celle de la clé : aucun paramètre ne permet d'en lire une autre.
Chaque lecture répond { "donnees": { … }, "date_releve": "…" }. Une note dans donnees signale ce qui compte pour lire les chiffres : une famille estimée, un relevé ancien, un produit mis à part, un historique plus court que la période. Affichez-la ou tenez-en compte. Une réponse peut gagner des champs sans changer de version : ignorez ceux que vous ne connaissez pas.
Quelles routes de lecture ?
| Route | Niveau | Ce qu'elle rend | Paramètres |
|---|---|---|---|
| /officine | catalogue | identité, stock, dates de relevé, qualité des données ; dès ventes, les douze derniers mois pleins ; en complet, la valeur du stock et la marge | aucun |
| /recherche | catalogue | produits par nom (mots dans le désordre, abréviations comprises) ou par code CIP ; dès ventes, le dernier mois vendu | q (requis), limite (≤ 50) |
| /fiche | catalogue | prix, stock, emplacement d'un ou plusieurs produits ; dès ventes, les ventes mois par mois et la couverture ; en complet, le PAMP et les marges | cip (requis, jusqu'à 20, séparés par des virgules), mois (≤ 24) |
| /liste | catalogue | les laboratoires ou les familles de l'officine, avec leur nombre de références | quoi (requis : laboratoires ou familles), q, limite (≤ 150) |
| /top-ventes | ventes | les produits les plus vendus sur N mois pleins, avec la période comptée (periode) | mois, q, laboratoire, famille, limite (≤ 100) |
| /palmares | ventes | les laboratoires ou les familles classés par chiffre d'affaires, avec periode, le total (total : combien en tout, et leur chiffre d'affaires) et la part du chiffre d'affaires que la liste représente (part_du_ca_pct) | par (requis : laboratoire ou famille), mois, q, famille, laboratoire, limite (≤ 50) |
| /laboratoires | ventes | raccourci de /palmares?par=laboratoire, mêmes champs | mois, q, famille, limite |
| /gamme | ventes | toute la gamme d'un laboratoire, références sans vente comprises, avec periode | laboratoire (requis), mois, limite (≤ 200) |
| /ventes-du-mois | ventes | toutes les ventes d'un mois, référence par référence, par pages de 200 ; chaque ligne porte aussi le mois précédent (quantite_mois_precedent, ca_ttc_mois_precedent) ; en page 1, par_famille donne chaque famille, le mois et le précédent | mois (requis, AAAA-MM), laboratoire, famille, page |
| /stock-dormant | ventes | le stock sans vente depuis N mois ; les produits dont la saison commence sont mis à part ; par_laboratoire résume tout le stock dormant par laboratoire, pas seulement la liste rendue, les autres en dernière ligne ((autres laboratoires)) | mois_sans_vente (≤ 36), laboratoire, famille, limite (≤ 200) |
| /couverture | ventes | le stock qui couvre au plus N jours de ventes (0 = rupture), avec la période des ventes comptées (periode) ; fins de saison et ventes ponctuelles mises à part | jours_max (≤ 365), mois, laboratoire, famille, limite (≤ 200) |
| /bilan | complet | l'officine mois par mois : unités, chiffre d'affaires TTC et HT, marge en euros et en pourcentage | mois (≤ 24), laboratoire, famille |
En complet, les routes de ventes ajoutent la marge, et /stock-dormant la valeur immobilisée au PAMP. Les noms de laboratoire et de famille se donnent sans souci des accents, des majuscules, des tirets ni des espaces : hygiene bucco dentaire trouve « Hygiène bucco-dentaire », dans les lectures comme dans l'export /produits. Un nom inconnu ne renvoie pas une liste vide sans explication : la note propose les noms proches. Exemple : /recherche?q=vitamine%20d&limite=10.
- periode : les mois pleins comptés, { "du": "AAAA-MM", "au": "AAAA-MM" }. Le mois en cours n'y est jamais : il est dans /ventes-du-mois, partiel.
- mois dans /fiche et /bilan : N compte le mois en cours, soit N moins 1 mois pleins, plus le mois en cours, partiel. La note le rappelle.
- historique (dès ventes) : présent seulement quand l'historique de l'officine est plus court que la période demandée. etat vaut en_cours dans les 48 heures qui suivent le premier relevé (les chiffres arrivent encore : renouvelez la demande quelques heures plus tard), sinon partiel. depuis donne le premier mois connu (AAAA-MM), mois_couverts et mois_demandes disent l'écart.
Comment exporter page par page ?
Pour remplir un tableur ou une base, trois routes rendent des colonnes fixes : { "donnees": [ … ], "nombre": n, "suivant": "<curseur>", "date_releve": "…" }. Repassez suivant dans curseur jusqu'à ce qu'il vaille null.
| Route | Niveau | Colonnes | Paramètres |
|---|---|---|---|
| /produits | catalogue | cip, nom, laboratoire, famille, famille_estimee, acte_ou_prestation, prix_vente_ttc, prix_vente_ht, taux_tva, stock, stock_au_releve, date_releve ; dernier_mois_vendu dès ventes ; prix_achat_ht en complet | q, cip, laboratoire, famille, limite (≤ 1 000), curseur |
| /stock | catalogue | cip, nom, quantite, emplacement, date_releve ; prix_achat_moyen_ht et valeur_stock_ht en complet | q, cip, limite, curseur |
| /ventes | ventes | cip, mois, quantite, prix_vente_ttc (prix moyen encaissé du mois), mois_en_cours, date_releve ; prix_achat_ht en complet | cip, depuis, jusqu_a (AAAA-MM), limite, curseur |
Comment lire les chiffres juste ?
- Deux prix : le prix catalogue est le prix affiché, hors honoraire de dispensation. Le prix moyen encaissé est celui du mois, honoraires compris : le chiffre d'affaires qui en découle est approché.
- La marge est calculée sur le PAMP, prix d'achat moyen pondéré : marge en euros = quantité × (prix de vente HT moins PAMP), marge en pourcentage = (prix de vente HT moins PAMP) ÷ prix de vente HT × 100. Elle ne compte ni les remises de fin d'année ni les accords avec les laboratoires : c'est une marge par produit, utile pour comparer, pas la marge comptable de l'officine.
- Sans prix d'achat connu, un produit n'a pas de marge (champ absent ou null), jamais 100 %.
- famille_estimee : la famille que Sydera donne à un produit quand l'officine ne lui en donne pas, choisie parmi les familles de l'officine elle-même.
- acte_ou_prestation : un forfait, une location, un code de suivi, une vaccination. Compté dans le chiffre d'affaires, retiré des listes de produits.
- Le mois est la plus petite unité. Le mois en cours est partiel (mois_en_cours).
- Chaque réponse est datée (date_releve). Un relevé de plus de deux jours est signalé dans la note.
Le détail de ce qu'Artemis relève est dans Ce qu'Artemis lit.
Quelles erreurs l'API renvoie-t-elle ?
Toujours { "erreur": "<code>", "message": "<explication en français>" }.
| Statut | Codes | Que faire |
|---|---|---|
| 400 | parametre | corriger le paramètre indiqué |
| 401 | cle_manquante, cle_inconnue, cle_revoquee | passer la clé, ou en demander une nouvelle au titulaire |
| 403 | acces_suspendu | l'accès Artemis de l'officine est en pause (essai terminé, abonnement arrêté, accès offert échu) ; la clé refonctionne dès la reprise |
| 403 | niveau_insuffisant | la route demande un niveau plus haut que celui de la clé ; demander au titulaire une clé du niveau nommé |
| 404 | ressource | la route n'existe pas ; le message liste celles qui existent |
| 405 | methode | lecture seule : GET uniquement |
| 409 | sans_donnees | l'officine est enregistrée, ses chiffres ne sont pas encore arrivés |
| 429 | quota_min, quota_jour | attendre le nombre de secondes de l'en-tête Retry-After (aussi dans reessayer_dans_s) |
| 500 | lecture | réessayer ; si cela recommence, écrire à support@sydera.ai |
| 503 | indisponible, api_en_pause | réessayer plus tard ; les clés restent valables |
Quelles sont les limites ?
60 lectures par minute et 10 000 par jour, par clé. Une requête refusée pour un paramètre mal formé ne compte pas.
Comment l'utiliser dans une application Lovable ?
- Gardez la clé en secret du projet, nommé ARTEMIS_API_KEY : More, puis Cloud, Secrets, Add secret. Jamais dans le code de l'application ni dans la conversation.
- Appelez l'API depuis une fonction serveur, jamais depuis la page, et réservez cette fonction aux utilisateurs connectés de l'application.
- Collez la notice developpeurs-lovable.md dans Project settings, puis Knowledge : elle donne à l'agent de Lovable les règles et une fonction serveur type.
Pour que l'agent de Lovable lise lui-même les chiffres pendant qu'il construit, ajoutez plutôt Artemis comme connecteur : voyez Ajouter dans Lovable.
Comment les assistants lisent-ils les mêmes chiffres ?
Claude, ChatGPT et les autres assistants passent par le serveur MCP https://artemis.sydera.ai/mcp, avec la connexion au compte Sydera : mêmes chiffres, même logique, et un assistant lit tout. Voyez Ajouter à Claude et Ajouter à ChatGPT.
Une question : support@sydera.ai.