Desarrolladores
La API de Meevia
Lee la agenda, reserva citas y consulta el catálogo y la ficha del paciente desde tu propio sistema. Esta página te lleva de la primera clave a la primera respuesta con éxito.
En esta página
Qué es y para quién sirve
La API le abre a tu sistema las partes de la clínica que tiene sentido automatizar: la agenda, el catálogo de profesionales y procedimientos, y la ficha básica del paciente. Lo que haces a través de ella sigue las mismas reglas que valen para quien opera la clínica dentro de la plataforma.
Es HTTP con JSON, sin biblioteca obligatoria y sin SDK que instalar. Si tu entorno sabe hacer una petición y leer una respuesta, ya sabe hablar con Meevia.
Casos habituales
- Una web o una app propia donde el paciente elige la hora y reserva por su cuenta.
- Un sistema que la clínica ya usa y que necesita ver la agenda del día sin que nadie teclee dos veces.
- Automatización interna: un panel propio, un informe, una rutina que confirma la asistencia.
Qué necesita tener la clínica
El acceso a la API forma parte del plan de la clínica. Si el plan actual no lo incluye, la primera llamada ya vuelve rechazada, y eso no lo arregla ningún cambio en tu código: es una conversación con el equipo comercial.
Qué no está aquí todavía
Esta versión lee y escribe agenda, y lee catálogo y paciente. Que Meevia avise a tu sistema cuando pasa algo en la clínica, la facturación y los pagos no forman parte de ella.
Cómo conseguir una clave
La clave nace en el panel de desarrollador, que está en developers.meevia.app y tiene carcasa propia, fuera del sistema de la clínica. Es así porque quien integra muchas veces no es de la clínica. No hay ningún camino por la API para crear una clave. La interfaz del panel está en portugués de Brasil, así que los nombres de pestaña y de permiso que se citan abajo son exactamente los que vas a leer en pantalla.
Abrir el panel de desarrollador
- 1Abre el panel de desarrolladorLa dirección es developers.meevia.app. Quien ya trabaja dentro del sistema de la clínica llega al mismo sitio por Integrações (Integraciones), en la tarjeta API e Webhooks, que es una puerta al panel.
- 2Entra con tu cuenta, o pide una invitaciónQuien administra la clínica entra directo. Quien viene de fuera necesita invitación: en la pestaña Acessos (Accesos), quien administra el panel invita por correo y elige entre Somente ver (solo ver), que consulta y no actúa, y Pode administrar (puede administrar), que además emite claves. Pedir la invitación es mejor que pedir la clave ya hecha, porque una clave que viaja por mensaje ya se ha filtrado.
- 3Elige la clínicaEl panel atiende todas las clínicas a las que tienes acceso, y la que elijas arriba es la dueña de todo lo que muestran las pestañas. Si trabajas para varias, aquí es donde cambias.
- 4En la pestaña Chaves (Claves), crea una clave nuevaPonle un nombre que diga dónde se va a usar. Seis meses después, ese nombre es la única forma de revocar la clave correcta sin tumbar la integración equivocada.
- 5Elige el modo y los ámbitosEl modo decide si la clave toca la clínica de verdad o el entorno de prueba. Los ámbitos deciden qué puede hacer. Marca solo lo que la integración necesita.
- 6Copia la clave antes de cerrar la ventanaLa clave completa aparece una sola vez, en el momento de emitirla. Meevia guarda el trozo que la identifica y nunca la parte secreta, así que cerrar sin copiar no tiene recuperación: revoca la clave y emite otra.
Una clave, una clínica
La clave vale para la clínica que la emitió, y solo para ella. Si atiendes a varias clínicas, son varias claves, cada una guardada por separado y sustituible sin tocar las demás. No existe una clave que vea más de una clínica.
Dónde guardarla
Guarda la clave en el servidor, en el almacén de variables de tu entorno. Una clave dentro del código de una aplicación o de una página es una clave publicada, porque cualquiera puede leerla.
Cuándo revocar
Revocar vale al instante y no tiene vuelta atrás: la clave deja de funcionar y sus llamadas pasan a ser rechazadas. Hazlo al cambiar de proveedor, al apagar una integración y a la mínima sospecha de filtración.
Quién puede qué
El permiso Pode administrar del panel abre las dos cosas que cambian algo: emitir y revocar claves, y reiniciar el entorno de prueba. Se recibe por invitación y vale por clínica, así que quien viene de fuera hace las dos sin depender de nadie. Reiniciar tiene un segundo camino: quien administra la clínica también reinicia. Quien solo tiene Somente ver ve las claves y no emite ninguna; el panel lo avisa en pantalla, en vez de esconder el botón.
Autenticación
Toda llamada va autenticada. La clave viaja en la cabecera de autorización, con el esquema que muestra el ejemplo, y no hay más: no hay inicio de sesión, ni sesión, ni token que caduque a mitad de camino.
curl -X GET \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/practitioners"La clave es un valor único, y es ese valor entero el que viaja en la cabecera. Tiene tres trozos pegados: el prefijo dice en qué modo está la clave, el trozo del medio la identifica y es el que aparece en la pestaña Chaves del panel, y el último es la parte secreta. Esa última Meevia no la guarda nunca en claro, así que ni el soporte puede leer la tuya. Envía siempre la clave completa: mandar solo la parte secreta es el descuido que más rechazos de autorización produce.
Una clave ausente, mal escrita, revocada o caducada reciben todas el mismo rechazo, sin decir cuál de los cuatro casos fue. Es a propósito. Decir cuál es dar una pista a quien está intentando adivinar.
Dos modos
Producción
mv_live_
Toca la clínica de verdad. Una cita creada desde aquí aparece en la agenda de recepción y dispara lo que la clínica haya configurado disparar.
Prueba
mv_test_
Toca un entorno aparte, con datos inventados, que existe solo para que experimentes. Nada de lo que pasa ahí roza la clínica real.
El modo se decide al emitir la clave y no cambia después. En la práctica mantienes las dos claves y cambias la variable de entorno para pasar de un lado al otro.
La clave que aparece en los ejemplos es inventada y no funciona en ninguna parte: está ahí solo para que reconozcas la forma de la tuya. Fíjate en que su prefijo es de producción. Si haces el paso a paso en modo de prueba, como recomienda esta página, la tuya va a empezar distinta.
Ámbitos
Cada ámbito abre una parte de la API, y la clave solo hace lo que sus ámbitos permiten. La falta de un ámbito aparece en la primera llamada que lo necesita, no al emitir la clave.
appointments:read
Leer la agenda
Listar las citas de un periodo y abrir una de ellas.
appointments:write
Tocar la agenda
Crear una cita, cambiarle el estado y cancelar.
catalog:read
Leer el catálogo
Profesionales, procedimientos y los horarios libres de un día.
patients:read
Leer paciente
Abrir la ficha básica de un paciente que ya conoces por el identificador. No existe búsqueda abierta por nombre en esta versión.
Concede el mínimo. Una integración que solo muestra la agenda en una pantalla grande no tiene por qué poder reservar citas. Y una clave escueta es un destrozo pequeño el día en que se filtre.
Los ámbitos no se editan después de emitir la clave. Ampliarlos es emitir una clave nueva con lo que falta, cambiarla en tu entorno y revocar la antigua.
Entorno de prueba
La clínica recibe un entorno de prueba solo para ella, aislado de la clínica real. La primera clave de prueba que se emite ya crea ese entorno, así que no hay nada que aprovisionar ni que pedir.
Qué viene ya dentro
Viene un paciente, un procedimiento y un profesional de ejemplo. Ninguno de ellos existe en la clínica de verdad. Las listas de profesionales y de procedimientos devuelven los identificadores de esos dos, así que consultar catálogo y horarios libres funciona en la primera sesión. Dar de alta es de la clínica: por la API, lo que se crea son citas.
Qué no se puede probar aquí
La API escribe en tres lugares: crear una cita, cambiar su situación y cancelarla. Hoy no se puede ejercitar ninguno de los tres aquí, y el motivo viene en cadena. Crear necesita el identificador del paciente, que no sale en pantalla ni vuelve de ninguna consulta, porque no hay listado de pacientes. Cambiar la situación y cancelar necesitan el identificador de una cita, y solo existiría si crear hubiera funcionado: la lista de citas nace vacía aquí. Quien necesite probar la escritura lo hace en la clínica de verdad, con el cuidado que eso pide: reserva en un hueco vacío y cancela en cuanto confirmes que funcionó.
Cómo reiniciarlo
La pestaña Ambiente de teste (Entorno de prueba) del panel tiene un botón que descarta el entorno actual y entrega otro, limpio, con los mismos datos iniciales. Las claves de prueba ya emitidas siguen valiendo: están ligadas a la clínica, no al entorno que se descartó.
Reiniciar borra todo lo que hayas creado ahí, y no hay deshacer. Es lo que quieres cuando una prueba ha ensuciado el entorno, y es justo lo que no quieres en mitad de una tanda de pruebas.
Reiniciar es de quien tiene Pode administrar en el panel o administra la clínica. Quien viene de fuera con ese permiso lo reinicia por su cuenta, sin tener a quién pedírselo.
La dirección de la API
Toda llamada sale hacia la misma dirección, y es una sola para todo el mundo. No hay una dirección por clínica: lo que separa una clínica de otra es la clave, nunca la URL.
https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1Vas a ver un trozo que parece repetido en mitad del camino. Está bien así. Uno es de la infraestructura que aloja la API y el otro es de la versión de la nuestra. Copia la dirección exactamente como aparece aquí; quitar la parte que parece sobrar devuelve una respuesta de dirección inexistente.
Primera llamada, de cero a la primera respuesta
Lleva cinco minutos, contando desde el inicio de sesión. Hazlo en modo de prueba: si algo sale distinto de lo esperado, quien lo paga es un paciente inventado.
- 1Emite una clave de pruebaSigue el camino descrito en Cómo conseguir una clave, marcando el modo de prueba y el ámbito de lectura del catálogo. Copia la clave.
- 2Guarda la clave en una variable de entornoAsí la clave no queda en el historial del terminal ni pegada en mitad del comando que le vas a mandar a un compañero.
- 3Pide la lista de profesionalesEs la llamada más sencilla de aquí: no recibe ningún parámetro, y el entorno de prueba ya viene con un profesional dentro. Si responde, tu clave, tu ámbito y tu dirección están bien de una sola vez.
- 4Mira lo que volvióUna respuesta con éxito trae al profesional de prueba. De ahí en adelante la receta es la misma para el resto: cambia la dirección, la cabecera sigue igual.
Cambia la clave de ejemplo por la variable en la que guardaste la tuya en el paso anterior, o por la clave entera. La que aparece aquí es inventada, y vuelve rechazada.
curl -X GET \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/practitioners"{
"data": [
{
"id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"name": "Dra. Helena Costa",
"specialty": "Dermatologia"
}
]
}Si no vino lo que esperabas
Compara lo que volvió con el catálogo de rechazos de esta página, que dice qué pasó y qué hacer en cada caso. Vale la pena mirar también la pestaña Requisições (Peticiones) del panel, que muestra la dirección llamada, la respuesta y la hora de cada llamada recibida. Solo guarda ese resumen, nunca el contenido que enviaste.
El formato de las respuestas
Las respuestas vienen envueltas siempre igual, y cada llamada muestra el formato de lo que devuelve. Programa contra el envoltorio e ignora lo que no conozcas: con el tiempo aparece información nueva, y la integración que ignora lo que no espera sobrevive a eso sin necesitarte.
Los envoltorios
- Un solo registro, dentro del envoltorio estándar.
data - Una lista, dentro de ese mismo envoltorio.
data - Una lista en páginas, junto al marcador que pide la siguiente.
datanext_cursorPuede venir sin valor - Esta respuesta se sale del patrón de las demás: trae el día consultado al lado de los horarios.
dateslots - El formato de todo rechazo, en cualquier llamada.
error
Listas largas
Las listas vienen en páginas. La respuesta trae un marcador de continuación: mientras venga con valor, manda ese mismo marcador en la llamada siguiente para pedir la página siguiente. Cuando venga vacío, se acabó. No intentes adivinar el total ni montar la paginación por tu cuenta.
Qué lleva cada respuesta
Cita
| Campo | Tipo |
|---|---|
id | uuid |
status | string |
starts_at | datetime |
ends_atPuede venir sin valor | datetime |
patient_idPuede venir sin valor | uuid |
professional_idPuede venir sin valor | uuid |
procedure_ids | array<uuid> |
created_at | datetime |
Paciente
| Campo | Tipo |
|---|---|
id | uuid |
name | string |
phonePuede venir sin valor | string |
emailPuede venir sin valor | string |
Profesional
| Campo | Tipo |
|---|---|
id | uuid |
namePuede venir sin valor | string |
specialtyPuede venir sin valor | string |
Procedimiento
| Campo | Tipo |
|---|---|
id | uuid |
name | string |
price | number |
duration_minutes | integer |
Horario libre
| Campo | Tipo |
|---|---|
time | string |
professional_id | uuid |
Rechazo
| Campo | Tipo |
|---|---|
code | string |
message | string |
detailsNo siempre viene | object |
Las llamadas
Cada una trae lo que recibe, lo que devuelve y un ejemplo listo para pegar en el terminal. Cambia los identificadores del ejemplo por los tuyos.
MétodoGETDirección/v1/appointments
Lista las citas de un periodo, en páginas.
- Ámbito exigido
appointments:readLeer la agenda- Repetición
- No se aplica
- Respuesta
- Cita
datanext_cursorPuede venir sin valor
| Parámetro | Tipo | Dónde va |
|---|---|---|
fromOpcional
| date | query |
toOpcional
| date | query |
statusOpcional
| string | query |
professional_idOpcional | uuid | query |
limitOpcional
| integer | query |
cursorOpcional
| string | query |
curl -X GET \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/appointments?from=2026-10-01&to=2026-10-31&limit=2"{
"data": [
{
"id": "9c1f4b2a-7e83-4d61-b0a5-2f8c6d31e4a7",
"status": "agendado",
"starts_at": "2026-10-03T14:30:00",
"ends_at": "2026-10-03T15:30:00",
"patient_id": "4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"procedure_ids": [
"2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d"
],
"created_at": "2026-09-28T11:04:22.517Z"
},
{
"id": "5e0b7a94-1d62-4c38-97af-8b41d2e6c03f",
"status": "confirmado",
"starts_at": "2026-10-03T16:00:00",
"ends_at": "2026-10-03T16:45:00",
"patient_id": "4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"procedure_ids": [
"2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d"
],
"created_at": "2026-09-28T11:04:22.517Z"
}
],
"next_cursor": "MjAyNi0xMC0wM3wxNDozMDowMHw5YzFmNGIyYS03ZTgzLTRkNjEtYjBhNS0yZjhjNmQzMWU0YTc="
}curl -X GET \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/appointments?from=2026-10-01&to=2026-10-31&limit=2&cursor=MjAyNi0xMC0wM3wxNDozMDowMHw5YzFmNGIyYS03ZTgzLTRkNjEtYjBhNS0yZjhjNmQzMWU0YTc%3D"{
"data": [],
"next_cursor": null
}MétodoPOSTDirección/v1/appointments
Reserva una cita para un paciente, con un profesional, a una hora.
- Ámbito exigido
appointments:writeTocar la agenda- Repetición
- Exige valor de repetición
- Respuesta
- Cita
data
| Parámetro | Tipo | Dónde va |
|---|---|---|
Idempotency-KeyObligatorio | string | header |
patient_idObligatorio | uuid | body |
professional_idObligatorio | uuid | body |
procedure_idsObligatorio
| array<uuid> | body |
starts_atObligatorio
| datetime | body |
statusOpcional
| string | body |
curl -X POST \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 7f3c05a1-9b24-4e6d-8c17-0a5f3d92b4e8" \
-d '{
"patient_id": "4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"procedure_ids": [
"2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d"
],
"starts_at": "2026-10-03T14:30:00",
"status": "agendado"
}' \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/appointments"{
"data": {
"id": "9c1f4b2a-7e83-4d61-b0a5-2f8c6d31e4a7",
"status": "agendado",
"starts_at": "2026-10-03T14:30:00",
"ends_at": "2026-10-03T15:30:00",
"patient_id": "4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"procedure_ids": [
"2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d"
],
"created_at": "2026-09-28T11:04:22.517Z"
}
}curl -X POST \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
-H "Content-Type: application/json" \
-d '{
"patient_id": "4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"procedure_ids": [
"2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d"
],
"starts_at": "2026-10-03T14:30:00"
}' \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/appointments"{
"error": {
"code": "validation_failed",
"message": "Cabeçalho Idempotency-Key é obrigatório para criar agendamento."
}
}MétodoGETDirección/v1/appointments/{id}
Abre una cita concreta.
- Ámbito exigido
appointments:readLeer la agenda- Repetición
- No se aplica
- Respuesta
- Cita
data
| Parámetro | Tipo | Dónde va |
|---|---|---|
idObligatorio | uuid | path |
curl -X GET \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/appointments/9c1f4b2a-7e83-4d61-b0a5-2f8c6d31e4a7"{
"data": {
"id": "9c1f4b2a-7e83-4d61-b0a5-2f8c6d31e4a7",
"status": "agendado",
"starts_at": "2026-10-03T14:30:00",
"ends_at": "2026-10-03T15:30:00",
"patient_id": "4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"procedure_ids": [
"2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d"
],
"created_at": "2026-09-28T11:04:22.517Z"
}
}MétodoPATCHDirección/v1/appointments/{id}/status
Cambia el estado de una cita, dentro de lo permitido.
- Ámbito exigido
appointments:writeTocar la agenda- Repetición
- Seguro repetir
- Respuesta
- Cita
data
| Parámetro | Tipo | Dónde va |
|---|---|---|
idObligatorio | uuid | path |
statusObligatorio
| string | body |
curl -X PATCH \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
-H "Content-Type: application/json" \
-d '{
"status": "confirmado"
}' \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/appointments/9c1f4b2a-7e83-4d61-b0a5-2f8c6d31e4a7/status"{
"data": {
"id": "9c1f4b2a-7e83-4d61-b0a5-2f8c6d31e4a7",
"status": "confirmado",
"starts_at": "2026-10-03T14:30:00",
"ends_at": "2026-10-03T15:30:00",
"patient_id": "4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"procedure_ids": [
"2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d"
],
"created_at": "2026-09-28T11:04:22.517Z"
}
}curl -X PATCH \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
-H "Content-Type: application/json" \
-d '{
"status": "realizado"
}' \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/appointments/9c1f4b2a-7e83-4d61-b0a5-2f8c6d31e4a7/status"{
"error": {
"code": "status_transition_not_allowed",
"message": "Transição de status não permitida por esta API.",
"details": {
"from": "agendado",
"to": "realizado"
}
}
}MétodoPOSTDirección/v1/appointments/{id}/cancel
Cancela una cita.
- Ámbito exigido
appointments:writeTocar la agenda- Repetición
- Seguro repetir
- Respuesta
- Cita
data
| Parámetro | Tipo | Dónde va |
|---|---|---|
idObligatorio | uuid | path |
curl -X POST \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/appointments/9c1f4b2a-7e83-4d61-b0a5-2f8c6d31e4a7/cancel"{
"data": {
"id": "9c1f4b2a-7e83-4d61-b0a5-2f8c6d31e4a7",
"status": "cancelado",
"starts_at": "2026-10-03T14:30:00",
"ends_at": "2026-10-03T15:30:00",
"patient_id": "4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"procedure_ids": [
"2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d"
],
"created_at": "2026-09-28T11:04:22.517Z"
}
}MétodoGETDirección/v1/patients/{id}
Abre la ficha básica de un paciente.
- Ámbito exigido
patients:readLeer paciente- Repetición
- No se aplica
- Respuesta
- Paciente
data
| Parámetro | Tipo | Dónde va |
|---|---|---|
idObligatorio | uuid | path |
curl -X GET \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/patients/4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63"{
"data": {
"id": "4d7e2c19-5a6b-4f30-9e81-c2a5b7d04f63",
"name": "Ana Ribeiro",
"phone": "+5511987654321",
"email": "ana.ribeiro@example.com"
}
}MétodoGETDirección/v1/practitioners
Lista los profesionales de la clínica.
- Ámbito exigido
catalog:readLeer el catálogo- Repetición
- No se aplica
- Respuesta
- Profesional
data
Esta llamada no recibe parámetros.
curl -X GET \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/practitioners"{
"data": [
{
"id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae",
"name": "Dra. Helena Costa",
"specialty": "Dermatologia"
}
]
}MétodoGETDirección/v1/procedures
Lista los procedimientos del catálogo.
- Ámbito exigido
catalog:readLeer el catálogo- Repetición
- No se aplica
- Respuesta
- Procedimiento
data
Esta llamada no recibe parámetros.
curl -X GET \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/procedures"{
"data": [
{
"id": "2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d",
"name": "Limpeza de pele profunda",
"price": 280,
"duration_minutes": 60
}
]
}MétodoGETDirección/v1/availability
Muestra los horarios libres de un día, y se puede acotar a un profesional o a un procedimiento.
- Ámbito exigido
catalog:readLeer el catálogo- Repetición
- No se aplica
- Respuesta
- Horario libre
dateslots
| Parámetro | Tipo | Dónde va |
|---|---|---|
dateObligatorio
| date | query |
professional_idOpcional | uuid | query |
procedure_idOpcional | uuid | query |
curl -X GET \
-H "Authorization: Bearer mv_live_a1b2c3d49f8e7d6c5b4a39281706f5e4d3c2b1a0" \
"https://wnricobmssysbwfhbmsm.supabase.co/functions/v1/api-v1/v1/availability?date=2026-10-03&procedure_id=2a9f8b31-6c74-4e05-9d28-a3f1e7b5c06d"{
"date": "2026-10-03",
"slots": [
{
"time": "09:00",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae"
},
{
"time": "10:00",
"professional_id": "1f6d5c84-3b92-4a07-8e15-d6c3f9b204ae"
}
]
}Repetir sin duplicar
La red se cae en mitad de la llamada, se agota el tiempo, y te quedas sin saber si la cita se creó. Repetir por tu cuenta puede reservar al mismo paciente dos veces.
Por eso toda creación viaja con un valor de repetición inventado por ti, uno para cada operación. Si vuelve a llegar con el mismo contenido, Meevia devuelve la respuesta que ya había dado, sin procesar otra vez.
Idempotency-Key
Cómo elegir ese valor
Genera un valor único por operación (un identificador aleatorio sirve) y guárdalo junto a tu intento, para reutilizar exactamente el mismo a la hora de repetir. Generar uno nuevo en cada intento es lo mismo que no tener ninguna protección.
La respuesta guardada vuelve tal como vino, incluso cuando fue un rechazo. Repetir con el valor de un intento que salió mal devuelve el mismo error, no un intento nuevo.
Reutilizar el mismo valor con contenido distinto se rechaza, y ese rechazo suele delatar dos operaciones distintas compartiendo un mismo valor. La misma respuesta aparece cuando una llamada gemela sigue en marcha, y ahí esperar unos instantes y repetir lo resuelve.
El valor vale un día. Después se olvida, y una repetición vuelve a procesarse de verdad.
Un intento que se quedó sin respuesta se da por perdido a los pocos minutos, y la llamada siguiente con ese valor ocupa su lugar. Así una petición que murió a mitad no te bloquea hasta el día siguiente.
- Minutos de espera antes de repetir un intento sin respuesta
5
Qué pasa al repetir cada llamada
No se aplica
Es lectura, y una lectura no cambia nada al repetirse.
Exige valor de repetición
Sin él la llamada se rechaza. Es la protección contra reservar al mismo paciente dos veces cuando la red falla a mitad.
Seguro repetir
Repetir lleva al mismo sitio: pedir el estado en el que la cita ya está devuelve la cita tal como está. Aquí no hace falta enviar valor de repetición.
Límites de uso
Cada clave tiene su propio tope de llamadas por minuto. Es por clave y no por clínica. Dos integraciones en la misma clínica no se pelean por el mismo límite, y una que disparó llamadas de más no tumba a la otra.
- Llamadas por minuto, en cada clave
120
La cuenta se pone a cero al cambiar cada minuto del reloj, y no en una ventana que se desliza. En la práctica, dos ráfagas disparadas justo en el cambio caen en minutos distintos, así que un pico corto puede pasar aunque sumado quede por encima del tope. No es holgura con la que se pueda contar: lo que sostiene una integración es el ritmo medio.
Cuando te pases, la respuesta trae en una cabecera propia, y no en el cuerpo, cuántos segundos esperar. Respeta ese número en vez de reintentar al momento. Si esto se vuelve rutina, el problema no es el tope: espacia las llamadas, guarda una copia de lo que cambia poco (el catálogo cambia poco) y deja de preguntar en bucle.
Retry-After
Cambios de estado permitidos
La API acepta un conjunto cerrado de cambios, y la tabla muestra cuáles: cada estado de origen tiene los destinos que permite, y lo que no está en la tabla se rechaza. Dar por realizada una cita y registrar una ausencia quedan fuera por decisión de producto. Los dos generan venta, cobro y consumo de sesión de bono. Siguen en manos de quien opera la clínica.
| Estado actual | Puede cambiar a |
|---|---|
pre_agendado | agendadoconfirmadocancelado |
agendado | confirmadocancelado |
confirmado | cancelado |
em_espera | cancelado |
Los estados
pre_agendado- Reservada, pero todavía sin confirmación de nadie. Es el estado en el que nace una cita nueva cuando no pides otro.
agendado- Está en la agenda y la clínica cuenta con ella.
confirmado- El paciente confirmó que viene. Es lo que mira recepción para saber con qué contar ese día.
em_espera- Está en la cola, esperando a que se abra un hueco. La API no pone a nadie aquí, pero sí lee a quien está, y desde aquí el único cambio posible es cancelar.
cancelado- Cancelada, y punto final: desde aquí la API ya no cambia nada.
realizado- La consulta ocurrió. Quien lo graba es la clínica, porque el cambio genera la venta. La API lo lee y no lo escribe.
faltou- El paciente no apareció. También es de la clínica: entra en el cobro por ausencia y en el consumo de sesión de bono. La API lo lee y no lo escribe.
Cuando la llamada no sale bien
Todo rechazo vuelve en el mismo formato, con un código corto que no cambia y un mensaje en portugués. En tu programa, decide siempre por el código, nunca por el mensaje: el mensaje existe para tu registro y puede reescribirse en cualquier momento.
Algunos rechazos traen además el detalle de lo que no pasó. No todos lo traen, así que tu código no puede depender de él.
plan_requiredCódigo de estado 403
La clave es válida, pero el plan de la clínica no incluye el acceso a la API.
Ningún cambio en tu código lo arregla. Avisa a la clínica, que habla con el soporte de Meevia: es asunto de plan.
scope_requiredCódigo de estado 403
La clave es válida, pero no tiene el ámbito que esta llamada exige.
Mira en la ficha de la llamada qué ámbito pide, y compáralo con los ámbitos de la clave en la pestaña Chaves del panel. Los ámbitos no se editan: emite otra clave con lo que falta, cámbiala en tu entorno y revoca la antigua.
not_foundCódigo de estado 404
Aquí llegan dos situaciones distintas: o la dirección no corresponde a nada, o lo que pediste no existe en esta clínica.
Comprueba primero la dirección, letra a letra, contra el ejemplo de la llamada; un plural de más cae en este caso. Si la dirección está bien, lo que falta es el registro: puede haber sido borrado, o ser de otra clínica. Acuérdate también de que el entorno de prueba tiene datos propios. Un identificador copiado de la clínica real no existe ahí dentro.
method_not_allowedCódigo de estado 405
La dirección existe, pero no atiende ese tipo de petición.
Comprueba en la ficha de la llamada qué método espera. Casi siempre es una lectura intentada como escritura, o al revés.
validation_failedCódigo de estado 422
Algo de lo que enviaste no pasó la comprobación: falta un dato obligatorio, o uno de ellos vino en un formato que no sirve.
El mensaje del rechazo dice qué no pasó. Compáralo con la tabla de parámetros de la llamada, con atención especial al formato de fecha y hora, que es donde más se falla.
rate_limitedCódigo de estado 429
Te pasaste del tope de llamadas por minuto de esa clave.
Espera los segundos que vienen en la cabecera de espera de la respuesta. No están en el cuerpo. Por eso mucha gente no encuentra el número y acaba reintentando al momento, lo que solo hunde más. Si pasa a menudo, ajusta el ritmo: espacia las llamadas, guarda una copia de lo que cambia poco y no preguntes en bucle.
idempotency_conflictCódigo de estado 409
El valor de repetición que enviaste ya se usó para otra cosa, o una llamada gemela sigue en marcha.
Si fue otra cosa, pasa a generar un valor nuevo para cada operación nueva; reaprovechar el mismo en operaciones distintas es lo que causa esto. Si es la gemela, espera unos instantes y repite con el mismo valor: en cuanto termine la primera, se devuelve la respuesta guardada.
status_transition_not_allowedCódigo de estado 422
El cambio que pediste no está permitido desde el estado en el que está la cita.
Lee la tabla de cambios permitidos, que muestra hacia dónde se puede ir desde cada estado. Dar por realizada una cita y registrar una ausencia no están ahí, y siguen siendo de la operación de la clínica. El rechazo viene con el estado actual y el pedido, lo que suele revelar que la cita ya estaba en otro.
sandbox_not_readyCódigo de estado 409
La clave es de prueba y el entorno de prueba de la clínica todavía no está en pie.
Repite en unos instantes. Si persiste, hay que reiniciar el entorno, lo que lo recrea desde cero, y eso lo haces tú mismo si tienes Pode administrar en el panel. Una clave de producción nunca cae en este caso.
internal_errorCódigo de estado 500
Algo se rompió de nuestro lado.
No es tu código. Inténtalo otra vez tras un intervalo. Si persiste, habla con el soporte de Meevia diciendo la hora y qué llamaste; la pestaña Requisições del panel ayuda a localizarlo.
¿Necesitas ayuda?
Cuéntanos qué llamaste, qué esperabas y qué volvió. La pestaña Requisições del panel muestra lo que nos llegó, y es por ahí por donde empezamos a mirar.
Esta página y la API
Si encuentras una diferencia entre lo que está escrito aquí y lo que respondió la API, la API tiene razón, y queremos saberlo. La fecha de abajo dice cuándo se comprobó esta página contra ella por última vez.