Островок — ETG API (RateHawk) API

Отрасль: Путешествия и транспорт. Актуально на 2026-10-24.

API Emerging Travel Group (Островок, RateHawk) версии V3 для бронирования отелей: поиск цен по региону, отелям или координатам, страница отеля со всеми тарифами, предбронирование, создание и завершение бронирования, проверка статуса, отмена, статический контент и дампы отелей. Есть B2B API (для турагентств) и Affiliate API; здесь — основные методы B2B. Перед использованием нужен договор, после интеграции может потребоваться сертификация.

Сценарии

Найти отели и цены в городе

Поиск отелей на даты поездки: от строки «Сочи» до списка отелей с ценами и всех тарифов выбранного отеля.

  1. Найди регион по названию: POST /api/b2b/v3/search/multicomplete/ с query (часть названия) и language. В ответе — до 5 регионов и отелей; возьми id нужного региона.
  2. Запроси цены по региону: POST /api/b2b/v3/search/serp/region/ с region_id, checkin, checkout, guests (adults и возраст детей по каждому номеру), residency (гражданство гостей), currency и language. Фильтры — filter.star_rating, filter.meal_type, filter.price_from / filter.price_to, размер выдачи — hotels_limit.
  3. Не давай пользователю выбирать тариф прямо из выдачи по региону: совпадение с тарифами страницы отеля не гарантируется.
  4. Когда пользователь выбрал отель, запроси все его тарифы: POST /api/b2b/v3/search/hp/ с hid (числовой ID отеля), теми же датами, гостями и residency. Тариф живёт около 30 минут — по истечении повтори запрос.
  5. Авторизация — HTTP Basic: KEY_ID как имя пользователя, API_KEY как пароль. Отлаживай на песочнице api-sandbox.ratehawk.com.
AUTH='<KEY_ID>:<API_KEY>'
API=https://api.ratehawk.com/api/b2b/v3

curl --user "$AUTH" "$API/search/multicomplete/" -H 'Content-Type: application/json' \
  -d '{"query": "Сочи", "language": "ru"}'

curl --user "$AUTH" "$API/search/serp/region/" -H 'Content-Type: application/json' \
  -d '{"checkin": "2026-11-20", "checkout": "2026-11-23", "residency": "ru", "language": "ru",
       "guests": [{"adults": 2, "children": []}], "region_id": <region_id>, "currency": "RUB",
       "hotels_limit": 50, "filter": {"star_rating": [4, 5]}}'

curl --user "$AUTH" "$API/search/hp/" -H 'Content-Type: application/json' \
  -d '{"hid": <hid>, "checkin": "2026-11-20", "checkout": "2026-11-23", "residency": "ru",
       "language": "ru", "guests": [{"adults": 2, "children": []}], "currency": "RUB"}'

Забронировать номер

Полный путь брони после выбора тарифа: проверка доступности, создание брони, запуск и ожидание подтверждения.

  1. Проверь тариф перед бронью: POST /api/b2b/v3/hotel/prebook/ с hash — ID тарифа со страницы отеля — и price_increase_percent, если готов принять небольшой рост цены. Если тариф ушёл, API подберёт альтернативу с тем же типом номера и питанием и вернёт новый hash. Таймаут клиента — не меньше 30 секунд, лучше 60.
  2. Сразу после prebook создай бронь: POST /api/b2b/v3/hotel/order/booking/form/ с partner_order_id (свой UUID, уникальный в рамках договора), book_hash из ответа prebook, language и user_ip конечного пользователя. Форма живёт 60 минут; в ответе — доступные способы оплаты.
  3. Запусти бронирование: POST /api/b2b/v3/hotel/order/booking/finish/ с partner.partner_order_id, payment_type (type, amount, currency_code — из способов оплаты формы), rooms[].guests (first_name, last_name), user.email и user.phone менеджера.
  4. Бронь асинхронная: опрашивай POST /api/b2b/v3/hotel/order/booking/finish/status/ с partner_order_id, пока статус не станет финальным (или подключи вебхук статуса). При оплате картой с 3D Secure в ответе придёт data_3ds.
  5. Брони тестового отеля hid = 8473727 на test-ключе настоящие — после проверки их нужно отменить.
import time, uuid, requests

API = "https://api.ratehawk.com/api/b2b/v3"
s = requests.Session()
s.auth = ("<KEY_ID>", "<API_KEY>")
s.headers["User-Agent"] = "MyTravelApp/1.0"

def call(path, body, timeout=60):
    r = s.post(f"{API}/{path}", json=body, timeout=timeout)
    r.raise_for_status()
    return r.json()

pre = call("hotel/prebook/", {"hash": rate_hash, "price_increase_percent": 5})
book_hash = pre["data"]["hotels"][0]["rates"][0]["book_hash"]

order_id = str(uuid.uuid4())
form = call("hotel/order/booking/form/", {"partner_order_id": order_id, "book_hash": book_hash,
                                          "language": "ru", "user_ip": client_ip})
pay = form["data"]["payment_types"][0]

call("hotel/order/booking/finish/", {
    "language": "ru",
    "partner": {"partner_order_id": order_id},
    "payment_type": {"type": pay["type"], "amount": pay["amount"], "currency_code": pay["currency_code"]},
    "rooms": [{"guests": [{"first_name": "Ivan", "last_name": "Petrov"}]}],
    "user": {"email": "manager@example.ru", "phone": "+79990001122"},
})

while True:
    st = call("hotel/order/booking/finish/status/", {"partner_order_id": order_id})
    if st["status"] != "processing":
        break
    time.sleep(5)
print(st["status"], st.get("data"))

Отменить бронирование

Отмена по запросу гостя — с проверкой, во что она обойдётся.

  1. Отменить можно только подтверждённую бронь: POST /api/b2b/v3/hotel/order/cancel/ с partner_order_id — тем же ID, что ты передавал при бронировании.
  2. В ответе amount_payable — сумма штрафа и валюта. Для невозвратного тарифа штраф реальный, поэтому показывай условия отмены пользователю до вызова.
  3. Апсейлы (ранний заезд, поздний выезд) автоматически не отменяются — учитывай их отдельно.
curl --user '<KEY_ID>:<API_KEY>' 'https://api.ratehawk.com/api/b2b/v3/hotel/order/cancel/' \
  -H 'Content-Type: application/json' \
  -d '{"partner_order_id": "9b2f6c1e-5d4a-4f7e-8c3b-1a2d3e4f5a6b"}'

Загрузить описание и фото отеля

Карточка отеля для своей витрины: описание, адрес, удобства и фотографии.

  1. Запроси контент: POST /api/b2b/v3/hotel/info/ с hid и language.
  2. Лимит — не больше 30 запросов за 60 секунд, поэтому кэшируй карточки у себя, а не запрашивай их при каждом показе.
  3. Передавай собственный User-Agent с названием своего приложения — без него запросы могут отклоняться.
  4. Для полной базы отелей используй дампы статического контента, а hotel/info — для точечного обновления.
curl --user '<KEY_ID>:<API_KEY>' 'https://api.ratehawk.com/api/b2b/v3/hotel/info/' \
  -H 'Content-Type: application/json' -H 'User-Agent: MyTravelApp/1.0' \
  -d '{"hid": 8473727, "language": "ru"}'

Базовые URL

Авторизация

Тип: Basic Auth

HTTP Basic Authentication ключом API вида <KEY_ID>:<API_KEY>: KEY_ID — имя пользователя, API_KEY — пароль. Ключи бывают трёх типов: sandbox, test (только тестовый отель hid = 8473727, брони реальные) и production. Ключи видны в разделе API настроек договора (доступ — у Master-аккаунта).

curl --user '<KEY_ID>:<KEY>' --data '{"id":"city_hotel_berlin_east","language":"en"}' "https://api.ratehawk.com/api/b2b/v3/hotel/info/"

Методы

POST /api/b2b/v3/search/multicomplete/ — Подсказки отелей и регионов

Автодополнение по части названия; до 5 результатов в каждой категории.

Параметр Где Тип Обяз. Описание
query body string да Часть названия отеля или региона
language body string нет Язык, например ru, en

POST /api/b2b/v3/search/serp/region/ — Поиск цен по региону

Не рекомендуется давать пользователю выбирать тарифы из этого ответа: точного совпадения с search/hp не гарантируется.

Также есть поиск по ID отелей (/api/b2b/v3/search/serp/hotels/) и по координатам.

Параметр Где Тип Обяз. Описание
checkin body string да Дата заезда, не позже 730 дней от текущей
checkout body string да Дата выезда, не позже 30 дней от заезда
region_id body integer да ID региона
residency body string нет Гражданство гостей, ISO 3166-1 alpha-2
guests body array нет Гости по номерам
guests[].adults body integer да Число взрослых в номере
guests[].children body array нет Возраст детей
currency body string нет Валюта цен
language body string нет Язык данных отеля
hotels_limit body integer нет Максимум отелей в ответе
timeout body number нет Максимальное время поиска, секунд
filter.star_rating body array нет Звёздность 1–5
filter.kind body array нет Тип отеля
filter.meal_type body string нет Тип питания, например all-inclusive
filter.price_from body integer нет Минимальная цена
filter.price_to body integer нет Максимальная цена

Пример запроса:

curl --user '<KEY_ID>:<API_KEY>' 'https://api.ratehawk.com/api/b2b/v3/search/serp/region/' \
--header 'Content-Type: application/json' \
--data '{
 "checkin": "2026-10-22",
 "checkout": "2026-10-25",
 "residency": "gb",
 "language": "en",
 "guests": [
 {
 "adults": 2,
 "children": []
 }
 ],
 "region_id": 6053839,
 "currency": "EUR",
 "filter": {
 "star_rating": [],
 "kind": [],
 "meal_type": [
 "all-inclusive"
 ]
 }
}'

POST /api/b2b/v3/search/hp/ — Страница отеля (все тарифы)

Вызывается, когда пользователь выбрал отель; рекомендуемое время жизни тарифа — 30 минут.

Параметр Где Тип Обяз. Описание
hid body integer да ID отеля (числовой); старое поле id устарело
checkin body string да Дата заезда
checkout body string да Дата выезда
residency body string нет Гражданство гостей
guests[].adults body integer да Число взрослых в номере
guests[].children body array нет Возраст детей
currency body string нет Валюта
language body string нет Язык
timeout body number нет Время поиска, секунд
filter body object нет Фильтры: star_rating, kind, meal_type, price_from, price_to

POST /api/b2b/v3/hotel/prebook/ — Предбронирование тарифа

Проверяет доступность тарифа перед бронированием; при недоступности ищет альтернативу того же типа номера и питания и возвращает новые book_hash/match_hash. Рекомендуемый таймаут — 60 секунд, минимальный — 30.

Параметр Где Тип Обяз. Описание
hash body string да ID тарифа
price_increase_percent body integer нет На сколько процентов допускается рост цены

POST /api/b2b/v3/hotel/order/booking/form/ — Создание процесса бронирования

Вызывается сразу после prebook; форма живёт 60 минут.

Параметр Где Тип Обяз. Описание
partner_order_id body string да Внешний ID брони (UUID)
book_hash body string да ID выбранного тарифа
language body string да Язык
user_ip body string да IP конечного пользователя

POST /api/b2b/v3/hotel/order/booking/finish/ — Запуск бронирования

Бронирование асинхронное — дальше опрашивайте статус. Невалидные данные пользователя могут попасть в стоп-лист.

Параметр Где Тип Обяз. Описание
language body string да Язык
partner.partner_order_id body string да Внешний ID брони
partner.comment body string нет Внутренний комментарий партнёра
partner.amount_sell_b2b2c body string нет Цена перепродажи в валюте договора
payment_type.type body string да Тип оплаты (например, hotel, deposit)
payment_type.amount body string да Сумма
payment_type.currency_code body string да Валюта, ISO 4217
rooms body array да Номера
rooms[].guests body array да Гости: first_name, last_name, is_child, age
user.email body string да Email менеджера партнёра
user.phone body string да Телефон менеджера партнёра
user.comment body string нет Комментарий для отеля
supplier_data body object нет Контакты инициатора брони: first_name_original, last_name_original, email, phone
arrival_datetime body string нет Ожидаемое время прибытия
return_path body string нет URL возврата после 3D Secure

POST /api/b2b/v3/hotel/order/booking/finish/status/ — Проверка статуса бронирования

Обязателен, если не используется вебхук статуса бронирования; при 3D Secure в ответе приходит data_3ds.

Параметр Где Тип Обяз. Описание
partner_order_id body string да ID брони партнёра, 1–256 символов

POST /api/b2b/v3/hotel/order/cancel/ — Отмена бронирования

Отменяются только успешно подтверждённые брони; при отмене невозвратного тарифа штраф реальный. Апсейлы автоматически не отменяются.

В ответе — amount_payable (сумма штрафа и валюта).

Параметр Где Тип Обяз. Описание
partner_order_id body string да ID брони партнёра

POST /api/b2b/v3/hotel/info/ — Контент отеля

Не больше 30 запросов за 60 секунд; передавайте собственный User-Agent, например RatehawkPartner/1.0 (python-requests/2.18.4).

Параметр Где Тип Обяз. Описание
hid body integer нет Числовой ID отеля (нужен он или устаревший id)
id body string нет Устаревший строковый ID отеля
language body string нет Язык

Нюансы

Ошибки

Код Описание
invalid_params 400 — не переданы обязательные данные (см. debug.validation_error)
decoding_json Тело запроса не разобрано как JSON
not_allowed_host Запросы с вашего хоста или IP запрещены
unexpected_method Неподдерживаемый HTTP-метод (используйте GET или POST)

Ограничения

Лимит задаётся на каждый эндпоинт и возвращается в заголовках: X-RateLimit-SecondsNumber (период, сек), X-RateLimit-RequestsNumber (максимум запросов за период), X-RateLimit-Remaining (остаток), X-RateLimit-Reset (окончание периода, UTC). Пример: 10 запросов в секунду.

Источники


Если этого недостаточно — официальная документация: https://docs.emergingtravel.com/docs/overview/ JSON: https://mcp-everything.ru/api/integrations/ostrovok-etg. MCP: https://mcp-everything.ru/mcp