Luna SaludReferencia de la APILuna Salud

Crear una cita

POST/appointments

Agenda una cita para un paciente existente de su organización con un profesional de salud y un servicio, presencial por defecto o en línea con telemedicine en true. La hora de fin se calcula con la duración del servicio. La hora de inicio debe ser futura, estar dentro de la disponibilidad del profesional y estar libre; use GET /availability para encontrar horarios disponibles. Si reintenta una solicitud idéntica, recibe la cita ya creada en lugar de un duplicado. La cita se crea como CONFIRMED y este endpoint no envía nada al paciente: ni confirmación, ni recordatorios, ni invitación de calendario. Luna le escribe al paciente más adelante solo cuando usted lo pide de forma explícita — notifyPatient en true en POST /appointments/{id}/reschedule, /cancel o /no-show, cada uno documentado en su endpoint — o cuando el personal de su clínica edita la cita en el panel de Luna, donde aplican los ajustes de cambios y recordatorios de su clínica como en cualquier cita. Se notifica al profesional de salud en el panel de Luna. En una cita en línea, la videollamada se crea en la plataforma conectada del profesional (Zoom, luego Google Meet, luego el video de Luna Health) y la liga de acceso del paciente se devuelve como video_call_url para que su sistema la entregue; es null cuando la reunión aún no se pudo crear. Las citas en línea todavía no se pueden reagendar desde la API. Requiere una clave de API con permiso de escritura.

Ejemplos de código

Node.js

const fetch = require('node-fetch');

async function llamarApi() {
  const claveApi = 'YOUR_API_KEY';
  const url = `https://account.lunahealth.app/api/appointments`;
  const requestBody = {
    // Agregue sus datos del cuerpo de la solicitud aquí
  };

  try {
    const response = await fetch(url, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${claveApi}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(requestBody)
    });
    
    if (!response.ok) {
      throw new Error(`API error: ${response.status}`);
    }
    
    const data = await response.json();
    console.log(data);
    return data;
  } catch (error) {
    console.error('Error al llamar a la API:', error);
    throw error;
  }
}

llamarApi();

Python

import requests

def llamarApi():
    claveApi = 'YOUR_API_KEY'
    
    url = 'https://account.lunahealth.app/api/appointments'
    
    headers = {
        'Authorization': f'Bearer {claveApi}',
        'Content-Type': 'application/json'
    }
    
    params = {

    }
    
    # Agregue sus datos del cuerpo de la solicitud aquí
    request_body = {}
        try:
        response = requests.post(
            url,
            headers=headers,
            params=params,
            json=request_body
        )
        response.raise_for_status()
        
        data = response.json()
        print(data)
        return data
    except requests.exceptions.RequestException as e:
        print(f'Error al llamar a la API: {e}')
        raise

llamarApi()

Cuerpo de la solicitud

Requerido

Campos de la solicitud

NombreTipoRequeridoDescripción
patientIdstringSíID del paciente
staffIdstringSíID del profesional de salud que atenderá al paciente
serviceIdstringSíID del servicio; su duración define la hora de fin
startTimestring (date-time)SíHora de inicio en ISO 8601 con desfase UTC, por ejemplo un start_time de GET /availability
locationIdstringNoID de la sucursal donde será la cita
reasonForVisitstringNoMotivo de la consulta, visible para el personal
telemedicinebooleanNoAgenda una cita en línea. La plataforma de video es la que el profesional tiene conectada (Zoom, luego Google Meet, luego el video de Luna Health) y la liga de acceso del paciente se devuelve como video_call_url. Por defecto es false, una cita presencial.

Ejemplo de solicitud

{
  "patientId": "string",
  "staffId": "string",
  "serviceId": "string",
  "startTime": "2025-01-01T00:00:00Z",
  "locationId": "string",
  "reasonForVisit": "string",
  "telemedicine": true
}

Respuestas

EstadoDescripción
200Respuesta exitosa
400Datos de entrada no válidos
401Autorización no proporcionada
403Acceso insuficiente
500Error interno del servidor

200 — Respuesta exitosa

Campos de la respuesta

NombreTipoRequeridoDescripción
idstringSí—
statusstringSí—
typestringSí—
titlestringnullSí—
descriptionstringnullSí—
start_timestringSí—
end_timestringSí—
telemedicinebooleanSí—
video_call_typestringSíPlataforma de video de una cita en línea: LUNAHEALTH, ZOOM o GOOGLE_MEET. NONE en citas presenciales y en las citas en línea donde la clínica envía su propia liga
created_atstringSí—
updated_atstringSí—
patientobject | nullSí—
staffsarray<object>Sí—
serviceobject | nullSí—
locationobject | nullSí—
video_call_urlstringnullSíLiga de acceso del paciente a una cita en línea, para que su sistema se la entregue. Trátela como una credencial de ese paciente: abre su sala de video. Es null en citas presenciales, cuando la clínica envía su propia liga (video_call_type NONE) y cuando la reunión aún no se pudo crear; en ese caso el panel de la clínica la crea al abrir la cita.

Ejemplo de respuesta

{
  "id": "string",
  "status": "NEW",
  "type": "string",
  "title": null,
  "description": null,
  "start_time": "string",
  "end_time": "string",
  "telemedicine": true,
  "video_call_type": "NONE",
  "created_at": "string",
  "updated_at": "string",
  "patient": {
    "id": "string",
    "first_name": null,
    "last_name": null,
    "email": null
  },
  "staffs": [
    {
      "id": "string",
      "first_name": null,
      "last_name": null
    }
  ],
  "service": {
    "id": "string",
    "name": "string"
  },
  "location": {
    "id": "string",
    "name": null
  },
  "video_call_url": null
}

400 — Datos de entrada no válidos

Campos de la respuesta

NombreTipoRequeridoDescripción
messagestringSíThe error message
codestringSíThe error code
issuesarray<object>NoAn array of issues that were responsible for the error

Ejemplo de respuesta

{
  "code": "BAD_REQUEST",
  "message": "Invalid input data",
  "issues": []
}

401 — Autorización no proporcionada

Campos de la respuesta

NombreTipoRequeridoDescripción
messagestringSíThe error message
codestringSíThe error code
issuesarray<object>NoAn array of issues that were responsible for the error

Ejemplo de respuesta

{
  "code": "UNAUTHORIZED",
  "message": "Authorization not provided",
  "issues": []
}

403 — Acceso insuficiente

Campos de la respuesta

NombreTipoRequeridoDescripción
messagestringSíThe error message
codestringSíThe error code
issuesarray<object>NoAn array of issues that were responsible for the error

Ejemplo de respuesta

{
  "code": "FORBIDDEN",
  "message": "Insufficient access",
  "issues": []
}

500 — Error interno del servidor

Campos de la respuesta

NombreTipoRequeridoDescripción
messagestringSíThe error message
codestringSíThe error code
issuesarray<object>NoAn array of issues that were responsible for the error

Ejemplo de respuesta

{
  "code": "INTERNAL_SERVER_ERROR",
  "message": "Internal server error",
  "issues": []
}