{
  "openapi": "3.1.0",
  "info": {
    "title": "Hotel OTA Commission Calculator API",
    "version": "1.0.0",
    "description": "See what Booking.com, Expedia, and other OTAs really cost your hotel each year, and what direct bookings would save.\n\nFree, no API key, CORS open. Fair use: about 120 requests per minute per IP. Also available as MCP tools at https://free-agent-tools.vercel.app/mcp"
  },
  "servers": [
    {
      "url": "https://hotel-ota-calculator.vercel.app"
    }
  ],
  "paths": {
    "/api/calculate": {
      "get": {
        "operationId": "hotelOtaCommission",
        "summary": "Annual OTA commission a hotel pays (Booking.com, Expedia, Agoda...) and savings from shifting bookings to direct",
        "description": "From room count, average daily rate, occupancy, OTA share, and commission, returns yearly room nights and revenue, OTA commission paid per year and per day, commission as a share of room revenue (HIGH >= 10%, MED >= 5%, else LOW), and net yearly savings if a percentage of OTA bookings moves to direct (after direct booking costs). Currency is whatever the caller uses.\n\nExample: https://hotel-ota-calculator.vercel.app/api/calculate?rooms=20&adr=120&occupancy=70&otaShare=60&commission=18&directCost=3&shift=20",
        "parameters": [
          {
            "name": "rooms",
            "in": "query",
            "required": true,
            "description": "Number of rooms.",
            "schema": {
              "type": "number",
              "description": "Number of rooms.",
              "minimum": 0
            }
          },
          {
            "name": "adr",
            "in": "query",
            "required": true,
            "description": "Average daily rate per occupied room, any currency.",
            "schema": {
              "type": "number",
              "description": "Average daily rate per occupied room, any currency.",
              "minimum": 0
            }
          },
          {
            "name": "occupancy",
            "in": "query",
            "required": false,
            "description": "Average yearly occupancy percent.",
            "schema": {
              "type": "number",
              "description": "Average yearly occupancy percent.",
              "default": 70,
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "otaShare",
            "in": "query",
            "required": false,
            "description": "Percent of room revenue booked through OTAs.",
            "schema": {
              "type": "number",
              "description": "Percent of room revenue booked through OTAs.",
              "default": 60,
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "commission",
            "in": "query",
            "required": false,
            "description": "Average OTA commission percent (often 15-25).",
            "schema": {
              "type": "number",
              "description": "Average OTA commission percent (often 15-25).",
              "default": 18,
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "directCost",
            "in": "query",
            "required": false,
            "description": "Cost of a direct booking as percent of revenue (card fees, booking engine, ads).",
            "schema": {
              "type": "number",
              "description": "Cost of a direct booking as percent of revenue (card fees, booking engine, ads).",
              "default": 3,
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "shift",
            "in": "query",
            "required": false,
            "description": "Percent of current OTA bookings moved to direct.",
            "schema": {
              "type": "number",
              "description": "Percent of current OTA bookings moved to direct.",
              "default": 20,
              "minimum": 0,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Result as JSON. Always includes a `disclaimer` field.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid input. The body explains what to send and gives an example."
          },
          "429": {
            "description": "Too many requests from one IP. Retry after the Retry-After seconds."
          }
        }
      },
      "post": {
        "operationId": "hotelOtaCommissionPost",
        "summary": "Annual OTA commission a hotel pays (Booking.com, Expedia, Agoda...) and savings from shifting bookings to direct (JSON body)",
        "description": "From room count, average daily rate, occupancy, OTA share, and commission, returns yearly room nights and revenue, OTA commission paid per year and per day, commission as a share of room revenue (HIGH >= 10%, MED >= 5%, else LOW), and net yearly savings if a percentage of OTA bookings moves to direct (after direct booking costs). Currency is whatever the caller uses.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "rooms",
                  "adr"
                ],
                "properties": {
                  "rooms": {
                    "type": "number",
                    "description": "Number of rooms.",
                    "minimum": 0
                  },
                  "adr": {
                    "type": "number",
                    "description": "Average daily rate per occupied room, any currency.",
                    "minimum": 0
                  },
                  "occupancy": {
                    "type": "number",
                    "description": "Average yearly occupancy percent.",
                    "default": 70,
                    "minimum": 0,
                    "maximum": 100
                  },
                  "otaShare": {
                    "type": "number",
                    "description": "Percent of room revenue booked through OTAs.",
                    "default": 60,
                    "minimum": 0,
                    "maximum": 100
                  },
                  "commission": {
                    "type": "number",
                    "description": "Average OTA commission percent (often 15-25).",
                    "default": 18,
                    "minimum": 0,
                    "maximum": 100
                  },
                  "directCost": {
                    "type": "number",
                    "description": "Cost of a direct booking as percent of revenue (card fees, booking engine, ads).",
                    "default": 3,
                    "minimum": 0,
                    "maximum": 100
                  },
                  "shift": {
                    "type": "number",
                    "description": "Percent of current OTA bookings moved to direct.",
                    "default": 20,
                    "minimum": 0,
                    "maximum": 100
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Result as JSON. Always includes a `disclaimer` field.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid input. The body explains what to send and gives an example."
          },
          "429": {
            "description": "Too many requests from one IP. Retry after the Retry-After seconds."
          }
        }
      }
    }
  }
}