{
  "markdown": "# Rate Ranger for AI agents\n\nRate Ranger watches what a hotel charges **after** your user has already booked\nit, and emails them if the rate drops far enough to be worth rebooking. Free,\nno account, no app.\n\nThis repository is the public contract for doing that programmatically: an\nOpenAPI spec, an MCP connector manifest, and worked examples.\n\n- **MCP connector:** `https://www.rateranger.io/api/mcp`\n- **HTTP API:** `https://www.rateranger.io/api/agent/bookings`\n- **Guide:** https://www.rateranger.io/for-agents/\n- **OpenAPI 3.1:** [`openapi.json`](openapi.json)\n\n## Do not drive the web form\n\nThe form at rateranger.io is protected by a CAPTCHA that issues no token to an\nautomated browser. An assistant will fill every field correctly and then fail at\nthe last step with nothing to click. Use the connector or the API instead.\n\n## Option 1: the MCP connector\n\nAdd `https://www.rateranger.io/api/mcp` as a custom connector. No key, no\naccount, no setup beyond the URL.\n\nIt exposes two tools:\n\n| Tool | What it does |\n| --- | --- |\n| `submit_hotel_booking` | Enrols one to ten bookings for one traveller |\n| `check_hotel_booking` | Reads a booking back, including whether it is confirmed yet |\n\nWorks in ChatGPT (Developer Mode), Claude Code and Cursor. It does **not** work\nas a claude.ai custom connector, which requires OAuth; there is no way to\ndeclare a server unauthenticated there.\n\nThe server speaks protocol revisions `2026-07-28`, `2025-11-25`, `2025-06-18`\nand `2025-03-26`, so both the current per-request-metadata shape and the older\n`initialize` handshake work.\n\n## Option 2: the HTTP API\n\n```bash\ncurl -X POST https://www.rateranger.io/api/agent/bookings \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"email\": \"traveller@example.com\",\n    \"agent\": \"my-assistant/1.0\",\n    \"bookings\": [{\n      \"hotel_name\": \"Novotel Bali Ubud Resort\",\n      \"city\": \"Ubud\",\n      \"country\": \"ID\",\n      \"check_in_date\": \"2027-07-14\",\n      \"check_out_date\": \"2027-07-17\",\n      \"total_price\": 742.50,\n      \"currency\": \"USD\"\n    }]\n  }'\n```\n\nAnswers `202 Accepted` with a `read_token` per booking.\n\n## The traveller has to confirm. Tell them so.\n\n**A successful submission monitors nothing.** Rate Ranger emails the traveller\none link. Until they click it, no price is checked and no alert can fire. If\nthey never click, everything is deleted after 7 days.\n\nSo do not tell your user their booking is being tracked. Tell them to check\ntheir inbox, then confirm it yourself with `check_hotel_booking` or\n`GET /api/agent/bookings/{token}` before you say anything stronger. Look at\n`booking.confirmed`, which is `false` until they act.\n\nThis is why no key is needed. The endpoint takes an email address from whoever\ncalls it, so if submission alone started the service, anyone could sign any\naddress up for mail it never asked for. The confirmation step is what makes an\nopen API safe to leave open.\n\n## `country` is required, and it matters\n\nISO 3166-1 alpha-2, for example `JP` or `ID`. It decides which rate source can\nfind the hotel at all. A booking without one cannot be monitored properly, so it\nis required here even though the web form treats it as optional.\n\n## Limits\n\n| | Per day |\n| --- | --- |\n| Anonymous caller, by IP | 50 bookings |\n| With a key | 100 bookings |\n| One email address, from one caller | 3 bookings |\n| One email address, from anyone | 10 bookings |\n\nEmail hello@rateranger.io for a key if you need more.\n\nPrices may include decimals. Only the web form restricts them to whole numbers.\n\n## Errors\n\nEvery error carries a stable `code` to branch on, plus a `message` for a human\nreading a log. Branch on `code`; the wording may change.\n\n| Code | Meaning |\n| --- | --- |\n| `invalid_email` | Not a valid address |\n| `disposable_email` | A throwaway provider, which cannot receive alerts |\n| `invalid_token` | Signature failed, wrong token type, or expired |\n| `not_found` | Token verified but matches no booking |\n| `rate_limited` | A daily limit was reached |\n\nFull request and response shapes are in [`openapi.json`](openapi.json).\n\n## Support\n\nhello@rateranger.io\n",
  "bytes": 4100,
  "sha": "4589310fa1d2f7ac86acb84d97b7bef7f861bd219ba66cbac66ca86507d85d8a",
  "repo_slug": "halymich/rate-ranger-api",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_rateranger_hotel_price_monitor_131472ce/readme"
}