API Я.ру (бета)

Внимание: пост для разработчиков! Представители других профессий могут быть несовместимы с текстом и проявлять при прочтении поведенческие признаки скуки.

Мы — разработчики Яндекса — внимательно слушаем, о чём нас просят пользователи, а также другие разработчики. Конечно, мы не всесильны и не можем обеспечить счастья сразу всем, но нам очень приятно, когда получается сделать что-то хорошее. Вот как сегодня. Мы начинаем публичное бета-тестирование не одного, а сразу двух сервисов:

  • API для нашего любимого блогохостинга — Я.ру,
  • сервиса OAuth-авторизации для этого и других наших API.

Разрабатывая их, мы не только придерживались принципов открытости и соответствия стандартам, но и дали себе волю заметно поднять «градус гиковости» — API строится на самых модных технологических принципах.

Авторизация — это начало работы с API, с неё и начнём. В качестве стандарта мы выбрали OAuth 2.0. Несмотря на то, что он пока только черновик, мы решили реализовать его по очень простой причине — это открытый стандарт, который собираются поддерживать самые развитые технологические компании мира. Его предыдущие версии реализованы, например, в Google и Twitter. Мы надеемся в будущем поддержать этот вид авторизации в других наших API, например — в Фотках (да-да, мы слышали, что вы жаловались на их сложную авторизацию!)

После авторизации с помощью API Я.ру можно программно просматривать и редактировать профиль пользователя, делиться ссылками, менять настроение, создавать сообщения в блогах и комментировать. Словом — почти всё, что можно делать на самом сервисе.

Структурно API построен по идеологии REST:

  • весь сервис представлен в виде ресурсов, имеющих состояние,
  • каждый ресурс имеет стандартный интерфейс доступа, основанный на методах и кодах ошибок HTTP,
  • ресурсы используют URI для навигации по связанным частям системы,
  • где можно, используются стандартные форматы представления данных и протоколы — в частности, Atom и AtomPub.

Мы выбрали REST, потому что он максимально отражает наши взгляды на то, каким должен быть API веб-сервиса. Стандартизованный интерфейс и открытые форматы дают разработчикам возможность использовать свои наработки и сторонние библиотеки для разных сервисов вместо того, чтобы писать абсолютно уникальный код для каждого. Со стороны же сервиса это сильно упрощает поддержку документации, а также, например, даёт возможность более удобно масштабировать сервисы и сочетать их друг с другом.

Это может показаться довольно сложным, поэтому, чтобы дать почувствовать, что на практике всё сильно проще, вот короткий пример кода на Питоне, который меняет настроение пользователя:

# -*- coding:utf-8 -*-
from urllib2 import urlopen, Request

import elementflow
import lxml.etree


ACCESS_TOKEN = 'f46606d61b9249078945599fb7192eb2'
NAMESPACES = {
  '': 'http://www.w3.org/2005/Atom',
  'y': 'yandex:data',
}
HOST = 'api-yaru.yandex.ru'


def auth_request(url, body=None):
    '''Создаёт авторизованный объект запроса.'''
    return urlopen(Request(url, data=body, headers={
        'Authorization': 'OAuth %s' % ACCESS_TOKEN
    }))

def get_link(rel):
    '''Возвращает URL нужного ресурса из профиля авторизованного пользователя.'''
    f = auth_request('https://%s/me/' % HOST)
    xml = lxml.etree.parse(f)
    namespaces = {'y': NAMESPACES['y']}
    links = xml.xpath('/y:person/y:link[@rel="%s"]' % rel, namespaces=namespaces)
    return links[0].attrib['href']

def change_mood(mood):
    '''Создаёт пост типа "смена настроения".'''
    with elementflow.xml(elementflow.Queue(), 'entry', namespaces=NAMESPACES) as xml:
        xml.element('category', {'scheme': 'urn:wow.ya.ru:posttypes', 'term': 'status'})
        xml.element('content', text=mood)
        xml.element('y:comments-disabled')
    auth_request(get_link('posts'), xml.file.pop())


if __name__ == '__main__':
    change_mood(u'Тестовое настроение')

Подробнее — в документации.

Выпуская API не в виде законченного сервиса, а бета-версией, мы приглашаем тестировать его всех заинтересованных разработчиков. Нам интересно получить от вас пожелания по функционалу и сообщения об ошибках, пишите в Клуб сервиса Я.ру. И API, и протокол OAuth, который тоже находится в стадии черновика, обязательно будут меняться, будьте к этому готовы.

За дело!

Иван Сагалаев и Григорий Бакунов, гики со стажем

44 комментария
Кому мешает статус черновика? :-) 

Спасибо!
API - это всегда радость :) Спасибо!
ахринеть... ура!!!
Ух ты, как здорово :) Спасибо.
Артёменко Александр
26 ноября 2015, 17:41
Ура, наконец-то можно и интегрировать ярушку себе в бложик, или написать command-line клиент! :)
Константин Ермаков
26 ноября 2015, 17:41
Запросить в браузере URL: https://oauth.yandex.ru/authorize?client_id=&response_type=code. При этом нужно быть залогиненным в Яндекс от имени того пользователя, которым будет представляться клиент.

После нажатия кнопки "Разрешить" вы получите страницу с кодом подтверждения.

По-моему, в ответе на запрос oauth.yandex.ru/authorize затерялся лишний пробел.
Григорий Бакунов
26 ноября 2015, 17:41
1. вот ты глазастый :)
2. ты камент не в тот пост написал - правильнее написать в клуб яру, туда где документация.
Константин Ермаков
26 ноября 2015, 17:41
1. :)
2. Скопировал камент.
Григорий Бакунов,
топик для тем для 199 ещё не вывешен, так что реквестирую в следующем выпуске чтоб ты рассказал каковы стратегические перспективы всего этого )
Спасибо на добром деле))
Ну все вроде супер, начал было привинчивать новый клиентик к платформе Symbian да вот беда OAuth 2. Ну может и не беда но под QT я знаю лишь qoauth костыль и он OAuth 2, если верно помню, не держит( ну по крайней мере допилю для Нокий с их Симбой хоть то, что можно без авторизации через сею мега-полезную приблуду делать
Странно, сделал все, как в документации, скопировал значение access_token из json-документа попробовал запустить пример кода на питоне, в ответ получаю urllib2.HTTPError: HTTP Error 401: Unauthorized

Как авторизоваться правильно?
Заработало, смог авторизоваться. После того, как оставил комментарий, вошел в клубы и создался мой профиль. :-)
Иван Сагалаев
26 ноября 2015, 17:41
Все бы проблемы так быстро решались :-). А что было, если не секрет?
Иван, а Вы планируете сделать либы для различных языков? Меня, лично, интересует Python. Очень рад буду, если эта либа появится и в pypi ;)
Иван Сагалаев
26 ноября 2015, 17:41
Это безусловно было бы полезно. Но у нас пока нет конкретных планов про это. Я очень хочу, чтобы библиотеки писали люди, которые реально пользуются API. Потому что с клиентской стороны лучше понятно, что библиотека должна уметь.
К сожалению, я не обладаю мастерством написания либ :(
Так бы помог, безусловно.
А будет ли особый раздел с либами, как у гугля или яху - "для разработчиков" или типа того?
Иван Сагалаев
26 ноября 2015, 17:41
Раздел такой будет в рамках api.yandex.ru. Там будет официальная документация, когда бета-тестирование закончится, и если к тому времени появятся либы, то и они будут.
Благодарю за помощь.
Я сделал все, как написано в доке, по шагам 1-3, поскольку не было паспорта Яндека, получил его. Яндекс показал, что я залогинен, у меня есть паспорт, тестовое приложение и отдал мне token.

После этого, я попробовал запустить код на питоне, он выбросил ошибку. Написав комментарий об ошибке, попробовал отправить его и тут же понял, что я не авторизован. Как оказалось далее, у меня не было ничего, кроме паспорта Яндекса. Меня пробросило на создание профиля, моей страницы, после чего отправился комментарий сюда.
После этого код на питоне заработал.

Надеюсь, понятно описал свои злоключения.
Иван Сагалаев
26 ноября 2015, 17:41
Понял. То есть яндексовый аккаунт бал, а ярушного ещё не было. Попробуем это явно в сообщении об ошибке писать.
 
сервис OAuth-авторизации для этого и других наших API

Можно ли таким образом авторизоваться для использования API pdd.yandex.ru ?
Задача слудующая: нужно получить токен для домена, присоединение которого подтверждено, с помощью запроса на https://pddimp.yandex.ru/get_token.xml?domain_name=... со своего сайта.
Пока что это получается сделать только вводя данный УРЛ в строке браузера (после авторизации конечно), а нужно чтоб пользователь мог получить токен без захода на pdd.yandex.ru и авторизации там (введя данные: access_token в своей CMS), т.е. простым нажатием кнопки.

Иван Сагалаев
26 ноября 2015, 17:41
Теоретически наверное можно, но мы с ребятами из ПДД не очень поняли, в чём выгода. Сейчас, вы заходите на pdd.yandex.ru и своей залогиненностью на Яндекс подтверждаете свою аутентичность. В случае с OAuth, вы будете заходить на oauth.yandex.ru, тоже в залогиненном состоянии, получать токен, и потом по нему получать второй токен. Кажется лишним. Или я неверно понял?
Сейчас для того чтобы использовать возможности API для pdd.yandex.ru нужно быть залогиненным на данном сервисе, причём делать это надо в ручную. Для админа или модератора портала это не совсем удобно. Мы хотим сделать этот процесс проще для пользователя, т.е. чтобы админ 1 раз зарегистрировался на yandex, зарегил приложение для OAuth, получил access_token. Далее введя данные у себя в CMS мог управлять доменами и ящиками сразу из CMS.
На данный момент запрос для получения токена для домена: https://pddimp.yandex.ru/get_token.xml?domain_name=... получается выполнить только в ручную !!!! , что требует изучение API для pdd,  при подаче запроса из CMS (будучи уже зарегистированным на сервисе), в ответ выдаётся страница с просьбой авторизоваться. Возможность использования OAuth-авторизации при запросах для PDD даст возможность сделать управление почтой на yandex удобнее.
Иван Сагалаев
26 ноября 2015, 17:41
Понял. Мы подумаем подробней над тем, чтобы возможно перетащить ПДД на OAuth-авторизацию. Там не всё так просто структурно, но кажется нет ничего невыполнимого.

Спасибо за идею!
Не нашел ничего свежее по этой теме, получилось ли перетащить ПДД на OAuth-авторизацию? Если да, то где или как?
Извините не нашёл форума по нужной тематике (Обсуждение API pdd.yandex.ru), поэтому пишу здесь, надеясь, что Иван им перескажет :-O
При реализации API pdd столкнулся с проблемой толи не точной работы,  толи неправильного описания работы запроса получения ящиков домена -  https://pddimp.yandex.ru/get_domain_users.xml?token=...&page=...&on_page=...
В описании (http://pdd.yandex.ru/help/section72/) сказано, что :

  • on_page – число почтовых ящиков на странице, не может быть больше 100, по умолчанию = 100
  • page - номер страницы списка почтовых ящиков, по умолчанию = 1  ... Ящики возвращаются в постраничной манере, в количестве on_page и  начиная  со страницы с порядковым номером page. Страницы нумеруются с 1.


Однако оказывается на самом деле page - это номер  ящика в выборке, с которой надо начинать вывод ящиков, а не страница.  Постараюсь объяснить на примере: на домене зарегистрированно 120 ящиков,  я выставляю в запросе on_page = 20, page = 1. Результат - выводятся 20  ящиков:ящики 2- 21 из 120 (уже заставляет задуматься что что-то не так.  Как тестировали ???). Следующий запрос(хочется ведь получить список всех  ящиков :)) -  on_page = 20, page = 2. Результат 20 ящиков: 19 из них из  предыдущей выдачи + 1 "новый", т.е.вывелись ящики со 3 по 22.
Надеюсь, что в скором времени данное недоразумение будет устраненно  (надеюсь что будет поменяно описание работы, а не её алгоритм. Ведь не  менять же всем разработчикам схему работы своих приложений:-@ ), а также надеюсь на скорейшее включение OAuth-авторизации для pdd.yandex.ru
Алексей, спасибо!

Увы, но похоже, что тестировал этот метод только пользователь, по просьбе которого он и был создан.
Да, надо поправить описание, а может даже и сам метод.
Им очень мало кто пользуется - четыре админа доменов, включая Вас.

Вот и я столкнулся с той же проблемой!

2 года прошло, а описание так и не поправили!

Настенко Илья
26 ноября 2015, 17:41

Так как все таки получить список всех ящиков? Никак?

А какой драфт протокола? И очень странно - я не увидел client_secret, вы используете только client_id?
Иван Сагалаев
26 ноября 2015, 17:41
10-й драфт, последний на сегодня: http://tools.ietf.org/html/draft-ietf-oauth-v2-10

Мы действительно не требуем client_secret, потому что в нём, кажется, совсем нет смысла. В десктопных и мобильных клиента принципиально невозможно что-либо спрятать, а в веб-клиентах с ролью секрета вполне справляется сам client_id, так как юзеру он никогда не показывается.

Кстати, так думаем не только мы, вот хорошая статья на эту тему Райана Пола: http://arstechnica.com/security/guides/2010/09/twitter-a-case-study-on-how-to-do-oauth-wrong.ars
А зачем кастомный content-type?

application/x-yaru+xml


Иван Сагалаев
26 ноября 2015, 17:41
Чтобы отличать форматы, когда появятся другие. Например, если мы захотим те же ресурсы выдавать и принимать в JSON'е или в каком-нибудь Portable Contacts.
Это да, но почему не просто application/xml?
Не то чтобы критично, просто это требует доделок с моей стороны, вот и интересуюсь зачем?
Иван Сагалаев
26 ноября 2015, 17:41
Если просто application/xml, то тогда не получится формально отличать этот формат от другого XML-формата.

А можешь подробней проблему на своей стороне описать? То есть, какая разница твоему парсеру, что написано в Content-type, если он всё равно рассчитывает наверняка только на один конкретный специфицированный в доке формат.
прасер ориентируется на Content-type, теперь надо вместо application/xml заставлять его понимать регулярку application/.*xml.

Не критично, просто было неожиданно. 
Вопросы сюда можно задавать?

Заголовки

{'Content-Length': '233', 'Content-type': 'application/atom+xml; type=entry; charset=utf-8', 'X-Request-Id': 1, 'Expect': '', 'Pragma': '', 'Content-Type': 'application/x-www-form-urlencoded', 'Authorization': 'OAuth b30bda914ebe48f1a2493ea5bf0e7af7'}


Тело

http://www.w3.org/2005/Atom">titleaccess>public<category scheme="urn:ya.ru:posttypes" term="text"/>text



В ответ получаю 400- Bad request без подробностей.

Иван Сагалаев
26 ноября 2015, 17:41
Да, вопросы сюда. Хотя, чувствую я, пора уже просто клуб выделенный завести :-).

То, что ошибка без подробностей -- наш баг, будем писать, в чём дело. А навскидку могу назвать проблему с тем, что в запросе два Content-type'а. Тот, который application/x-www-form-urlencoded, явно лишний. Сама entry выглядит правильно.
Подскажите пожалуйста, где можно поискать примеры работы с я.ру на php?
перерыл документацию по REST однако протокол для меня новый - не совсем разобрался.
Иван Сагалаев
26 ноября 2015, 17:41
REST -- это не протокол, это подход. Чтобы работать с API, вам нужна HTTP-библиотека и XML или JSON парсер/генератор.

Конкретно про PHP я ничего не подскажу, но могу предложить спросить в клубе сервиса.
зачёт ! реально полезная штука
Мастер Груша х_х
26 ноября 2015, 17:41
Подскажите, пожалуйста, как правильно после получения токена получить список ресурсов на Android?
Мне очень не хватает Я.ру. - это был обжитой и просторный родной дом... Без него, как заграницей - что попало... Если так, то спасибо! Жду, надеюсь - Хочу домой...