Как публичный API становится платформой для интеграторов
Один эндпоинт `/contacts` — это ещё не платформа. Платформа начинается там, где поверх API появляется второй уровень: третье приложение, которому пользователь даёт доступ, партнёр, перепродающий доступ своим клиентам, и SDK, который security-команда интегратора может прочитать глазами. TL;DR: три архитектурных свойства — OAuth рядом с ключами, Partner API с изоляцией sub-проектов и open-source SDK — превращают обычный API в платформу. Разбираю каждое: суть, код, где граница.
Коротко
- OAuth и API-ключ — не «современное против устаревшего», а два инструмента для двух сценариев. Ключ — для собственного бэкенда клиента, OAuth — для стороннего приложения, которому пользователь дал доступ. Подмена одного другим — типовая утечка.
- Partner API — это не «много обычных ключей». Отдельный тип ключа, sub-проекты через
parent_project_id, жёсткая изоляцияproject_idна трёх уровнях. Без этого reseller-контур течёт на первой ошибке. - Open-source SDK — не подарок сообществу, а инструмент. Снимает блокировку security-аудита, разблокирует bug fix через PR, работает сигналом зрелости API. Ценность — при дисциплине «SDK не содержит бизнес-логики».
Это разбор трёх свойств, которые отличают API-как-функцию от API-как-платформы. Не «как подключиться» — а как устроена авторизация третьих сторон, перепродажа доступа и открытый SDK. Каждый из трёх — отдельная инженерная тема со своей границей безопасности, и половина ошибок интеграции возникает от их смешивания.
OAuth 2.0 против API-ключа: кто действует от чьего имени
Регулярно всплывает ложная альтернатива: «у нас уже есть API-ключ, зачем OAuth» или наоборот «мы делаем современный API, ключи — устаревший подход». Обе формулировки исходят из того, что ключ и OAuth решают одну задачу разными способами. Они решают разные задачи, и главный вопрос при проектировании авторизации звучит просто: «кто действует от чьего имени».
Два сценария, которые часто путают:
- Своё приложение. Компания купила SaaS, у неё есть бэкенд, она хочет, чтобы её бэкенд общался с API. Бэкенд её, ключ её, действия — от её имени. Правильный инструмент — API-ключ.
- Стороннее приложение. Появился сервис-партнёр, который хочет работать с данными клиента. Клиент должен дать разрешение на доступ. Сервис-партнёр не знает ключ клиента, не должен его знать и не должен получать. Правильный инструмент — OAuth 2.0.
Самая частая ошибка — клиент копирует production-ключ и вставляет его в форму «введите API-ключ» стороннего сервиса. С этого момента сервис имеет полный доступ ко всему, что доступно по ключу, хранит его в своей БД (сольётся БД — сольётся ключ), а отозвать доступ клиент может только вручную в кабинете основного SaaS. На практике этого никто не делает. OAuth закрывает обе проблемы: стороннее приложение не получает долгоживущий ключ, а клиент отзывает установку в один клик — доступ исчезает немедленно.
Важно: OAuth — это не «безопаснее ключа», а другая модель доверия. Короткоживущие токены, отзыв, scope нужны, когда доступом владеет третья сторона. Когда доступом владеет сама компания, у неё нет проблемы «третья сторона сольёт мой ключ» — она сама владелец. OAuth для собственного бэкенда — лишний танец с токенами без выгоды: вместо одного заголовка появляется получение access token, обновление через refresh, обработка 401 на истечении.
Оба механизма в BOTIX живут на одних эндпоинтах api.botix.pro/public/v1/*. Разница — в одном заголовке и в аудите:
# Своё приложение — API-ключ
GET /public/v1/contacts HTTP/1.1
Host: api.botix.pro
Authorization: Bearer XXXXXXXX…
# Third-party приложение — OAuth access token
GET /public/v1/contacts HTTP/1.1
Host: api.botix.pro
Authorization: Bearer <oauth_access_token>
X-OAuth-App-Id: <client_id>С точки зрения эндпоинта различия минимальные. Различие — в учёте: OAuth-запросы логируются с привязкой к oauth_app_id (отдельная колонка в таблице btx_api_log), и клиент видит, какое именно приложение что делало.
Что обязательно входит в OAuth-flow
Когда команда впервые делает OAuth, велик соблазн срезать углы. Не делать PKCE, не делать state, не делать короткий expiry. Каждая срезка превращает OAuth в дырявое решето, которое формально называется OAuth, а даёт меньше защиты, чем добротный API-ключ. Минимальный набор для Authorization Code flow:
- PKCE с
code_verifierиcode_challenge— закрывает атаку «authorization code interception». - Параметр
state, случайный и проверяемый, — без него возможна CSRF-атака на callback. - Авторизационный код живёт 5–10 минут и используется одноразово.
- Access token — около часа. Refresh token — 30–90 дней, ротируется при каждом обмене (старый инвалидируется).
- Владельцу кабинета доступен список активных installations с отзывом в один клик.
В BOTIX реализованы все пять. Документация — developers.botix.pro/oauth. Регистрация приложения (для разработчика) — app.botix.pro/settings/oauth-apps. Подключённые приложения и их отзыв (для пользователя) — app.botix.pro/settings/connected-apps. Две страницы намеренно разнесены: разработчик регистрирует, пользователь даёт согласие.
Scope — это и есть граница, которой у ключа нет. API-ключ всегда даёт полный доступ. У OAuth-токена есть заявленный набор разрешений, и на странице согласия пользователь видит список и решает, разрешать или нет:
messages:read messages:send
contacts:read contacts:write
chats:read channels:read
scenarios:read scenarios:run
webhooks:read webhooks:writeПринцип наименьших привилегий: приложение, которое умеет только рассылать сообщения, не должно иметь возможности удалять контакты. Список scope в BOTIX небольшой и сознательно не дробится мелко — каждый scope соответствует понятной пользователю группе действий. Расширение списка возможно; удаление scope из стабильного списка — breaking change.
Когда переходить с ключа на OAuth: если у проекта одно приложение, интегрируемое с BOTIX, — API-ключ навсегда, OAuth не нужен. Если планируется маркетплейс приложений — OAuth нужен с самого начала. Граница между двумя случаями — момент появления первого стороннего приложения. До него OAuth — преждевременная оптимизация, в этот момент — необходимость. Полный разбор flow целиком — в когда нужен OAuth: PKCE, scope, отзыв.
White-label и Partner API: sub-проекты и жёсткая изоляция
Второй уровень наступает, когда API начинают использовать не прямые клиенты, а партнёры, встраивающие его в свой продукт: агентство под своим брендом, ISV со своим SaaS, системный интегратор. Для них обычный публичный API быстро становится тесным.
У прямого клиента контур простой: один аккаунт, один проект, несколько ключей, один webhook. У партнёра — многоуровневый: сам партнёр имеет аккаунт сверху, внутри него десятки-сотни конечных клиентов, у каждого свой логический проект со своими данными, биллингом, webhook'ом. Первый и самый частый ошибочный ответ на такой запрос — «заведите отдельный аккаунт на каждого клиента». 47 клиентов — 47 кабинетов, 47 ключей, 47 биллингов. На бумаге работает, в эксплуатации разваливается: партнёр не хочет 47 раз вводить реквизиты и не может централизованно мониторить здоровье интеграций.
Правильная модель — иерархия, а не много обычных ключей:
- Партнёрский уровень аутентификации. Отдельный тип ключа — partner-key — с более высокими привилегиями, чем у обычного project-key: создание sub-проектов через API, перечисление существующих, получение ключа для каждого. Эти операции вынесены в отдельный набор эндпоинтов
/partner/v1/*; обращение к ним с обычным ключом возвращает 403. - Sub-проекты как первоклассная сущность. В БД sub-проект — это
btx_projects.parent_project_idс foreign key на родительский партнёрский проект. Не флаг, не эмуляция через префиксы, не URL-схема/v1/{project_id}/.... У каждого sub-проекта свои webhook'и, настройки, биллинг — строка сparent_project_idдаёт единое место, где проверяется принадлежность. - Биллинг-события через API. Партнёр почти всегда биллит конечных клиентов по своей модели, отличной от тарифов поставщика. Ему нужны сырые данные — количество запросов, сообщений, активных контактов по каждому sub-проекту за период: либо
GET /partner/usage, либо webhook-события в конце расчётного периода. - Audit-логи на партнёрском уровне. Когда конечный клиент пишет «у нас что-то не работает», партнёр должен диагностировать сам, без привлечения поставщика — доступ к журналу по sub-проектам регулируется тем же partner-ключом.
Изоляция project_id — критическая граница
Внутри одного партнёрского аккаунта могут жить sub-проекты конкурирующих компаний — два барбершопа с разных концов района. Возможность одного увидеть данные другого — катастрофа, а не баг. Поэтому изоляция строится на трёх уровнях сразу:
- Уровень БД.
WHERE project_id = ?в каждом контентном запросе. Multi-tenant фильтр — не опция, а правило. - Уровень API. Явный
project_idв каждом запросе + проверка, что sub-проект принадлежит партнёрскому аккаунту, выпустившему ключ. - Уровень ключей. Нельзя получить ответ по одному sub-проекту, передав ключ другого.
Ключевой механизм — вызов Auth::assertProjectAccess($projectId) в начале каждого эндпоинта, работающего с проектом. Партнёрский уровень добавляет слой: проверяется не только доступ к sub-проекту, но и то, что он принадлежит партнёру, выпустившему ключ. Это формальное правило, зафиксированное в CLAUDE.md репозитория и проверяемое в code-review: без него данные потекут между проектами на первой же ошибке.
Тонкий момент для reseller — секрет webhook у каждого sub-проекта отдельный. Общий секрет по всем sub-проектам означает: компрометация одного клиента = компрометация подписи всех. Изоляция project_id без изоляции секретов подписи — дырявая.
Отдельно — OAuth поверх партнёрского контура. Когда у партнёра появляется собственный дашборд с агрегированной аналитикой по всем клиентам, ему нужны partner-scope: они позволяют OAuth-приложению, установленному в партнёрский аккаунт, видеть все sub-проекты, а не только тот, в который оно установлено напрямую. Это по-прежнему OAuth, а не «дайте партнёру ваш ключ»: ключ от sub-проекта даёт полный набор прав, включая удаление и смену биллинга, — нарушение наименьших привилегий. Про хранение ключей и white-label в такой схеме — партнёр через API: OAuth, ключи, white-label.
Как это складывается
[Партнёр]
|
|--[partner-key] -- создаёт sub-проекты, перечисляет, мониторит (/partner/v1/*)
|
|--[Sub-проект 1] -- [API-key 1] -- воркеры партнёра, изоляция по project_id
| |-- свой webhook-секрет
|--[Sub-проект 2] -- [API-key 2]
| ...
|--[Sub-проект N]
[Third-party дашборд партнёра]
|
|--[OAuth-app, зарегистрировано партнёром]
|--[installation для sub-проекта K]
|-- access_token (1ч) + refresh_token (30д)
|-- scope: chats:read, messages:read
|-- виден клиенту, отзывается в клик
|-- логируется по oauth_app_idТри независимых канала: partner-key для управления контуром, project API-key для собственных воркеров партнёра, OAuth — для всего, что видит и разрешает конечный клиент.
Что уже есть, а что в roadmap
Честная картина по состоянию платформы: OAuth installations работают — авторизация от имени клиента, scope, отзыв, аудит по oauth_app_id доступны сейчас. Полноценный Partner API как отдельный слой /partner/v1/* (партнёрский тип ключа, sub-проекты через API, биллинг-события и audit-логи на партнёрском уровне), а также white-label-домены для кабинета под брендом партнёра — в roadmap без публичного релиза. До его выхода reseller-модель собирается из доступных кирпичей: OAuth для third-party, отдельный ключ на каждый sub-проект, локальная агрегация usage на стороне партнёра. Работает, но требует ручных шагов при заведении клиента — то самое узкое место, которое партнёрский уровень снимает автоматизацией. (Не путать с реферальной партнёрской программой botix.pro/partners — та про «привёл клиента, получаешь процент», а не про технический reseller-контур.)
Что спросить у платформы, если вы reseller: sub-проект — отдельная сущность в БД или эмуляция через флаги? Есть ли partner-уровень ключа с правом создавать sub-проекты через API? Отдельный ли webhook-секрет у каждого sub-проекта? Есть ли OAuth со scope и страницей согласия? Если предлагают «обходной путь через ваш ключ» — third-party для клиента вы делать не сможете. Как заводится sub-проект программно — разбор в multi-tenant через API: проекты, ключи, изоляция.
Open-source SDK: зачем открывать исходный код
Третье свойство платформы вопрос «открывать ли исходники SDK» обычно обсуждают через категорию щедрости: «принесём пользу сообществу» против «лучше потратим время на фичи». Обе стороны рассуждают о морали, а не о бизнесе. На деле open-source SDK — инструмент с конкретными функциями, каждая из которых закрывает задачу, которую закрытый SDK либо не решает, либо решает дорого.
Функция 1. Security-аудит без участия поставщика. Корпоративная интеграция почти всегда проходит через security-команду. Закрытая библиотека для них — чёрный ящик, который что-то делает с данными. Дальше три дорогих варианта: заблокировать интеграцию (частый исход), потребовать SOC 2 Type II / ISO 27001 / DPA (десятки тысяч долларов и месяцы), запросить исходники по NDA (недели). Open-source закрывает все три: security открывает GitHub-репозиторий, видит, что библиотека делает только заявленное, и пропускает интеграцию. SOC 2 при этом всё равно нужен — для инфраструктуры и процессов, — но SDK как точка входа в код корпорации становится прозрачным.
Функция 2. Bug fix не блокируется вендором. В закрытом SDK любая ошибка — тикет в поддержку и новая версия через месяц-три, всё это время у интегратора костыль или нерабочая интеграция. В открытом — либо PR с фиксом, либо временный форк через VCS-ссылку в composer.json / package.json, пока upstream не примет правку. Никакой блокировки.
Функция 3. Сигнал зрелости API. Открытый SDK под свободной лицензией — сигнал, что у API есть стабильный контракт, который не стыдно показать. Закрытый почти всегда читается как «наколхозили, поэтому прячут». Работает не на сознательном уровне: инженер посмотрел репозиторий, не нашёл ничего стыдного — и покупатель формулирует «серьёзные люди».
Функция 4. Контрибьюции сообщества. На старте это односторонняя отдача — нормально. По мере роста появляются PR с типичными улучшениями: retry, timeout, прокси, совместимость с нетипичной версией зависимости. У зрелых SDK (Stripe, Twilio, Slack) — десятки внешних контрибьюторов; у молодых — единицы или ноль, и это нормально.
В BOTIX сигнал встроен в стратегию SDK с самого начала: три SDK (PHP, Python, Node), CLI и три example-репозитория для популярных фреймворков (Laravel, Express, Flask) выложены на GitHub в организацию BOTIX-pro с открытой лицензией. Пакеты опубликованы в Composer (botix-pro/sdk), PyPI (botix) и npm (@botix/sdk):
composer require botix-pro/sdk:^1.1
pip install botix==1.1.0
npm install @botix/sdk@1.1.0Один и тот же API представлен через три SDK с одинаковой структурой методов. Если разработчик переключается между языками, переучиваться не нужно — структура client.contacts.create(...) одинакова в Python, Node и PHP. Это не совпадение, а сознательная работа.
Сколько это стоит поставщику. Главный страх — «код утащат». Утащить SDK без потери смысла невозможно: он бесполезен без API, к которому обращается; под чужой API переписать легче, чем переиспользовать. Второй страх — раскрытие архитектуры — решается дисциплиной: SDK не содержит бизнес-логики, он делает ровно три вещи — формирует запрос, подписывает его, парсит ответ. Индекс категорий, бизнес-правила, расчёты — на стороне API. При такой дисциплине открытый код не раскрывает ничего, кроме формата работы с публичным API, который и так лежит в openapi.yaml. Третий страх — поддержка: публичный репозиторий означает входящие issues, и без выделенного человека SDK превращается в кладбище с просрочкой — антиреклама.
Когда open-source SDK не нужен: API нишевой и вся аудитория по NDA; API в стадии активного breaking-change (сообщество увидит нестабильность в публичном репозитории — сигнал, обратный ожидаемому); нет человека на review PR и ответы на issues. Все три условия — про ранние стадии. Когда продукт зреет и аудитория растёт, закрытый SDK становится якорем, и переход на open-source — уже не «давать ли подарок», а «убрать ли якорь». Про то, как не сломать интеграторов при обновлениях SDK, — версии SDK и semver: обновления без breaking, а стратегию zero-dependency — zero-dependency SDK в open-source.
Три свойства вместе
OAuth рядом с ключами, Partner API с изоляцией sub-проектов и open-source SDK — не три независимых фичи, а один ответ на вопрос «готов ли API стать платформой». OAuth пускает третьи стороны безопасно, Partner API даёт перепродавать доступ без утечек между клиентами, открытый SDK снимает трение на входе у энтерпрайза. Решение про платформенный слой — продуктовое, не техническое: не каждый API должен быть платформой. Но если решение принято, эти свойства закладывают в архитектуру заранее, а не на третьей итерации после первых жалоб.
Попробуйте API BOTIX
Получите ключ, отправьте первый запрос и поймайте webhook — прямо в браузере, без боевого канала.
Попробовать API бесплатноЧитайте также
Zero-dependency SDK, open-source и партнёрский API
Версии SDK и semver: как выпускать обновления, не ломая партнёрские интеграции
OAuth, хранение ключей и white-label в партнёрском API
Multi-tenant, polling vs webhook и OAuth для агентства
