POST
/appointmentsTroubleshooting
Bug 510 — Cannot read properties of null (reading 'admitionStatus')
Por qué `POST /appointments` falla con 510 y cómo enviar el payload correcto.
El endpoint `POST /api/v1/appointments` delegate a MedicalCore RD en `/api/cita/insert`. MedicalCore es extremadamente estricto con la estructura del payload: cualquier campo extra en `paciente`, un `area._id` mal mapeado o un `start/end` con timezone mal calculado devuelve 510 Not Extended.
Esta guía resume las 4 causas más frecuentes del 510 (en orden de aparición) y la estructura EXACTA del payload validado.
Headers obligatorios: `Content-Type: application/json`, `x-api-key: <MEDEX_API_KEY>`, `enterpriseid: 150575`, `ownerid: 150575`.
Mapeo crítico: `cita.area._id` debe ser el área de CONSULTA (660, 1816, 622), NO la specialty (1704, 1690, 1723). El wrapper `/areas` expone especialidades; las áreas de consulta son un subconjunto interno.
Timezone: `cita.start` en formato `-04:00` (AST) y `cita.end` en formato `Z` (UTC). `start = utc - 4h`, `end = start + 20min` en UTC.
Saneamiento de `paciente`: el `raw` de `/patients/search` tiene ~40 campos. Sólo enviar los 11 básicos.
Operations: leer de `paciente.raw.properties` — NO hardcodear todos a `false`, MedicalCore los usa para resolver el estado de admisión.
Campos PROHIBIDOS en `paciente` (causan el 510): `medicoCabecera`, `patientMaster`, `centroMedicos`, `agent`, `companions`, `properties`, `admitionStatus`, `patientContactDetailId`, `datosDeSistemaIntegrado`, `branch`, `direccion`, `padronUrl`, `pais`, `paisPasaporte`, `maritalStatus`, `titular`, `numeroAfiliado`, `isValidIdentification`, `emailValidation`, `forms`, `question_sets`, `cuestionario`, `viaDeContacto`, `contactIndicator`, `token`, `createdBy`, `createdDate`, `updatedBy`, `updatedDate`, `ownerId`, `baseApiPathv2`, `baseApiPathPatientBraceletv2`, `isMedic`, `fullName`.
Flujo recomendado
Orden en que deberías llamar a los endpoints.
- 11. Síntoma:
Cannot read properties of null (reading 'admitionStatus')→paciente.rawcon ~40 campos +areamal mapeado. Fix: limpiarpacientea 11 campos y traducirarea. - 22. Síntoma:
Cannot read properties of undefined (reading '_id')→ faltacita.area._id. Fix: incluir el objetoareacon su_id. - 33. Síntoma:
Invalid appointment structure. Must contain cita object with doctorId and pacienteId.→ faltacita.pacienteIda nivel raíz. Fix: incluirpacienteIdtanto encitacomo encita.citaPaciente. - 44. Síntoma:
la fecha fin debe ser mayor a la fecha de inicio→ cálculo mal del timezone (sumaba 4h en vez de restar). Fix: restar 4h para formato-04:00.
Mapeo de campos
De dónde sale cada valor que tienes que enviar.
| Campo | Origen |
|---|---|
cita.area._id | Mapeo specialty → consulta (660, 1816, 622) |
cita.start | Slot UTC → restar 4h → `-04:00` |
cita.end | `start + 20min` en `Z` (UTC) |
cita.citaPaciente.paciente | Saneado a 11 campos desde `raw` |
cita.operations | `paciente.raw.properties` |
Cuerpo de la petición
Payload COMPLETO validado contra MedicalCore RD. Estructura probada y funcional.
Ejemplos
Ejemplo 1
Payload validado (Opción B)Estructura completa que NO devuelve 510. Copia y adapta los IDs a tu caso.
payload-validado-(opción-b).json·json
{
"cita": {
"citaId": null,
"doctorId": 153625,
"pacienteId": 4958123,
"pacienteCedula": "223-0073480-7",
"attentionType": "h",
"type": "p",
"recurrente": false,
"doctor": {
"_id": 153625,
"nombre": "Pedro",
"apellido": "Rodriguez Gonzalez",
"fullName": "Pedro Rodriguez Gonzalez",
"universalId": "",
"especialidad": " Medicina Interna"
},
"area": {
"_id": 660,
"description": "Consulta de Medicina Interna",
"type": {
"_id": 1,
"description": "Doctores"
}
},
"subArea": {
"_id": 153625,
"fullName": "Pedro Rodriguez Gonzalez"
},
"start": "2026-08-05T11:40:00-04:00",
"end": "2026-08-05T16:00:00.000Z",
"status": "Pendiente por confirmar",
"citaPaciente": {
"place": {
"_id": 150575,
"name": "Médico Express RD"
},
"service": {
"_id": 2221,
"description": "CONSULTA DE SEGUNDA OPINIÓN LOCAL",
"duration": {
"_id": 1,
"label": "240 Minutos",
"value": "m",
"time": 240
},
"baseApiPath": "api/especialidad"
},
"pacienteId": 4958123,
"paciente": {
"_id": 4958123,
"nombre": "DANIEL GIOVANNI",
"apellido": "SANTILLAN PEREZ",
"sexo": "M",
"email": "SANTILLANDSP@GMAIL.COM",
"fechaNacimiento": "1989-05-26T08:00:00.000Z",
"newPatient": false,
"numeroDeRecord": "2024-3831",
"numeroIdentificacion": "223-0073480-7",
"telefono": [
{
"tipo": "Móvil",
"numero": "829-605-8450"
}
],
"afiliaciones": []
},
"comment": null,
"internment": false,
"coverages": [
{
"_id": 75229,
"codCobertura": "00423315A",
"description": "CONSULTA DE SEGUNDA OPINIÓN LOCAL",
"duration": {
"_id": 1,
"label": "20 Minutos",
"value": "m",
"time": 20
},
"tipo": "Otros",
"subTipo": " ",
"dispositivo": false,
"usePaymentLink": false,
"servicioAseguradora": {
"code": "1",
"description": "Ambulatorio"
}
}
]
},
"branch": {
"_id": 392,
"description": "San Isidro"
},
"servicioAseguradora": {
"code": "1",
"description": "Ambulatorio"
},
"doneSaved": false,
"operations": {
"priority": false,
"fallRisk": false,
"wheelChair": false,
"vip": false,
"companion": false,
"overWeight": false,
"pregnant": true,
"needSupport": false,
"disabled": false,
"special": false
},
"ubicacion": null,
"pagadorReferidor": null,
"pagador": {},
"referallDoctors": [],
"ordenMedica": {
"numero": null,
"doctor": {
"_id": 0,
"fullName": null,
"especialidad": null
}
}
}
}cURL
request.sh·bash
curl -X POST "https://apimedex.dploy.lol/api/v1/appointments" \
-H "Content-Type: application/json" \
-H "x-api-key: $MEDEX_API_KEY" \
-H "enterpriseid: 150575" \
-H "ownerid: 150575" \
-d '{
"cita": {
"citaId": null, "doctorId": 153625, "pacienteId": 4958123, "pacienteCedula": "223-0073480-7",
"attentionType": "h", "type": "p", "recurrente": false,
"doctor": { "_id": 153625, "nombre": "Pedro", "apellido": "Rodriguez Gonzalez", "fullName": "Pedro Rodriguez Gonzalez", "universalId": "", "especialidad": " Medicina Interna" },
"area": { "_id": 660, "description": "Consulta de Medicina Interna", "type": { "_id": 1, "description": "Doctores" } },
"subArea": { "_id": 153625, "fullName": "Pedro Rodriguez Gonzalez" },
"start": "2026-08-05T11:40:00-04:00", "end": "2026-08-05T16:00:00.000Z", "status": "Pendiente por confirmar",
"citaPaciente": {
"place": { "_id": 150575, "name": "Médico Express RD" },
"service": { "_id": 2221, "description": "CONSULTA DE SEGUNDA OPINIÓN LOCAL", "duration": { "_id": 1, "label": "240 Minutos", "value": "m", "time": 240 }, "baseApiPath": "api/especialidad" },
"pacienteId": 4958123,
"paciente": { "_id": 4958123, "nombre": "DANIEL GIOVANNI", "apellido": "SANTILLAN PEREZ", "sexo": "M", "email": "SANTILLANDSP@GMAIL.COM", "fechaNacimiento": "1989-05-26T08:00:00.000Z", "newPatient": false, "numeroDeRecord": "2024-3831", "numeroIdentificacion": "223-0073480-7", "telefono": [{"tipo": "Móvil", "numero": "829-605-8450"}], "afiliaciones": [] },
"comment": null, "internment": false,
"coverages": [{ "_id": 75229, "codCobertura": "00423315A", "description": "CONSULTA DE SEGUNDA OPINIÓN LOCAL", "duration": { "_id": 1, "label": "20 Minutos", "value": "m", "time": 20 }, "tipo": "Otros", "subTipo": " ", "dispositivo": false, "usePaymentLink": false, "servicioAseguradora": { "code": "1", "description": "Ambulatorio" } }]
},
"branch": { "_id": 392, "description": "San Isidro" },
"servicioAseguradora": { "code": "1", "description": "Ambulatorio" },
"doneSaved": false,
"operations": { "priority": false, "fallRisk": false, "wheelChair": false, "vip": false, "companion": false, "overWeight": false, "pregnant": true, "needSupport": false, "disabled": false, "special": false },
"ubicacion": null, "pagadorReferidor": null, "pagador": {}, "referallDoctors": [],
"ordenMedica": { "numero": null, "doctor": { "_id": 0, "fullName": null, "especialidad": null } }
}
}'Respuestas4
| Status | Descripción |
|---|---|
| 200 | Cita creada. Devuelve `{ data: { citaId: "2026-XXXX", _id: 9XXXXXX, ... } }`. |
| 400 | Estructura inválida. Verificar `citaId`, `pacienteId`, `doctorId`, `area._id`. |
| 510 | MedicalCore no pudo procesar. Verificar: (a) `paciente` saneado, (b) `area._id` mapeado a consulta, (c) timezone correcto, (d) `pacienteId` a nivel raíz. |
| 510 | Mensaje alternativo cuando se manda `start` y `end` con timezone mal calculado. |
200
Cita creada. Devuelve `{ data: { citaId: "2026-XXXX", _id: 9XXXXXX, ... } }`.response-200.json·json
{
"data": {
"citaId": "2026-XXXX",
"_id": 9000000,
"status": "Pendiente por confirmar"
}
}400
Estructura inválida. Verificar `citaId`, `pacienteId`, `doctorId`, `area._id`.response-400.json·json
{
"error": "Invalid appointment structure. Must contain cita object with doctorId and pacienteId."
}510
MedicalCore no pudo procesar. Verificar: (a) `paciente` saneado, (b) `area._id` mapeado a consulta, (c) timezone correcto, (d) `pacienteId` a nivel raíz.response-510.json·json
{
"error": "Cannot read properties of null (reading 'admitionStatus')"
}510
Mensaje alternativo cuando se manda `start` y `end` con timezone mal calculado.response-510.json·json
{
"error": "la fecha fin debe ser mayor a la fecha de inicio"
}