Skip to main content

Contrato FHIR

El cliente envía recursos FHIR R4 a POST /fhir. La identidad de cada entidad es el número externo del cliente (no el DNI ni el beneficio PAMI): así el gateway y el backend correlacionan sin depender de datos de PAMI.

Headers

HeaderObligatorioUso
x-api-keyAutenticación del cliente (token Ajolote)
x-source-message-idClave de idempotencia del envío. Repetir el mismo id = duplicado (no reprocesa)

Systems de identificadores

Los identifier.system acordados (configurables por env, con estos defaults):

EntidadSystem (default)
Paciente (nº externo)https://cliente.example.org/ids/patient
Episodiohttps://cliente.example.org/ids/encounter
Prácticahttps://cliente.example.org/ids/procedure
Documentohttps://cliente.example.org/ids/document
Turnohttps://cliente.example.org/ids/appointment
Beneficio PAMIhttps://pami.gob.ar/beneficiario
DNIhttps://www.argentina.gob.ar/dni

Referencias por identificador lógico

Las referencias entre recursos se hacen por identifier, no por reference: "Patient/123". Ejemplo — un episodio que apunta a su paciente:

"subject": {
"type": "Patient",
"identifier": { "system": "https://cliente.example.org/ids/patient", "value": "PAC-00" }
}

Una referencia resuelve si el destino está en el mismo bundle o ya existe en el dominio del gateway.

Extensiones

ExtensiónURL (default)DóndeContenido
Autorización (OP).../StructureDefinition/authorizationEncounter / Procedure / Appointmentsub-ext number (nº de OP)
Cobertura.../StructureDefinition/coverageEncountersub-ext credential + plan
Uso de diagnóstico.../StructureDefinition/diagnosis-useConditionvalueCode
La extensión coverage es de cara al backend

El gateway no modela credencial ni plan: pasa la extensión coverage verbatim en el payload. Es el backend quien la lee para resolver credencial + plan (ver El endpoint /inbound). Un episodio sin coverage es aceptado por el gateway pero rechazado (422) por el backend.

Recursos soportados

Patient, Encounter, Condition, Procedure, Appointment, DocumentReference. Se aceptan sueltos o dentro de un Bundle (transaction/collection).

Episodio (Encounter) — ejemplo completo

{
"resourceType": "Encounter",
"identifier": [{ "system": "https://cliente.example.org/ids/encounter", "value": "ENC-001" }],
"status": "in-progress",
"class": { "code": "IMP" },
"subject": {
"type": "Patient",
"identifier": { "system": "https://cliente.example.org/ids/patient", "value": "PAC-00" }
},
"period": { "start": "2026-06-01T09:30:00-03:00" },
"extension": [
{
"url": "https://cliente.example.org/fhir/StructureDefinition/coverage",
"extension": [
{ "url": "credential", "valueString": "150123456789-00" },
{ "url": "plan", "valueString": "PAMI_PI" }
]
},
{
"url": "https://cliente.example.org/fhir/StructureDefinition/authorization",
"extension": [{ "url": "number", "valueString": "AUTH-001" }]
}
]
}

Mapeos relevantes:

  • class.code → tipo de episodio: IMP = internación (hospitalization), AMB = ambulatorio.
  • status: in-progress = alta/abierto; finished/cancelled = cierre; entered-in-error = baja (soft-delete).

Errores controlados (respuesta síncrona)

Cuando la validación síncrona falla, el gateway responde 422 (o 400 si el payload es estructuralmente inválido) con un OperationOutcome. El código estable viaja en issue.details.coding.code:

CódigoSignificado
INVALID_BUNDLEPayload no es un Bundle/recurso FHIR válido
UNSUPPORTED_RESOURCE_TYPEresourceType no soportado
MISSING_IDENTIFIER / MISSING_REFERENCEFalta el identificador o la referencia
PATIENT_NOT_FOUNDEl episodio/documento referencia un paciente inexistente
ENCOUNTER_NOT_FOUNDLa práctica/documento referencia un episodio inexistente
PROCEDURE_NOT_FOUNDEl documento referencia una práctica inexistente
TARGET_NOT_FOUNDEl subject.type del documento no es Patient/Encounter/Procedure
Qué NO valida la capa síncrona

El gateway sólo valida contra lo que él conoce. Reglas que dependen de datos exclusivos del backend (ej.: que el planCode exista en el catálogo de Proteus) no se validan acá: el cliente recibe 202 y, si el plan no existe, el mensaje muere después como denied en el outbox. Cerrar ese hueco requeriría que el gateway conozca el catálogo de planes.