company_banner

Миграция на новую версию API

    Moving the Mote-Morris House: Leesburg, Florida

    Подходит к концу время жизни первой версии нашего API. Для тех, кто еще не перевёл свои приложения на новую версию, мы подготовили руководство по миграции.

    Самое, что вероятно бросается в глаза — в новой версии нет XML. Да, мы оставили только JSON, но этим всё не ограничивается.

    REST

    При проектировании API мы следовали REST-подходу в именовании URL’ов и использовании возможностей HTTP-протокола.

    Если кратко, то в ответах нашего API помимо стандартных 200, 302, 403, 404 и 500 статусов можно увидеть: 201, 204, 405, 429, 503 и некоторые другие. Клиент API должен уметь корректно их обрабатывать: не делать бессмысленные повторы при 429 и/или 400 и не падать от получения 503.

    При именовании URL'ов мы использовали термины «коллекция» и «элемент коллекции», а непосредственно действия выражаем при помощи HTTP-методов.

    Теперь для осуществления поиска по вакансиям вместо обращения к /1/json/vacancy/search/ появился адрес коллекции «Вакансии»: /vacancies.

    Сделав GET-запрос по этому адресу, можно получить как полную коллекцию (все вакансии на сайте), так и какой-то срез, указав query-параметры: GET /vacancies?text=голова. Указав параметр `text`, мы применили фильтр к коллекции и тем самым получили результаты поиска по вакансиям.

    Полный список параметров доступен в одноименном разделе документации.

    Можно получить отдельный элемент коллекции, в данном случае вакансию: GET /vacancies/7760476.

    У ресурса-коллекции могут быть также подколлекции, какие-то предустановленные срезы всей коллекции. GET /vacancies/favorited вернет те вакансии, которые добавлены у авторизованного пользователя, в «отобранные».

    Чтобы добавить вакансию в «отобранные», необходимо добавить вакансию в соответствующую подколлекцию:
    PUT /vacancies/favorited/{vacancy_id}


    Чтобы убрать, необходимо удалить ее из этой коллекции.
    DELETE /vacancies/favorited/{vacancy_id}


    Запросы PUT и DELETE являются идемпотентными: если вы попробуете «отобрать» вакансию, которая уже находится в отобранных, PUT вернёт 204, тем самым ответив: «Вы хотите, чтобы эта вакансия была в отобранных? Без проблем. Она в отобранных». Даже если она уже там была. Также и с удалением.

    Чтобы создать вакансию (эта функциональность еще не реализована, но запланирована) необходимо будет сделать запрос POST /vacancies, указав в теле параметры создаваемой вакансии. Главное отличие POST от PUT заключается в том, что первый не идемпотентен, то есть при повторном запросе будет попытка создать еще одну вакансию.

    В итоге: корректное и широкое применение HTTP-методов, HTTP-кодов и именование URL’ов в соответствии c понятиями: коллекция, подколлекция и элемент коллекции — в нашем понимание и есть REST.

    Пагинация и коллекции

    Еще немного про коллекции. Все коллекции, которые поддерживают пагинацию (резюме, вакансии, компании и все их подколлекции) выглядят единообразно и имеют корневой объект вида:

    {
      "found": 0,
      "per_page": 20,
      "page": 0,
      "pages": 1,
      "items": []
    }
    


    К любому запросу коллекции можно в параметрах указать page=N&per_page=M. Нумерация идёт с нуля, по умолчанию выдаётся первая (нулевая) страница с 20 объектами на странице.

    Версионность

    Мы убрали версионность, в API теперь нет префикса в адресе: /1/.... Все URL идут от корня: api.hh.ru/dictionaries. Со временем данные будут расширяться, всегда обеспечивая обратную совместимость. Исключения из этого правила могут быть только в двух случаях:
    • исправление какого-либо критичного дефекта: в релиз, а может даже и в опубликованную документацию, закрадётся ошибка, исправляя которую нам придется изменить формат данных.
    • закрытие API в связи с изменением бизнес-логики: hh.ru перестанет выдавать базу вакансий, у нас исчезнут отклики на сайте как сервис и прочие невероятные, фантастические случаи, когда мы теоретически не сможем поддерживать формат выдаваемых данных.


    Меньше «хардкода»

    В том месте, где мы выдаём значение, которое представляет собою сущность, доступную в нашем API, мы предоставляем полную ссылку, чтобы избавить вас от необходимости «хардкодить» в вашем приложении адреса.
    К примеру, в поиске вакансий:

    {
      "items": [
        {
          "url": "https://api.hh.ru/vacancies/1337"
        }
      ]
    }
    


    Получив результаты поиска вам нет необходимости самим конструировать ссылку для получения полной информации о вакансии, вам достаточно взять значение ключа url.

    Поиск и просмотр вакансий

    Теперь о самих данных. Основное и самое популярное использование нашего API — это поиск и выдача вакансий.
    Раньше это было доступно по адресам /1/json/vacancy/search/ и /1/json/vacancy/{vacancy_id} соответственно. Теперь, следуя REST-подходу, мы объединили это в коллекцию /vacancies.

    Для поиска вам необходимо сделать GET-запрос к ресурсу, передав необходимые query-параметры. Для получения отдельной вакансии — сделать GET-запрос за отдельным элементом: GET /vacancies/7760476 (https://api.hh.ru/vacancies/7760476.

    Также раньше у нас был отдельный адрес для получения вакансий конкретной компании, теперь это доступно через поиск: GET /vacancies?employer_id=1455 https://api.hh.ru/vacancies?employer_id=1455

    Справочники

    Для осуществления запроса к поиску, а также для понимания ответов мы выдаём справочники наших сущностей: тип занятости, график работы, валюты, опыт работы. Раньше это было доступно по отдельным адреса:
    • GET /1/json/employment/
    • GET /1/json/schedule/
    • GET /1/json/experience/
    • GET /1/json/currency/

    Теперь мы объединили все эти небольшие справочники в один ресурс `/dictionaries` api.hh.ru/dictionaries. (описание в документации: github.com/hhru/api/blob/master/docs/dictionaries.md).

    Отдельные справочники, содержащие большое количество значения (специализации, регионы, метро) мы оставили по отдельным адресам:

    Специализации были объединены с профессиональными областями (раньше это было два разных адреса: field и specialization).
    Регионы были переименованы в /areasapi.hh.ru/areas.

    Авторизация и новые сервисы


    Но HeadHunter API не ограничивается поиском вакансий и сопутствующими справочниками. В новой версии доступна авторизация, просмотр откликов и многое другое. Это выходит за рамки статьи про миграцию, но описание всех этих методов доступно в нашей документации. Читайте, пробуйте, пишите нам, следите за новостями!
    HeadHunter
    112,67
    HR Digital
    Поделиться публикацией

    Комментарии 6

      +4
      В ответе на «пагинированную» коллекцию по-хорошему ещё бы отдавать адреса ресурсов для получения следующей и предыдущей «страниц», если таковые имеются.

      Ну и для всех интересующихся реализациями RESTful API — вот неплохая книга, для упорядочивания знаний: www.amazon.com/gp/product/B00890OBFI/ref=kinw_myk_ro_title
        +2
        Да, спасибо, хорошое предложение. Думаю, в ближайшее время добавим.
        И это будет как раз пример то, как API развивается, добавляя новые данные, не нарушая обратную совместимость.
        0
        Со временем данные будут расширяться, всегда обеспечивая обратную совместимость.

        Не так давно (кажется, это было в прошлую пятницу) столкнулся с проблемой. При парсинге резюме раньше поле gender содержало идентификатор пола (male, female). Начиная с некоторого времени gender стал приходить в виде объекта, содержащего id и человекочитаемое название пола. Зачем нужно второе — непонятно, ну и ладно. Главное, что это поломало существующий функционал.

        Кстати, очень печально, что API описано так скудно: для полей не указывается хотя бы информация о максимальной длине поля, о его обязательности и о том, как поле передаётся в случае отсутствия значения (null или отсутствие поля). А по резюме так вообще почти никакой информации на странице описания API.
          +1
          Формат выдачи резюме действительно на данный момент не описан в документации. Более того, на данный момент официально он не запущен, мы как раз готовимся его выпустить вместе с подробной документацией и дополнительными сервисами по созданию, редактированию и обновлению резюме. После публичного релиза формат, естественно, будет зафиксирован и дальнейшие обновления не будут ломать обратную совместимость. Как это сделано в случае сервиса вакансий и сервиса откликов.

          Изменение формата поля «пол» было как раз фикс одного из последних багов: приведение в единый вид всех полей, значения которых доступны в справочниках (/dictionaries и т.п.)

          Приносим свои извинения за то, что, возможно, сбили с толку, так как действительно в документации уже есть упоминание про выдачу резюме, но просим всегда разрабатывать, основываясь на документации, а не на текущих ответах сервера. Ответ всегда может содержать ошибку, когда как в документации описан контракт. В тех моментах, когда документации нет, сервис скорее всего находится в стадии релиз-кандидата и в него могут вносить правки.

          Спасибо за замечание, добавим этот момент на страницу документации.

          Вы разрабатываете приложение, использующее наш сервис резюме? Если у вас есть дополнительные вопросы, замечания, предложения, любой feedback, пишите на api@hh.ru — с удовольствием проконсультируем и учтём все ваши предложения по улучшению API.
          0
          Интересен рассказ и о серверной стороне построения API: как масштабируете, каковы нагрузки, создаваемые клиентами, используете ли обычные серверы веб-приложений или выделенные, есть ли кто-то за nginx-ом и тому подобное.
            0
            Да, мы планируем написать статью о том, что под капотом нашего API. Следите за обновлениями блога.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое