{
  "openapi": "3.0.3",
  "info": {
    "title": "Hospitality PMS API",
    "version": "1.1.0",
    "description": "API por hotel para consultar datos y enviar órdenes de estancia y despertadores. Solicita al responsable de la integración una clave con los permisos necesarios. El hotel se obtiene de la credencial; no se admite tenant_id ni x-tenant-id. Las escrituras requieren permisos explícitos e Idempotency-Key. La respuesta distingue la operación aplicada en Hospitality de su sincronización. Guía: https://hospitality.fibwi.com/pms-api-docs."
  },
  "servers": [
    {
      "url": "https://hospitality.fibwi.com/api/pms/v1"
    }
  ],
  "security": [
    {
      "PmsKey": []
    }
  ],
  "components": {
    "securitySchemes": {
      "PmsKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "hosp_pms_..."
      }
    },
    "schemas": {
      "Room": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "room_number": {
            "type": "string"
          },
          "extension": {
            "type": "string"
          },
          "housekeeping_status": {
            "type": "string"
          },
          "is_checked_in": {
            "type": "boolean"
          },
          "outbound_enabled": {
            "type": "boolean"
          },
          "checkin_at": {
            "type": "string",
            "nullable": true
          },
          "stay_checkin_date": {
            "type": "string",
            "nullable": true
          },
          "stay_checkout_date": {
            "type": "string",
            "nullable": true
          },
          "updated_at": {
            "type": "string"
          }
        }
      },
      "Stay": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "room_number": {
            "type": "string"
          },
          "extension": {
            "type": "string"
          },
          "housekeeping_status": {
            "type": "string"
          },
          "is_checked_in": {
            "type": "boolean"
          },
          "outbound_enabled": {
            "type": "boolean"
          },
          "checkin_at": {
            "type": "string",
            "nullable": true
          },
          "stay_checkin_date": {
            "type": "string",
            "nullable": true
          },
          "stay_checkout_date": {
            "type": "string",
            "nullable": true
          },
          "updated_at": {
            "type": "string"
          },
          "guest_name": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "Call": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "room_id": {
            "type": "integer",
            "nullable": true
          },
          "room_number": {
            "type": "string",
            "nullable": true
          },
          "checkout_id": {
            "type": "integer",
            "nullable": true
          },
          "uniqueid": {
            "type": "string",
            "nullable": true
          },
          "linkedid": {
            "type": "string",
            "nullable": true
          },
          "calldate": {
            "type": "string"
          },
          "src": {
            "type": "string"
          },
          "dst": {
            "type": "string"
          },
          "disposition": {
            "type": "string",
            "nullable": true
          },
          "billsec": {
            "type": "integer"
          },
          "outbound": {
            "type": "boolean"
          },
          "billed": {
            "type": "boolean"
          },
          "amounts": {
            "type": "object",
            "properties": {
              "net": {
                "type": "string"
              },
              "tax": {
                "type": "string"
              },
              "total": {
                "type": "string"
              },
              "tax_rate": {
                "type": "string"
              },
              "currency": {
                "type": "string"
              }
            }
          }
        }
      },
      "Wakeup": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "room_id": {
            "type": "integer"
          },
          "room_number": {
            "type": "string"
          },
          "extension": {
            "type": "string"
          },
          "wakeup_date": {
            "type": "string"
          },
          "wakeup_time": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "triggered",
              "awaiting_confirmation",
              "unconfirmed",
              "no_answer",
              "failed",
              "cancelled"
            ]
          },
          "triggered_at": {
            "type": "string",
            "nullable": true
          },
          "cancelled_at": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string"
          }
        }
      },
      "Event": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "source_event_id": {
            "type": "string"
          },
          "category": {
            "type": "string",
            "enum": [
              "stay",
              "services",
              "cdr"
            ]
          },
          "type": {
            "type": "string"
          },
          "occurred_at": {
            "type": "string"
          },
          "room_id": {
            "type": "integer",
            "nullable": true
          },
          "room_number": {
            "type": "string",
            "nullable": true
          },
          "extension": {
            "type": "string",
            "nullable": true
          },
          "payload": {
            "type": "object",
            "description": "Campos propios del evento. Los eventos CDR incluyen amounts con neto, IVA, total y moneda; uniqueid identifica la llamada en origen cuando está disponible."
          }
        }
      },
      "CommandCheckin": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "room_number",
          "guest_first_name",
          "guest_last_name",
          "stay_checkin_date",
          "stay_checkout_date"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "checkin"
            ]
          },
          "room_number": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          },
          "guest_first_name": {
            "type": "string",
            "maxLength": 200
          },
          "guest_last_name": {
            "type": "string",
            "maxLength": 200
          },
          "guest_doc_id": {
            "type": "string",
            "maxLength": 200
          },
          "guest_phone": {
            "type": "string",
            "maxLength": 200
          },
          "guest_email": {
            "type": "string",
            "maxLength": 200
          },
          "guest_address": {
            "type": "string",
            "maxLength": 500
          },
          "stay_checkin_date": {
            "type": "string",
            "format": "date"
          },
          "stay_checkout_date": {
            "type": "string",
            "format": "date"
          },
          "outbound_enabled": {
            "type": "boolean"
          }
        }
      },
      "CommandStayUpdate": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "room_number",
          "expected_checkin_at",
          "changes"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "stay_update"
            ]
          },
          "room_number": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          },
          "expected_checkin_at": {
            "type": "string",
            "format": "date-time"
          },
          "changes": {
            "type": "object",
            "minProperties": 1,
            "additionalProperties": false,
            "properties": {
              "guest_first_name": {
                "type": "string",
                "maxLength": 200
              },
              "guest_last_name": {
                "type": "string",
                "maxLength": 200
              },
              "guest_doc_id": {
                "type": "string",
                "maxLength": 200
              },
              "guest_phone": {
                "type": "string",
                "maxLength": 200
              },
              "guest_email": {
                "type": "string",
                "maxLength": 200
              },
              "guest_address": {
                "type": "string",
                "maxLength": 500
              },
              "stay_checkin_date": {
                "type": "string",
                "format": "date"
              },
              "stay_checkout_date": {
                "type": "string",
                "format": "date"
              },
              "outbound_enabled": {
                "type": "boolean"
              }
            }
          }
        }
      },
      "CommandCheckout": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "room_number",
          "expected_checkin_at"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "checkout"
            ]
          },
          "room_number": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          },
          "expected_checkin_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CommandRoomMove": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "room_number",
          "expected_checkin_at",
          "target_room_number"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "room_move"
            ]
          },
          "room_number": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          },
          "expected_checkin_at": {
            "type": "string",
            "format": "date-time"
          },
          "target_room_number": {
            "type": "string"
          }
        }
      },
      "CommandWakeupSet": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "room_number",
          "wakeup_date",
          "wakeup_time"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "wakeup_set"
            ]
          },
          "room_number": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          },
          "wakeup_date": {
            "type": "string",
            "format": "date"
          },
          "wakeup_time": {
            "type": "string",
            "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
          },
          "expected_checkin_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CommandWakeupCancel": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "room_number",
          "wakeup_id"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "wakeup_cancel"
            ]
          },
          "room_number": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          },
          "wakeup_id": {
            "type": "string",
            "pattern": "^[0-9]+$"
          },
          "expected_checkin_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Command": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/CommandCheckin"
          },
          {
            "$ref": "#/components/schemas/CommandStayUpdate"
          },
          {
            "$ref": "#/components/schemas/CommandCheckout"
          },
          {
            "$ref": "#/components/schemas/CommandRoomMove"
          },
          {
            "$ref": "#/components/schemas/CommandWakeupSet"
          },
          {
            "$ref": "#/components/schemas/CommandWakeupCancel"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "checkin": "#/components/schemas/CommandCheckin",
            "stay_update": "#/components/schemas/CommandStayUpdate",
            "checkout": "#/components/schemas/CommandCheckout",
            "room_move": "#/components/schemas/CommandRoomMove",
            "wakeup_set": "#/components/schemas/CommandWakeupSet",
            "wakeup_cancel": "#/components/schemas/CommandWakeupCancel"
          }
        }
      },
      "Operation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "applied"
            ]
          },
          "pbx_sync": {
            "type": "string",
            "enum": [
              "pending",
              "processing",
              "applied",
              "failed",
              "not_required"
            ]
          },
          "result": {
            "type": "object"
          },
          "sync_attempts": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "synced_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      }
    }
  },
  "paths": {
    "/rooms": {
      "get": {
        "summary": "Habitaciones y limpieza",
        "operationId": "listRoom",
        "description": "Permiso requerido: rooms:read. Orden ascendente por ID. Esta paginación no constituye un feed de actualizaciones.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Cursor opaco next_cursor de una respuesta anterior. Mantener los mismos filtros. En eventos, conservarlo entre ciclos; en otros recursos paginados, iniciar sin cursor para obtener una nueva foto completa."
          },
          {
            "name": "room_number",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Consulta correcta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Room"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "next_cursor": {
                          "type": "string"
                        },
                        "has_more": {
                          "type": "boolean"
                        },
                        "limit": {
                          "type": "integer"
                        }
                      }
                    },
                    "server_time": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/stays": {
      "get": {
        "summary": "Estancias activas",
        "operationId": "listStay",
        "description": "Permiso requerido: stays:read. Orden ascendente por ID. Esta paginación no constituye un feed de actualizaciones.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Cursor opaco next_cursor de una respuesta anterior. Mantener los mismos filtros. En eventos, conservarlo entre ciclos; en otros recursos paginados, iniciar sin cursor para obtener una nueva foto completa."
          },
          {
            "name": "room_number",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Consulta correcta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Stay"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "next_cursor": {
                          "type": "string"
                        },
                        "has_more": {
                          "type": "boolean"
                        },
                        "limit": {
                          "type": "integer"
                        }
                      }
                    },
                    "server_time": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/calls": {
      "get": {
        "summary": "Histórico de llamadas",
        "operationId": "listCall",
        "description": "Permiso requerido: calls:read. Orden ascendente por ID. Esta paginación no constituye un feed de actualizaciones.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Cursor opaco next_cursor de una respuesta anterior. Mantener los mismos filtros. En eventos, conservarlo entre ciclos; en otros recursos paginados, iniciar sin cursor para obtener una nueva foto completa."
          },
          {
            "name": "room_number",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Consulta correcta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Call"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "next_cursor": {
                          "type": "string"
                        },
                        "has_more": {
                          "type": "boolean"
                        },
                        "limit": {
                          "type": "integer"
                        }
                      }
                    },
                    "server_time": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/wakeups": {
      "get": {
        "summary": "Despertadores",
        "operationId": "listWakeup",
        "description": "Permiso requerido: wakeups:read. Orden ascendente por ID. Esta paginación no constituye un feed de actualizaciones.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Cursor opaco next_cursor de una respuesta anterior. Mantener los mismos filtros. En eventos, conservarlo entre ciclos; en otros recursos paginados, iniciar sin cursor para obtener una nueva foto completa."
          },
          {
            "name": "room_number",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "date",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Consulta correcta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Wakeup"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "next_cursor": {
                          "type": "string"
                        },
                        "has_more": {
                          "type": "boolean"
                        },
                        "limit": {
                          "type": "integer"
                        }
                      }
                    },
                    "server_time": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/events": {
      "get": {
        "summary": "Eventos incrementales",
        "operationId": "listEvent",
        "description": "Permiso requerido: events:read. También se exige el permiso del recurso de cada evento: stays:read, calls:read, wakeups:read o rooms:read. Orden de publicación; occurred_at puede ser anterior al de otros eventos. Una página puede estar vacía y tener has_more=true mientras se publica una cola histórica.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Cursor opaco next_cursor de una respuesta anterior. Mantener los mismos filtros. En eventos, conservarlo entre ciclos; en otros recursos paginados, iniciar sin cursor para obtener una nueva foto completa."
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "stay",
                "services",
                "cdr"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Consulta correcta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Event"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "next_cursor": {
                          "type": "string"
                        },
                        "has_more": {
                          "type": "boolean"
                        },
                        "limit": {
                          "type": "integer"
                        }
                      }
                    },
                    "server_time": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/hotel": {
      "get": {
        "summary": "Hotel y permisos de la credencial",
        "operationId": "getHotel",
        "responses": {
          "200": {
            "description": "Hotel asociado",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer"
                        },
                        "name": {
                          "type": "string"
                        },
                        "timezone": {
                          "type": "string"
                        }
                      }
                    },
                    "api_version": {
                      "type": "string"
                    },
                    "scopes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "server_time": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/commands": {
      "post": {
        "operationId": "applyCommand",
        "summary": "Enviar una orden del PMS",
        "description": "Requiere stays:write para checkin, stay_update, checkout y room_move; wakeups:write para wakeup_set y wakeup_cancel. Usa una Idempotency-Key nueva por operación real y repite la misma para recuperar una respuesta perdida. Hospitality guarda el cambio y el recibo de operación en una sola transacción. No se realizan llamadas telefónicas al recibir la orden: wakeup_set programa el despertador.",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:-]{8,128}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Command"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Operación aplicada en Hospitality. pbx_sync indica por separado su confirmación PBX.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Operation"
                    },
                    "replayed": {
                      "type": "boolean"
                    }
                  }
                }
              }
            },
            "headers": {
              "Idempotency-Replayed": {
                "schema": {
                  "type": "string"
                }
              },
              "Location": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "200": {
            "description": "Operación aplicada en Hospitality. pbx_sync indica por separado su confirmación PBX.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Operation"
                    },
                    "replayed": {
                      "type": "boolean"
                    }
                  }
                }
              }
            },
            "headers": {
              "Idempotency-Replayed": {
                "schema": {
                  "type": "string"
                }
              },
              "Location": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/commands/{commandId}": {
      "get": {
        "operationId": "getCommand",
        "summary": "Consultar resultado y sincronización de una orden",
        "description": "Requiere el permiso de escritura asociado al tipo de orden. El ID debe pertenecer al hotel de la credencial. No se repite la operación. Consulta pbx_sync para conocer la sincronización: pending o processing indican que sigue en curso; failed requiere contactar con el responsable de la integración y no revierte la modificación aplicada en Hospitality.",
        "parameters": [
          {
            "in": "path",
            "name": "commandId",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Estado actual",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Operation"
                    },
                    "server_time": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Error de la consulta",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    },
                    "request_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
