Когда панель подключают к боту, своему сайту или к другой панели, обзор «что такое API» уже бесполезен - нужен точный список вызовов, их параметров и форм ответа. Этот справочник собран иначе, чем обычные доки: мы сняли фактический контракт с одиннадцати работающих панелей и сверили его со своим ядром. Ниже - все десять вызовов, поля заказа по типам услуг и три места, где интеграции ломаются чаще всего.
Справочник ниже описывает, что вызывать. О том, что при этом должна проверять сама панель - границы объёма, дубли по ссылке, права клиента, лимит запросов, - есть отдельная статья про злоупотребление API: интеграция, написанная без оглядки на эти правила, упирается в них уже на проде.
Почему API у панелей почти одинаковый
Практически вся отрасль говорит одним протоколом - его принято называть API v2. Он сложился исторически: один движок задал формат, остальные повторили его, чтобы к ним могли подключаться уже написанные клиенты реселлеров. Для интегратора это редкая удача - клиент, написанный под одну панель, работает с другой почти без правок.
Общие для всех правила ровно четыре:
- Один эндпоинт. Обычно
/api/v2, метод всегдаPOST, ответ всегда JSON. - Ключ полем, а не заголовком. Он передаётся как обычный параметр
key- никакихAuthorizationиBearer. - Действие полем
action. Не роут и не HTTP-метод определяют операцию, а значение этого поля. - Никаких версий в URL. «v2» - часть пути эндпоинта, а не заголовок и не параметр.
Практический вывод для владельца панели: свой формат придумывать не надо. Собственный протокол отрежет вас от реселлеров, у которых интеграция уже написана, - а именно они приносят объём. Зачем вообще выдавать ключи наружу и кому, разобрано в статье про API панели и работу с реселлерами.
Семь действий, десять вызовов
Действий в стандарте семь, но у четырёх есть пакетная форма - отсюда десять разных вызовов, которые придётся поддержать:
action=services- список услуг. Отдаёт массив:service(публичный номер),name,type,category,rate,min,max,refill,cancel.action=add- создать заказ. Обязателенservice, остальные поля зависят от типа услуги. Ответ -{"order": 23501}.action=statusсorder- статус одного заказа:charge,start_count,status,remains,currency.action=statusсorders- до ста номеров через запятую за один запрос.action=refillсorder- создать доливку. Ответ - номер доливки, часто строкой:{"refill": "1"}.action=refillсorders- пакетная доливка, до ста заказов.action=refill_statusсrefill- статус доливки по её номеру.action=refill_statusсrefills- то же пачкой.action=cancelсorders- отмена, документирована только пакетной.action=balance- баланс:{"balance": "100.84292", "currency": "USD"}.
Всё остальное - надмножества конкретной панели. У нас, например, есть одиночная отмена по order и action=create как синоним add, но писать клиента под такие удобства нельзя: на другой панели их не окажется.
Поля заказа зависят от типа услуги
Главное заблуждение при первой интеграции - что заказ это ссылка и количество. Так выглядит только базовый тип. Поле type в services приходит строковым именем, и от него зависит весь набор параметров add:
- Default -
linkиquantity, необязательныеrunsиintervalдля постепенной выдачи. - Custom Comments -
linkиcomments: количество не передаётся вообще, оно выводится из числа строк списка. - Семейство Mentions - шесть разных типов, и различаются они источником аудитории: готовый список
usernames,hashtag, подписчики чужого аккаунта, лайкнувшие конкретную публикацию. - SEO -
keywordsвместе с количеством, Poll - номер варианта ответаanswer_number. - Package - только
link: ни количества, ни дополнительных полей, объём зашит в саму услугу. - Subscriptions -
linkнет вообще. Вместо негоusername, границыminиmax, задержкаdelayиз закрытого списка значений в минутах и дата окончанияexpiryв форматеd/m/Y. - Web Traffic - самый широкий:
country,device,type_of_traffic, и все три задаются числами из справочника, а не словами. При выборе трафика с поискового ключа обязателен ещёgoogle_keyword, при своём реферере -referring_url.
Две технические детали, на которых спотыкаются почти все. Списки - комментарии, ключевые слова, имена, хештеги - передаются одной строкой с переводами строк как разделителем, а не JSON-массивом. И числовые справочники device и type_of_traffic в ответе services не приходят: их значения надо знать заранее из документации панели.
И ещё одно, что стоит признать честно: в нумерации типов есть дырки. Минимум шесть номеров движки знают, но ни в одной панели из нашей выборки они не встречаются. Поэтому обещать «поддерживаем все типы» нельзя - правильная стратегия для панели-приёмника - внятный отказ на незнакомый тип вместо попытки угадать поля. Подробнее о том, чем типы различаются по смыслу, - в статье про типы услуг поставщика.
Три места, где ломаются интеграции
Эти три вещи не написаны почти ни в одной документации, и именно они дают баги, которые всплывают через неделю после запуска.
- Форма пакетного ответа зависит от действия. У
statusэто объект, где ключ - номер заказа. Уrefill,refill_statusиcancel- массив объектов с номером внутри элемента. Один разборщик на все пакетные ответы не годится. - Ошибка по элементу приходит вложенной. Не общим
{"error": ...}на весь запрос, а внутри своего элемента - под тем же ключом, что и результат. Если код читает только верхний уровень, то девяносто девять успешных заказов из ста он обработает, а сотый молча потеряет. - Доливка адресуется своим номером, а не номером заказа.
action=refillвозвращает номер доливки, и только по немуrefill_statusеё найдёт. Связи «заказ - его доливка» в API нет вообще: номер обязан сохранить у себя клиент. Некоторые панели принимают вrefill_statusещё и номер заказа как надмножество - у нас так и сделано, чтобы не ломать уже написанные интеграции, - но по стандарту этого нет.
К этому же списку относится отмена: одиночного cancel в стандарте нет, только пакетный. Клиент, который отменяет заказы по одному, должен всё равно отправлять список из одного элемента и разбирать массив в ответе.
Статусы и ошибки: строки, а не константы
Статус заказа приходит человекочитаемой строкой: Pending, In progress, Processing, Partial, Completed, Canceled, Fail, Error. У доливки свой набор - Completed, Rejected и промежуточный In progress, а на несуществующий номер приходит Refill not found.
Отсюда четыре правила для клиента:
- Сравнивать регистронезависимо и не полагаться на пробелы: у разных панелей встречаются варианты написания одного и того же состояния.
- Неизвестный статус - не ошибка. Он означает «состояние не изменилось, спросим позже», а не «заказ провалился». Иначе первое же расширение набора на стороне панели превратится у вас в лавину ложных возвратов.
- Деньги парсить как строку.
chargeиbalanceприходят строками с четырьмя знаками после точки - через float это округляется в чужую пользу. - Ошибки уровня запроса - тоже строки в JSON:
Incorrect API key,Incorrect order ID,Incorrect action. HTTP-код при этом может остаться двухсотым, так что проверять только его недостаточно.
Что значат сами статусы с точки зрения покупателя и что панель обязана делать с каждым - в статье про статусы заказов; почему объём «сдувается» после доставки и как работает доливка - в разборе отвала и Refill.
Как проверить интеграцию до продакшена
Шесть проверок, которые ловят почти все ошибки до первого живого заказа:
- Прогнать
servicesи сравнить пришедшие типы с тем, что умеет ваш код. Незнакомый тип должен приводить к отказу с понятным текстом, а не к заказу с пустыми полями. - Создать по одному заказу каждого типа, который собираетесь продавать. Ошибки в наборе полей видны только так - валидация на стороне панели строгая.
- Пакетный
statusна сотне номеров, из которых один заведомо не существует. Это проверка разбора вложенной ошибки - той самой, что теряет заказы по одному. - Полный цикл доливки:
refill, сохранить номер, спроситьrefill_statusпо номеру доливки. Если ваш код спрашивает по номеру заказа и получает ответ, значит вы полагаетесь на надмножество конкретной панели. - Неверный ключ. Ответ обязан остаться JSON. Если пришёл HTML, вы смотрите на страницу ошибки веб-сервера, а не на API, и клиент должен это отличать - иначе авария на стороне панели выглядит для вас как отказ по каждому заказу.
- Частота опроса. Пачками до ста, не чаще раза в минуту на заказ, с увеличением паузы после каждого сбоя. Завершённые заказы не опрашивать вообще - это самая частая причина упереться в лимит на пустом месте.
Со стороны панели-поставщика к этому добавляется своя работа: лимиты на ключ, журнал вызовов и защита от повторной отправки одного и того же заказа. Что стоит проверить перед выдачей ключа реселлеру, разобрано в статье о том, как продавать SMM-услуги как поставщик. Проверить, поддерживается ли ваш поставщик у нас, можно на странице проверки поставщиков.
Итог
API v2 выглядит простым - один эндпоинт, семь действий - и именно поэтому его недооценивают. Реальная сложность в трёх местах: набор полей заказа задаёт тип услуги, форма пакетного ответа зависит от действия, а доливка живёт под своим номером. Клиент, который учитывает эти три вещи, переносится с панели на панель почти без правок; клиент, который их пропустил, теряет заказы молча.
Если API нужен вам не для чужой панели, а для своей, проверить всё это можно без вложений: заказы, которые уходят через наш каталог, не тарифицируются вообще, а по сторонним поставщикам первые 100 заказов в месяц бесплатны. Ключ и полная документация выдаются сразу - можно написать клиента и прогнать все десять вызовов ещё до того, как у панели появится первый покупатель. Как считается лимит, разобрано в статье про расчёт тарифа аренды.