"> Aller au contenu principal
PHP PHP PHP v1.0.0 PolyForm NC 1.0

RPPS API PHP SDK

qrcommunication/rppsapi

PHP 8.1+, guzzlehttp/guzzle ^7.0

Installation

bash
composer require qrcommunication/rppsapi
Requirements : PHP 8.2+, ext-json. The guzzlehttp/guzzle dependency is included automatically.

Quick Start

Two main patterns: retrieve a full profile by RPPS number, or search for practitioners by last name, first name and/or postal code.

php
<?php

use QrCommunication\RppsApi\RppsClient;
use QrCommunication\RppsApi\RppsClientOptions;
use QrCommunication\RppsApi\Dto\RppsSearchCriteria;
use QrCommunication\RppsApi\Exception\RppsException;

$client = new RppsClient(new RppsClientOptions(
    fhirApiKey: $_ENV['FHIR_API_KEY'] ?? null,
));

// ── Profil complet par numéro RPPS ─────────────────────────────

try {
    $profil = $client->getByRpps('10005173140');

    echo $profil->identite->civiliteExercice->libelle . ' ';
    echo $profil->identite->prenomExercice . ' ' . $profil->identite->nomExercice . "\n";
    echo 'Profession : ' . $profil->profession->libelle . "\n";

    foreach ($profil->activites as $activite) {
        echo '  Structure : ' . $activite->structure->raisonSociale . "\n";
        echo '  Adresse   : ' . $activite->structure->adresse->libelleCommune . "\n";
    }

    foreach ($profil->diplomesEtAutorisations as $da) {
        if ($da->diplome) {
            echo '  Diplôme : ' . $da->diplome->libelle . "\n";
        }
    }

    foreach ($profil->savoirFaire as $sf) {
        echo '  Savoir-faire : ' . $sf->savoirFaire->libelle . "\n";
    }

    foreach ($profil->messageriesMssante as $mss) {
        echo '  MSSanté : ' . $mss->adresseBal . "\n";
    }

    // Statut des sources interrogées
    foreach ($profil->sources as $source) {
        $status = $source->success ? 'OK' : 'ERREUR';
        echo "  [{$status}] {$source->source->value} — {$source->durationMs}ms\n";
    }

} catch (RppsException $e) {
    echo 'Erreur RPPS : ' . $e->getMessage() . "\n";
}

// ── Recherche par critères ──────────────────────────────────────

$results = $client->search(new RppsSearchCriteria(
    nom: 'DUPONT',
    codePostal: '75',
));

echo "Total trouvé : {$results->total}\n";
echo "Durée : {$results->durationMs}ms\n";

foreach ($results->results as $r) {
    echo "  {$r->civilite} {$r->prenomExercice} {$r->nomExercice}";
    echo " — {$r->profession->libelle}";
    echo " — {$r->libelleCommune}\n";
}

// ── Pagination ──────────────────────────────────────────────────

$page2 = $client->search(new RppsSearchCriteria(nom: 'MARTIN'), page: 2, pageSize: 50);

Configuration

RppsClientOptions is a readonly object passed to the RppsClient constructor. All parameters have working default values.

php
use QrCommunication\RppsApi\RppsClientOptions;

$options = new RppsClientOptions(
    fhirBaseUrl:      'https://gateway.api.esante.gouv.fr/fhir/v2',  // URL de base FHIR ANS
    fhirApiKey:       'votre-cle-esante-api-key',                    // Clé API Gravitee (optionnel)
    tabularBaseUrl:   'https://tabular-api.data.gouv.fr/api/resources', // URL Tabular data.gouv.fr
    timeout:          30.0,                                           // Timeout Guzzle en secondes
    tabularPageSize:  100,                                            // Taille de page pour les requêtes Tabular
    disabledSources:  ['fhir', 'mssante'],                           // Sources à désactiver
);
Parameter Type Default Description
fhirBaseUrl string 'https://gateway.api.esante.gouv.fr/fhir/v2' Base URL of the ANS FHIR API
fhirApiKey string|null null Gravitee API key (ESANTE-API-KEY). Without this key, the FHIR source is ignored.
tabularBaseUrl string 'https://tabular-api.data.gouv.fr/api/resources' Base URL of the Tabular data.gouv.fr API
timeout float 30.0 Timeout in seconds for Guzzle HTTP requests
tabularPageSize int 100 Number of rows per page for Tabular requests (used by search)
disabledSources string[] [] List of sources to disable. Accepted values: 'fhir', 'personne-activite', 'diplomes', 'savoir-faire', 'carte-cps', 'mssante'

Methods

getByRpps

PUBLIC
getByRpps(string $rpps): RppsFullProfile

Retrieves the full profile of a practitioner from their RPPS number (11 digits). Queries all enabled sources (identity, activities, degrees, skills, CPS cards, MSSanté mailboxes, FHIR) and returns an aggregated object.

ParameterTypeDescription
$rpps string 11-digit RPPS number. Leading/trailing spaces are ignored.
Throws RppsException if the RPPS number does not contain exactly 11 digits.
php
$profil = $client->getByRpps('10005173140');
// Retourne RppsFullProfile

validateRpps

STATIC
static validateRpps(string $rpps): string

Validates an RPPS number. Returns the cleaned number (without spaces) if valid. Throws RppsException if the format is incorrect (must contain exactly 11 digits).

php
// Validation statique (pas besoin d'instancier RppsClient)
$clean = RppsClient::validateRpps('10005173140'); // '10005173140'
$clean = RppsClient::validateRpps(' 10005173140 '); // '10005173140' (trim)

// Lance RppsException :
RppsClient::validateRpps('123');          // Trop court
RppsClient::validateRpps('1234567890A'); // Contient une lettre

DTOs

All DTOs are final readonly classes. Missing values are empty strings '' or default instances (never null), unless otherwise noted.

RppsFullProfile

Aggregated profile returned by getByRpps().

PropertyTypeDescription
rppsstring11-digit RPPS number
identificationNationalestringNational PP identifier
identiteIdentiteTitle, last name and first name of practice
professionProfessionProfession code and label, professional category
activitesActivite[]Activities and linked structures (one entry per structure with technical identifier)
diplomesEtAutorisationsDiplomeEtAutorisation[]Obtained degrees and practice authorizations
savoirFaireSavoirFaire[]Declared specialties and competencies
cartesCpsCarteCps[]CPS cards (Healthcare Professional Card)
messageriesMssanteMessagerieMssante[]MSSanté secure messaging addresses
fhirFhirDataFHIR data (Practitioner + PractitionerRoles). Empty if no API key.
sourcesSourceStatus[]Status of each queried source (success, duration, possible error)
queriedAtstringISO 8601 timestamp of the request
totalDurationMsfloatTotal execution time in milliseconds

Identite

Civil identity of the practitioner's practice.

PropertyTypeDescription
civiliteCodeLabelAdministrative title (e.g. M / Mr.)
civiliteExerciceCodeLabelPractice title (e.g. DR / Doctor)
nomExercicestringPractice last name
prenomExercicestringPractice first name

Profession

Profession declared in the RPPS.

PropertyTypeDescription
codestringProfession code (e.g. 10)
libellestringProfession label (e.g. Médecin)
categorieCodeLabelProfessional category (code + label)

Activite

Professional activity linked to a structure.

PropertyTypeDescription
modeExerciceCodeLabelPractice mode (e.g. self-employed, salaried)
savoirFaireCodeLabelSkill associated with the activity
typeSavoirFaireCodeLabelType of skill
secteurActiviteCodeLabelActivity sector
sectionTableauPharmaciensCodeLabelSection of the pharmacists' register
roleCodeLabelRole within the structure
genreActiviteCodeLabelActivity type
autoriteEnregistrementstringRegistration authority
structureStructureLinked practice structure

Structure

Healthcare facility or practice office.

PropertyTypeDescription
identifiantTechniquestringTechnical identifier of the structure
raisonSocialestringLegal name of the site
enseigneCommercialestringCommercial name of the site
numeroSiretstringSIRET number
numeroSirenstringSIREN number
numeroFinessSitestringFINESS number of the site
numeroFinessEtablissementJuridiquestringFINESS number of the legal entity
telephonestringPrimary phone number
telephone2stringSecondary phone number
telecopiestringFax number
emailstringEmail address of the structure
codeDepartementstringDepartment code
libelleDepartementstringDepartment label
ancienIdentifiantstringFormer identifier of the structure
adresseAdresseStructureFull postal address

AdresseStructure

Normalized postal address of a structure.

PropertyTypeDescription
complementDestinatairestringAddressee complement
complementPointGeographiquestringGeographic location complement
numeroVoiestringStreet number
indiceRepetitionVoiestringStreet number repetition index (bis, ter…)
codeTypeVoiestringStreet type code
libelleTypeVoiestringStreet type label (Rue, Avenue…)
libelleVoiestringStreet name
mentionDistributionstringDistribution note
bureauCedexstringCedex office
codePostalstringPostal code
codeCommunestringINSEE municipality code
libelleCommunestringMunicipality label
codePaysstringCountry code
libellePaysstringCountry label

DiplomeEtAutorisation

Obtained degree or practice authorization. Each entry represents either a degree or an authorization (never both at once). Properties are null if the value is absent.

PropertyTypeDescription
typeDiplomeCodeLabel|nullType of degree obtained (non-null if degree)
diplomeCodeLabel|nullDegree obtained (code + label)
typeAutorisationCodeLabel|nullAuthorization type (non-null if authorization)
disciplineAutorisationCodeLabel|nullAuthorization discipline

SavoirFaire

Specialty or competency declared in the RPPS.

PropertyTypeDescription
professionCodeLabelProfession associated with the skill
categorieProfessionnelleCodeLabelProfessional category
typeSavoirFaireCodeLabelType of skill (specialty, capacity…)
savoirFaireCodeLabelSkill (code + label)

CarteCps

Healthcare Professional Card (CPS) associated with the practitioner.

PropertyTypeDescription
typeCarteCodeLabelCPS card type
numeroCartestringCard number
identifiantNationalCartestringNational identifier stored in the card
dateDebutValiditestringValidity start date
dateFinValiditestringValidity end date
dateOppositionstringOpposition date (if card is opposed)
dateMiseAJourstringLast update date

MessagerieMssante

MSSanté secure messaging mailbox.

PropertyTypeDescription
typeBalstringMSSanté mailbox type
adresseBalstringMSSanté address (e.g. jean.dupont@medecin.mssante.fr)
dematerialisationbooltrue if dematerialization is enabled
savoirFaireCodeLabelSkill associated with this mailbox
structureIdentifiantstringIdentifier of the linked structure
structureTypeIdentifiantstringIdentifier type of the structure
serviceRattachementstringAttached service
raisonSocialestringLegal name of the mailbox structure
codePostalstringPostal code of the mailbox structure
departementstringDepartment of the mailbox structure

FhirData

Raw FHIR data returned by the ANS API. Available only if fhirApiKey is configured and the source is not disabled.

PropertyTypeDescription
practitionerarray|nullRaw FHIR Practitioner resource (decoded from JSON)
practitionerRolesarray[]Array of FHIR PractitionerRole resources (up to 50)

CodeLabel

Code/label pair reused in all DTOs for reference data (title, profession, practice mode, etc.).

PropertyTypeDescription
codestringValue code (e.g. '10', 'DR')
libellestringHuman-readable label (e.g. 'Médecin', 'Docteur')
php
$profil->profession->libelle;           // 'Médecin'
$profil->profession->code;              // '10'
$profil->identite->civiliteExercice->libelle; // 'Docteur'

$arr = $profil->profession->categorie->toArray();
// ['code' => 'C', 'libelle' => 'Civil']

SourceStatus

Execution status of a data source.

PropertyTypeDescription
sourceSourceNameSource identifier (enum)
successbooltrue if the request succeeded
rowCountintNumber of rows returned
durationMsfloatExecution time in milliseconds
errorstring|nullError message if success === false, or reason for disabling

RppsSearchCriteria

Criteria passed to search(). At least one non-null, non-empty criterion is required.

PropertyTypeDescription
nomstring|nullPractice last name (partial contains search)
prenomstring|nullPractice first name (partial contains search)
codePostalstring|nullPostal code — exact filter if 5 characters, otherwise contains

RppsSearchResponse

Paginated response returned by search().

PropertyTypeDescription
resultsRppsSearchResult[]Results for the current page (deduplicated by RPPS)
totalintTotal number of results (all pages)
pageintCurrent page number
pageSizeintNumber of results per page
durationMsfloatExecution time in milliseconds
criteriaRppsSearchCriteriaCriteria used for this request

RppsSearchResult

Lightweight search result (fewer fields than RppsFullProfile). For a full profile, call getByRpps($result->rpps).

PropertyTypeDescription
rppsstringRPPS number
identificationNationalestringNational PP identifier
civilitestringPractice title label
nomExercicestringPractice last name
prenomExercicestringPractice first name
professionCodeLabelProfession (code + label)
categorieProfessionnelleCodeLabelProfessional category
modeExerciceCodeLabelPractice mode
savoirFaireCodeLabelPrimary skill
raisonSocialestringLegal name of the structure
codePostalstringPostal code of the structure
libelleCommunestringMunicipality of the structure
departementstringDepartment of the structure

Data Sources

The SDK aggregates 6 sources queried on each call to getByRpps(). Each source corresponds to a resource on data.gouv.fr or the ANS FHIR API.

Source Enum SourceName Resource ID Provided data
personne-activite PersonneActivite fffda7e9-0ea2-4c35-bba0-4496f3af935d Identity, profession, activities, structures
diplomes Diplomes 41ae70ac-90c8-4c4e-8644-4ef1b100f045 Obtained degrees and practice authorizations
savoir-faire SavoirFaire fb55f15f-bd61-4402-b551-51ef387f2fab Declared specialties and competencies
carte-cps CarteCps 210eb05e-564b-42be-994a-d1800b63e9b7 CPS cards (type, number, validity)
mssante Mssante afe01105-d9a1-41fe-921f-e40ea48b2ba6 MSSanté secure messaging
fhir Fhir — ANS FHIR API Practitioner + PractitionerRoles FHIR (API key required)
The 5 Tabular sources query tabular-api.data.gouv.fr/api/resources/{resource-id}/data/ with an exact filter on Identifiant PP (RPPS column). The FHIR source uses gateway.api.esante.gouv.fr/fhir/v2/Practitioner.

Enum SourceName

PHP backed enum used in SourceStatus::$source and RppsClientOptions::$disabledSources.

php
use QrCommunication\RppsApi\Enum\SourceName;

SourceName::Fhir->value;             // 'fhir'
SourceName::PersonneActivite->value; // 'personne-activite'
SourceName::Diplomes->value;         // 'diplomes'
SourceName::SavoirFaire->value;      // 'savoir-faire'
SourceName::CarteCps->value;         // 'carte-cps'
SourceName::Mssante->value;          // 'mssante'
CaseValue
SourceName::Fhir'fhir'
SourceName::PersonneActivite'personne-activite'
SourceName::Diplomes'diplomes'
SourceName::SavoirFaire'savoir-faire'
SourceName::CarteCps'carte-cps'
SourceName::Mssante'mssante'

Error Handling

The SDK throws RppsException (extends \RuntimeException) in two cases: invalid RPPS number or missing search criteria. Network or API errors are silently caught and recorded in RppsFullProfile::$sources with success === false.

php
use QrCommunication\RppsApi\Exception\RppsException;

// ── Cas 1 : RPPS invalide ───────────────────────────────────────
try {
    $profil = $client->getByRpps('123');
} catch (RppsException $e) {
    // "Numéro RPPS invalide : "123". Le RPPS doit contenir exactement 11 chiffres."
    echo $e->getMessage();
}

// ── Cas 2 : aucun critère de recherche ─────────────────────────
try {
    $results = $client->search(new RppsSearchCriteria());
} catch (RppsException $e) {
    // "Au moins un critère de recherche est obligatoire (nom, prenom ou codePostal)."
    echo $e->getMessage();
}

// ── Cas 3 : erreur source (silencieuse, consultable après coup) ─
$profil = $client->getByRpps('10005173140');

foreach ($profil->sources as $source) {
    if (!$source->success) {
        // La source a échoué, mais le reste du profil est disponible
        echo "[{$source->source->value}] ERREUR : {$source->error}\n";
    }
}

Examples

Full profile by RPPS

php
$client = new RppsClient(new RppsClientOptions(
    fhirApiKey: getenv('ESANTE_API_KEY'),
));

$profil = $client->getByRpps('10005173140');

// Identité
echo $profil->identite->civiliteExercice->libelle;  // 'Docteur'
echo $profil->identite->prenomExercice;              // 'JEAN'
echo $profil->identite->nomExercice;                 // 'DUPONT'

// Profession
echo $profil->profession->libelle;                   // 'Médecin'
echo $profil->profession->code;                      // '10'

// Structures d'exercice
foreach ($profil->activites as $activite) {
    echo $activite->structure->raisonSociale . "\n";
    echo $activite->structure->adresse->libelleCommune . ' ';
    echo $activite->structure->adresse->codePostal . "\n";
    echo $activite->modeExercice->libelle . "\n";
}

// Diplômes
foreach ($profil->diplomesEtAutorisations as $da) {
    if ($da->diplome !== null) {
        echo '[Diplôme] ' . $da->diplome->libelle . "\n";
    }
    if ($da->typeAutorisation !== null) {
        echo '[Autorisation] ' . $da->typeAutorisation->libelle . "\n";
    }
}

// Messageries MSSanté
foreach ($profil->messageriesMssante as $mss) {
    echo $mss->adresseBal . ' (' . $mss->typeBal . ")\n";
}

// FHIR (si clé configurée)
if ($profil->fhir->practitioner !== null) {
    echo 'ID FHIR : ' . $profil->fhir->practitioner['id'] . "\n";
    echo count($profil->fhir->practitionerRoles) . " rôle(s) FHIR\n";
}

Disable sources

Useful to speed up requests when certain data is not needed.

php
// Identité + profession uniquement (sans CPS, MSSanté, FHIR)
$clientLeger = new RppsClient(new RppsClientOptions(
    disabledSources: ['carte-cps', 'mssante', 'fhir'],
));

// Identité seulement (désactiver tout sauf personne-activite)
$clientMinimal = new RppsClient(new RppsClientOptions(
    disabledSources: ['carte-cps', 'mssante', 'fhir', 'diplomes', 'savoir-faire'],
));

// Vérifier quelles sources ont été désactivées dans la réponse
$profil = $clientLeger->getByRpps('10005173140');
foreach ($profil->sources as $src) {
    if (!$src->success && $src->error === 'disabled') {
        echo "[DESACTIVE] {$src->source->value}\n";
    }
}

FHIR Configuration

The ANS FHIR API is free but requires a Gravitee API key. Without a key, the FHIR source is ignored (no error, the profile remains complete from other sources).

  1. Create an account on portal.api.esante.gouv.fr
  2. Create an application
  3. Subscribe to the API Annuaire Santé en libre accès offer
  4. Retrieve the ESANTE-API-KEY key
php
$client = new RppsClient(new RppsClientOptions(
    fhirApiKey: $_ENV['ESANTE_API_KEY'], // ou getenv('ESANTE_API_KEY')
));
The key is sent in the HTTP header ESANTE-API-KEY on each request to gateway.api.esante.gouv.fr/fhir/v2. It is never transmitted to the Tabular APIs.

AI Skill

The SDK includes an AI skill that installs complete documentation directly into your code agent (Claude Code, Cursor, Codex, Windsurf, Cline, Aider, Gemini CLI).

bash
bash vendor/qrcommunication/rppsapi/skill/install.sh

Manual installation: cp -r vendor/qrcommunication/rppsapi/skill ~/.claude/skills/sdk-rpps