GET
/me
Quién soy
El centro al que pertenece la clave y los permisos que lleva.
sólo clave válida
Respuesta 200: Me
v1.0.0 · openapi.json
https://api.bloombooking.com/api/v1
API REST del centro. Es la base de todas las conectividades de BloomBooking: la web pública de reservas, el servidor MCP, los agentes de voz y de WhatsApp y las integraciones del propio centro hablan con este mismo motor.
Cada centro emite sus claves desde Ajustes → API. Se manda en cada petición como Authorization: Bearer bb_… (o X-API-Key). Una clave pertenece a un solo centro y lleva permisos explícitos, así que una integración de sólo lectura no puede anular citas aunque quiera.
La clave se enseña una vez, al crearla: después sólo vive su hash. Si se pierde, se revoca y se emite otra.
Los instantes van en ISO 8601 con offset (2026-09-01T09:00:00.000Z). Los rangos de días (from, to) son días civiles del centro, y las respuestas traen además la hora de pared del local y su zona IANA: quien integra no tiene por qué saber que Canarias no empieza el día a la misma hora que Madrid.
Siempre { "error": { "code", "message", "details?" } } con el código estable en code. El 409 al reservar (slot_taken) no es un fallo de la integración: es que alguien ha cogido ese hueco primero.
120 peticiones por minuto y clave. Al pasarse, 429 con rate_limited.
La clave y el centro al que pertenece.
/meQuién soy
El centro al que pertenece la clave y los permisos que lleva.
sólo clave válida
Respuesta 200: Me
Locales, servicios y profesionales.
/locationsLocales del centro
Cada local trae su zona horaria: las horas de pared se derivan de ahí.
catalog:read
Respuesta 200: LocationList
/servicesServicios
El catálogo completo del centro. Con bookable_online=true sólo lo que el centro publica en su web pública de reservas.
catalog:read
location_id |
uuid | |
bookable_online |
string |
Respuesta 200: ServiceList
/professionalsProfesionales
Con location_id, sólo quien tiene horario en esa sede.
catalog:read
location_id |
uuid |
Respuesta 200: ProfessionalList
Qué huecos hay libres.
/availabilityHuecos libres de un servicio
El mismo motor que la agenda del centro: horario real del profesional × recursos libres, con el quantum y el margen entre citas del centro. La sala y el aparato no se eligen aquí: los asigna el sistema al reservar.
availability:read
service_id obligatorio |
uuid | |
from obligatorio |
string | Fecha civil del centro, YYYY-MM-DD |
to obligatorio |
string | Fecha civil del centro, YYYY-MM-DD |
professional_id |
uuid | |
limit |
integer |
Respuesta 200: Availability
Fichas de las clientas del centro.
/clientsBuscar clientes
Por texto libre (q), por teléfono (en cualquier formato: se normaliza a E.164 antes de buscar) o por correo.
clients:read
q |
string | |
phone |
string | |
email |
string | |
page |
integer | |
page_size |
integer |
Respuesta 200: ClientList
/clientsCrear cliente
Si ya hay una ficha con ese teléfono o ese correo, se devuelve esa: duplicar la ficha de una clienta habitual no es una opción.
clients:write
Cuerpo: ClientInput
Respuesta 201: ClientEnvelope
/clients/{id}Ficha de un cliente
clients:read
id obligatorio |
uuid |
Respuesta 200: ClientEnvelope
Consultar, reservar y anular.
/appointmentsCitas de un rango de días
from y to son días civiles del centro, no instantes.
appointments:read
from obligatorio |
string | Fecha civil del centro, YYYY-MM-DD |
to obligatorio |
string | Fecha civil del centro, YYYY-MM-DD |
location_id |
uuid | |
client_id |
uuid | |
professional_id |
uuid | |
status |
pending · confirmed · in_progress · completed · no_show · cancelled | |
page |
integer | |
page_size |
integer |
Respuesta 200: AppointmentList
/appointmentsReservar una cita
La hora se vuelve a comprobar contra el motor antes de guardar, y el solape lo impide Postgres con una constraint de exclusión: si dos sistemas piden el mismo hueco a la vez, el segundo recibe 409 slot_taken. El cliente se indica con client_id o se describe en client (se reconoce por teléfono o correo antes de crear ficha).
appointments:write
Cuerpo: CreateAppointment
Respuesta 201: AppointmentEnvelope
/appointments/{id}Una cita
appointments:read
id obligatorio |
uuid |
Respuesta 200: AppointmentEnvelope
/appointments/{id}/cancelAnular una cita
El motivo queda en la ficha y viaja en el evento appointment.cancelled.
appointments:write
id obligatorio |
uuid |
Cuerpo: CancelAppointment
Respuesta 200: AppointmentEnvelope
Me{
"type": "object",
"properties": {
"tenant": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"slug": {
"type": "string",
"minLength": 3,
"maxLength": 63,
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
},
"name": {
"type": "string"
}
},
"required": [
"id",
"slug",
"name"
]
},
"key": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"prefix": {
"type": "string"
},
"scopes": {
"type": "array",
"items": {
"type": "string",
"enum": [
"catalog:read",
"availability:read",
"clients:read",
"clients:write",
"appointments:read",
"appointments:write"
]
}
},
"expires_at": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
{
"type": "null"
}
]
}
},
"required": [
"id",
"name",
"prefix",
"scopes",
"expires_at"
]
}
},
"required": [
"tenant",
"key"
]
}
Location{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"timezone": {
"type": "string"
},
"address_line": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"postal_code": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"city": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
}
},
"required": [
"id",
"name",
"timezone",
"address_line",
"postal_code",
"city",
"phone",
"email"
]
}
LocationList{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Location"
}
}
},
"required": [
"items"
]
}
Service{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"group_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"group_name": {
"type": "string"
},
"location_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"duration_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"price_cents": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"is_collective": {
"type": "boolean"
},
"max_capacity": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"bookable_online": {
"type": "boolean"
}
},
"required": [
"id",
"name",
"group_id",
"group_name",
"location_id",
"duration_minutes",
"price_cents",
"is_collective",
"max_capacity",
"bookable_online"
]
}
ServiceList{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Service"
}
}
},
"required": [
"items"
]
}
Professional{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"is_active": {
"type": "boolean"
}
},
"required": [
"id",
"name",
"is_active"
]
}
ProfessionalList{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Professional"
}
}
},
"required": [
"items"
]
}
Slot{
"type": "object",
"properties": {
"starts_at": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
"ends_at": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
"local_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Fecha civil del centro, `YYYY-MM-DD`"
},
"local_time": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
},
"professional_id": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
},
"professional_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"room_id": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
},
"room_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
}
},
"required": [
"starts_at",
"ends_at",
"local_date",
"local_time",
"professional_id",
"professional_name",
"room_id",
"room_name"
]
}
Availability{
"type": "object",
"properties": {
"service": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"duration_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"price_cents": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"location_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"timezone": {
"type": "string"
}
},
"required": [
"id",
"name",
"duration_minutes",
"price_cents",
"location_id",
"timezone"
]
},
"days": {
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Fecha civil del centro, `YYYY-MM-DD`"
},
"slots": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Slot"
}
}
},
"required": [
"date",
"slots"
]
}
},
"total_slots": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"empty_reason": {
"type": "string",
"enum": [
"none",
"no_professionals",
"no_rooms",
"no_equipment",
"no_working_hours",
"all_busy"
]
}
},
"required": [
"service",
"days",
"total_slots",
"empty_reason"
]
}
Client{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"first_name": {
"type": "string"
},
"last_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"email": {
"anyOf": [
{
"type": "string",
"format": "email",
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
},
{
"type": "null"
}
]
},
"phone": {
"anyOf": [
{
"type": "string",
"pattern": "^\\+[1-9]\\d{6,14}$"
},
{
"type": "null"
}
]
},
"created_at": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
},
"required": [
"id",
"first_name",
"last_name",
"email",
"phone",
"created_at"
]
}
ClientList{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Client"
}
},
"total": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"page": {
"type": "integer",
"minimum": 1,
"maximum": 9007199254740991
},
"page_size": {
"type": "integer",
"minimum": 1,
"maximum": 9007199254740991
}
},
"required": [
"items",
"total",
"page",
"page_size"
]
}
ClientInput{
"type": "object",
"properties": {
"first_name": {
"type": "string",
"minLength": 2,
"maxLength": 80
},
"last_name": {
"anyOf": [
{
"type": "string",
"maxLength": 80
},
{
"type": "null"
}
]
},
"email": {
"anyOf": [
{
"anyOf": [
{
"type": "string",
"format": "email",
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
},
{
"type": "string",
"const": ""
}
]
},
{
"type": "null"
}
]
},
"phone": {
"anyOf": [
{
"type": "string",
"maxLength": 40
},
{
"type": "null"
}
]
}
},
"required": [
"first_name"
]
}
ClientEnvelope{
"type": "object",
"properties": {
"client": {
"$ref": "#/components/schemas/Client"
}
},
"required": [
"client"
]
}
Appointment{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"status": {
"type": "string",
"enum": [
"pending",
"confirmed",
"in_progress",
"completed",
"no_show",
"cancelled"
]
},
"source": {
"type": "string",
"enum": [
"staff",
"online",
"api",
"assistant"
]
},
"starts_at": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
"ends_at": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
"local_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Fecha civil del centro, `YYYY-MM-DD`"
},
"local_time": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
},
"timezone": {
"type": "string"
},
"location_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"client": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"phone": {
"anyOf": [
{
"type": "string",
"pattern": "^\\+[1-9]\\d{6,14}$"
},
{
"type": "null"
}
]
}
},
"required": [
"id",
"name",
"phone"
]
},
"service": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"duration_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"price_cents": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
}
},
"required": [
"id",
"name",
"duration_minutes",
"price_cents"
]
},
"professional": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
}
},
"required": [
"id",
"name"
]
},
{
"type": "null"
}
]
},
"room": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
}
},
"required": [
"id",
"name"
]
},
{
"type": "null"
}
]
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"cancel_reason": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"created_at": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
},
"required": [
"id",
"status",
"source",
"starts_at",
"ends_at",
"local_date",
"local_time",
"timezone",
"location_id",
"client",
"service",
"professional",
"room",
"notes",
"cancel_reason",
"created_at"
]
}
AppointmentList{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Appointment"
}
},
"total": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"page": {
"type": "integer",
"minimum": 1,
"maximum": 9007199254740991
},
"page_size": {
"type": "integer",
"minimum": 1,
"maximum": 9007199254740991
}
},
"required": [
"items",
"total",
"page",
"page_size"
]
}
AppointmentEnvelope{
"type": "object",
"properties": {
"appointment": {
"$ref": "#/components/schemas/Appointment"
}
},
"required": [
"appointment"
]
}
CreateAppointment{
"type": "object",
"properties": {
"service_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"starts_at": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
"professional_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"client_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"client": {
"$ref": "#/components/schemas/ClientInput"
},
"status": {
"default": "confirmed",
"type": "string",
"enum": [
"pending",
"confirmed"
]
},
"notes": {
"anyOf": [
{
"type": "string",
"maxLength": 2000
},
{
"type": "null"
}
]
}
},
"required": [
"service_id",
"starts_at"
]
}
CancelAppointment{
"type": "object",
"properties": {
"reason": {
"type": "string",
"minLength": 3,
"maxLength": 500
}
},
"required": [
"reason"
]
}
Error{
"type": "object",
"properties": {
"error": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {}
},
"required": [
"code",
"message"
]
}
},
"required": [
"error"
]
}