{
  "openapi": "3.1.0",
  "info": {
    "title": "MASTERIZE · Reservas",
    "version": "1.1.0",
    "description": "Agenda una llamada gratuita de 30 minutos por Google Meet con MASTERIZE (ERP a la medida y automatización para talleres industriales). Horario: lunes a viernes de 15:00 a 18:00, hora del centro de México (America/Mexico_City). Dos pasos: 1) GET /api/booking.php → toma `first` (el horario libre más cercano) o cualquiera de `slots`; 2) POST con date, time, name, email y company. La confirmación con el enlace de Google Meet llega al correo indicado. Si el POST responde 409, el horario se ocupó: vuelve al paso 1. Límite: 60 consultas y 5 reservas por hora por IP."
  },
  "servers": [
    {
      "url": "https://masterizetech.com"
    }
  ],
  "paths": {
    "/api/booking.php": {
      "get": {
        "operationId": "consultarDisponibilidad",
        "summary": "Horarios libres de los próximos 30 días (responde al instante)",
        "parameters": [
          {
            "name": "action",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "const": "availability"
            },
            "description": "Opcional; es la única acción de GET."
          }
        ],
        "responses": {
          "200": {
            "description": "Horarios libres por día (hora del centro de México, bloques de 30 min).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "timezone": {
                      "type": "string",
                      "example": "America/Mexico_City"
                    },
                    "slots": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "pattern": "^\\d{2}:\\d{2}$"
                        }
                      },
                      "example": {
                        "2026-10-07": [
                          "15:00",
                          "15:30",
                          "16:00"
                        ]
                      }
                    },
                    "duration": {
                      "type": "integer",
                      "example": 30,
                      "description": "Minutos por llamada."
                    },
                    "first": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "El horario libre más cercano, listo para reservar.",
                      "properties": {
                        "date": {
                          "type": "string",
                          "format": "date"
                        },
                        "time": {
                          "type": "string",
                          "pattern": "^\\d{2}:\\d{2}$"
                        }
                      },
                      "example": {
                        "date": "2026-10-12",
                        "time": "15:00"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Demasiadas consultas; reintenta después de Retry-After."
          },
          "502": {
            "description": "El calendario no respondió; reintenta más tarde."
          }
        }
      },
      "post": {
        "operationId": "reservarLlamada",
        "summary": "Reserva una llamada de 30 min",
        "description": "JSON (application/json o text/plain) o formulario (application/x-www-form-urlencoded). `action` es opcional. date y time deben salir de consultarDisponibilidad.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "date",
                  "time",
                  "name",
                  "email",
                  "company"
                ],
                "properties": {
                  "action": {
                    "type": "string",
                    "const": "book",
                    "description": "Opcional."
                  },
                  "date": {
                    "type": "string",
                    "format": "date",
                    "example": "2026-10-07"
                  },
                  "time": {
                    "type": "string",
                    "pattern": "^\\d{2}:\\d{2}$",
                    "example": "15:30"
                  },
                  "name": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 80
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 120
                  },
                  "company": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 120,
                    "description": "Nombre del taller o empresa."
                  },
                  "phone": {
                    "type": "string",
                    "maxLength": 20,
                    "description": "WhatsApp (opcional)."
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 600,
                    "description": "Qué quiere resolver el taller (opcional)."
                  }
                }
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "date",
                  "time",
                  "name",
                  "email",
                  "company"
                ],
                "properties": {
                  "action": {
                    "type": "string",
                    "const": "book",
                    "description": "Opcional."
                  },
                  "date": {
                    "type": "string",
                    "format": "date",
                    "example": "2026-10-07"
                  },
                  "time": {
                    "type": "string",
                    "pattern": "^\\d{2}:\\d{2}$",
                    "example": "15:30"
                  },
                  "name": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 80
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 120
                  },
                  "company": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 120,
                    "description": "Nombre del taller o empresa."
                  },
                  "phone": {
                    "type": "string",
                    "maxLength": 20,
                    "description": "WhatsApp (opcional)."
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 600,
                    "description": "Qué quiere resolver el taller (opcional)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reserva confirmada.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "event": {
                      "type": "object",
                      "properties": {
                        "date": {
                          "type": "string",
                          "format": "date"
                        },
                        "time": {
                          "type": "string"
                        },
                        "timezone": {
                          "type": "string"
                        },
                        "duration": {
                          "type": "integer"
                        },
                        "hangoutLink": {
                          "type": "string",
                          "description": "Enlace de Google Meet."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Datos inválidos; el mensaje dice qué revisar (fecha, horario, nombre, correo, empresa)."
          },
          "409": {
            "description": "Ese horario ya se ocupó; consulta la disponibilidad otra vez y elige otro."
          },
          "429": {
            "description": "Demasiadas reservas desde esta IP; reintenta después de Retry-After."
          }
        }
      }
    }
  }
}
