Vérifier un numéro RPPS avec l'API Annuaire Santé (FHIR R4)

14/04/2026
Dès qu'un professionnel de santé déclare son numéro RPPS dans un formulaire, un import de fichier ou un back-office, vous héritez d'une donnée que personne n'a contrôlée. L'API FHIR de l'Annuaire Santé, ouverte et gratuite, permet de confronter ce numéro au référentiel national de l'ANS en une requête HTTP.
Ce tutoriel couvre l'ensemble du processus : obtenir une clé API, construire la requête FHIR, parser la réponse, et intégrer le tout dans un backend NestJS. Il précise aussi, et c'est le point le plus souvent raté, dans quels cas cette vérification apporte vraiment quelque chose. Comptez 10 minutes de lecture.
Quand vérifier un RPPS a du sens
Le numéro RPPS (Répertoire Partagé des Professionnels de Santé) est l'identifiant national unique de chaque professionnel de santé en France. Il est attribué à vie par l'Ordre professionnel concerné.
La question à se poser avant d'écrire la moindre ligne de code : d'où vient le numéro que vous vous apprêtez à vérifier ?
Le RPPS est déclaré par l'utilisateur ou importé. C'est là que la vérification est utile, et même nécessaire. Un formulaire d'inscription, un onboarding administré par vos équipes, un import CSV depuis un logiciel tiers, un annuaire de praticiens que vous publiez : dans tous ces cas, rien ne garantit que le numéro existe, ni qu'il désigne la personne en face de vous. L'appel FHIR confirme l'existence de la fiche, son statut, et vous laisse recouper le nom.
Le RPPS vient de Pro Santé Connect. Là, le contrôle de statut fait doublon. PSC s'appuie sur l'Annuaire Santé, lui-même alimenté par le RPPS et le FINESS. Une radiation ferme la fiche RPPS et entraîne la révocation de la carte CPS et de l'e-CPS, donc le praticien radié n'obtient déjà plus de jeton PSC. Rappeler l'API pour lire active revient à interroger le même référentiel une étape plus loin. Ce que l'Annuaire vous apporte dans ce cas de figure est ailleurs : les spécialités, les savoir-faire, les situations d'exercice et les structures de rattachement qui alimentent vos règles d'habilitation.
Autrement dit, l'API sert à valider une donnée d'origine incertaine ou à enrichir un profil authentifié. Elle ne sert pas de second rideau derrière PSC.
L'API Annuaire Santé en bref
L'Annuaire Santé est la base de données nationale de référence des professionnels de santé. Il agrège les données du RPPS, de FINESS (établissements), des cartes CPx, de MSSanté et d'Ameli.
L'ANS expose ces données via une API REST conforme à FHIR R4 (Fast Healthcare Interoperability Resources). FHIR est le standard international d'interopérabilité en santé. Si vous ne connaissez pas FHIR, retenez trois choses :
- Les données sont structurées en ressources (Practitioner, Organization, HealthcareService...)
- Les réponses sont des Bundles contenant une ou plusieurs ressources
- L'API suit les conventions REST classiques (GET, paramètres de recherche, pagination)
L'API est hébergée sur le gateway gateway.api.esante.gouv.fr et gérée par la plateforme Gravitee. L'accès en lecture est libre après obtention d'une clé API, sans authentification lourde.
La documentation officielle est sur ansforge.github.io/annuaire-sante-fhir-documentation, et le modèle FHIR détaillé dans le guide d'implémentation.
Prenez la v2, pas la v1
L'API existe en deux versions et la v1 est en fin de vie. Tout nouveau développement doit cibler /fhir/v2/. Le piège : appeler https://gateway.api.esante.gouv.fr/fhir sans préciser la version vous renvoie une réponse v1, choix fait par l'ANS pour ne pas casser les intégrations existantes. Précisez toujours /fhir/v2/ explicitement.
Les différences qui vous concernent en pratique :
| v1 | v2 | |
|---|---|---|
| Header d'authentification | GRAVITEE-API-KEY |
ESANTE-API-KEY |
Paramètre identifier |
http://rpps.fr|{rpps} |
{rpps} (numéro nu) |
| ID techniques Practitioner et PractitionerRole | Différents de la v1 | |
| Identifiant métier sur PractitionerRole | absent | présent |
| Alignement FRCore | non | oui |
Le point le plus dangereux d'une migration est le troisième : si vous avez stocké des ID techniques de Practitioner ou de PractitionerRole en base, ils ne correspondent plus en v2. Appuyez-vous sur l'identifiant métier (le RPPS) plutôt que sur l'ID technique.
Obtenir sa clé API
L'API Annuaire Santé est gratuite. L'accès se fait en trois étapes :
- Créer un compte sur le portail Gravitee de l'ANS, portal.api.esante.gouv.fr
- S'abonner à l'API "Annuaire Santé FHIR" depuis le catalogue
- Récupérer la clé API dans votre espace développeur
La clé se transmet via le header HTTP ESANTE-API-KEY dans chaque requête. Aucun token OAuth, aucun certificat : un simple header suffit.
Le démonstrateur portail.openfhir.annuaire.sante.fr est un outil distinct, utile pour tester vos requêtes dans le navigateur avant de les coder. Il interroge la v2 par défaut. Notez qu'il n'existe pas d'environnement bac à sable : l'API sert les données publiques de production.
Requête FHIR pas à pas : vérifier un praticien
L'endpoint
GET https://gateway.api.esante.gouv.fr/fhir/v2/Practitioner
?identifier={RPPS_NUMBER}
En v2, le paramètre identifier accepte le numéro RPPS nu. La valeur attendue est le numéro seul, sans le préfixe 8 du SubjectNameID de PSC.
La syntaxe FHIR system|value reste possible si vous voulez lever toute ambiguïté avec l'IDNPS : le system du RPPS est https://rpps.esante.gouv.fr, celui de l'IDNPS est l'OID urn:oid:1.2.250.1.71.4.2.1. Vous pouvez aussi filtrer avec le paramètre identifier-type.
Pour récupérer en une requête le professionnel et ses situations d'exercice, ajoutez un _revinclude :
GET https://gateway.api.esante.gouv.fr/fhir/v2/Practitioner
?identifier={RPPS_NUMBER}
&_revinclude=PractitionerRole:practitioner
La réponse
{
"resourceType": "Bundle",
"type": "searchset",
"total": 1,
"entry": [
{
"resource": {
"resourceType": "Practitioner",
"identifier": [
{
"type": {
"coding": [
{
"system": "https://hl7.fr/ig/fhir/core/CodeSystem/fr-core-cs-v2-0203",
"code": "RPPS"
}
]
},
"system": "https://rpps.esante.gouv.fr",
"value": "10101234567"
}
],
"active": true,
"name": [
{
"family": "MARTIN",
"given": ["Marie"]
}
],
"qualification": [
{
"code": {
"coding": [
{
"system": "urn:oid:1.2.250.1.213.1.6.1.109",
"code": "SM26",
"display": "Médecine générale"
}
]
}
}
]
}
}
]
}
Les 4 vérifications à effectuer
| # | Vérification | Champ | Condition |
|---|---|---|---|
| 1 | Le praticien existe | bundle.total |
>= 1 |
| 2 | Le praticien est en exercice | entry[0].resource.active |
=== true |
| 3 | La qualification correspond | qualification[].code.coding[].code |
Cohérent avec le SubjectRole PSC |
| 4 | Le nom correspond | name[0].family / name[0].given |
Cross-check avec les claims PSC |
Le champ active prend tout son sens sur un numéro déclaré : il distingue une fiche fermée (retraite, radiation, décès) d'un professionnel réellement en activité. Sur un RPPS issu de PSC, il sera toujours à true, puisque l'authentification a déjà eu lieu en amont sur ce référentiel.
La vérification #4 est celle qu'on oublie le plus souvent alors qu'elle porte l'essentiel de la valeur en contexte déclaratif : un numéro RPPS valide saisi par quelqu'un d'autre que son titulaire reste un numéro valide.
Implémentation NestJS
Le service de vérification
Le service ci-dessous s'adresse au cas déclaratif : un numéro saisi ou importé, dont vous voulez confirmer qu'il correspond à une fiche ouverte de l'Annuaire.
// auth/services/rpps-verification.service.ts
import { Injectable, Logger } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { ConfigService } from '@nestjs/config';
import { Cache } from 'cache-manager';
import { Inject } from '@nestjs/common';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
@Injectable()
export class RppsVerificationService {
private readonly logger = new Logger(RppsVerificationService.name);
constructor(
private httpService: HttpService,
private configService: ConfigService,
@Inject(CACHE_MANAGER) private cacheManager: Cache,
) {}
/**
* Confirme qu'un numéro RPPS déclaré correspond à une fiche
* ouverte de l'Annuaire Santé. À appeler à la saisie du numéro
* (inscription, import, back-office), pas à chaque connexion
* d'un utilisateur déjà authentifié via Pro Santé Connect.
*/
async verify(rppsNumber: string): Promise<boolean> {
// Vérifier le cache (TTL 24h)
const cacheKey = `rpps:${rppsNumber}`;
const cached = await this.cacheManager.get<boolean>(cacheKey);
if (cached !== undefined && cached !== null) {
return cached;
}
try {
const url = `${this.configService.get('ANNUAIRE_SANTE_URL')}/fhir/v2/Practitioner`;
const response = await this.httpService.axiosRef.get(url, {
params: {
identifier: rppsNumber,
},
headers: {
'ESANTE-API-KEY': this.configService.get(
'ANNUAIRE_SANTE_API_KEY',
),
},
});
const bundle = response.data;
if (!bundle.entry?.length) {
await this.cacheManager.set(cacheKey, false, 86400000); // 24h
return false;
}
const practitioner = bundle.entry[0].resource;
const isActive = practitioner.active === true;
await this.cacheManager.set(cacheKey, isActive, 86400000);
return isActive;
} catch (error) {
this.logger.error(
`RPPS verification failed for ${rppsNumber}: ${error.message}`,
);
// En cas d'erreur API, on refuse l'accès par précaution
return false;
}
}
}
Quand déclencher l'appel
Le bon moment est celui où la donnée entre dans votre système : validation du formulaire d'inscription, traitement d'un import, création d'une fiche depuis le back-office. Une fois le numéro validé et rattaché à un compte, le revérifier à chaque connexion n'apporte rien et consomme votre quota.
Le cache de 24 heures présent dans le service couvre les cas de saisies répétées et les imports contenant des doublons. Il évite d'envoyer dix fois la même requête pendant qu'un utilisateur corrige son formulaire.
Reste une question de gouvernance métier : que faire si une fiche se ferme des mois après l'inscription ? Plutôt qu'un contrôle à chaque requête HTTP, un job planifié qui repasse sur votre base de professionnels et signale les fiches devenues inactives fait le travail sans dégrader l'expérience.
Variables d'environnement
# Annuaire Santé (vérification RPPS)
ANNUAIRE_SANTE_URL=https://gateway.api.esante.gouv.fr
ANNUAIRE_SANTE_API_KEY=your-gravitee-api-key
Les pièges à connaître
1. Passer le RPPS avec le préfixe 8. Le SubjectNameID de PSC est au format 8{RPPS}. L'API Annuaire attend le numéro RPPS seul, sans le préfixe. Pensez à faire subjectNameId.substring(1) avant d'appeler l'API.
2. Coder contre la v1 sans le savoir. Appeler gateway.api.esante.gouv.fr/fhir sans numéro de version vous sert du v1, alors que la v1 est en fin de vie. Vous vous retrouvez à écrire du code contre le header GRAVITEE-API-KEY et la syntaxe identifier=http://rpps.fr|{number}, tous deux abandonnés en v2. Mettez /fhir/v2/ en dur dans votre configuration.
3. Ne pas gérer les erreurs API. L'API peut retourner des 429 (rate limit) ou des 503 (maintenance). Prévoyez un comportement par défaut : refuser l'accès en cas d'échec (fail closed) est plus sûr que de laisser passer (fail open).
4. Vérifier au mauvais moment. L'appel se fait à l'entrée de la donnée dans votre système, pas à chaque connexion ni à chaque requête HTTP. Sur un compte déjà rattaché à un RPPS validé, la vérification répétée consomme votre quota sans rien changer à la décision.
5. Ignorer le champ active. Sur un numéro déclaré, la simple existence de la fiche ne suffit pas : un praticien radié ou retraité reste présent dans l'annuaire avec active: false. C'est le seul champ qui distingue une fiche ouverte d'une fiche fermée. Détail utile en v2 : sur une ressource inactive, l'API ne renvoie que l'ID technique, l'identifiant du professionnel et le champ active. Si votre parsing suppose la présence de name ou de qualification, il cassera précisément sur ces fiches.
6. Doubler Pro Santé Connect avec un contrôle de statut. Si le numéro RPPS provient d'une authentification PSC, le droit d'exercice a déjà été tranché en amont : la révocation de la CPS et de l'e-CPS suit la fermeture de la fiche RPPS. Utilisez l'API pour récupérer les spécialités et les structures de rattachement, pas pour relire active.
FAQ
L'API Annuaire Santé est-elle gratuite ?
Oui. L'accès en lecture à l'API FHIR est gratuit après inscription sur le portail Gravitee de l'ANS. Aucun frais d'abonnement ni de volume. Il suffit d'une clé API transmise dans le header ESANTE-API-KEY.
Peut-on vérifier un RPPS sans Pro Santé Connect ?
Oui, et c'est même le cas d'usage principal. L'API Annuaire Santé est indépendante de PSC : elle accepte n'importe quel numéro RPPS, quelle que soit sa provenance. Un formulaire d'inscription, un import de fichier ou un back-office administrateur sont autant de contextes où vous manipulez un RPPS sans passer par PSC, et où la vérification est justifiée.
Faut-il revérifier le RPPS après une authentification Pro Santé Connect ?
Non, pas pour contrôler le droit d'exercice. PSC repose sur l'Annuaire Santé, alimenté par le RPPS : une radiation ferme la fiche et entraîne la révocation de la carte CPS et de l'e-CPS, donc le professionnel concerné n'obtient plus de jeton PSC. Relire le champ active après coup interroge le même référentiel sans ajouter de garantie. L'appel à l'API garde en revanche tout son intérêt pour récupérer les spécialités, savoir-faire et structures de rattachement qui pilotent vos habilitations.
À quelle fréquence appeler l'API ?
À l'entrée de la donnée dans votre système : saisie du numéro, import, création de fiche. Pour surveiller la fermeture éventuelle d'une fiche après coup, un job planifié sur votre base de professionnels est plus adapté qu'un contrôle à chaque connexion, et beaucoup plus économe en quota.
L'API fonctionne-t-elle pour les pharmaciens et infirmiers ?
Oui. L'Annuaire Santé couvre tous les professionnels inscrits au RPPS : médecins, pharmaciens, chirurgiens-dentistes, sages-femmes, infirmiers, masseurs-kinésithérapeutes, et d'autres. Le endpoint Practitioner et le paramètre identifier fonctionnent de la même manière pour tous.
Conclusion
La vérification RPPS via l'API FHIR de l'Annuaire Santé est simple à implémenter : une requête GET, un header API key, et quatre champs à lire dans la réponse. La difficulté n'est pas technique, elle est dans le cadrage. Vérifiez les numéros dont l'origine n'est pas fiable, laissez Pro Santé Connect trancher le droit d'exercice quand il est dans la boucle, et servez-vous de l'Annuaire pour ce qu'il fait de mieux dans ce cas : décrire l'exercice réel du professionnel au sein de votre application de santé.
Besoin d'intégrer l'authentification e-santé de bout en bout ? Chez Bob le développeur, on accompagne les projets santé de l'architecture au déploiement. Contactez-nous.
