# AMAGU MARKET: приём заказов партнёра, API v1

Базовый адрес: https://amagu-market.ru/api/v1

Доступ выдаёт AMAGU MARKET: зарегистрированный клиент, аккаунт партнёра и
API-ключ с разрешением `orders`. Передавайте `X-API-Key` или `Authorization: Bearer`.
Ключ выгрузки товаров без разрешения orders не может создавать заказы.

## Приём продаж

`POST /orders`, `Content-Type: application/json`, обязательный `Idempotency-Key`.

```json
{"items":[{"marketplace":"ozon","external_order_id":"100001","external_line_id":"1","product_id":"11111111-1111-4111-8111-111111111111","quantity":1}]}
```

Пакет содержит 1–100 позиций, максимум 256 КБ; администратор может снизить лимит.
marketplace: постоянный код площадки до 64 символов, строчные латинские буквы,
цифры, точка, дефис и подчёркивание. external_order_id и external_line_id:
постоянные строковые идентификаторы до 120 символов каждый. product_id: UUID
МойСклад из `id` карточки товара. Числовые ID сайта не принимаются. quantity:
целое число 1–100000; поштучные продажи разрешены независимо от упаковки.
Товары Ресанта не принимаются: для них пока нет резерва МойСклад.

Пакет атомарный: ошибка любой позиции отменяет весь новый резерв. При нехватке
товара — 409. Суммы рассчитывает AMAGU по своей цене на момент приёма; цену не
передавайте. Изменение цены не пересчитывает прошлые продажи.

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

Успешный ответ содержит `items`: sale_id, period_id, marketplace,
external_order_id, external_line_id, product_id, quantity, cancelled_quantity,
unit_price и status. `stock_reservation=committed` подтверждает резерв на сайте.
`moysklad=queued` означает сохранённое задание на синхронизацию; резерв МойСклад
пока не подтверждён. `unchanged` означает, что новых позиций не было.

## Свободный остаток и принятые резервы

GET /stocks возвращает в stock_quantity общий свободный остаток для новых
заказов. Для товаров МойСклад он учитывает резервы всех покупателей, включая
ваши принятые продажи. Все клиенты, API-ключи и кабинеты маркетплейсов
используют один общий пул товара.

При status=reserved и stock_reservation=committed количество уже вычтено
на сайте в той же транзакции, что и приём продажи. Ждать синхронизации
с МойСклад для уменьшения остатка сайта не нужно. Последующее обновление
остатков учитывает подтверждённый резерв МойСклад один раз.
Свои принятые резервы повторно из stock_quantity не вычитайте.

Пример — было 22 шт., приняты продажи на 10 шт., API отдаёт 12 шт.
При дополнительном страховом запасе 3 шт. для новых продаж остаётся 9 шт.
При распределении между несколькими кабинетами учитывайте этот общий пул.

Повтор с прежним Idempotency-Key и ответ duplicate дополнительный резерв
не создают. Кеш GET /stocks — до 15 секунд; generated_at показывает время
формирования ответа. Внешние изменения МойСклад поступают после фоновой
синхронизации. При приёме нового заказа доступное количество проверяется снова.

## Повторы и потеря ответа

Idempotency-Key: 1–128 печатных ASCII-символов без пробелов. При потере ответа,
таймауте или 503 повторяйте прежнее тело с прежним ключом. `replayed=true`
означает, что возвращён результат прежнего запроса. Иное тело с тем же ключом — 409.
Не меняйте ключ при повторе. Ротация API-ключа не сбрасывает историю клиента.

Защита от дублей также действует по marketplace + external_order_id +
external_line_id для клиента. Прежняя позиция с новым ключом запроса возвращает
status=duplicate без второго резерва. Изменение её товара или количества — 409.
Не повторяйте внешний идентификатор для другой продажи. Исправления цены и возвраты отправленного товара согласуйте с менеджером.
Отмены неотправленных позиций передавайте через /orders/cancellations.

## Получение состояния

- `GET /orders?limit=20&offset=0`: ваши расчётные периоды и суммы общих заказов.
- `GET /orders/{period_id}?limit=100&offset=0`: период и журнал принятых продаж;
  если has_more=true, используйте next_offset.

sync_status=pending: ожидается синхронизация; synced: последняя версия отправлена
в МойСклад и резерв подтверждён; error: обратитесь к AMAGU. При временном сбое
МойСклад сохраняются резерв сайта и задание повторной синхронизации. Состав
распределяется по физическим складам. Проверяйте состояние не чаще раза в минуту.
Заказы другого клиента недоступны.

После закрытия периода AMAGU формирует счёт на оплату по общему заказу. Старые
дубли не переносятся в новый период. Максимум 2000 строк общего заказа; при
достижении предела требуется закрыть период.

Ошибки: 401 — ключ недействителен; 403 — нет прав или приём выключен;
404 — период не принадлежит клиенту либо отсутствует; 409 — конфликт/нехватка
товара; 413 — тело слишком большое; 422 — неверный формат; 429 — лимит;
503 — временная недоступность. При 429/503 соблюдайте Retry-After, без частых
параллельных повторов. Весь API использует общие лимиты по IP, ключу и серверу.

Полная схема: https://amagu-market.ru/api/v1/openapi.json
Документация: https://amagu-market.ru/api-docs#orders

## Отмены и подтверждение отправки

POST /orders/cancellations, API-ключ, Idempotency-Key и тело:

```json
{"items":[{"marketplace":"ozon","external_order_id":"100001","external_line_id":"1"}]}
```

До выставления счёта отмена удаляет неотправленную позицию из общего заказа,
уменьшает сумму и освобождает резерв сайта (stock_reservation=released).
Снятие резерва МойСклад ставится в отдельную сохраняемую очередь. Повтор отмены
не увеличивает остаток повторно. Последняя отмена оставляет пустой общий заказ.

После выставления счёта или оплаты: status=requires_review, задача менеджеру,
суммы и резервы не изменяются автоматически. Проверьте pending_corrections
в периоде. POST /orders/shipments с теми же полями фиксирует отправку позиции,
status=shipped. Её последующая отмена как неотправленной вернёт 409.

Общий расчётный заказ не подлежит сборке. Статусы сайта используются для учёта
и сами не снимают резервы. По окончании срока период и общий заказ закрываются
автоматическим планировщиком; сборка для выставления счёта не требуется.
