Rate Ranger for AI agents

An HTTP API for enrolling a hotel booking in price monitoring on behalf of the person you are helping. No account, no key, no browser.

Rate Ranger watches what a hotel charges after your user has already booked it, and emails them if the rate drops far enough to be worth rebooking. This page is the contract for doing that programmatically.

Do not drive the web form. It is protected by a CAPTCHA that issues no token to an automated browser, so a browser-driving agent will fill the form correctly and then fail at the last step with nothing to click. Use the API below instead.

Submit a booking

POST https://www.rateranger.io/api/agent/bookings
curl -X POST https://www.rateranger.io/api/agent/bookings \
  -H 'Content-Type: application/json' \
  -d '{
    "email": "traveller@example.com",
    "agent": "my-assistant/1.0",
    "bookings": [{
      "hotel_name": "Novotel Bali Ubud Resort",
      "city": "Ubud",
      "country": "ID",
      "check_in_date": "2027-07-14",
      "check_out_date": "2027-07-17",
      "total_price": 7428070,
      "currency": "IDR",
      "room_type": "Superior Room",
      "num_guests": 2,
      "num_rooms": 1,
      "booking_platform": "direct"
    }]
  }'

Response, 202 Accepted:

{
  "status": "pending_confirmation",
  "message": "1 booking(s) recorded. We have emailed the traveller a single link to
              confirm. Nothing is monitored and no price is checked until they click it.",
  "confirmation_required": true,
  "results": [
    {
      "index": 0,
      "status": "pending_confirmation",
      "booking_id": "5c96e96b-0d7e-4b5d-96f8-db003bc3e919",
      "read_token": "..."
    }
  ]
}

A successful submission monitors nothing. We email the traveller one link. Until they click it, no price is checked and no alert can fire. If they never click, everything we hold is deleted after 7 days.

So do not tell your user their booking is being tracked. Tell them to check their inbox. Then confirm it yourself with the read endpoint before you say anything stronger.

This exists because the endpoint takes an email address from whoever calls it. If submission alone started the service, anyone could sign any address up for mail it never asked for. The confirmation step is what makes an open API safe to leave open, and it is why you do not need a key to use it.

Fields

FieldRequiredNotes
emailYes The traveller's address. One per call. This is where the confirmation and any later alerts go.
bookingsYes 1 to 10 per call.
hotel_nameYes As the property is normally listed. Closer to the official name is better; we match it against live hotel data.
cityYesCity, not district.
countryYes ISO 3166-1 alpha-2, for example JP or ID. See the note below: this one matters more than it looks.
check_in_date, check_out_dateYes YYYY-MM-DD. Check-in must be in the future and check-out after it.
total_priceYes The whole cost of the stay, not a nightly rate. Decimals are fine.
currencyNo ISO 4217, defaults to USD. Must be one we support; a bad one is rejected by name.
room_typeNoFree text.
num_guests, num_roomsNo Default 2 and 1.
booking_platformNo booking.com, expedia, hotels.com, agoda, trip.com, priceline, direct, or other.
agentNo Name yourself. It is logged, never shown to the traveller, and helps us work out who to talk to if an integration starts sending malformed batches.

Always send country. It decides which rate source can find the hotel. A booking without one falls to a fallback source that cannot look up a hotel id, and without that id we can never send an alert, however far the price falls. You almost certainly know the country. Send it.

Check what happened

GET https://www.rateranger.io/api/agent/bookings/{read_token}

Use the read_token from the submission. It reaches that one booking and nothing else. Poll it to find out whether the traveller confirmed, and later to see the current rate.

{
  "status": "ok",
  "booking": {
    "booking_id": "5c96e96b-...",
    "hotel_name": "Novotel Bali Ubud Resort",
    "monitoring_status": "watching",
    "confirmed": true,
    "booked_price": 7428070.0,
    "currency": "IDR",
    "last_checked": "2026-08-31T02:06:31+00:00",
    "lowest_price": 6900000.0,
    "lowest_source": "agoda",
    "saving": 528070.0,
    "saving_pct": 7.1
  }
}

saving is only ever populated when a real alert could fire for that booking. If we cannot link the traveller to a bookable page for the hotel, or the drop is too small to be worth an email, it stays null and a saving_note explains why. We would rather report nothing than a number your user cannot act on.

Reading the results array

One entry per booking you sent, in the same order, each with its own outcome. One bad date does not reject the rest.

statusMeaning
pending_confirmation Recorded. Waiting on the traveller's email click.
duplicate Already recorded for this address. Sending it again does nothing and does not re-email anyone, so retrying is safe.
rejected We cannot monitor it. reason and message say why. The common ones are a past check-in, check-out on or before check-in, and a non-refundable booking.
rate_limited You are out of allowance for today. Everything before it in the batch still went through.

Non-refundable bookings are refused on purpose. The whole method is cancel the old booking and rebook cheaper. If it cannot be cancelled, an alert costs your user money instead of saving it.

Limits

Without a key10 bookings per day, per IP
With a key50 bookings per day
Per call10 bookings
Per traveller3 confirmation emails per day, across everyone

Email hello@rateranger.io if you need more and we will issue a key. Send it as X-RateRanger-Key. An unrecognised key does not fail the request; it drops you to the anonymous limit.

Use https://www.rateranger.io as the base URL. It is the only supported host.

Cost

Free, for you and for the traveller. There is no account and no card. Rate Ranger earns an affiliate commission only if the traveller decides to rebook through a link in an alert, and never charges them anything.

Machine-readable

Ready to start saving?

Enter your booking details and we handle the rest. Free, no account needed.

Get started