Download OpenAPI specification:
Contrat REST vendor-neutral entre la borne d'accueil patient (ApiBorne kiosk) et l'éditeur du système de gestion médical. Il couvre le parcours patient complet : identification, consultation du RDV, mise à jour du patient, gestion des documents, check-in et opérations satellites.
Pendant le parcours patient, l'éditeur est appelé selon l'un des deux modes de
connectivité configurés côté ApiBorne (réglage kioskContractVia, page
Intégration de l'admin) :
{serveur ApiBorne}/api/contractRelay/api/apiborneIntegrationService/... et
le serveur ApiBorne relaie la requête telle quelle vers l'éditeur
(passthrough — éditeur injoignable → 502 RELAY_UPSTREAM_UNREACHABLE côté
borne).Le contrat vu par l'éditeur est identique dans les deux modes : seul le chemin réseau change. Dans tous les cas, le serveur ApiBorne reste requis pour la configuration de la borne au démarrage et la numérotation des tickets.
Toutes les opérations du contrat sont OBLIGATOIRES. Il n'y a pas de routes
optionnelles ni de déclaration de support : un éditeur qui n'a pas la
fonctionnalité implémente la forme minimale conforme — liste de documents vide
(la borne saute le flow), 204 sans effet (PATCH patient, prescripteur), 404
systématique (codes de convocation non gérés), 401 INVALID_CREDENTIALS
(pas de comptes personnel), { "ready": true } (pas de notion de notification).
C'est ce qui garde la configuration côté ApiBorne simple et sans exception.
Chaque requête porte deux headers obligatoires :
| Header | Contenu |
|---|---|
X-Kiosk-Auth-Key |
Clé d'autorisation partagée (provisionnée chez l'éditeur, connue de la conf borne) |
X-Kiosk-Device-Id |
Identifiant unique du device borne, connu de l'éditeur |
L'éditeur DOIT valider les deux : device inconnu → 401 UNKNOWN_DEVICE,
clé invalide pour ce device → 401 INVALID_AUTH_KEY.
ApiBorne envoie en plus le header X-Kiosk-Office-Id : l'identité de
l'office/du groupe de licences telle que configurée côté ApiBorne (identifiant
libre choisi par l'éditeur ; EasyDoct utilise la forme composée
{officeId}!#!{officeVisibleId}). Un éditeur multi-sites DEVRAIT s'en servir
pour sélectionner l'office cible au lieu de le résoudre via sa table de
devices (la flotte des bornes est gérée dans l'admin ApiBorne, un device
peut lui être inconnu). Un éditeur mono-site peut l'ignorer. Ce header doit
être autorisé dans Access-Control-Allow-Headers (CORS).
En mode relais serveur, ces headers (X-Kiosk-Auth-Key,
X-Kiosk-Device-Id, X-Kiosk-Office-Id) sont transmis inchangés à
l'éditeur : X-Kiosk-Device-Id reste l'identifiant de la borne réelle, jamais
celui du serveur ApiBorne — la validation attendue de l'éditeur est identique
dans les deux modes.
Le contrat impose un chiffrement applicatif de bout en bout entre la borne
et l'éditeur, par-dessus TLS : l'établissement génère une paire de clés RSA, la
clé PRIVÉE reste sur le serveur de l'éditeur, la clé PUBLIQUE est saisie dans
l'admin ApiBorne et transportée à la borne via sa configuration. Le serveur
ApiBorne et tous les intermédiaires réseau sont incapables de déchiffrer
(zero-knowledge) : en mode relais serveur, le relais ne voit passer que des
corps chiffrés (passthrough zero-knowledge). C'est aussi ce chiffrement qui
rend acceptable une URL contrat http sur un réseau local en mode borne
directe.
Le chiffrement s'applique aux routes de communication émises par la borne
(les 10 opérations du parcours patient : identifyPatients,
getAppointmentByCode, getAppointmentById, updatePatient,
setAppointmentPrescriber, listAppointmentDocuments,
uploadAppointmentDocument, deleteAppointmentDocument, checkInAppointment,
getNotificationReadiness) — requêtes et réponses 2xx.
Ne sont PAS chiffrés :
openapi-config.yaml) : ce sont des
référentiels sans donnée patient, consommés par le serveur ApiBorne ;staffSignIn et setAppointmentStatus : émises par le serveur ApiBorne,
qui est le consommateur légitime de leurs réponses (E2E sans objet, TLS seul).La borne envoie deux headers sur toutes les méthodes (GET inclus, car les réponses sont sensibles) :
| Header | Contenu |
|---|---|
X-Kiosk-Encryption: v1 |
Version du protocole de chiffrement |
X-Kiosk-Encryption-Key |
SessionKey AES-256 wrappée RSA-OAEP-SHA256, en base64 |
Le corps chiffré (requêtes avec corps) remplace le JSON clair par l'enveloppe
(voir le schéma EncryptedEnvelope) :
{ "encrypted": { "v": 1, "iv": "<base64 12 octets>", "data": "<base64 ciphertext+tag>" } }
{ "encrypted": { v, iv, data } }, chiffrée avec la même sessionKey que
la requête et un IV neuf (jamais celui de la requête), plus le header
X-Kiosk-Encryption: v1.ErrorDto normal) — cela
préserve la politique de retry et le diagnostic. Les messages d'erreur ne
doivent JAMAIS contenir de données patient.Si l'éditeur ne peut pas déchiffrer (clé inconnue, tag invalide, enveloppe
malformée), il répond 400 DECRYPTION_FAILED (en clair). La borne ne retente
jamais et ne bascule jamais en clair (anti-downgrade) : l'erreur est
affichée et tracée.
La limite contractuelle de 10 Mo (uploadAppointmentDocument) s'entend sur le
JSON en clair. Le transport chiffré ajoute ~35 % (base64 du ciphertext) :
l'éditeur DOIT dimensionner sa limite de corps HTTP en conséquence.
L'éditeur PEUT conserver plusieurs clés privées et essayer chacune à l'unwrap de la sessionKey. Procédure : déployer la nouvelle clé privée chez l'éditeur AVANT de saisir la nouvelle clé publique dans l'admin ApiBorne, puis retirer l'ancienne clé privée après la propagation de la configuration.
Les deux headers doivent être ajoutés au CORS de l'éditeur :
Access-Control-Allow-Headers: …, X-Kiosk-Encryption, X-Kiosk-Encryption-KeyAccess-Control-Expose-Headers: X-Kiosk-EncryptionEn mode relais serveur, les routes du parcours ne reçoivent que des appels serveur → serveur : l'exigence CORS navigateur (preflights et headers ci-dessus) ne s'applique plus au parcours.
context)Chaque requête POST/PATCH/PUT peut porter un objet context optionnel :
context.locationId : identifiant du lieu (site) associé au device.context.config : sous-ensemble strict de la configuration borne consommé par
l'éditeur (identification, documents, checkIn).context.vendorData : données opaques précédemment renvoyées par l'éditeur (voir plus bas).Règle contractuelle : si context.config est fourni, l'éditeur DOIT l'utiliser
et NE DOIT JAMAIS rappeler le serveur ApiBorne pour obtenir de la configuration.
Si context.config est absent, l'éditeur utilise sa propre base de configuration
(mode legacy direct).
vendorDataLes réponses peuvent contenir des champs vendorData (objets JSON opaques, au niveau
réponse, patient ou rendez-vous). La borne ne les interprète jamais : elle les renvoie
tels quels dans context.vendorData des appels suivants du même parcours qui
concernent la même entité. L'éditeur peut s'en servir pour véhiculer des identifiants
internes (éviter des relectures en base).
date (YYYY-MM-DD) pour les dates de naissance,
date-time avec offset (YYYY-MM-DDThh:mm:ss±hh:mm) pour les horodatages.data:).patient.id, appointment.id, documentId, examId,
locationId…) : chaînes opaques choisies par l'éditeur (max 128 caractères,
utilisables dans une URL). La borne ne les interprète pas.Statuts HTTP réels + corps { "error": { "code", "message", "details" } } :
| Code | HTTP | Sens |
|---|---|---|
INVALID_AUTH_KEY |
401 | Clé X-Kiosk-Auth-Key invalide pour ce device |
UNKNOWN_DEVICE |
401 | X-Kiosk-Device-Id inconnu |
VALIDATION_ERROR |
400 | Requête malformée ou champ invalide |
UNKNOWN_PATIENT |
404 | Patient introuvable |
UNKNOWN_APPOINTMENT |
404 | Rendez-vous introuvable |
UNKNOWN_DOCUMENT |
404 | Document introuvable |
ALREADY_CHECKED_IN |
409 | Check-in impossible car déjà effectué (voir sémantique check-in) |
UPLOAD_TOO_LARGE |
413 | Upload au-delà de la taille max supportée |
DECRYPTION_FAILED |
400 | Enveloppe chiffrée indéchiffrable (clé inconnue, tag invalide) — jamais retenté, jamais de fallback en clair |
INTERNAL_ERROR |
500 | Erreur interne éditeur |
NOT_SUPPORTED |
501 | DÉPRÉCIÉ — toutes les opérations sont obligatoires ; répondez la forme minimale conforme plutôt que 501 |
La borne retente les erreurs réseau et les 5xx (selon sa politique de retry), mais jamais les 4xx.
Les anomalies de check-in sont transmises par code métier vendor-neutral
(ex. PR, DI), jamais par identifiant interne d'un éditeur. Le référentiel des
codes provient de la configuration borne (serveur ApiBorne).
Le contrat renvoie des données patient/RDV pures. Le matching des critères d'admission et des messages d'information (kiosk informations) est effectué côté borne à partir de sa propre configuration — l'éditeur n'a rien à implémenter.
Recherche les patients correspondant aux critères (lecture carte de santé ou saisie manuelle) et renvoie, pour chacun, ses rendez-vous du jour éligibles au parcours borne.
birthDate seul ou lastName+firstName (+ birthDate) constituent le
minimum utile ; socialSecurityId est prioritaire quand il est fourni.context.config.identification.twoFieldsIdentification vaut true,
l'éditeur DOIT aussi tenter les recherches croisées à deux champs
(nom+date, prénom+date, nom+prénom) quand la recherche stricte ne donne rien.200 avec patients: [] (pas une erreur).appointments: [].object (KioskIntegrationContext) Contexte transmis par la borne. Si | |
required | object (IdentifyCriteria) Critères d'identification. Au minimum |
{- "context": {
- "locationId": "loc-42",
- "config": {
- "identification": {
- "twoFieldsIdentification": true
}
}
}, - "criteria": {
- "socialSecurityId": "180057510612345",
- "lastName": "DURAND",
- "firstName": "MARIE",
- "birthDate": "1980-05-12"
}
}{- "patients": [
- {
- "patient": {
- "id": "string",
- "firstName": "string",
- "lastName": "string",
- "birthName": "string",
- "birthDate": "2019-08-24",
- "sex": "male",
- "email": "string",
- "mobilePhone": "string",
- "phone": "string",
- "address": {
- "line1": "string",
- "line2": "string",
- "zipCode": "string",
- "city": "string"
}, - "socialSecurityId": "string",
- "heightCm": 0,
- "weightKg": 0,
- "referringPractitioner": {
- "name": "string",
- "rppsId": "string"
}, - "vendorData": { }
}, - "appointments": [
- {
- "id": "string",
- "patientId": "string",
- "startDate": "2019-08-24T14:15:22Z",
- "convocationDate": "2019-08-24T14:15:22Z",
- "locationId": "string",
- "examId": "string",
- "examTypeId": "string",
- "examLabel": "string",
- "locationLabel": "string",
- "practitionerId": "string",
- "roomId": "string",
- "status": "scheduled",
- "prescriber": {
- "name": "string",
- "rppsId": "string"
}, - "ticketNumber": 0,
- "ticketNumberFormatted": "string",
- "managementPageUrl": "string",
- "preparatorySurveyCompleted": true,
- "vendorData": { }
}
]
}
], - "vendorData": { }
}Met à jour les données administratives du patient (sémantique PATCH : seuls
les champs présents dans patient sont modifiés ; un champ absent est
inchangé ; null explicite efface la valeur si l'éditeur le supporte).
Après un 204, la borne recharge le rendez-vous via
GET /appointments/{appointmentId} pour obtenir les données canoniques.
| patientId required | string <= 128 characters Identifiant patient ( |
object (KioskIntegrationContext) Contexte transmis par la borne. Si | |
required | object (PatientUpdate) Champs modifiables du patient (sémantique PATCH) |
{- "context": {
- "locationId": "loc-42"
}, - "patient": {
- "firstName": "Marie",
- "lastName": "Durand",
- "birthDate": "1980-05-12",
- "email": "marie.durand@example.com",
- "mobilePhone": "+33612345678",
- "address": {
- "line1": "12 rue des Lilas",
- "line2": "",
- "zipCode": "75011",
- "city": "Paris"
}, - "socialSecurityId": "280057510612345",
- "heightCm": 168,
- "weightKg": 62,
- "referringPractitioner": {
- "name": "MARTIN Paul",
- "rppsId": "10101010101"
}
}
}{- "error": {
- "code": "VALIDATION_ERROR",
- "message": "criteria.birthDate must be an ISO 8601 date (YYYY-MM-DD)",
- "details": {
- "field": "criteria.birthDate"
}
}
}Résout un rendez-vous à partir d'un code : contenu d'un QR code de convocation ou identifiant lisible communiqué au patient. L'éditeur décide des formats de code qu'il accepte ; la borne transmet le code tel quel (URL-encodé).
| code required | string <= 512 characters Code scanné (QR) ou saisi par le patient, tel quel |
{- "patient": {
- "id": "string",
- "firstName": "string",
- "lastName": "string",
- "birthName": "string",
- "birthDate": "2019-08-24",
- "sex": "male",
- "email": "string",
- "mobilePhone": "string",
- "phone": "string",
- "address": {
- "line1": "string",
- "line2": "string",
- "zipCode": "string",
- "city": "string"
}, - "socialSecurityId": "string",
- "heightCm": 0,
- "weightKg": 0,
- "referringPractitioner": {
- "name": "string",
- "rppsId": "string"
}, - "vendorData": { }
}, - "appointment": {
- "id": "string",
- "patientId": "string",
- "startDate": "2019-08-24T14:15:22Z",
- "convocationDate": "2019-08-24T14:15:22Z",
- "locationId": "string",
- "examId": "string",
- "examTypeId": "string",
- "examLabel": "string",
- "locationLabel": "string",
- "practitionerId": "string",
- "roomId": "string",
- "status": "scheduled",
- "prescriber": {
- "name": "string",
- "rppsId": "string"
}, - "ticketNumber": 0,
- "ticketNumberFormatted": "string",
- "managementPageUrl": "string",
- "preparatorySurveyCompleted": true,
- "vendorData": { }
}, - "otherAppointments": [
- {
- "id": "string",
- "patientId": "string",
- "startDate": "2019-08-24T14:15:22Z",
- "convocationDate": "2019-08-24T14:15:22Z",
- "locationId": "string",
- "examId": "string",
- "examTypeId": "string",
- "examLabel": "string",
- "locationLabel": "string",
- "practitionerId": "string",
- "roomId": "string",
- "status": "scheduled",
- "prescriber": {
- "name": "string",
- "rppsId": "string"
}, - "ticketNumber": 0,
- "ticketNumberFormatted": "string",
- "managementPageUrl": "string",
- "preparatorySurveyCompleted": true,
- "vendorData": { }
}
], - "vendorData": { }
}Résout un rendez-vous du jour à partir du numéro de ticket émis au check-in ET de la date de naissance du patient (garde d'accès). C'est le parcours de l'app patient « Pass » (saisie manuelle : le patient tape le numéro imprimé sur son ticket et sa date de naissance).
L'éditeur accepte le format de ticket qu'il expose (brut 2 ou formaté
RA-2) et vérifie que la naissance correspond au patient du RDV. Renvoie
la même forme que by-code. Ticket+naissance non concordants → 404.
object (KioskIntegrationContext) Contexte transmis par la borne. Si | |
| ticketNumber required | string <= 64 characters Numéro de ticket émis au check-in, tel que saisi/scanné par le patient. L'éditeur accepte le format qu'il expose (brut |
| birthDate required | string <date> Date de naissance du patient (ISO |
| officePlaceVisibleId required | string <= 128 characters Identifiant du lieu de soins (officePlace) où le ticket a été émis. Requis : le numéro de ticket est recyclé par lieu, l'identification est scopée au lieu. |
{- "context": {
- "locationId": "string",
- "config": {
- "identification": {
- "twoFieldsIdentification": true
}, - "documents": { },
- "checkIn": { }
}, - "vendorData": { }
}, - "ticketNumber": "string",
- "birthDate": "2019-08-24",
- "officePlaceVisibleId": "string"
}{- "patient": {
- "id": "string",
- "firstName": "string",
- "lastName": "string",
- "birthName": "string",
- "birthDate": "2019-08-24",
- "sex": "male",
- "email": "string",
- "mobilePhone": "string",
- "phone": "string",
- "address": {
- "line1": "string",
- "line2": "string",
- "zipCode": "string",
- "city": "string"
}, - "socialSecurityId": "string",
- "heightCm": 0,
- "weightKg": 0,
- "referringPractitioner": {
- "name": "string",
- "rppsId": "string"
}, - "vendorData": { }
}, - "appointment": {
- "id": "string",
- "patientId": "string",
- "startDate": "2019-08-24T14:15:22Z",
- "convocationDate": "2019-08-24T14:15:22Z",
- "locationId": "string",
- "examId": "string",
- "examTypeId": "string",
- "examLabel": "string",
- "locationLabel": "string",
- "practitionerId": "string",
- "roomId": "string",
- "status": "scheduled",
- "prescriber": {
- "name": "string",
- "rppsId": "string"
}, - "ticketNumber": 0,
- "ticketNumberFormatted": "string",
- "managementPageUrl": "string",
- "preparatorySurveyCompleted": true,
- "vendorData": { }
}, - "otherAppointments": [
- {
- "id": "string",
- "patientId": "string",
- "startDate": "2019-08-24T14:15:22Z",
- "convocationDate": "2019-08-24T14:15:22Z",
- "locationId": "string",
- "examId": "string",
- "examTypeId": "string",
- "examLabel": "string",
- "locationLabel": "string",
- "practitionerId": "string",
- "roomId": "string",
- "status": "scheduled",
- "prescriber": {
- "name": "string",
- "rppsId": "string"
}, - "ticketNumber": 0,
- "ticketNumberFormatted": "string",
- "managementPageUrl": "string",
- "preparatorySurveyCompleted": true,
- "vendorData": { }
}
], - "vendorData": { }
}Recharge un rendez-vous déjà connu de la borne (après mise à jour du patient,
ou en mode simulation). Renvoie la même forme que by-code.
| appointmentId required | string <= 128 characters Identifiant du rendez-vous ( |
{- "patient": {
- "id": "string",
- "firstName": "string",
- "lastName": "string",
- "birthName": "string",
- "birthDate": "2019-08-24",
- "sex": "male",
- "email": "string",
- "mobilePhone": "string",
- "phone": "string",
- "address": {
- "line1": "string",
- "line2": "string",
- "zipCode": "string",
- "city": "string"
}, - "socialSecurityId": "string",
- "heightCm": 0,
- "weightKg": 0,
- "referringPractitioner": {
- "name": "string",
- "rppsId": "string"
}, - "vendorData": { }
}, - "appointment": {
- "id": "string",
- "patientId": "string",
- "startDate": "2019-08-24T14:15:22Z",
- "convocationDate": "2019-08-24T14:15:22Z",
- "locationId": "string",
- "examId": "string",
- "examTypeId": "string",
- "examLabel": "string",
- "locationLabel": "string",
- "practitionerId": "string",
- "roomId": "string",
- "status": "scheduled",
- "prescriber": {
- "name": "string",
- "rppsId": "string"
}, - "ticketNumber": 0,
- "ticketNumberFormatted": "string",
- "managementPageUrl": "string",
- "preparatorySurveyCompleted": true,
- "vendorData": { }
}, - "otherAppointments": [
- {
- "id": "string",
- "patientId": "string",
- "startDate": "2019-08-24T14:15:22Z",
- "convocationDate": "2019-08-24T14:15:22Z",
- "locationId": "string",
- "examId": "string",
- "examTypeId": "string",
- "examLabel": "string",
- "locationLabel": "string",
- "practitionerId": "string",
- "roomId": "string",
- "status": "scheduled",
- "prescriber": {
- "name": "string",
- "rppsId": "string"
}, - "ticketNumber": 0,
- "ticketNumberFormatted": "string",
- "managementPageUrl": "string",
- "preparatorySurveyCompleted": true,
- "vendorData": { }
}
], - "vendorData": { }
}Reflète chez l'éditeur un changement de statut effectué dans le Cockpit ApiBorne (accueil au guichet, fin de prise en charge) — l'agenda de l'éditeur reste la source de vérité et doit refléter l'état réel.
Progression UNIQUEMENT vers l'avant (checkedIn → inCare → done) :
si le RDV est déjà à l'état demandé ou au-delà, l'appel est idempotent
(200 sans effet). Un RDV annulé ou déjà terminé n'est pas modifiable
(400 VALIDATION_ERROR).
Contrairement aux opérations borne, l'appel vient du serveur ApiBorne :
seul le header X-Kiosk-Auth-Key est requis (pas de device, comme
staff/sign-in), la clé devant correspondre à l'établissement du RDV.
| appointmentId required | string <= 128 characters Identifiant du rendez-vous ( |
| status required | string Enum: "checkedIn" "inCare" "done" État cible du RDV |
{- "status": "checkedIn"
}{- "status": "checkedIn"
}Enregistre le prescripteur du rendez-vous (typiquement après validation par le patient d'une proposition issue de l'analyse d'ordonnance). Opération idempotente : rejouer la même valeur donne le même état.
Note : le flux d'analyse d'ordonnance (analysis.prescriberProposals de la
réponse d'upload) n'est pas activé pour les intégrations libres à ce
stade — l'analyse a vocation à être portée par ApiBorne, pas exigée de
l'éditeur. Il reste pleinement utilisé par l'intégration EasyDoct.
| appointmentId required | string <= 128 characters Identifiant du rendez-vous ( |
object (KioskIntegrationContext) Contexte transmis par la borne. Si | |
required | object (PractitionerRef) Référence d'un praticien (prescripteur, médecin traitant…) |
{- "prescriber": {
- "name": "MARTIN Paul",
- "rppsId": "10101010101"
}
}{- "error": {
- "code": "VALIDATION_ERROR",
- "message": "criteria.birthDate must be an ISO 8601 date (YYYY-MM-DD)",
- "details": {
- "field": "criteria.birthDate"
}
}
}Enregistre l'arrivée du patient pour ce rendez-vous et déclenche, côté éditeur, la suite du parcours (mise en salle d'attente, notification des équipes…).
anomalyCodes : codes d'anomalies constatées pendant le parcours
(référentiel fourni par la configuration borne, vendor-neutral).sequence.number: 1 ;
les suivants référencent le RDV principal via mainAppointmentId.200 avec le ticket existant. 409 ALREADY_CHECKED_IN est réservé
au cas où l'état du RDV rend le check-in réellement impossible.ticketNumber/ticketNumberFormatted sont absents si l'éditeur ne gère pas
de file d'appel (la borne peut alors générer un ticket local).| appointmentId required | string <= 128 characters Identifiant du rendez-vous ( |
object (KioskIntegrationContext) Contexte transmis par la borne. Si | |
| identifiedWithHealthCard required | boolean Le patient s'est identifié avec sa carte de santé (et non manuellement) |
| attendantCheckIn | boolean Default: false Check-in effectué par un accompagnant/brancardier (mode paramédical) |
| anomalyCodes required | Array of strings[ items <= 32 characters ] Codes des anomalies constatées pendant le parcours (référentiel de la configuration borne) |
| documentsComplete | boolean or null Dossier documentaire complet au moment du check-in : tous les types de documents requis ( |
required | object Position de ce RDV dans le parcours multi-RDV du patient |
| otherAppointmentsReadyForCheckIn | boolean Default: false Au moins un autre RDV du jour du patient est également prêt pour le check-in (indication pour le regroupement des notifications côté éditeur) |
| mainAppointmentId | string or null <= 128 characters Identifiant du RDV principal (présent seulement pour les RDV liés, |
| linkedAppointmentIds | Array of strings[ items <= 128 characters ] Identifiants des autres RDV du jour inclus dans le même parcours |
| examId | string or null <= 128 characters Identifiant d'examen de ce RDV |
| otherExamIds | Array of strings[ items <= 128 characters ] Identifiants d'examen des autres RDV du parcours |
object or null Numéro de ticket proposé par la borne (réservé auprès du serveur ApiBorne avant le check-in). L'éditeur PEUT l'adopter comme numéro d'appel et DOIT l'accepter sans erreur s'il ne l'adopte pas. Quand la configuration borne est portée par ApiBorne, la borne affiche et imprime ce ticket quel que soit le contenu de |
{- "context": {
- "locationId": "loc-42"
}, - "identifiedWithHealthCard": true,
- "attendantCheckIn": false,
- "anomalyCodes": [
- "PR"
], - "sequence": {
- "number": 1,
- "count": 1
}, - "examId": "exam-77",
- "linkedAppointmentIds": [ ],
- "otherExamIds": [ ]
}{- "ticketNumber": 0,
- "ticketNumberFormatted": "string",
- "vendorData": { }
}Indique si le dossier du rendez-vous est complet au sens de l'éditeur (documents requis présents, prescripteur renseigné…), c'est-à-dire si le check-in pourra notifier les équipes sans signaler un dossier incomplet. La borne s'en sert pour décider d'ajouter l'anomalie « dossier incomplet ».
Un éditeur sans notion de notification renvoie 200 { "ready": true }
(jamais 501).
| appointmentId required | string <= 128 characters Identifiant du rendez-vous ( |
| identifiedWithHealthCard | boolean Default: false Le patient s'est identifié avec sa carte de santé |
| sequenceNumber | integer >= 1 Default: 1 Rang du RDV dans le parcours multi-RDV (1 = principal) |
| examId | string <= 128 characters Identifiant d'examen du RDV |
| otherExamIds | Array of strings[ items <= 128 characters ] Identifiants d'examen des autres RDV du jour (séparés par des virgules) |
{- "ready": true,
- "reason": "notificationNotConfigured",
- "vendorData": { }
}Renvoie les documents déjà rattachés au rendez-vous et la liste des types de
documents attendus (obligatoires) pour ce rendez-vous. La borne en déduit
les documents manquants (comparaison sur documentType).
| appointmentId required | string <= 128 characters Identifiant du rendez-vous ( |
{- "documents": [
- {
- "id": "string",
- "documentType": "string",
- "label": "string",
- "availableOnPhone": true
}
], - "requiredDocumentTypes": [
- {
- "documentType": "string",
- "label": "string",
- "availableOnPhone": true
}
], - "vendorData": { }
}Rattache un document au rendez-vous. Les pages sont des images (JPEG ou PNG) encodées en base64, dans l'ordre de lecture. L'éditeur est libre du stockage (conversion PDF, compression…).
413 UPLOAD_TOO_LARGE. La borne limite ses
uploads à la taille annoncée dans sa configuration.rotationAngle est une indication de rotation à appliquer aux pages
(sens horaire) ; un éditeur peut l'ignorer.documentType: prescription) et que
l'éditeur dispose d'une analyse automatique, il PEUT renvoyer analysis
avec des propositions de prescripteur soumises au patient. Sinon, il omet
simplement analysis. Intégrations libres : ce flux n'est pas activé à
ce stade (la borne ne sollicite pas l'analyse ; l'IA a vocation à être
portée par ApiBorne) — il reste utilisé par l'intégration EasyDoct.DELETE préalable
(la borne s'en charge).| appointmentId required | string <= 128 characters Identifiant du rendez-vous ( |
object (KioskIntegrationContext) Contexte transmis par la borne. Si | |
| documentType required | string (DocumentType) <= 64 characters ^[A-Za-z][A-Za-z0-9_-]*$ Code de type de document, vendor-neutral. Le RÉFÉRENTIEL appartient à
l'éditeur : il l'expose via Un vocabulaire standard de 41 codes est défini dans
|
required | Array of objects (DocumentPage) non-empty Pages du document dans l'ordre de lecture |
| rotationAngle | integer Default: 0 Enum: 0 90 180 270 Rotation (sens horaire) à appliquer aux pages — indication, ignorable |
{- "documentType": "prescription",
- "rotationAngle": 0,
- "pages": [
- {
- "contentBase64": "/9j/4AAQSkZJRgABAQAAAQ…",
- "mimeType": "image/jpeg"
}, - {
- "contentBase64": "/9j/4AAQSkZJRgABAQAAAQ…",
- "mimeType": "image/jpeg"
}
]
}{- "documentId": "string",
- "analysis": {
- "prescriberProposals": [
- {
- "name": "string",
- "rppsId": "string"
}
]
}, - "vendorData": { }
}Supprime un document rattaché au rendez-vous (utilisé par la borne avant de
ré-uploader un document du même type). Supprimer un document déjà supprimé
renvoie 404 UNKNOWN_DOCUMENT.
| appointmentId required | string <= 128 characters Identifiant du rendez-vous ( |
| documentId required | string <= 128 characters Identifiant du document ( |
{- "error": {
- "code": "INVALID_AUTH_KEY",
- "message": "Invalid authorization key for this device",
- "details": null
}
}OPTIONNEL. Renvoie le questionnaire préparatoire attendu pour ce RDV,
en le créant à la volée si la configuration de l'éditeur le prévoit, et
renvoie son identifiant de résultat (surveyResultId) à charger ensuite
via getPreparatorySurvey.
Un éditeur qui ne gère pas de questionnaire préparatoire (ou aucun attendu
pour ce RDV) renvoie 200 { "surveyResultId": null, "completed": false }
(ou 404 s'il n'expose pas la fonctionnalité) : la borne / l'app patient
n'affiche alors pas de module questionnaire.
| appointmentId required | string <= 128 characters Identifiant du rendez-vous ( |
{- "surveyResultId": "string",
- "name": "string",
- "completed": true
}OPTIONNEL. Renvoie la définition du questionnaire (schéma SurveyJS,
jsonDef), les valeurs de préremplissage et les données déjà saisies.
surveyResultId provient de ensurePreparatorySurvey.
| surveyResultId required | string <= 128 characters Identifiant du résultat de questionnaire ( |
{- "jsonDef": null,
- "prefilledInfos": [
- {
- "name": "string",
- "value": null
}
], - "existingData": { },
- "alreadyDone": true
}OPTIONNEL. Enregistre les réponses du patient. data est l'objet de
résultat SurveyJS (paires nom→valeur). Renvoie les éléments servant à
générer le PDF du résultat (définition, réponses, entête/pied…).
| surveyResultId required | string <= 128 characters Identifiant du résultat de questionnaire ( |
object (KioskIntegrationContext) Contexte transmis par la borne. Si | |
required | object Objet de résultat SurveyJS (nom → valeur) |
{- "context": {
- "locationId": "string",
- "config": {
- "identification": {
- "twoFieldsIdentification": true
}, - "documents": { },
- "checkIn": { }
}, - "vendorData": { }
}, - "data": { }
}{- "jsonDef": "string",
- "jsonResult": "string",
- "patient": "string",
- "appointmentStartDate": "string",
- "officeName": "string",
- "footer": "string"
}OPTIONNEL. Corps binaire application/pdf (le PDF est généré côté
client à partir des réponses). Sans lui, le résultat n'est pas
téléchargeable côté éditeur.
| surveyResultId required | string <= 128 characters Identifiant du résultat de questionnaire ( |
{- "error": {
- "code": "INVALID_AUTH_KEY",
- "message": "Invalid authorization key for this device",
- "details": null
}
}Valide les identifiants d'un membre du personnel chez l'éditeur et renvoie les établissements auxquels il a accès. Utilisé par le serveur ApiBorne pour le login du Cockpit quand la source d'authentification est l'éditeur : ApiBorne rapproche ensuite chaque établissement de sa configuration locale (licence) pour établir la session. Contrairement aux autres opérations, seul le header X-Kiosk-Auth-Key est requis (pas de device : l'appel ne vient pas d'une borne). Identifiants invalides → 401 avec le code INVALID_CREDENTIALS.
| login required | string <= 256 characters Identifiant de connexion du membre du personnel (email ou login éditeur) |
| password required | string <= 256 characters Mot de passe (transmis uniquement en HTTPS) |
{- "login": "string",
- "password": "string"
}{- "offices": [
- {
- "officeId": "string",
- "officeVisibleId": "string",
- "name": "string"
}
], - "userEmail": "string",
- "userDisplayName": "string",
- "vendorData": { }
}