Présentation
L’API REST OPMR Martinique expose en lecture l’ensemble des données de comparaison des prix : référentiel produits (EAN-13 normalisés GS1), prix courants par enseigne et point de vente, historique compressé, et métadonnées qualité. Elle permet à la Préfecture, à l’OPMR, aux journalistes, aux chercheurs et aux développeurs tiers de réutiliser les données sans coût additionnel (CCTP § 3.7).
URL de base de production : https://api.opmr.martinique.gouv.fr/v1
URL de l’environnement de pré-production : https://opmr.135-125-79-125.nip.io/api/v1
Le contrat OpenAPI 3.1 ci-dessous est généré automatiquement par notre API Gateway FastAPI (services/api-gateway/) et agrège les routes exposées par Drupal (opmr_api) et le service ETL.
Authentification
L’API supporte deux modes d’authentification, choisis selon le contexte d’usage :
| Mode | Cible | Description |
|---|---|---|
OAuth2 Client Credentials |
SI Préfecture, OPMR, partenaires | Flow client_credentials RFC 6749 § 4.4. Endpoint /oauth/token. JWT signé RS256, JWKS rotation 30 j. |
API Key (Bearer) |
Journalistes, chercheurs | Clé API à durée limitée (1 mois renouvelable) délivrée par l’OPMR sur demande. Header Authorization: Bearer <key>. |
mTLS |
Distributeurs (ingestion) | Authentification mutuelle TLS pour les POST /v1/ingest/*. Certificat client X.509 signé par l’OPMR. |
Anonyme (lecture publique) |
Tout le monde | Endpoints publics agrégés accessibles sans clé (rate-limit strict, 60 req/min). |
Tiers et quotas (rate-limit)
| Tier | Quota / minute | Burst | Identifiant |
|---|---|---|---|
anonymous | 60 requêtes | 120 | par IP |
standard | 600 requêtes | 1 200 | par client OAuth2 |
partner | 6 000 requêtes | 12 000 | par client OAuth2 ou clé API |
internal | illimité | — | SI Préfecture / OPMR (mTLS) |
Headers de réponse standardisés (RFC 9239) : X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, Retry-After en cas de 429.
Produits
GET /v1/produits Liste paginée des produits
Retourne la liste des produits du référentiel, avec pagination et filtres optionnels.
Paramètres de requête
| Nom | Type | Obligatoire | Description |
|---|---|---|---|
page | integer | Non | Numéro de page (défaut : 1) |
per_page | integer | Non | Items par page (défaut : 50, max : 200) |
categorie | string | Non | Filtrer par catégorie (ex : alimentation/cremerie) |
bqp_only | boolean | Non | Limiter aux produits du Bouclier Qualité Prix |
q | string | Non | Recherche full-text MeiliSearch (nom, marque, EAN) |
Réponses
application/json — Liste paginée
{
"data": [
{
"ean": "3017620422003",
"nom": "Nutella pâte à tartiner 400 g",
"marque": "Ferrero",
"categorie": "alimentation/epicerie-sucree",
"conditionnement": { "quantite": 400, "unite": "g", "pack_count": 1 },
"bqp": false,
"image_url": "https://opmr.135-125-79-125.nip.io/themes/custom/opmr_theme/images/products/3017620422003.jpg",
"nutriscore": "E",
"url": "/produit?ean=3017620422003"
}
],
"meta": {
"page": 1,
"per_page": 50,
"total": 60,
"total_pages": 2
},
"links": {
"self": "/v1/produits?page=1",
"next": "/v1/produits?page=2",
"prev": null
}
}
GET /v1/produits/{ean} Détail d’un produit
Fiche détaillée d’un produit identifié par son code-barres EAN-13.
Paramètres de chemin
| Nom | Type | Obligatoire | Description |
|---|---|---|---|
ean | string (13) | Oui | Code-barres EAN-13 normalisé GS1 avec checksum valide |
Réponses
application/json — Produit complet{
"ean": "3017620422003",
"nom": "Nutella pâte à tartiner 400 g",
"marque": "Ferrero",
"fabricant": { "nom": "Ferrero France", "pays": "FR" },
"prix_actuel": {
"min": 3.85,
"max": 5.20,
"moyen": 4.42,
"unite": "EUR/400g",
"prix_unitaire": 11.05,
"unite_unitaire": "EUR/kg"
},
"magasins_proposant": 18,
"derniere_collecte": "2026-05-17T14:23:00+02:00"
}
{
"type": "https://opmr.martinique.gouv.fr/errors/not-found",
"title": "Produit non trouvé",
"status": 404,
"detail": "Aucun produit avec l’EAN 1234567890123",
"instance": "/v1/produits/1234567890123"
}
Prix
GET /v1/prix Prix courants paginés, filtrables
Liste des prix courants observés, filtrables par EAN, enseigne, surface de vente, fraîcheur.
Paramètres
| Nom | Type | Description |
|---|---|---|
ean | string | Filtrer par produit |
enseigne | string | Filtrer par enseigne (ex : carrefour) |
surface | enum | hypermarche, supermarche, proximite |
commune | string | Code INSEE commune (ex : 97209) |
max_age_hours | integer | Fraîcheur max en heures (défaut : 168) |
include_promo | boolean | Inclure les promotions (défaut : false) |
{
"data": [
{
"ean": "3017620422003",
"magasin_id": "carrefour-dillon",
"enseigne": "Carrefour",
"surface": "hypermarche",
"commune_insee": "97209",
"prix": 4.20,
"unite": "EUR/400g",
"prix_unitaire": 10.50,
"unite_unitaire": "EUR/kg",
"promo": false,
"rupture": false,
"date_collecte": "2026-05-17T08:15:23+02:00",
"source": "distributeur",
"confiance": 1.0
}
]
}
Magasins
GET /v1/magasins Liste des 150+ points de vente géolocalisés
Liste géolocalisée des points de vente couverts par l’OPMR (150+ magasins en Martinique).
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [-61.0517, 14.6037] },
"properties": {
"id": "carrefour-dillon",
"enseigne": "Carrefour",
"surface": "hypermarche",
"adresse": "Avenue Frantz Fanon, 97200 Fort-de-France",
"commune_insee": "97209",
"horaires": { "lun-sam": "08:30-21:00", "dim": "08:30-12:30" }
}
}
],
"meta": { "total": 152 }
}
Historique des prix
GET /v1/historique Série temporelle de prix (hypertable TimescaleDB)
Évolution du prix d’un EAN sur une période donnée, agrégée par jour ou par semaine selon le granularity demandé.
Paramètres
| Nom | Type | Description |
|---|---|---|
ean | string | Obligatoire — code EAN-13 |
from | date ISO 8601 | Date de début (défaut : J-30) |
to | date ISO 8601 | Date de fin (défaut : J) |
granularity | enum | day (défaut), week, month |
enseigne | string | Filtrer par enseigne (sinon: moyenne toutes enseignes) |
{
"ean": "3017620422003",
"granularity": "day",
"series": [
{ "date": "2026-05-10", "min": 3.85, "max": 5.20, "moyen": 4.38, "n_releves": 14 },
{ "date": "2026-05-11", "min": 3.85, "max": 5.20, "moyen": 4.40, "n_releves": 16 },
{ "date": "2026-05-12", "min": 3.85, "max": 5.20, "moyen": 4.42, "n_releves": 17 }
]
}
Ingestion (distributeurs, mTLS obligatoire)
POST /v1/ingest/prices Batch JSON jusqu’à 10 000 items
Endpoint d’ingestion utilisé par les distributeurs signataires du protocole pour transmettre leurs prix. mTLS + OAuth2 Client Credentials obligatoires.
Corps de la requête
{
"items": [
{
"ean": "3017620422003",
"magasin_id": "carrefour-dillon",
"prix": 4.20,
"unite": "EUR/400g",
"promo": false,
"horodatage": "2026-05-17T08:15:23+02:00"
}
]
}
{
"accepted": 1,
"rejected": 0,
"trace_id": "01ABC...XYZ",
"errors": []
}
{
"type": "https://opmr.martinique.gouv.fr/errors/validation",
"title": "Validation des données échouée",
"status": 422,
"errors": [
{ "path": "items.0.ean", "code": "INVALID_EAN_CHECKSUM" }
]
}
POST /v1/ingest/csv Upload CSV multipart
Upload d’un fichier CSV au format normalisé OPMR (header obligatoire ean,magasin_id,prix,unite,promo,horodatage). Idempotent via hash SHA256.
Endpoints meta
GET /health Healthcheck du gateway et upstreams
Vérifie que le gateway tourne et que ses upstreams (Drupal, ETL) répondent.
{
"service": "opmr-api-gateway",
"version": "1.0.0",
"environment": "production",
"status": "ok",
"checks": {
"gateway": "ok",
"drupal": "ok",
"etl": "ok"
}
}
GET /metrics Métriques Prometheus (scraping interne)
Format Prometheus exposition standard. Réservé aux scrapers internes (réseau privé).
GET /openapi.json Contrat OpenAPI 3.1 agrégé
Le contrat OpenAPI 3.1 complet, généré dynamiquement par notre aggregate() en union des spécifications Drupal et ETL.
Télécharger la spec OpenAPI 3.1
La spécification OpenAPI 3.1 complète est disponible en JSON et YAML pour intégration dans vos outils :
openapi.yaml (1.0.0) openapi.json (1.0.0)services/api-gateway/).