API GoodDoctor
Une API REST claire pour gérer les médecins.
GoodDoctor est une API de style Stripe pour l'ERP hospitalier. Écritures idempotentes, pagination par curseur, journal d'événements et webhooks signés, avec la même forme de ressource prévisible sur chaque endpoint.
Construite sur quelques idées simples
Apprenez ces six concepts une fois et chaque endpoint se comporte comme vous l'attendez.
Authentification par jeton
Échangez un email et un mot de passe sur /v1/auth/login contre un JWT à courte durée de vie, puis envoyez-le comme jeton Bearer à chaque requête.
Écritures idempotentes
Passez une Idempotency-Key sur les requêtes de création. Une nouvelle tentative avec la même clé renvoie le résultat d'origine au lieu de le dupliquer.
Pagination par curseur
Les endpoints de liste renvoient les pages les plus récentes d'abord. Parcourez-les avec limit et starting_after, has_more vous dit quand vous arrêter.
Événements
Chaque changement d'état est enregistré comme un événement que vous pouvez lister et rejouer via /v1/events, pour une piste d'audit complète.
Webhooks signés
Enregistrez des endpoints pour recevoir les événements en temps réel. Les livraisons sont signées et réessayées avec un délai progressif jusqu'à acquittement.
Ressources prévisibles
Des formes de ressources de style Stripe : identifiants stables, champ object et horodatages Unix. Snake_case en entrée, snake_case en sortie.
Démarrage
Trois étapes, de vos identifiants à votre premier médecin créé.
- 01
Obtenir un jeton
Envoyez vos identifiants en POST sur /v1/auth/login et lisez access_token dans la réponse.
- 02
Appeler l'API
Joignez le jeton dans l'en-tête Authorization: Bearer à chaque requête vers /v1/doctors et les autres ressources.
- 03
Écouter les événements
Enregistrez un endpoint de webhook, ou interrogez /v1/events, pour réagir aux changements en temps réel.
Exemples par endpoint
Chaque endpoint, avec un exemple prêt à copier en TypeScript, Java (Spring Boot) et Python.
/v1/auth/loginS'authentifier
Échangez vos identifiants contre un jeton Bearer à courte durée de vie.
const res = await fetch("http://localhost:8080/v1/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
email: "admin@hospital.cm",
password: "changeme123",
}),
});
const { access_token } = await res.json();/v1/doctorsCréer un médecin
Création idempotente : réessayez avec la même Idempotency-Key sans créer de doublon.
const res = await fetch("http://localhost:8080/v1/doctors", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
first_name: "Amina",
last_name: "Okafor",
gender: "FEMALE",
type: "SPECIALISTE",
specialisations: ["CARDIOLOGY"],
email: "amina@hospital.cm",
}),
});
const doctor = await res.json();/v1/doctorsLister les médecins
Pagination par curseur : utilisez limit et starting_after, has_more indique s'il reste des pages.
const res = await fetch(
"http://localhost:8080/v1/doctors?limit=10",
{ headers: { Authorization: `Bearer ${token}` } },
);
const { data, has_more } = await res.json();/v1/doctors/{id}Récupérer un médecin
Lit une seule ressource médecin par son identifiant.
const id = "doc_123";
const res = await fetch(
`http://localhost:8080/v1/doctors/${id}`,
{ headers: { Authorization: `Bearer ${token}` } },
);
const doctor = await res.json();/v1/doctors/{id}Mettre à jour un médecin
Mise à jour partielle : envoyez uniquement les champs à modifier.
const id = "doc_123";
const res = await fetch(
`http://localhost:8080/v1/doctors/${id}`,
{
method: "PATCH",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({ phone: "+237 690 00 00 00" }),
},
);
const doctor = await res.json();/v1/doctors/{id}Supprimer un médecin
Renvoie un accusé de suppression { id, object, deleted }.
const id = "doc_123";
const res = await fetch(
`http://localhost:8080/v1/doctors/${id}`,
{
method: "DELETE",
headers: { Authorization: `Bearer ${token}` },
},
);
const { deleted } = await res.json();/v1/eventsLister les événements
Parcourez le journal d'audit de tous les changements d'état.
const res = await fetch(
"http://localhost:8080/v1/events?limit=20",
{ headers: { Authorization: `Bearer ${token}` } },
);
const { data } = await res.json();/v1/webhook_endpointsEnregistrer un webhook
Le secret de signature n'est renvoyé qu'une seule fois, à la création.
const res = await fetch(
"http://localhost:8080/v1/webhook_endpoints",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({
url: "https://example.com/webhooks",
enabled_events: "*",
}),
},
);
const { signing_secret } = await res.json();Référence des endpoints
Le cœur de l'API. Tous les chemins sont relatifs à votre URL de base.
| POST | /v1/auth/login | S'authentifier |
| POST | /v1/doctors | Créer un médecin |
| GET | /v1/doctors | Lister les médecins |
| GET | /v1/doctors/{id} | Récupérer un médecin |
| PATCH | /v1/doctors/{id} | Mettre à jour un médecin |
| DELETE | /v1/doctors/{id} | Supprimer un médecin |
| GET | /v1/events | Lister les événements |
| POST | /v1/webhook_endpoints | Enregistrer un webhook |
Prêt à intégrer ?
Obtenez un jeton, envoyez votre première requête et configurez un webhook. Une question ou un besoin d'accès ? Écrivez-nous.