Правила работы с Gigma API
Эта страница описывает общие правила интеграции. Точный набор полей, заголовков, кодов ответа и ограничений всегда берите из карточки конкретного метода или из OpenAPI: backend не использует один универсальный контракт для всех endpoint.
Базовый адрес
https://api.gigma.ru/api Например, путь POST /api/login вызывается по адресу:
https://api.gigma.ru/api/login Заголовки и формат тела
Для JSON-ответа передавайте:
Accept: application/json Для запроса с JSON-телом добавляйте:
Content-Type: application/json Другие форматы указываются в карточке метода:
- загрузка файлов —
multipart/form-data; - introspection клиентского токена —
application/x-www-form-urlencoded; - запрос без тела не требует
Content-Type.
Не устанавливайте multipart/form-data вручную вместе с boundary: это должен сделать HTTP-клиент при формировании формы.
Авторизация
API использует несколько независимых способов доступа.
| Контекст | Заголовок | Где используется |
|---|---|---|
| Сотрудник | Authorization: Bearer <erp_access_token> | Административный API |
| Приложение | Token: <application_token> | Публичные и клиентские методы конкретного Application |
| Клиент | Authorization: Bearer <counterparty_access_token> | Профиль и персональные commerce-операции |
| Приложение + клиент | Оба заголовка одновременно | Заказы, подписки и другие application-scoped методы |
| Backend-интеграция | Authorization: Basic <base64(client_id:client_secret)> | POST /api/counterparty/auth/introspect |
Точный набор авторизации указан у каждого метода. ERP Bearer и Counterparty Bearer выглядят одинаково на уровне HTTP, но относятся к разным guards и не взаимозаменяются.
Bearer и серверные credentials — непрозрачные секреты
Sanctum Bearer может содержать служебные разделители, однако клиент не должен разбирать его на части. Используйте значение access_token.value целиком. client_secret introspection-интеграции храните только на backend.
App Token определяет Application, но в прямой браузерной интеграции не может считаться конфиденциальным: пользователь видит сетевые запросы. Не используйте App Token как замену клиентскому Bearer или проверке прав.
Нельзя:
- помещать токен в URL или query-параметр;
- записывать его в аналитику, error tracking и access-логи;
- определять пользователя по части токена;
- хранить backend-секреты в браузере.
При наличии собственного backend предпочтительна локальная httpOnly-сессия: Bearer проверяется сервером, а браузер не получает долгоживущий секрет Gigma после обмена.
Готовый запрос
Запрос профиля сотрудника:
curl --request GET
--url https://api.gigma.ru/api/user
--header 'Accept: application/json'
--header 'Authorization: Bearer <erp_access_token>' Сокращённый успешный ответ:
{
"user": {
"id": 17,
"login": "manager@example.test",
"first_name": "Ирина",
"is_banned": false,
"permissions": []
}
} Wrapper и состав объекта зависят от Resource-класса конкретного endpoint. Не выводите имя корневого поля из URL по аналогии.
Успешные ответы
Успех определяется диапазоном 2xx, но конкретный код и тело являются частью контракта метода.
В текущем backend встречаются разные варианты:
- создание может вернуть
200с Resource либо явно заданный201; - обновление обычно возвращает
200с объектом; - удаление нередко возвращает
200с{ "message": "..." }, а не204; - асинхронная операция может использовать собственный статус.
Поэтому:
- принимайте весь документированный диапазон
2xx; - не пытайтесь парсить тело у ответа, для которого указан
204; - не считайте любой
POSTавтоматически ответом201; - не считайте любой
DELETEавтоматически ответом204.
Форматы значений
Единого формата для всех исторических endpoint нет. Используйте схему конкретного поля.
| Значение | Правило клиента |
|---|---|
| Дата | Обычно YYYY-MM-DD; проверяйте format: date |
| Дата и время | Парсите как ISO 8601 и сохраняйте timezone |
| Деньги | Не преобразовывайте decimal-string в float без необходимости |
| Boolean | Новые поля используют true/false; legacy-ответы могут содержать 0/1 |
| ID | Считайте ссылкой на ресурс или живой справочник, а не бизнес-константой |
| Nullable | Различайте отсутствующее поле и явно переданный null |
Пагинация, фильтры и сортировка
Пагинация не унифицирована глобально. В API есть:
- Laravel paginator с
data,current_page,last_page,linksи URL страниц; - UI-таблицы с
columns, ресурсным массивом иpagination; - непагинированные коллекции со своим wrapper и полем count.
Параметры page, per_page, query, date_from и date_to встречаются часто, но поддерживаются не каждым методом. Отправляйте только параметры, перечисленные в его карточке. Не переносите фильтры одного ресурса на другой автоматически.
Ошибки
Нет или невалиден Bearer
{
"message": "Unauthenticated."
} Нет App Token
{
"message": "Application token is missing"
} Ошибка валидации
Обычный Form Request возвращает errors, а message может присутствовать или отсутствовать:
{
"message": "The given data was invalid.",
"errors": {
"phone": ["Поле phone является обязательным."],
"products.0.id": ["Выбранное значение некорректно."]
}
} Ключи вложенных полей записываются через точку. Не привязывайте обработку к языку текста: используйте HTTP-код и имя поля.
Как клиенту реагировать
| Код | Что означает | Действие клиента |
|---|---|---|
400 | Запрос понятен, но текущий flow или состояние не подходит | Исправить последовательность действий; не повторять без изменения |
401 | Нет, истёк или не подходит токен | Удалить локальную сессию или повторить вход; тот же токен не отправлять циклически |
403 | Идентичность подтверждена, но нет permission, scope или token ability | Остановить запрос и проверить настройки доступа |
404 | Ресурс отсутствует либо скрыт проектной/application-границей | Не перебирать ID; проверить контекст проекта и приложения |
409 | Конфликт состояния или повтор операции | Получить актуальное состояние и решить конфликт |
415 | Неверный Content-Type | Пересобрать запрос в формате из карточки метода |
422 | Не прошла валидация или бизнес-проверка | Показать ошибки полей либо исправить данные |
429 | Превышен лимит | Учесть Retry-After, применить backoff с jitter и не создавать параллельный retry-шторм |
5xx или timeout | Результат неизвестен либо backend временно недоступен | Для чтения — ограниченный retry; для записи — сначала сверить состояние через GET |
Rate limits
Лимиты задаются на уровне конкретных маршрутов. Универсального публичного значения «60 запросов в минуту для всего API» нет.
Примеры из текущей конфигурации backend:
| Операция | Ограничение |
|---|---|
POST /api/login | 5 запросов в минуту |
POST /api/counterparty/login | 5 в минуту на project + contact и 30 в минуту на IP |
POST /api/counterparty/send_password | 3 в час на project + contact и 20 в час на IP |
POST /api/counterparty/auth/introspect | 60 в минуту на IP и 300 в минуту на backend-клиент |
POST /api/counterparty/session/heartbeat | 6 в минуту на клиентскую сессию |
Эти значения описывают текущую реализацию, а не бессрочную квоту продукта. Клиент всё равно должен корректно обрабатывать 429 и заголовки ответа.
Повторы и идемпотентность
Общего публичного контракта Idempotency-Key для Gigma API нет.
| Запрос | Рекомендация |
|---|---|
GET | Можно повторить с ограниченным exponential backoff |
POST создания или оплаты | Не повторять вслепую после timeout/5xx; сначала найти результат по бизнес-идентификатору |
PUT/PATCH | Повтор допустим только если карточка метода и операция действительно идемпотентны |
DELETE | Не считать глобально идемпотентным: повтор может вернуть другой код или тело |
На стороне продукта сохраняйте собственный correlation ID и состояние попытки. Пользовательское действие, которое может создать заказ, платёж или подписку, блокируйте от двойной отправки.
Webhook
В текущем публичном контракте Application поддерживает событие order.paid.
При доставке Gigma передаёт:
X-Webhook-Event: order.paid
X-Webhook-Event-Id: <event_id>
X-Webhook-Delivery-Id: <delivery_id>
X-Webhook-Timestamp: <unix_timestamp>
X-Signature: sha256=<hex_digest>
Content-Type: application/json Подпись вычисляется по исходным байтам тела:
HMAC_SHA256(secret, timestamp + "." + raw_body) Получатель должен:
- проверить допустимый возраст
X-Webhook-Timestamp; - вычислить HMAC по необработанному body и сравнить подпись constant-time способом;
- дедуплицировать событие по
X-Webhook-Event-Idили доставку поX-Webhook-Delivery-Id; - сохранить событие транзакционно;
- быстро вернуть любой
2xx.
Redirect не используется, timeout доставки — 10 секунд. После неуспеха повторы планируются через 1, 5, 30, 120 и 720 минут. После исчерпания попыток доставка переходит в failed и может быть повторно отправлена администратором.
Подробная настройка находится в «Платформа / Приложения».
Версионирование и совместимость
Публичные пути сейчас находятся под /api без /v1. Отсутствие версии в URL не означает, что клиент может полагаться на недокументированные поля или внутренние классы.
Для устойчивой интеграции:
- отправляйте только документированные поля;
- допускайте появление новых необязательных полей в JSON;
- не полагайтесь на порядок ключей;
- фиксируйте контрактные тесты на критические сценарии;
- проверяйте изменения OpenAPI перед релизом клиента.
Машиночитаемый слой
- openapi.json — методы, security schemes и схемы, извлечённые из карточек endpoint;
- Swagger UI — просмотр и ручная проверка запросов;
- llms.txt — индекс документации для агента;
- llms-full.txt — полный текст страниц;
- erp-rules.txt — короткие правила безопасной интеграции.
OpenAPI не подменяет runtime-код: генератор намеренно не угадывает ID справочников и не выводит 201/204 только из HTTP-метода.
Спецификация собирается из карточек методов, поэтому отсутствие данных означает «не зафиксировано», а не «запрещено». Код 2XX значит, что точный статус не подтверждён карточкой; отсутствие requestBody не доказывает, что тело не нужно; example иллюстрирует формат, а не допустимый диапазон значений. Полный список правил чтения для агента — в erp-rules.txt §13.
Следующие шаги
- Разберите модель платформы на странице «Как устроена Gigma».
- Получайте ID через живые справочники.
- Выберите нужный доменный раздел: E-Commerce или Платформа.
- Для собственного backend начните с introspection.