# info.summary
Disponibilidad y reservas en negocios locales que usan Maître.

# info.description
Endpoints públicos y sin clave. No hay tokens ni registro: el control es un
límite de peticiones por IP, el mismo que protege la página de reservas.

Toda reserva creada desde fuera entra como `pending` y queda pendiente de que
el negocio la confirme. Un integrador no puede darla por hecha, ni decirle a
una persona que su hora está garantizada.

Para asistentes conversacionales hay una superficie mejor: el servidor MCP en https://maitreai.es/api/mcp, que trabaja con el slug del negocio en lugar de con UUID.

# paths./api/availability.get.description
Devuelve solo horas. Nunca nombres, teléfonos ni cuántas reservas hay:
saber que las 21:00 está ocupada no debe revelar quién va a ir.

Límite: 10 peticiones por minuto y por IP.

# paths./api/availability.get.parameters[].description
Filtra por la agenda de un profesional concreto.

# paths./api/availability.get.responses.429.description
Se ha superado el límite por IP. Espera y reintenta.

# paths./api/availability.get.responses.503.description
No se pudo comprobar la disponibilidad. Es distinto de "está cerrado": no presentes esto como que el negocio no tiene hueco.

# paths./api/reservations.post.description
Comprueba antes `/api/availability`: la hora se valida contra el aforo y
el horario, y una hora inventada devuelve 400.

La reserva nace `pending`. El campo `status` del cuerpo solo se respeta si
quien llama es miembro del negocio con sesión iniciada; desde fuera se
ignora y siempre sale `pending`.

Límite: 10 peticiones por minuto y por IP.

# paths./api/reservations.post.responses.201.description
Reserva creada, pendiente de confirmación del negocio.

# paths./api/reservations.post.responses.429.description
Se ha superado el límite por IP. Espera y reintenta.

# paths./api/cancel.get.summary
Consultar una reserva por su token de cancelación

# paths./api/cancel.get.description
El token viaja en el enlace que recibe el cliente al reservar. No se puede derivar de nada: sin ese enlace, esta operación no sirve.

Límite: 60 peticiones por minuto y por IP.

# paths./api/cancel.get.responses.429.description
Se ha superado el límite por IP. Espera y reintenta.

# paths./api/cancel.post.description
Límite: 5 peticiones por minuto y por IP, para que el token no se pueda probar a ciegas.

# paths./api/cancel.post.requestBody.content.application/json.schema.properties.accept_fee.description
Acepta el cargo por cancelación tardía, cuando el negocio lo tenga configurado.

# paths./api/cancel.post.responses.429.description
Se ha superado el límite por IP. Espera y reintenta.

# paths./api/public/branding.get.summary
Si la página pública de un negocio debe mostrar la marca Maître

# paths./api/public/branding.get.description
Detalle de presentación que consume la propia página del negocio. Se documenta porque es público y sin clave, no porque un integrador lo necesite.

# paths./api/public/branding.get.responses.429.description
Se ha superado el límite por IP. Espera y reintenta.

# paths./api/health.get.description
Devuelve 200 si todo responde y 503 si algo va degradado. Es el destino de `rel="status"` en el catálogo de APIs.

# paths./api/health.get.responses.429.description
Se ha superado el límite por IP. Espera y reintenta.

# components.schemas.Availability.properties.slots.description
Horas reservables. Vacío puede ser "lleno" o "cerrado" — mira closedReason.

# components.schemas.Availability.properties.bookedSlots.description
Horas que el día tiene pero ya están ocupadas.

# components.schemas.Availability.properties.closedReason.description
Presente solo cuando el día no da nada por un motivo estructural, no porque esté lleno.

# components.schemas.NewReservation.properties.source.description
Canal de origen. Un asistente que reserve por su cuenta debe enviar `assistant`, que es lo que ya pone /api/mcp: sin ese valor el canal cuenta como `web` y no hay forma de medirlo.

# components.schemas.NewReservation.properties.status.description
Solo lo respeta una llamada autenticada de alguien del negocio. Desde fuera se ignora.

# components.schemas.Reservation.description
La reserva creada, tal y como queda guardada.

# components.schemas.Reservation.properties.cancellation_token.description
Necesario para /api/cancel. Entrégaselo al cliente, no lo guardes tú.