{"openapi":"3.1.0","info":{"title":"Aviedo Reseller API","version":"1.0","summary":"API для реселлеров Aviedo: каталог, заказы, вебхуки","description":"С помощью API вы продаёте товары Aviedo в своём магазине, Telegram-боте или на сайте: получаете каталог с вашими ценами в долларах, создаёте заказы с оплатой с долларового баланса, получаете коды, ключи и аккаунты, следите за статусами и переписываетесь с продавцом по заказу.\n\n- **Базовый адрес:** `https://api.aviedo.net/v1`\n- **Формат:** JSON в UTF-8, только HTTPS\n- **Авторизация:** токен + HMAC-подпись каждого запроса\n- **Деньги:** доллары США, строки с двумя знаками — `\"12.67\"`\n- **Время:** московское, ISO-8601 со смещением — `\"2026-10-12T16:00:00+03:00\"`\n- **Тестовый режим:** `\"test\": true` в заказе — баланс не списывается, заказ сам проходит все статусы\n- **Поддержка:** [t.me/av1de](https://t.me/av1de)\n\n**Вся интеграция укладывается в четыре вызова:**\n\n1. `GET /v1/catalog` — получить каталог с вашими ценами.\n2. `POST /v1/orders` — купить. Один запрос, деньги списываются сразу.\n3. Узнать результат: вебхук на ваш URL **или** опрос `GET /v1/events` раз в 10–30 секунд.\n4. Показать покупателю `order.delivery`.\n\n**В Aviedo три вида товаров** (поле `kind` у товара):\n\n| `kind` | Что это | Примеры | Что получает покупатель | Сроки |\n|---|---|---|---|---|\n| `auto` | автоматические | пополнение игр, подарочные карты, Telegram Stars и Premium, Steam, Robux | зачисление на аккаунт, код или ссылку | обычно 1–10 минут |\n| `uploaded` | загруженные | ключи, аккаунты, подписки | готовые строки (ключ, `логин:пароль`) | **сразу**, в ответе на создание заказа |\n| `manual` | ручные | донат «через вход», услуги | выполнение продавцом, общение в чате | от минут до нескольких часов |\n\nДокументация ниже читается сверху вниз: сначала руководство (быстрый старт, подпись, деньги, заказы, статусы, вебхуки, тестовый режим, ошибки, примеры кода), затем справочник по каждому методу и объекту. Все примеры ответов — настоящие ответы боевого API, полученные в тестовом режиме.\n\n## Быстрый старт (5 минут)\n\n**1. Получите ключи.** Откройте кабинет реселлера [https://aviedo.net/reseller](https://aviedo.net/reseller), вкладку **Настройки**, и скопируйте **API токен** (начинается с `rsl_`) и **Секретный ключ** (43 символа). Кабинет доступен после одобрения заявки реселлера.\n\n**2. Проверьте ключи.** Подойдёт любой терминал с `curl` и `openssl`:\n\n```bash\nexport AVIEDO_TOKEN='rsl_ВАШ_ТОКЕН'\nexport AVIEDO_SECRET='ВАШ_SECRET'\n\nTS=$(date +%s)\nSIG=$(printf '%s\\n%s\\n%s\\n%s' \"$TS\" \"GET\" \"/v1/me\" \"\" | openssl dgst -sha256 -hmac \"$AVIEDO_SECRET\" -r | cut -d' ' -f1)\ncurl -s https://api.aviedo.net/v1/me \\\n  -H \"Authorization: Bearer $AVIEDO_TOKEN\" \\\n  -H \"X-Aviedo-Timestamp: $TS\" \\\n  -H \"X-Aviedo-Signature: $SIG\"\n```\n\nОтвет с `\"ok\": true` и вашим балансом означает, что токен и подпись верны. Если пришла ошибка, посмотрите `error.code` и раздел «Авторизация и подпись».\n\n**3. Выберите товар.** `GET /v1/catalog` возвращает весь каталог. У каждого товара есть `id`, цена `price.unit_price`, правила количества `quantity` и список полей `fields`, которые нужно передать в заказе.\n\n**4. Создайте тестовый заказ.** Добавьте `\"test\": true` — баланс не тратится, поставщику ничего не уходит, а заказ сам пройдёт статусы как настоящий:\n\n```json\n{\n  \"product_id\": 853,\n  \"external_id\": \"shop-1001\",\n  \"max_total_usd\": \"12.67\",\n  \"fields\": { \"telegram_username\": \"durov\" },\n  \"test\": true\n}\n```\n\nЧерез ~20 секунд заказ станет `completed`, и придёт событие `order.completed` (вебхуком или в `GET /v1/events`). Готовые скрипты, которые делают всё это целиком, — в разделе «Примеры кода».\n\n**5. Подключите получение результата.** Укажите в кабинете (**Настройки → Webhook**) адрес вашего обработчика или опрашивайте `GET /v1/events` раз в 10–30 секунд.\n\n**6. Прогоните тестовые сценарии** (раздел «Тестовый режим»), уберите `\"test\": true` — интеграция готова.\n\n## Авторизация и подпись\n\nКаждый запрос, кроме `GET /v1/status`, подписывается — включая GET: в ответах есть коды и ключи. Формула одна для всех методов.\n\n### Заголовки\n\n| Заголовок | Значение |\n|---|---|\n| `Authorization` | `Bearer rsl_…` — ваш API токен |\n| `X-Aviedo-Timestamp` | текущее unix-время в секундах, например `1791810000` |\n| `X-Aviedo-Signature` | `hex(HMAC-SHA256(секретный_ключ, строка_для_подписи))` — 64 символа в нижнем регистре |\n| `Content-Type` | `application/json` — обязателен для всех POST, иначе `415 unsupported_media_type` |\n\nИмена заголовков пишутся через дефис. Заголовки с подчёркиванием (`X_Aviedo_Signature`) сервер отбрасывает.\n\n### Алгоритм по шагам\n\n1. Соберите путь вместе с query-строкой **один раз**: `/v1/orders?status=processing&limit=50`. Ровно эту строку вы и отправите.\n2. Сериализуйте тело в JSON-строку **один раз**. У GET тела нет — используйте пустую строку. У POST без параметров отправляйте `{}`.\n3. Возьмите текущее время `ts` — целое число секунд.\n4. Склейте **четыре части через перевод строки `\\n`** (LF, байт `0x0A`). После тела перевода строки нет:\n\n   ```\n   строка_для_подписи = ts + \"\\n\" + METHOD + \"\\n\" + PATH + \"\\n\" + BODY\n   ```\n\n   - `METHOD` — заглавными буквами: `GET` или `POST`.\n   - `PATH` — путь и query **ровно в том виде, в каком они уходят в запросе**, без домена. Сортировать параметры не нужно.\n   - `BODY` — точные байты тела в UTF-8. У GET это пустая строка, поэтому строка для подписи заканчивается на `\\n`.\n5. Посчитайте `HMAC-SHA256`. Ключ — строка секретного ключа **как есть** (43 символа), декодировать её из base64 не нужно. Результат переведите в hex в нижнем регистре.\n6. Отправьте три заголовка и **те же** путь и тело, что подписывали.\n\nДопустимое расхождение часов — ±300 секунд. Время сервера приходит в заголовке `X-Aviedo-Server-Time` во всех ответах API (кроме ошибок, сгенерированных прокси/nginx) и в `GET /v1/status` (без авторизации).\n\n### Разобранный пример\n\n```\nсекретный ключ = dEmO-sEcReT_9f2Kq7Lx3Vb8Nm1Zc5Hw0Jr4Tg6Yp2A\nts             = 1791810000                (2026-10-12T16:00:00+03:00)\nMETHOD         = POST\nPATH           = /v1/orders\nBODY           = {\"product_id\":853,\"quantity\":1,\"external_id\":\"shop-1001\",\"max_total_usd\":\"12.67\",\"fields\":{\"telegram_username\":\"durov\"}}\n```\n\nСтрока для подписи (символ `⏎` здесь — один байт `\\n`):\n\n```\n1791810000⏎POST⏎/v1/orders⏎{\"product_id\":853,\"quantity\":1,\"external_id\":\"shop-1001\",\"max_total_usd\":\"12.67\",\"fields\":{\"telegram_username\":\"durov\"}}\n```\n\nРезультат:\n\n```\nX-Aviedo-Signature: 1e6a3898f30a90e7be69081392844460608b83cdc8a81606446af34a7600a551\n```\n\n### Тестовые векторы\n\nСекретный ключ и `ts` — те же, что в примере выше. Прогоните свою функцию подписи по этому списку: все значения сверены в PHP, Python, Node.js, openssl и на нашем сервере.\n\n```text\n1. GET /v1/me, тело пустое\n   47cd3ed2521ade347af11c10b20407db8275485e4afd9dfb2d27849a966a1ca7\n\n2. GET /v1/orders?status=processing&limit=50, тело пустое\n   0c740fefc4c56ed6f4d329e2a2593669582deac4a52f5e0dbe2db3d2ca4363a5\n\n3. POST /v1/orders, тело из примера выше\n   1e6a3898f30a90e7be69081392844460608b83cdc8a81606446af34a7600a551\n\n4. POST /v1/orders/T9145E3EB9AD/cancel, тело {}\n   d68f7eb209ca712442a6ce7b62482363138a552161ca8205ef5909e6a17ca094\n\n5. Вебхук (формула в разделе «Вебхуки»): t=1791810000, тело\n   {\"id\":1042,\"type\":\"ping\",\"created_at\":\"2026-10-12T16:00:00+03:00\",\"test\":false,\"data\":{}}\n   9368001464b1e7ef2e2dc6b735ed4e317f2d79b845e00db0dfee62486f87d70b\n```\n\nПроверить вектор в командной строке:\n\n```bash\nprintf '%s\\n%s\\n%s\\n%s' 1791810000 GET /v1/me \"\" \\\n  | openssl dgst -sha256 -hmac 'dEmO-sEcReT_9f2Kq7Lx3Vb8Nm1Zc5Hw0Jr4Tg6Yp2A' -r\n# 47cd3ed2521ade347af11c10b20407db8275485e4afd9dfb2d27849a966a1ca7 *stdin\n```\n\n### Частые ошибки подписи\n\n- **Подписали одно тело, а отправили другое.** Так бывает, когда тело сериализуется дважды: `requests.post(json=...)` в Python, `CURLOPT_POSTFIELDS => $array` в PHP, `axios.post(url, object)` в Node.js. Сериализуйте JSON один раз в строку, подпишите её и отправьте эту же строку.\n- **Query-строка в подписи и в запросе закодирована по-разному.** Например, библиотека сама добавила `params=` или пересобрала URL. Соберите URL один раз.\n- **Подписали без query-строки** (`/v1/orders` вместо `/v1/orders?limit=50`) или с доменом (`https://api.aviedo.net/v1/me`).\n- **Лишние символы в секретном ключе** — пробел или перевод строки в конце после копирования.\n- **Разделитель** — точка, пробел или `\\r\\n` вместо `\\n`.\n- **Время в миллисекундах** (`Date.now()` в JavaScript без деления на 1000).\n\nВ ответе `401 invalid_signature` сервер присылает подсказки, по которым видно, что именно он подписывал. Секретный ключ в ответе не приходит никогда:\n\n```json\n\"details\": {\n  \"server_time\": 1791816163,\n  \"string_to_sign_prefix\": \"1791816163\\nPOST\\n/v1/orders/quote\\n\",\n  \"body_sha256\": \"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d\",\n  \"body_length\": 30\n}\n```\n\nСравните `string_to_sign_prefix` со своей строкой без тела, а `body_sha256` — с SHA-256 вашего тела.\n\n### Что проверяет сервер (в этом порядке)\n\n1. Запрос пришёл по HTTPS. Иначе `403 https_required` (редиректа нет).\n2. Переданы все три заголовка. Иначе `401 missing_credentials`: каких не хватает — в `details.missing` и в тексте `message`.\n3. Токен существует: действующий или старый в течение 24 часов после перевыпуска. Иначе `401 unauthorized`.\n4. Время в окне ±300 секунд. Иначе `401 timestamp_out_of_window`, в `details.server_time` — наше время.\n5. Подпись совпала (сравнение за постоянное время). Иначе `401 invalid_signature`.\n6. Аккаунт не заблокирован и статус реселлера «одобрен». Иначе `403 account_banned` или `403 reseller_not_approved`. Проверка идёт **на каждом запросе**: если доступ отозван, ключ сразу перестаёт работать.\n7. Лимит запросов не превышен. Иначе `429 rate_limited`.\n\n### Ключи и безопасность\n\n- Храните секретный ключ **только на сервере**. Его нельзя класть в браузер, мобильное приложение, Telegram-бота на стороне клиента или публичный репозиторий.\n- **Перевыпуск.** В кабинете есть кнопка «Перевыпустить ключи». Новая пара работает сразу, старая — ещё **24 часа**, чтобы вы успели обновить конфигурацию (срок виден в `GET /v1/me` → `key.previous_key_valid_until`). Пока старая пара действует, вебхуки подписываются обоими ключами.\n- Вебхуки приходят с нашего IP `201.51.24.228`. Если вы ограничиваете входящие запросы по IP, разрешите этот адрес.\n- Повтор перехваченного запроса в пределах 300 секунд ничего не испортит: заказы идемпотентны по `external_id`, сообщения — по `client_message_id`, отмена идемпотентна.\n\n## Формат запросов и ответов\n\n| | |\n|---|---|\n| Протокол | только HTTPS (TLS 1.2+). Запрос по `http://` получает `403 https_required`. **Редиректов нет нигде**: API никогда не отвечает 3xx, поэтому POST не превратится в GET |\n| Пути | точные, без завершающего `/` и без `.php`. Неизвестный путь — `404 not_found` |\n| Query-параметры | строгие: **неизвестный параметр** (опечатка, `_=123` для обхода кэша) даёт `400 unknown_parameter` со списком допустимых в `details.allowed` |\n| Тело | JSON-объект в UTF-8, не больше 8 МБ. Неизвестное поле в теле — `400 unknown_parameter` |\n| Деньги | **строки** в долларах с двумя знаками: `\"12.67\"`. Исключение — цена за единицу у поштучных товаров, у неё шесть знаков: `\"0.015960\"` |\n| Курс | строка с шестью знаками: `\"87.270000\"` |\n| Время | ISO-8601 со смещением, московское: `\"2026-10-12T16:00:00+03:00\"`. В подписи — unix-время в секундах |\n| ID заказа | 12 символов: `[0-9A-F]{12}` у боевых (тот же номер, что виден в магазине), `T` + 11 символов у тестовых |\n| Остальные ID | целые числа: товар, раздел, категория, группа, сообщение, событие |\n| Сжатие | ответы сжимаются gzip, если клиент передал `Accept-Encoding: gzip` (большой каталог — обязательно) |\n\n### Успешный ответ\n\n```json\n{\n  \"ok\": true,\n  \"data\": { },\n  \"request_id\": \"req_63f28101673f\"\n}\n```\n\nУ списков дополнительно приходит `pagination`, у некоторых методов — `meta` (например, `{\"idempotent_replay\": true}`). **Принимайте любой код 2xx**: создание отвечает `201`, повтор создания — `200`.\n\n### Ответ с ошибкой\n\n```json\n{\n  \"ok\": false,\n  \"error\": {\n    \"code\": \"insufficient_funds\",\n    \"message\": \"Недостаточно средств: нужно 319.20 $, на балансе 250.00 $\",\n    \"retryable\": false,\n    \"retry_after\": null,\n    \"details\": { \"required\": \"319.20\", \"balance\": \"250.00\", \"missing\": \"69.20\" }\n  },\n  \"request_id\": \"req_92b0e6f1a3c4\"\n}\n```\n\n- Логику стройте на `error.code`. Поле `message` — для человека, его текст может меняться.\n- `retryable: true` — запрос можно повторить не раньше чем через `retry_after` секунд (то же значение в заголовке `Retry-After`).\n- `request_id` указывайте, когда пишете в поддержку.\n- Полный список кодов — в разделе «Ошибки».\n\n### Заголовки ответа\n\n| Заголовок | Где | Смысл |\n|---|---|---|\n| `X-Request-Id` | всегда | то же, что `request_id` в теле |\n| `X-Aviedo-Server-Time` | во всех ответах API (кроме ошибок, сгенерированных прокси/nginx) | unix-время сервера в секундах — для сверки часов |\n| `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` | методы с авторизацией | лимит самой «узкой» корзины, остаток и unix-время сброса окна (раздел «Лимиты») |\n| `Retry-After` | ошибки с `retryable: true` | через сколько секунд повторять |\n| `ETag` | `GET /v1/catalog`, `GET /v1/products` | для запросов с `If-None-Match` |\n| `Cache-Control` | всегда | `no-store`; у каталога — `private, no-cache` |\n\n### Совместимость\n\nВ пределах `/v1` мы только **добавляем**: новые поля в ответах, новые события, коды ошибок, подтипы товаров и типы полей.\n\n- Не падайте на незнакомых полях ответа.\n- Незнакомый статус заказа считайте `processing`.\n- Незнакомый `type` товара обрабатывайте по его `kind`; незнакомый тип поля — как `text`.\n- Незнакомый код ошибки обрабатывайте по HTTP-статусу и `retryable`.\n\nЛомающие изменения выйдут только в `/v2`, после этого `/v1` проработает ещё минимум 3 месяца. Все изменения записываются в «Журнал изменений».\n\n## Деньги, цены и курс\n\n### Цены\n\n**Все цены в API — в долларах и уже включают вашу реселлерскую наценку.** Пересчитывать ничего не нужно, скрытых комиссий нет: с баланса списывается ровно `price.total` заказа.\n\n| `price.model` | Где | Как считается сумма заказа |\n|---|---|---|\n| `fixed` | все товары, кроме поштучных | `total = unit_price × quantity`, точно до цента |\n| `per_unit` | Telegram Stars (цена 1 звезды), Steam (цена 1 единицы валюты кошелька) | `total = round_half_up(unit_price × quantity, 2)`. `unit_price` — опубликованная строка с шестью знаками, поэтому сумму можно посчитать самому до цента |\n\nПримеры `per_unit` (настоящие цены на момент написания):\n- Stars, `unit_price: \"0.015960\"`, 100 звёзд: `1.596` → `1.60`.\n- Steam (₽), `unit_price: \"0.011560\"`, пополнение на 1000 ₽: `11.560` → `11.56`.\n\nЧтобы посчитать точно, работайте в целых числах: `unit_price` в миллионных долях × `quantity`, затем `(x + 5000) / 10000` с отбрасыванием дробной части — это центы.\n\n**Цены меняются.** Курс обновляется примерно раз в 30 минут, цены поставщиков сверяются каждый час. Поэтому:\n- обновляйте каталог раз в 15–60 минут (с `If-None-Match`, раздел «Товары»);\n- передавайте в заказе обязательный `max_total_usd` — сумму, которую видел покупатель. Если цена выросла, заказ не создастся (`409 price_changed`) и деньги не спишутся. Если снизилась — спишется меньшая, текущая сумма.\n\n### Курс\n\n`GET /v1/rate` показывает, сколько рублей стоит 1 $. Он нужен, только если вы продаёте за рубли и хотите ориентироваться на наш курс. Если курс не обновлялся больше 120 минут, он помечается `fresh: false`. Пока курс устаревший:\n- каталог и товары работают, цены в них посчитаны по последнему известному курсу;\n- `POST /v1/orders/quote` и `POST /v1/orders` отвечают `503 rate_unavailable` (`retryable: true`, `Retry-After: 300`);\n- `GET /v1/status` показывает `rate_fresh: false` и `orders_enabled: false`.\n\nЕсли курса нет совсем (такого не должно случаться), каталог, товары и `GET /v1/rate` тоже отвечают `503 rate_unavailable`.\n\n### Баланс\n\nЗаказы оплачиваются с **долларового баланса** реселлера (`GET /v1/balance`). Пополнить его можно в магазине Aviedo в разделе «Пополнить» ($): USDT TRC20 / BEP20 / TON или Bybit UID. Через API пополнить нельзя. Каждое списание, возврат и пополнение видно в `GET /v1/balance/history`.\n\n### Гарантии по деньгам\n\n1. **Один `external_id` — не больше одного заказа и одного списания.** Навсегда и даже при одновременных запросах.\n2. Заказ создаётся **атомарно**: запись заказа, списание и резерв товара — одна транзакция. Если заказа нет, деньги не списаны.\n3. `GET /v1/orders/external/{external_id}` с ответом `404` — **окончательное** доказательство, что заказа нет и деньги не списаны, но только когда исходный `POST /v1/orders` уже вернул любой ответ, кроме `5xx` и сетевой ошибки, или с его отправки прошло больше 60 секунд (подробно — в разделе «Создание заказа и идемпотентность»).\n4. Загруженный товар либо выдаётся сразу (`completed`), либо заказ не создаётся вовсе (`409 out_of_stock`). Ситуации «списали, а товара нет» не бывает.\n5. Возврат всегда **полный**: `refund.amount = price.total`, и он сразу зачисляется на долларовый баланс.\n6. `quote` ничего не списывает и не резервирует. Тестовые заказы баланс не трогают.\n\n## Товары: автоматические, загруженные, ручные\n\nКаталог устроен как витрина магазина: **разделы** (игры и сервисы) → **категории** → **товары**. Внутри категории товары могут быть разбиты на **группы** (например, «Гемы» и «Боевой пропуск»).\n\n### Виды товаров (`kind`) и подтипы (`type`)\n\n| `kind` | `type` | Что это | `result` — что получит покупатель |\n|---|---|---|---|\n| `auto` | `game_topup` | пополнение игрового аккаунта по ID игрока | `topup` — зачисление, показывать нечего |\n| `auto` | `gift_card` | подарочная карта | `code` — код карты |\n| `auto` | `voucher` | ваучер или код | `code` |\n| `auto` | `telegram_stars` | звёзды Telegram на username | `topup` |\n| `auto` | `telegram_premium` | Telegram Premium на 3, 6 или 12 месяцев | `topup` |\n| `auto` | `telegram_gift` | подарок Telegram | `topup` |\n| `auto` | `steam_topup` | пополнение кошелька Steam (RUB, UAH, KZT) | `topup` |\n| `auto` | `robux` | Robux. **Нужно действие покупателя** (см. ниже) | `topup` |\n| `auto` | `spotify` | Spotify Premium | `link` — ссылка |\n| `uploaded` | `digital_item` | ключ, аккаунт или подписка, загруженные заранее | `item` — строка с ключом или `логин:пароль` |\n| `manual` | `manual` | ручное выполнение по данным, которые передал покупатель | `service` — работу выполнит продавец |\n| `manual` | `manual_login` | вход через Supercell ID по коду из почты (Brawl Stars, Clash Royale, Clash of Clans, Hay Day) | `service` |\n\nСписок подтипов может расширяться. Незнакомый `type` обрабатывайте по `kind`, а что показывать покупателю — по `result`.\n\nСразу после создания заказ находится в статусе:\n- `uploaded` — сразу `completed`, ключи уже в `delivery.items` ответа;\n- `auto` — `processing` (Robux через несколько секунд перейдёт в `action_required`);\n- `manual` — `pending` (ждёт, пока продавец возьмёт заказ).\n\n### Количество (`quantity`)\n\n| Товар | Что означает `quantity` | Диапазон |\n|---|---|---|\n| `digital_item` | число штук | `1 … min(остаток, лимит на заказ)` (лимит — `GET /v1/me` → `limits.uploaded_max_per_order`) |\n| `gift_card`, `voucher` | число кодов | `min … min(остаток, максимум поставщика, 10)` |\n| `telegram_stars` | число звёзд | `quantity.min … quantity.max` |\n| `steam_topup` | сумма пополнения в валюте кошелька (`price.unit`) | `quantity.min … quantity.max`, целое; минимум поставщика уже учтён в `min` |\n| все остальные | всегда `1` | `1 … 1` |\n\n- `min` и `max` зависят от остатка и лимитов поставщика — **не хардкодьте их**. `max: null` — верхней границы нет (технический предел — 1 000 000 000).\n- Количество вне диапазона отклоняется с `422 quantity_out_of_range` (в `details` — `min`, `max`, `step`; `max` — действующая верхняя граница, при `quantity.max: null` — 1 000 000 000). **Молча подрезать количество мы не будем.**\n- Если у товара `min = max = 1`, поле `quantity` можно не передавать. Иначе оно обязательно.\n- `quantity.label` — готовая подпись для поля ввода («Количество звёзд», «Сумма пополнения, RUB»).\n\n### Наличие и доступность\n\n| Поле | Смысл |\n|---|---|\n| `available` | можно ли купить прямо сейчас |\n| `unavailable_reason` | если `available: false`: `out_of_stock` (закончился), `hidden` (временно скрыт), `expired` (истёк срок временного товара) |\n| `available_until` | у временных товаров — момент, когда товар исчезнет; иначе `null` |\n| `stock.in_stock` | есть ли товар в наличии |\n| `stock.count` | точный или примерный остаток в штуках. `null` — без ограничений или неизвестно (пополнения, Stars, Premium, ручные товары) |\n| `stock.checked_at` | когда остаток в последний раз сверяли с поставщиком (подарочные карты и ваучеры) |\n| `eta` | ориентир по срокам, готовый текст для покупателя |\n| `requires.chat` | ручной товар: продавец может написать в чат заказа (раздел «Чат») |\n| `requires.end_user_action` | после оплаты покупатель должен открыть ссылку и подтвердить вход (Roblox) |\n| `requires.email_code` | перед заказом нужно отправить код на почту покупателя (Supercell ID) |\n\n### Как синхронизировать каталог\n\n| Метод | Когда | Особенности |\n|---|---|---|\n| `GET /v1/catalog` | раз в 15–60 минут | весь каталог деревом: ~800 товаров, ответ ~1,2 МБ (≈80 КБ в gzip). С `If-None-Match` придёт `304` без тела. Лимит **6 запросов в минуту** (304 тоже считаются) |\n| `GET /v1/products?ids=…` | перед показом конкретных товаров | до 200 ID через запятую, возвращает **даже скрытые** товары с `available: false`; удалённые ID — в `meta.not_found`. Без `ids` метод отдаёт плоский список и считается в тот же лимит 6/мин, что и каталог |\n| `GET /v1/products/{id}` | на странице товара, перед заказом | самые свежие цена и наличие: остаток подарочных карт и ваучеров уточняется у поставщика (кэш до 2 минут) |\n\nВ каталог не попадают скрытые, удалённые и истёкшие товары, а также пустые разделы и категории. Закончившиеся товары остаются с `available: false` и `unavailable_reason: \"out_of_stock\"` — как значок «нет в наличии» в магазине. Разделы идут как на витрине: сначала игры, потом сервисы, внутри — по алфавиту. Названия отдаются как на витрине, поэтому в них встречаются эмодзи.\n\n**ETag.** Сохраните заголовок `ETag` из ответа и передавайте его в `If-None-Match` **как есть** (вместе с `W/` и кавычками, если они есть). Подпись для такого запроса всё равно нужна. ETag меняется при каждом обновлении курса (примерно раз в 30 минут) и при любой правке каталога.\n\n### Roblox: действие покупателя\n\nУ товаров с `requires.end_user_action: true` после оплаты заказ переходит в `action_required`:\n\n```json\n\"status\": \"action_required\",\n\"action\": {\n  \"type\": \"open_url\",\n  \"url\": \"https://…/verify/…\",\n  \"expires_at\": \"2026-10-12T23:30:00+03:00\",\n  \"hint\": \"Откройте ссылку, войдите в аккаунт Roblox и подтвердите вход (2FA). После этого Robux будут зачислены автоматически.\"\n}\n```\n\n**Сразу** передайте ссылку и подсказку покупателю: время на подтверждение ограничено (около 30 минут). `expires_at` заполняется, если поставщик сообщил срок действия ссылки, иначе `null`. Если покупатель не успел, поддержка выдаст новую ссылку (придёт новое событие `order.action_required` с новым `url`) или вернёт деньги (`order.refunded`).\n\nКогда покупатель подтвердил вход и поставщик начал зачисление, заказ **возвращается в `processing`** (`action` снова `null`), приходит `order.processing`, а затем `order.completed`. Если сигнал от поставщика задержался, заказ может перейти из `action_required` сразу в `completed` — это нормально. Если Robux зачислены не полностью, выпускается ссылка на довыдачу остатка без повторного списания: заказ снова переходит в `action_required` с новым `url`.\n\n### Supercell ID: вход по коду из почты\n\nУ товаров с `requires.email_code: true` (`type: manual_login`) порядок такой:\n\n1. Покупатель вводит у вас почту своего Supercell ID.\n2. Вы вызываете `POST /v1/products/{id}/send-code` с телом `{\"email\": \"player@example.com\"}` — Supercell отправит покупателю письмо с кодом.\n3. Покупатель вводит код из письма.\n4. **Сразу** создайте заказ с `\"fields\": {\"email\": \"player@example.com\", \"code\": \"123456\"}` — код живёт недолго.\n\nОтправлять код на одну почту можно не чаще раза в 60 секунд и не больше 10 раз за 24 часа (лимит общий для всех реселлеров), подробности — в описании метода `send-code`.\n\n## Поля заказа\n\nЧто передать в заказе, описано в массиве `fields` товара. В самом заказе поля передаются **одним объектом «ключ → строка»**:\n\n```json\n\"fields\": { \"telegram_username\": \"durov\" }\n```\n\n### Описание поля\n\n| Свойство | Смысл |\n|---|---|\n| `key` | ключ в объекте `fields`. Стабилен: не меняется при редактировании товара |\n| `label` | подпись для покупателя (на русском) |\n| `type` | тип поля, см. ниже |\n| `required` | без обязательного поля заказ отклоняется |\n| `min_length`, `max_length` | ограничения длины строки или `null` |\n| `pattern` | регулярное выражение, совместимое с PCRE и JS, или `null` |\n| `options` | для `select`: `[{\"value\", \"label\"}]`. Передавать нужно **`value`** |\n| `hint` | подсказка для покупателя или `null` |\n| `sensitive` | `true` у паролей. В ответах такое значение маскируется как `\"••••••\"` |\n\n`fields_version` у товара меняется при любом изменении набора полей. Перестраивайте форму, когда значение изменилось.\n\n### Типы полей\n\n| `type` | Что передавать | Как мы проверяем |\n|---|---|---|\n| `text` | строку | длина, `pattern`, если он указан |\n| `password` | строку | длина. Хранится в зашифрованном виде, в ответах маскируется |\n| `email` | e-mail | формат e-mail, до 254 символов |\n| `select` | одно из `options[].value` | только значения из списка. **Значение по умолчанию мы не подставляем** |\n| `telegram_username` | username: можно с `@`, как `t.me/name` или `https://t.me/name` | после очистки `^[A-Za-z0-9_]{3,32}$` |\n| `ipv4` | IPv4-адрес **вашего покупателя**, а не вашего сервера | формат IPv4 |\n\nСписок типов может расширяться (например, `number` — целое число строкой). Незнакомый тип показывайте как обычное текстовое поле.\n\n### Правила\n\n- Значения передаются строками; целые числа тоже принимаются и превращаются в строку без потери цифр (`500` → `\"500\"`, длинные ID сохраняются точно). Дробные числа и запись вида `1e20` не принимаются — ID и номера надёжнее всегда передавать строкой. Другой тип значения (`true`, `1.5`, `1e20`, массив, объект) — `400 invalid_request`, имя параметра в `details.param` (например, `\"fields.player_id\"`). `fields: null` и `fields: {}` считаются «полей нет».\n- Пробелы в начале и в конце обрезаются. Обязательное поле не может быть пустым.\n- Неизвестный ключ в `fields` даёт ошибку `unknown_field` (в ней же — список допустимых ключей), поэтому опечатки не проходят молча.\n- Все ошибки полей приходят **разом** одним ответом `422 validation_failed`:\n\n```json\n\"details\": {\n  \"errors\": [\n    { \"field\": \"fields.colour\", \"code\": \"unknown_field\", \"message\": \"У товара нет такого поля\", \"allowed\": [\"telegram_username\"] },\n    { \"field\": \"fields.telegram_username\", \"code\": \"invalid_format\", \"message\": \"Только латиница, цифры и _, 3–32 символа\" }\n  ]\n}\n```\n\nВозможные `errors[].code`: `required`, `too_long`, `too_short`, `invalid_format`, `invalid_option` (с `allowed`), `out_of_range`, `unknown_field` (с `allowed`).\n\n### Типовые ключи\n\n| Товары | Ключи |\n|---|---|\n| Telegram Stars, Premium | `telegram_username` |\n| Telegram-подарки | `telegram_username`, `comment` (необязательно, до 200 символов) |\n| Steam | `steam_login` (до 64 символов) |\n| Roblox | `roblox_username` (до 64), `roblox_password` (необязательно, `sensitive`) |\n| Пополнение игр | ключи поставщика, например `player_id`, `user_id`, `server_id`, `zone_id`, `region_id`. Берите их из `fields` конкретного товара |\n| Товары, где поставщику нужен IP покупателя | `end_user_ip` (`ipv4`) |\n| Spotify | `email`, `password` |\n| Supercell ID (`manual_login`) | `email`, `code`, `comment` |\n| Ручные товары | поля формы категории (например, `privyazannaya_pochta`, `parol`) и всегда необязательный `comment` (до 1000 символов) для пожеланий покупателя |\n\nПример описания поля-списка:\n\n```json\n{ \"key\": \"region\", \"label\": \"Регион\", \"type\": \"select\", \"required\": true, \"min_length\": null, \"max_length\": null, \"pattern\": null, \"options\": [ { \"value\": \"Europe\", \"label\": \"Europe\" }, { \"value\": \"Asia\", \"label\": \"Asia\" } ], \"hint\": null, \"sensitive\": false }\n```\n\nКлючи полей ручных товаров получены транслитерацией подписи (`Привязанная почта` → `privyazannaya_pochta`) и дальше не меняются, даже если подпись отредактируют.\n\n## Создание заказа и идемпотентность\n\nЗаказ создаётся и оплачивается **одним запросом** `POST /v1/orders`:\n\n```json\n{\n  \"product_id\": 853,\n  \"quantity\": 1,\n  \"external_id\": \"shop-1001\",\n  \"max_total_usd\": \"12.67\",\n  \"fields\": { \"telegram_username\": \"durov\" },\n  \"meta\": { \"customer\": \"client-42\" }\n}\n```\n\n| Поле | Обязательно | Смысл |\n|---|---|---|\n| `product_id` | да | ID товара |\n| `quantity` | если `quantity.max` у товара больше 1 | количество (раздел «Товары») |\n| `external_id` | **да** | ваш номер заказа: 1–64 символа `[A-Za-z0-9_.:-]`, уникальный навсегда в пределах вашего аккаунта |\n| `max_total_usd` | **да** | наибольшая сумма, которую вы согласны заплатить: строка `\"12.67\"` (число `12.67` тоже принимается). Если текущая сумма выше — `409 price_changed`, если ниже — спишется текущая |\n| `fields` | если у товара есть обязательные поля | раздел «Поля заказа» |\n| `meta` | нет | до 10 пар «строка → строка» (ключ до 40 символов, значение до 200). Возвращаются как есть в заказе, событиях и вебхуках |\n| `accept_chat` | для ручных товаров без вебхука | раздел «Чат» |\n| `test` | нет | `true` — тестовый заказ (раздел «Тестовый режим») |\n| `test_scenario` | нет | сценарий теста, только вместе с `\"test\": true` |\n\nПеред покупкой можно вызвать `POST /v1/orders/quote` с тем же телом: он проверит поля, количество, наличие, баланс и (для Telegram Premium) получателя, ничего не списывая. Всё, из-за чего `POST /v1/orders` вернул бы ошибку, `quote` перечисляет в `problems` с теми же кодами и `details` — в том числе незаполненные обязательные поля (`validation_failed`, `code: \"required\"`) и не переданное `quantity` (`quantity_out_of_range`). Если количество не прошло проверку, `quantity`, `total` и `balance_after` в ответе посчитаны для `quantity.min` — только для ориентира.\n\n### Порядок проверок\n\n1. Подпись и доступ, лимит запросов.\n2. Формат тела (`invalid_json`, `unknown_parameter`, `invalid_request`).\n3. **Поиск `external_id`.** Если такой заказ уже есть, сразу возвращается он (`200`, `meta.idempotent_replay: true`) или `409 external_id_conflict`. Повтор работает, даже если цена уже изменилась, товар закончился или идут технические работы.\n4. Технические работы и свежесть курса (`503 maintenance`, `503 rate_unavailable`).\n5. Товар и его доступность (`404 product_not_found`, `409 product_unavailable`).\n6. Для ручных товаров — вебхук или `accept_chat` (`422 chat_required`).\n7. Поля (`422 validation_failed`).\n8. Количество и наличие (`422 quantity_out_of_range`, `409 out_of_stock`).\n9. Цена против `max_total_usd` (`409 price_changed`).\n10. Для Telegram Premium — синхронная проверка получателя у поставщика (`422 account_not_found`, `503 provider_unavailable`).\n11. Баланс (`402 insufficient_funds`).\n12. Создание: заказ, списание и резерв в одной транзакции → `201 Created`.\n\n### Золотые правила\n\n1. **Сгенерируйте `external_id` до первого запроса и не меняйте его при повторах.** Удобнее всего взять номер заказа в вашей системе.\n2. Если ответа нет (таймаут, обрыв), повторите **тот же** запрос: подпись и время пересчитайте, `external_id` и тело оставьте прежними.\n3. На повтор с теми же параметрами придёт `200` с тем же заказом в его текущем состоянии и `\"meta\": {\"idempotent_replay\": true}`. Второго списания не будет, даже если два запроса пришли одновременно.\n4. Если тот же `external_id` пришёл с **другими** `product_id`, `quantity` или `fields`, придёт `409 external_id_conflict` (в `details.order_id` — найденный заказ). Это защита от ошибки в вашем коде. `max_total_usd`, `meta` и `accept_chat` при сравнении не учитываются. Значения `fields` сравниваются в том виде, в каком вы их передали (обрезаются только пробелы по краям, порядок ключей не важен): `\"@durov\"` и `\"durov\"` — **разные** запросы, а `500` и `\"500\"` — одинаковые. Не переданный `quantity` равен `1`.\n5. Повторяйте только при `retryable: true` или сетевой ошибке, не раньше чем через `retry_after` секунд. На `4xx` с `retryable: false` повтор ничего не изменит.\n6. Если неясно, создан ли заказ, вызовите `GET /v1/orders/external/{external_id}`. Ответ `404` означает, что заказ **точно не создан**, если исходный `POST` уже вернул любой ответ, кроме `5xx` и сетевой ошибки, или с его отправки прошло больше 60 секунд. Раньше этого срока `404` значит лишь «ещё не сохранён»: подождите и проверьте снова или повторите тот же `POST`.\n7. Таймаут на своей стороне ставьте **не меньше 45 секунд**. Создание обычно занимает меньше секунды, но для некоторых товаров мы синхронно проверяем получателя у поставщика.\n\nПочему 60 секунд — окончательный срок: сервер не сохраняет заказ позже чем через 30 секунд после того, как полностью получил запрос (время ожидания в очереди входит в эти 30 секунд). Не успел — создание отменяется с `503 server_busy`, деньги не списываются. Если запрос ждал в очереди больше 15 секунд, создание не начинается вовсе (тоже `503 server_busy`). Оставшиеся 30 секунд — запас на передачу по сети.\n\n### Что делать, если…\n\n| Ситуация | Что произошло | Что делать |\n|---|---|---|\n| Таймаут или обрыв сети при `POST /v1/orders` | неизвестно | повторить **тот же** запрос с тем же `external_id` (это безопасно) или проверить `GET /v1/orders/external/{id}`; его `404` окончателен, только если с отправки прошло больше 60 секунд |\n| `5xx` на `POST /v1/orders` | неизвестно | то же, что при таймауте |\n| `4xx`, кроме `409 external_id_conflict` | заказ **не** создан, деньги не списаны | исправить запрос или условие |\n| `409 external_id_conflict` | с этим номером уже есть **другой** заказ | найти ошибку в своём коде; заказ из `details.order_id` — ваш |\n| `409 price_changed` | не создан | обновить цену, подтвердить её у покупателя и повторить с тем же `external_id` и новым `max_total_usd` |\n| `402 insufficient_funds` | не создан | пополнить баланс и повторить с тем же `external_id` |\n| `503 rate_unavailable` / `maintenance` / `server_busy` | не создан | повторить позже с тем же `external_id` |\n| Заказ в `processing` с `delayed: true` | у поставщика сбой, поддержка уже разбирается | ничего не делать: заказ станет `completed` (после повторной отправки) или `refunded` |\n| Пришёл `refunded` | деньги **уже** на вашем балансе | вернуть деньги покупателю или купить заново с **новым** `external_id` |\n| `refunded` пришёл после `completed` | редкий случай: спор или брак, деньги возвращены | обработать как обычный возврат. `delivery` и `completed_at` в заказе станут `null` — выданные коды берите из сохранённого `order.completed` |\n\nГотовые функции «создать заказ с безопасными повторами» на PHP, Python и Node.js — в разделе «Примеры кода».\n\n### Отмена\n\nОтменить можно только **ручной** заказ, пока продавец его не взял (статус `pending`, `order.cancellable: true`): `POST /v1/orders/{id}/cancel` — мгновенный полный возврат на баланс. Автоматические заказы уходят поставщику в течение минуты, загруженные выдаются сразу — их отменить нельзя (`409 not_cancellable`). Для ручного заказа в работе напишите в чат заказа.\n\n## Статусы заказа\n\nСтатусов всего пять:\n\n| `status` | `status_text` | Что происходит | Что показать покупателю | Финальный? |\n|---|---|---|---|---|\n| `pending` | Ожидание продавца | ручной заказ ждёт, пока продавец возьмёт его в работу | «Заказ принят, ожидайте» | нет |\n| `processing` | В процессе | заказ выполняет поставщик (`auto`) или продавец (`manual`) | «Выполняется» | нет |\n| `action_required` | Требуется действие | покупатель должен открыть ссылку `action.url` | ссылку и подсказку `action.hint` | нет |\n| `completed` | Выполнен | готово, результат в `delivery` | `delivery.items`, инструкцию, фото | да* |\n| `refunded` | Возврат | деньги возвращены на ваш баланс, сумма в `refund.amount` | «Заказ отменён, деньги возвращены» | да |\n\n\\* В редком случае (спор, брак) поддержка может вернуть деньги и **после** выполнения: `completed` сменится на `refunded`. Обрабатывайте `order.refunded` в любой момент. После возврата `delivery` и `completed_at` в заказе снова `null`, поэтому сохраняйте `delivery.items` из `order.completed` у себя.\n\nТипичные пути:\n\n```\nuploaded:  POST → completed\nauto:      POST → processing → completed\n                            ↘ action_required → processing → completed      (Roblox)\n                            ↘ processing (delayed: true) → completed | refunded\nmanual:    POST → pending → processing → completed\n                        ↘ refunded       ↘ refunded\nлюбой:     completed → refunded                                               (спор, брак)\n```\n\n**`delayed`.** Если у автоматического заказа заминка у поставщика, он остаётся в `processing`, но получает `delayed: true` и приходит событие `order.delayed`. Поддержка уже разбирается: повторит отправку (заказ станет `completed`) или вернёт деньги (`refunded`). Делать ничего не нужно.\n\n**`refund.reason`** — почему вернули деньги:\n\n| `reason` | Когда |\n|---|---|\n| `cancelled_by_reseller` | вы отменили ручной заказ через `POST /v1/orders/{id}/cancel` |\n| `out_of_stock` | товар закончился у поставщика |\n| `supplier_failed` | поставщик окончательно не смог выполнить заказ |\n| `support_decision` | решение поддержки (в том числе после выполнения) |\n\n**`revision`** растёт при каждом изменении заказа. События могут прийти не по порядку, поэтому **сохраняйте заказ, только если его `revision` больше уже сохранённого**.\n\n- Незнакомый статус считайте `processing`.\n- Опрашивать один заказ имеет смысл не чаще раза в 15 секунд. Лучше принимать вебхуки или читать `GET /v1/events`.\n\n## Получение результата\n\nУзнать, что заказ изменился, можно тремя способами, от лучшего к худшему:\n\n1. **Вебхук** — мы отправляем POST на ваш URL при каждом событии (раздел «Вебхуки»).\n2. **Лента событий** `GET /v1/events?after_id=…` раз в 10–30 секунд — те же события, без публичного адреса у вас.\n3. **Опрос заказа** `GET /v1/orders/{id}` не чаще раза в 15 секунд — проще всего, но медленнее и тратит лимит.\n\nОбработка одинаковая: для любого события `order.*` берите `data.order` и сохраняйте его, если `revision` больше сохранённого.\n\n**Что лежит в `order.delivery`** (заполняется при `completed`):\n\n| Поле | Смысл |\n|---|---|\n| `items[]` | выданные значения по порядку: `{\"type\": \"code\", \"value\": \"…\"}` — код карты или ваучера, `item` — ключ или аккаунт (`логин:пароль`), `link` — ссылка. У пополнений (`result: topup`) массив пустой — подтверждением служит сам статус `completed` |\n| `instructions` | инструкция продавца для покупателя: `text` (простой текст с переносами `\\n`) и `html` (только теги `b i u s a code pre br`); `null`, если инструкции нет |\n| `attachments[]` | фото от продавца (подтверждение у ручных заказов): `{\"type\": \"photo\", \"url\", \"mime\"}`. **Скачайте их и храните у себя** — ссылки могут перестать работать |\n| `delivered_at` | когда заказ выполнен |\n\nПока заказ в `completed`, результат можно запрашивать через API в любое время и сколько угодно раз. **Сохраняйте `delivery.items` у себя, когда получаете `order.completed`:** если после выполнения деньги вернут (`refunded`), `delivery` и `completed_at` в заказе станут `null`. Коды и ключи также дублируются системным сообщением в чате заказа.\n\n## Чат заказа\n\nПо каждому заказу есть чат с продавцом. Для ручных товаров он **обязателен**: продавец может попросить код подтверждения, скриншот или уточнение, и без вашего ответа заказ не будет выполнен.\n\n### Условие для ручных товаров\n\nЕсли у товара `requires.chat: true` (все `kind: manual`), должно выполняться одно из двух:\n- у вас указан Webhook URL, **или**\n- в заказе передано `\"accept_chat\": true`. Этим вы подтверждаете, что ваша система читает `GET /v1/events` и отвечает продавцу.\n\nИначе заказ не создаётся: `422 chat_required`.\n\n### Как работать с чатом\n\n1. Приходит событие `message.created` (вебхуком или в `GET /v1/events`) с сообщением в `data.message`.\n2. Вы показываете сообщение покупателю или своему оператору.\n3. Ответ отправляете через `POST /v1/orders/{id}/messages` — текстом и/или фото.\n4. Прочитанное отмечаете через `POST /v1/orders/{id}/messages/read`.\n\n| `from` | Кто |\n|---|---|\n| `reseller` | вы (ваши сообщения событий `message.created` не создают) |\n| `support` | продавец или поддержка Aviedo |\n| `system` | служебные сообщения: выдача товара, «Заказ выполнен», возврат |\n\nНепрочитанными считаются сообщения от продавца и системные. Они видны в трёх местах: `order.chat.unread`, `GET /v1/me` → `unread_messages` (по боевым заказам) и фильтр `GET /v1/orders?has_unread=1`.\n\n### Правила сообщений\n\n- Текст — до 4000 символов. Управляющие символы удаляются, переносы строк сохраняются.\n- Фото — JPG, PNG или WEBP в base64 (`image.content_base64`, можно с префиксом `data:image/…;base64,`), до 5 МБ после декодирования, каждая сторона до 8000 px и не больше 16 мегапикселей. Картинка проверяется по содержимому и всегда **перекодируется**: уменьшается до 2560 px, поворачивается по EXIF, сохраняется как JPEG (PNG и WEBP — только с прозрачностью), метаданные удаляются. Поэтому `mime` и расширение ссылки могут отличаться от загруженного файла.\n- Дубли отсекаются **только** по `client_message_id` (1–64 символа `[A-Za-z0-9_.:-]`): повтор с тем же значением вернёт `200`, `meta.idempotent_replay: true` и уже созданное сообщение. Без `client_message_id` каждый запрос, в том числе повтор после таймаута, создаёт новое сообщение — передавайте его всегда.\n- Лимиты: 30 сообщений в минуту, из них с фото — 10; на заказ — 20 фото и 50 МБ; на аккаунт — 200 фото и 200 МБ за 24 часа.\n- Писать можно, пока `order.chat.can_write = true`: пока заказ не завершён и ещё 14 дней после выполнения или возврата. Позже — `409 chat_closed`.\n- Ссылки на фото ведут на `https://aviedo.net/chat-photo/…`. Скачивайте вложения и храните у себя.\n\n## Вебхуки\n\nКаждое изменение по вашим API-заказам становится **событием**. Получать события можно двумя способами с одинаковой обработкой:\n- **вебхук** — мы отправляем POST на ваш URL;\n- **опрос** — вы читаете `GET /v1/events?after_id=…` раз в 10–30 секунд.\n\nWebhook URL указывается в кабинете реселлера (**Настройки → Webhook**), один на все события. Требования к адресу:\n- только `https://`, без логина и пароля в ссылке и без части после `#`;\n- порт не указан (443) или указан ровно `443` либо `8443`;\n- имя хоста без точки в конце;\n- адрес ведёт в интернет: `localhost`, `*.local`, `*.internal`, частные, служебные и зарезервированные IP-диапазоны (в том числе IPv6) запрещены;\n- адреса Aviedo (`aviedo.net`, `*.aviedo.net` и имена, которые указывают на наш сервер) использовать нельзя.\n\nСсылка проверяется при сохранении и ещё раз перед каждой отправкой, включая все IP-адреса из DNS. Проверить вебхук можно методом `POST /v1/webhooks/test` — он сразу отправит событие `ping` и покажет результат.\n\n### Типы событий\n\n| `type` | Когда | `data` |\n|---|---|---|\n| `order.processing` | продавец взял ручной заказ; авто-заказ вернулся в работу после действия покупателя или повторной отправки | `{ \"order\": Order }` |\n| `order.action_required` | покупателю нужно открыть ссылку (в том числе выдана новая ссылка) | `{ \"order\": Order }` |\n| `order.delayed` | у авто-заказа заминка у поставщика (`delayed: true`) | `{ \"order\": Order }` |\n| `order.completed` | заказ выполнен, результат в `order.delivery` | `{ \"order\": Order }` |\n| `order.refunded` | деньги возвращены (в том числе после выполнения) | `{ \"order\": Order }` |\n| `message.created` | новое сообщение от продавца или системное | `{ \"order_id\", \"external_id\", \"message\": Message }` |\n| `ping` | тест из `POST /v1/webhooks/test` (только вебхуком, в ленте его нет) | `{}` |\n\nПроще всего так: **для любого `order.*` берите `data.order` и сохраняйте его по `order.id`, если `revision` больше сохранённого.** `order.delivery` из `order.completed` сохраняйте отдельно: после возврата (в том числе после выполнения) в заказе снова `delivery: null`. Тип события нужен, только если вы хотите реагировать на события по-разному. `order.completed` для загруженных товаров тоже приходит, хотя заказ уже был `completed` в ответе на создание. Отдельного события о создании заказа нет — заказ приходит в ответе `POST /v1/orders`.\n\n### Запрос от нас\n\n```\nPOST /aviedo/webhook HTTP/1.1\nHost: shop.example.com\nContent-Type: application/json\nUser-Agent: Aviedo-Webhooks/1.0\nX-Aviedo-Event: order.completed\nX-Aviedo-Event-Id: 1042\nX-Aviedo-Attempt: 1\nX-Aviedo-Signature: t=1791810000,v1=9368001464b1e7ef2e2dc6b735ed4e317f2d79b845e00db0dfee62486f87d70b\n\n{\"id\":1042,\"type\":\"order.completed\",\"created_at\":\"2026-10-12T16:00:00+03:00\",\"test\":false,\"data\":{\"order\":{…}}}\n```\n\nТело — объект Event: `id` (растёт), `type`, `created_at`, `test` (`true` у событий тестовых заказов) и `data`. `X-Aviedo-Attempt` — номер попытки доставки.\n\n### Требования к обработчику\n\n- Ответьте любым кодом `2xx` в течение **10 секунд**. Тело ответа не важно: мы читаем не больше 2 КБ и решаем по коду. Долгую обработку выносите в фон.\n- Редиректы **не выполняются**: URL должен отвечать напрямую (`3xx` — неудачная попытка).\n- Одно событие может прийти **больше одного раза**. Отбрасывайте повторы по полю `id` из **подписанного** тела. Заголовок `X-Aviedo-Event-Id` — удобная копия, но он не входит в подпись.\n- Порядок не гарантирован между заказами. События одного заказа отправляются по очереди (следующее ждёт, пока доставится или окончательно не доставится предыдущее), но всё равно ориентируйтесь на `order.revision`.\n- Храните заказы по `order.id`, а не только по `external_id`: у тестовых и боевых заказов свои пространства `external_id`, и номера могут совпасть.\n- В боевой интеграции игнорируйте события с `\"test\": true` и не выдавайте по ним настоящий товар. В ленте `GET /v1/events?test=0` тестовых событий нет.\n\n### Проверка подписи\n\n```\nv1 = hex( HMAC-SHA256( секретный_ключ, t + \".\" + сырое_тело ) )\n```\n\n1. Извлеките из заголовка `X-Aviedo-Signature` значение `t` и все значения `v1`.\n2. Отклоните запрос, если `|сейчас − t| > 300` секунд.\n3. Посчитайте HMAC от **сырого** тела запроса, без повторной сериализации JSON.\n4. Сравните результат с каждым `v1` функцией постоянного времени (`hash_equals`, `hmac.compare_digest`, `crypto.timingSafeEqual`). Запрос подлинный, если совпала хотя бы одна подпись.\n\nВ течение 24 часов после перевыпуска ключей в заголовке приходят две подписи: `t=…,v1=<новым ключом>,v1=<старым ключом>`. Тестовый вектор — в разделе «Авторизация и подпись». Готовые обработчики на PHP, Python и Node.js — в «Примерах кода».\n\n### Повторы и приостановка\n\nЕсли ответ не `2xx`, ответа нет за 10 секунд или произошла ошибка соединения, мы повторяем отправку через **1 мин, 5 мин, 30 мин, 2 ч, 6 ч и 24 ч** — всего 7 попыток примерно за 32 часа. Каждая попытка подписывается заново со свежим `t`. После неудачной попытки остальные события вашего аккаунта ждут около минуты, чтобы не заваливать упавший сервер.\n\nЕсли за 3 суток не было ни одного успешного ответа, отправка **приостанавливается**: `GET /v1/me` → `webhook.status: \"paused\"`, в кабинете у поля Webhook появляется отметка «(приостановлен)». Включить её снова можно повторным сохранением URL в кабинете или успешным `POST /v1/webhooks/test`.\n\nСобытия, созданные, пока вебхук не указан или приостановлен, **вебхуком не отправляются** — но все они есть в `GET /v1/events` (хранятся 30 дней). После восстановления заберите пропущенное оттуда.\n\n## Лимиты и пагинация\n\n### Лимиты\n\nОкно — календарная минута. Каждый запрос засчитывается в общий лимит и в лимит своего метода.\n\n| Что | Лимит | `details.bucket` |\n|---|---|---|\n| Все запросы с авторизацией | 120 в минуту на аккаунт | `all` |\n| `GET /v1/catalog` и `GET /v1/products` без `ids` | 6 в минуту (ответы `304` тоже считаются) | `catalog` |\n| `POST /v1/orders` | 30 в минуту | `orders` |\n| `POST /v1/orders/quote` | 60 в минуту | `quote` |\n| `POST /v1/orders/{id}/messages` | 30 в минуту, из них с фото — 10 | `chat`, `chat_photo` |\n| Фото в чатах | 200 фото и 200 МБ за 24 часа на аккаунт; 20 фото и 50 МБ на заказ | `chat_photo_day`, `chat_photo_bytes_day` |\n| `POST /v1/products/{id}/send-code` | 10 в минуту; одна отправка одновременно; 200 за 24 часа на аккаунт; на одну почту — раз в 60 секунд и 10 за 24 часа (для всех реселлеров) | `send_code`, `send_code_inflight`, `send_code_day` |\n| `POST /v1/webhooks/test` | 5 в минуту | `webhook_test` |\n| Загруженные товары в одном заказе | `GET /v1/me` → `limits.uploaded_max_per_order` штук | — |\n| С одного IP-адреса | 20 запросов в секунду (кратковременно до 40) | — |\n\nОстаток приходит в заголовках `X-RateLimit-Limit`, `X-RateLimit-Remaining` и `X-RateLimit-Reset` (unix-время начала следующей минуты). При превышении — `429 rate_limited` с `Retry-After`; в `details` — какая корзина (`bucket`), её `limit` и `reset`. Лимит по IP отвечает тем же кодом `rate_limited` с `Retry-After: 1` и без `details`.\n\nРекомендуемая частота:\n- каталог — раз в 15–60 минут с `If-None-Match`;\n- события — `GET /v1/events` раз в 10–30 секунд, если вебхука нет;\n- конкретный заказ — не чаще раза в 15 секунд.\n\nНужно больше — напишите в поддержку.\n\n### Пагинация\n\n| Где | Порядок | Как листать |\n|---|---|---|\n| `GET /v1/orders`, `GET /v1/balance/history` | от новых к старым | передавайте `cursor` = `pagination.next_cursor`, пока `has_more = true` |\n| `GET /v1/events`, `GET /v1/orders/{id}/messages` | от старых к новым | передавайте `after_id` = `pagination.next_after_id` |\n| `GET /v1/catalog`, `GET /v1/products` | — | без страниц, весь список сразу |\n\nКурсор — непрозрачная строка: передавайте её как есть и только в тот же список, из которого она получена (курсор боевого списка в тестовом даёт `400 invalid_request`). `next_after_id` всегда заполнен: если новых записей нет, он равен переданному `after_id`.\n\n## Тестовый режим\n\nПередайте `\"test\": true` в `POST /v1/orders` (и в `POST /v1/orders/quote`). Тестовый заказ:\n\n- **не списывает баланс**, не создаёт настоящий заказ, ничего не заказывает у поставщиков и не отправляется продавцам;\n- получает ID на `T` (`T` и 11 символов `[0-9A-F]`, например `T9145E3EB9AD`) и `\"test\": true` в заказе и во всех событиях;\n- проходит **те же проверки, что и настоящий, в том же порядке и с теми же ошибками**: подпись, формат тела, техработы, курс, товар и его доступность, `chat_required`, поля, количество, наличие, `max_total_usd`. Баланс проверяется (`402 insufficient_funds`), но не списывается. Существование получателя у поставщика не проверяется, а остаток подарочных карт и ваучеров и список серверов берутся из кэша, как в каталоге, — поставщику запросы не уходят. Поэтому изредка тестовый заказ пройдёт там, где боевой получит `409 out_of_stock`, и наоборот;\n- идемпотентен по `external_id` так же, как настоящий (`201`, затем `200` с `meta.idempotent_replay: true`, `409 external_id_conflict` при других параметрах), но в **своём пространстве** номеров: тестовый `external_id` не мешает боевому заказу с тем же номером. Для тестовых заказов при сравнении учитывается ещё `test_scenario`;\n- сам проходит статусы по выбранному сценарию и создаёт события в `GET /v1/events` и на ваш Webhook URL — с той же подписью и теми же повторами, что и боевые;\n- доступен через `GET /v1/orders/{id}`, `GET /v1/orders?test=1` и `GET /v1/orders/external/{external_id}?test=1`; работают отмена и чат;\n- не попадает в обычный список заказов, в статистику, в историю баланса и в счётчик `GET /v1/me` → `unread_messages`;\n- хранится 7 дней, затем удаляется вместе с перепиской и фото. События тестовых заказов живут в ленте 30 дней, как все события.\n\nЛимиты запросов у тестовых и боевых заказов общие.\n\n**Не смешивайте тестовые и боевые заказы.** Храните заказы по `order.id` (у тестовых он начинается с `T`), а не только по `external_id` — тестовый и боевой заказ могут иметь одинаковый `external_id`. В боевой интеграции игнорируйте события с `\"test\": true`; `GET /v1/events?test=0` отдаёт только события боевых заказов, `test=1` — только тестовых.\n\n### Сценарии\n\nСценарий выбирается полем `test_scenario` (только вместе с `\"test\": true`, иначе `400 invalid_request`). По умолчанию — `success`. Время примерное: сервер проверяет шаги каждые 2 секунды.\n\n| `test_scenario` | `kind = uploaded` | `kind = auto` | `kind = manual` |\n|---|---|---|---|\n| `success` | сразу `completed`, в `delivery.items` ключи `TEST-XXXX-XXXX-XXXX` (по одному на штуку) | `processing` → ~20 с `completed` | `pending` → ~30 с `processing` → ~30 с `completed` с тестовым фото |\n| `refund` | — | `processing` → ~20 с `refunded`, `reason: \"supplier_failed\"` | `pending` → ~30 с `refunded`, `reason: \"support_decision\"` |\n| `delay` | — | `processing` → ~15 с `order.delayed` (`delayed: true`) → ~45 с `completed` | — |\n| `action_required` | — | `processing` → ~10 с `action_required` со ссылкой-заглушкой → ~45 с снова `processing` → ~15 с `completed` | — |\n| `chat` | — | `processing` → ~10 с сообщение продавца «Тест: пришлите код» → **ваш ответ** через `POST /v1/orders/{id}/messages` → ~3 с ответ продавца → ~5 с `completed` | `pending` → ~30 с `processing` → ~3 с «Тест: пришлите код» → **ваш ответ** → ~3 с ответ продавца → ~5 с `completed` |\n| `completed_then_refunded` | сразу `completed` → ~30 с `refunded` (`support_decision`) | как `success`, затем ~30 с `refunded` (`support_decision`) | как `success`, затем ~30 с `refunded` (`support_decision`) |\n| `out_of_stock` | заказ не создаётся: `409 out_of_stock`, `details.available: 0` | так же | так же |\n| `account_not_found` | заказ не создаётся: `422 account_not_found`, в `details.field` — первое обязательное поле товара (`null`, если полей у товара нет) | так же | так же |\n\nПрочерк — сценарий для такого `kind` недоступен: `400 invalid_request` с `details.param = \"test_scenario\"` и списком допустимых сценариев в `details.allowed`. `quote` с `\"test\": true` проверяет то же, что обычный, а сценарии `out_of_stock` и `account_not_found` показывает в `problems`.\n\n### Что приходит в тестовом заказе\n\n- **Результат** той же формы, что у настоящего товара этого `type`: у пополнений `delivery.items` пустой, у `gift_card` и `voucher` — коды (`type: \"code\"`), у `digital_item` — ключи (`type: \"item\"`), у `spotify` — ссылка (`type: \"link\"`). Значения помечены: `TEST-XXXX-XXXX-XXXX` и `https://example.com/aviedo-test/…`. `delivery.instructions` — настоящая инструкция категории. Тестовое фото: `https://aviedo.net/image/api-test-photo.jpg`.\n- **Ссылка действия** (`action_required`): `https://example.com/aviedo-test/verify/TEST-…`, открывать её не нужно, `expires_at: null`.\n- **Сообщения** появляются на тех же шагах, что у боевого заказа, и приходят событием `message.created`: «Тест: заказ выполнен! 🤝» при выполнении (у ручных перед ним — сообщение продавца с тестовым фото), сообщение о возврате при `refunded`, у загруженных товаров — «Ваши товары: …» и инструкция категории.\n- **Отмена.** Тестовый ручной заказ в `pending` (первые ~30 секунд) отменяется так же, как боевой: `refunded`, `refund.reason: \"cancelled_by_reseller\"`, сценарий на этом останавливается.\n- **Чат.** Текст и фото принимаются с теми же правилами и лимитами. В сценарии `chat` заказ ждёт вашего ответа без ограничения по времени.\n\n### Что прогнать перед запуском\n\n| Проверка | Как |\n|---|---|\n| Подпись GET и POST | `GET /v1/me`, `GET /v1/orders?test=1&limit=1`, `POST /v1/orders/quote` |\n| Загруженный товар сразу в ответе | `success` на товаре `kind: uploaded`, `quantity: 2` |\n| Авто-заказ доходит до результата | `success` на `kind: auto` — ждёте `order.completed` |\n| Возврат | `refund` — ждёте `order.refunded`, показываете покупателю |\n| Заминка у поставщика | `delay` — `order.delayed`, затем `order.completed` |\n| Ссылка для покупателя | `action_required` — показываете `action.url` и `action.hint` |\n| Чат | `chat` на ручном товаре с `accept_chat: true` — отвечаете продавцу |\n| Возврат после выполнения | `completed_then_refunded` |\n| Ошибки создания | `out_of_stock`, `account_not_found`, слишком маленький `max_total_usd` |\n| Повтор запроса | тот же `POST` ещё раз — `200` и `idempotent_replay: true` |\n| Отмена | ручной заказ `success` → сразу `POST /v1/orders/{id}/cancel` |\n\n## Ошибки\n\nОшибка всегда приходит в одном формате: `ok: false` и объект `error` с полями `code`, `message`, `retryable`, `retry_after`, `details`. Решения принимайте по `code` и `retryable`.\n\n**Создан ли заказ?** Любой ответ `4xx` на `POST /v1/orders`, кроме `409 external_id_conflict`, означает: заказ **не создан**, деньги **не списаны**. При `5xx` и сетевой ошибке результат неизвестен — повторите тот же запрос с тем же `external_id` (раздел «Создание заказа и идемпотентность»).\n\n| `code` | HTTP | Повтор | Когда | Что делать |\n|---|---|---|---|---|\n| `invalid_json` | 400 | нет | тело не является JSON-объектом | исправить сериализацию |\n| `invalid_request` | 400 | нет | неверный тип или значение параметра; имя — в `details.param`. Также: значение в `fields` не строка и не целое число или `fields` не объект, неверный курсор, сценарий теста не подходит товару (`details.allowed`), товару не нужен код Supercell (`details.reason = \"email_code_not_required\"`), у заказа уже 20 фото или 50 МБ фото | исправить запрос |\n| `unknown_parameter` | 400 | нет | неизвестный параметр в теле или в query-строке; имя в `details.param`, допустимые — в `details.allowed` | исправить имя (часто опечатка) |\n| `missing_credentials` | 401 | нет | нет одного из трёх заголовков авторизации; каких — в `details.missing` и в `message` | добавить заголовки |\n| `unauthorized` | 401 | нет | токен неизвестен, отозван или старый токен после 24 часов с перевыпуска | взять действующий токен в кабинете |\n| `invalid_signature` | 401 | нет | подпись не совпала; подсказки в `details` | раздел «Авторизация и подпись» |\n| `timestamp_out_of_window` | 401 | нет | часы расходятся с нашими больше чем на 300 с (`details.server_time`) | синхронизировать часы (NTP) |\n| `insufficient_funds` | 402 | нет | баланса меньше суммы заказа: `details.required`, `balance`, `missing` | пополнить баланс и повторить с тем же `external_id` |\n| `https_required` | 403 | нет | запрос пришёл по `http://` | использовать `https://` |\n| `reseller_not_approved` | 403 | нет | статус реселлера не «одобрен» | написать в поддержку |\n| `account_banned` | 403 | нет | аккаунт заблокирован | написать в поддержку |\n| `not_found` | 404 | нет | неизвестный путь (в том числе с `/` в конце) | проверить URL |\n| `product_not_found` | 404 | нет | товар удалён или не существовал | убрать товар у себя |\n| `order_not_found` | 404 | нет | такого заказа у вас нет | для `/orders/external/…` — «заказ не создан» (с оговоркой про 60 секунд) |\n| `method_not_allowed` | 405 | нет | неверный HTTP-метод; допустимые — в `details.allowed` и заголовке `Allow` | — |\n| `product_unavailable` | 409 | нет | товар временно скрыт или его срок истёк; `details.reason`: `hidden` или `expired` | скрыть у себя и проверить позже |\n| `out_of_stock` | 409 | нет | товара не хватает; `details.available` — сколько есть | уменьшить количество или подождать |\n| `price_changed` | 409 | нет | текущая сумма выше вашего `max_total_usd`; новая — в `details.total` | показать новую цену покупателю и повторить с тем же `external_id` |\n| `external_id_conflict` | 409 | нет | этот `external_id` уже использован с **другими** параметрами; заказ — в `details.order_id` | найти ошибку в коде, взять новый `external_id` |\n| `not_cancellable` | 409 | нет | заказ уже нельзя отменить (`details.status`) | написать в чат заказа |\n| `chat_closed` | 409 | нет | переписка закрыта (прошло 14 дней после завершения заказа) | — |\n| `payload_too_large` | 413 | нет | тело больше 8 МБ (`details.max_bytes`) или картинка больше 5 МБ | уменьшить |\n| `unsupported_media_type` | 415 | нет | у POST нет `Content-Type: application/json` | добавить заголовок |\n| `validation_failed` | 422 | нет | ошибки в полях заказа, в `email` для send-code или в картинке; список — в `details.errors[]` | исправить данные покупателя |\n| `quantity_out_of_range` | 422 | нет | количество не передано или вне `min..max`; в `details` — `min`, `max` (действующая граница, не больше 1 000 000 000), `step` | исправить количество |\n| `account_not_found` | 422 | нет | получатель не найден у поставщика (Telegram Premium); поле — в `details.field` (`null`, если у товара нет полей) | проверить данные покупателя |\n| `chat_required` | 422 | нет | ручной товар, а у вас нет вебхука и не передан `accept_chat: true` | раздел «Чат» |\n| `rate_limited` | 429 | да | превышен лимит; какой — в `details.bucket` | ждать `retry_after` |\n| `send_code_cooldown` | 429 | да | на эту почту уже отправляли код (`details.reason`: `cooldown`, `email_daily_limit`, `provider_throttled`) | ждать `retry_after` |\n| `internal_error` | 500 | да | ошибка на нашей стороне | повторить; заказ — **с тем же** `external_id` |\n| `rate_unavailable` | 503 | да | курс доллара устарел, заказы временно не принимаются | повторить позже, следить за `GET /v1/status` |\n| `maintenance` | 503 | да | идут технические работы | повторить позже |\n| `provider_unavailable` | 503 | да | поставщик или сервис проверки временно недоступен | повторить позже |\n| `server_busy` | 503 | да | создание заказа не успело завершиться за 30 секунд или запрос ждал в очереди больше 15 секунд; заказ не создан | повторить **тот же** запрос с тем же `external_id` |\n| `insufficient_storage` | 507 | да | на сервере временно мало места для файлов, фото в чат не принимаются (текст принимается) | повторить позже или написать текстом |\n\nОшибки уровня сети и прокси приходят в том же JSON-формате: превышение лимита запросов с одного IP — `429 rate_limited` (`Retry-After: 1`), повреждённый HTTP-запрос — `400 invalid_request`, тело больше 10 МБ — `413 payload_too_large`, сбой шлюза — `500 internal_error` (`retry_after: 5`), запрос по `http://` — `403 https_required`, путь вне `/v1/` — `404 not_found`. Эти ответы формирует прокси (nginx), поэтому в них нет заголовка `X-Aviedo-Server-Time` и заголовков лимитов.\n\n**Коды в `quote`.** `POST /v1/orders/quote` не отвечает ошибкой на причины, по которым заказ нельзя оформить, — они приходят списком `data.problems[]` с теми же кодами и `details`, что у `POST /v1/orders` с этим телом (в том числе незаполненные обязательные поля и не переданное `quantity`): `product_unavailable`, `chat_required`, `validation_failed`, `quantity_out_of_range`, `out_of_stock`, `account_not_found`, `provider_unavailable`, `insufficient_funds`, `price_changed`.\n\n**Ошибки доставки в `POST /v1/webhooks/test`** (поле `data.error`, ответ при этом `200`):\n\n| `error` | Когда |\n|---|---|\n| `webhook_not_configured` | Webhook URL не указан |\n| `invalid_url` | ссылка не прошла проверку: не `https://`, логин или пароль в ссылке, часть после `#`, порт не 443 и не 8443, точка в конце имени, `localhost`, `*.local`, `*.internal`, IP-адрес из запрещённого диапазона прямо в ссылке, адрес Aviedo |\n| `address_not_allowed` | имя хоста по DNS указывает на частный, служебный или зарезервированный IP или на сервер Aviedo |\n| `dns_error` | имя хоста не найдено |\n| `connection_failed` | не удалось подключиться |\n| `tls_error` | ошибка TLS (сертификат, имя) |\n| `timeout` | нет ответа за 10 секунд |\n| `redirect_not_followed` | ответ `3xx` |\n| `http_error` | ответ не `2xx` |\n| `request_failed` | другая ошибка соединения |\n\n`port_not_allowed` зарезервирован и сейчас не возвращается: недопустимый порт даёт `invalid_url`.\n\n## Примеры кода\n\nВсе примеры ниже — полные рабочие файлы. Каждый из них запущен на боевом API в тестовом режиме: клиенты создали тестовые заказы и дождались `completed`, повторный запрос вернул тот же заказ с `idempotent_replay: true`, обработчики вебхуков приняли настоящие подписанные события (в том числе в обратном порядке и с двумя подписями после перевыпуска ключей) и отклонили подделанные. Ключи берутся из переменных окружения `AVIEDO_TOKEN` и `AVIEDO_SECRET`.\n\nЧто в них есть:\n- **клиент** с подписью запросов — методы `get` и `post` возвращают разобранный ответ API, сетевые сбои превращаются в ошибку `network_error` с `retryable: true`;\n- **создание заказа с безопасными повторами** — `createOrder` повторяет запрос с тем же `external_id` при `retryable: true` и сетевых сбоях, а в конце проверяет заказ через `GET /v1/orders/external/{id}`;\n- **покупка** — проверка ключа, `quote`, создание тестового заказа и ожидание результата;\n- **приём вебхука** — проверка подписи и времени, отбрасывание повторов по `event.id`, сохранение заказа по `order.id` только с большим `revision` и отдельное сохранение `delivery` (после возврата его в заказе уже нет).\n\n### PHP 8.0+ (cURL)\n\n`AviedoClient.php`:\n\n```php\n<?php\ndeclare(strict_types=1);\n\nfinal class AviedoClient\n{\n    public function __construct(\n        private string $token,\n        private string $secret,\n        private string $base = 'https://api.aviedo.net',\n        private int $timeout = 45,\n    ) {\n    }\n\n    public function get(string $path, array $query = []): array\n    {\n        if ($query) {\n            $path .= '?' . http_build_query($query, '', '&', PHP_QUERY_RFC3986);\n        }\n        return $this->request('GET', $path, '');\n    }\n\n    public function post(string $path, array $data = []): array\n    {\n        $body = json_encode($data ?: new stdClass(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR);\n        return $this->request('POST', $path, $body);\n    }\n\n    public function request(string $method, string $path, string $body): array\n    {\n        $ts = (string) time();\n        $signature = hash_hmac('sha256', $ts . \"\\n\" . $method . \"\\n\" . $path . \"\\n\" . $body, $this->secret);\n        $headers = [\n            'Authorization: Bearer ' . $this->token,\n            'X-Aviedo-Timestamp: ' . $ts,\n            'X-Aviedo-Signature: ' . $signature,\n            'Accept: application/json',\n        ];\n        $options = [\n            CURLOPT_CUSTOMREQUEST  => $method,\n            CURLOPT_RETURNTRANSFER => true,\n            CURLOPT_FOLLOWLOCATION => false,\n            CURLOPT_CONNECTTIMEOUT => 10,\n            CURLOPT_TIMEOUT        => $this->timeout,\n            CURLOPT_ENCODING       => '',\n        ];\n        if ($method !== 'GET') {\n            $headers[] = 'Content-Type: application/json';\n            $options[CURLOPT_POSTFIELDS] = $body;\n        }\n        $options[CURLOPT_HTTPHEADER] = $headers;\n\n        $ch = curl_init($this->base . $path);\n        curl_setopt_array($ch, $options);\n        $raw = curl_exec($ch);\n        $status = (int) curl_getinfo($ch, CURLINFO_RESPONSE_CODE);\n        $error = curl_error($ch);\n\n        if ($raw === false) {\n            return self::failure('network_error', $error, true, 0);\n        }\n        $json = json_decode($raw, true);\n        if (!is_array($json) || !isset($json['ok'])) {\n            return self::failure('bad_response', 'HTTP ' . $status, $status >= 500, $status);\n        }\n        $json['http_status'] = $status;\n        return $json;\n    }\n\n    public function createOrder(array $order, int $attempts = 5): array\n    {\n        $last = null;\n        for ($i = 1; $i <= $attempts; $i++) {\n            $res = $this->post('/v1/orders', $order);\n            if ($res['ok'] || empty($res['error']['retryable'])) {\n                return $res;\n            }\n            $last = $res;\n            if ($i < $attempts) {\n                sleep(max((int) ($res['error']['retry_after'] ?? 0), 2 ** $i));\n            }\n        }\n        $query = empty($order['test']) ? [] : ['test' => 1];\n        $found = $this->get('/v1/orders/external/' . rawurlencode($order['external_id']), $query);\n        return $found['ok'] ? $found : $last;\n    }\n\n    private static function failure(string $code, string $message, bool $retryable, int $status): array\n    {\n        return [\n            'ok'          => false,\n            'http_status' => $status,\n            'error'       => ['code' => $code, 'message' => $message, 'retryable' => $retryable, 'retry_after' => null, 'details' => null],\n        ];\n    }\n}\n```\n\n`buy.php` — проверка ключа, покупка и ожидание результата:\n\n```php\n<?php\ndeclare(strict_types=1);\n\nrequire __DIR__ . '/AviedoClient.php';\n\n$api = new AviedoClient(getenv('AVIEDO_TOKEN') ?: 'rsl_ВАШ_ТОКЕН', getenv('AVIEDO_SECRET') ?: 'ВАШ_SECRET');\n\n$me = $api->get('/v1/me');\nif (!$me['ok']) {\n    exit('Ключ не работает: ' . $me['error']['code'] . ' — ' . $me['error']['message'] . PHP_EOL);\n}\necho 'Баланс: $' . $me['data']['balance']['available'] . PHP_EOL;\n\n$product = $api->get('/v1/products/853');\nif (!$product['ok'] || !$product['data']['available']) {\n    exit('Товар сейчас недоступен' . PHP_EOL);\n}\n\n$order = [\n    'product_id'    => 853,\n    'external_id'   => 'shop-' . date('YmdHis') . '-' . bin2hex(random_bytes(2)),\n    'max_total_usd' => $product['data']['price']['unit_price'],\n    'fields'        => ['telegram_username' => 'durov'],\n    'test'          => true,\n];\n\n$quote = $api->post('/v1/orders/quote', $order);\nif (!$quote['ok'] || !$quote['data']['can_order']) {\n    foreach ($quote['data']['problems'] ?? [$quote['error']] as $p) {\n        echo 'Нельзя оформить: ' . $p['code'] . ' — ' . $p['message'] . PHP_EOL;\n    }\n    exit(1);\n}\n\n$res = $api->createOrder($order);\nif (!$res['ok']) {\n    $e = $res['error'];\n    exit(($e['retryable'] ? 'Повторите позже с тем же external_id: ' : 'Заказ не создан: ') . $e['code'] . ' — ' . $e['message'] . PHP_EOL);\n}\n$o = $res['data'];\necho 'Заказ ' . $o['id'] . ' (' . $o['external_id'] . '): ' . $o['status_text'] . PHP_EOL;\n\n$deadline = time() + 180;\nwhile (!in_array($o['status'], ['completed', 'refunded'], true) && time() < $deadline) {\n    sleep(15);\n    $r = $api->get('/v1/orders/' . $o['id']);\n    if ($r['ok'] && $r['data']['revision'] > $o['revision']) {\n        $o = $r['data'];\n        echo 'Статус: ' . $o['status_text'] . PHP_EOL;\n        if ($o['status'] === 'action_required') {\n            echo 'Передайте покупателю ссылку: ' . $o['action']['url'] . PHP_EOL;\n        }\n    }\n}\n\nif ($o['status'] === 'completed') {\n    foreach ($o['delivery']['items'] as $item) {\n        echo 'Выдать покупателю (' . $item['type'] . '): ' . $item['value'] . PHP_EOL;\n    }\n    if ($o['delivery']['instructions'] !== null) {\n        echo 'Инструкция: ' . $o['delivery']['instructions']['text'] . PHP_EOL;\n    }\n} elseif ($o['status'] === 'refunded') {\n    echo 'Возврат $' . $o['refund']['amount'] . ', причина: ' . $o['refund']['reason'] . PHP_EOL;\n}\n```\n\n`webhook.php` — обработчик вебхука. Для проверки локально: `php -S 127.0.0.1:8095 webhook.php`. В бою разместите его за вашим веб-сервером по адресу, указанному в кабинете. Хранилище в файле здесь для наглядности — используйте свою базу данных.\n\n```php\n<?php\ndeclare(strict_types=1);\n\nfunction aviedo_verify(string $header, string $raw, string $secret, int $tolerance = 300): bool\n{\n    $t = null;\n    $signatures = [];\n    foreach (explode(',', $header) as $part) {\n        [$key, $value] = array_pad(explode('=', trim($part), 2), 2, '');\n        if ($key === 't' && ctype_digit($value)) {\n            $t = $value;\n        } elseif ($key === 'v1' && preg_match('/^[0-9a-f]{64}$/', $value)) {\n            $signatures[] = $value;\n        }\n    }\n    if ($t === null || !$signatures || abs(time() - (int) $t) > $tolerance) {\n        return false;\n    }\n    $expected = hash_hmac('sha256', $t . '.' . $raw, $secret);\n    foreach ($signatures as $signature) {\n        if (hash_equals($expected, $signature)) {\n            return true;\n        }\n    }\n    return false;\n}\n\nfunction aviedo_store(callable $change): void\n{\n    $fp = fopen(__DIR__ . '/aviedo-store.json', 'c+');\n    flock($fp, LOCK_EX);\n    $db = json_decode(stream_get_contents($fp) ?: '{}', true) ?: [];\n    $change($db);\n    ftruncate($fp, 0);\n    rewind($fp);\n    fwrite($fp, json_encode($db, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));\n    flock($fp, LOCK_UN);\n    fclose($fp);\n}\n\n$secret = getenv('AVIEDO_SECRET') ?: 'ВАШ_SECRET';\n$raw = (string) file_get_contents('php://input');\n\nif (!aviedo_verify($_SERVER['HTTP_X_AVIEDO_SIGNATURE'] ?? '', $raw, $secret)) {\n    http_response_code(401);\n    exit('bad signature');\n}\n\n$event = json_decode($raw, true);\nif (!is_array($event) || !isset($event['id'], $event['type'])) {\n    http_response_code(400);\n    exit('bad payload');\n}\n\naviedo_store(static function (array &$db) use ($event): void {\n    $eventId = (string) $event['id'];\n    if (isset($db['events'][$eventId])) {\n        return;\n    }\n    $db['events'][$eventId] = $event['type'];\n\n    if (str_starts_with($event['type'], 'order.')) {\n        $order = $event['data']['order'];\n        $saved = $db['orders'][$order['id']] ?? null;\n        if ($saved === null || $order['revision'] > $saved['revision']) {\n            $db['orders'][$order['id']] = $order;\n        }\n        if ($order['delivery'] !== null) {\n            $db['deliveries'][$order['id']] = $order['delivery'];\n        }\n    } elseif ($event['type'] === 'message.created') {\n        $db['messages'][$event['data']['order_id']][] = $event['data']['message'];\n    }\n});\n\nhttp_response_code(200);\necho 'ok';\n```\n\n### Python 3.8+ (requests)\n\n`aviedo.py`:\n\n```python\nimport hashlib\nimport hmac\nimport json\nimport time\nimport urllib.parse\n\nimport requests\n\n\nclass AviedoClient:\n    def __init__(self, token, secret, base=\"https://api.aviedo.net\", timeout=45):\n        self.token = token\n        self.secret = secret.encode()\n        self.base = base\n        self.timeout = timeout\n        self.session = requests.Session()\n\n    def get(self, path, params=None):\n        if params:\n            path += \"?\" + urllib.parse.urlencode(params)\n        return self.request(\"GET\", path)\n\n    def post(self, path, data=None):\n        body = json.dumps(data or {}, ensure_ascii=False, separators=(\",\", \":\")).encode()\n        return self.request(\"POST\", path, body)\n\n    def request(self, method, path, body=b\"\"):\n        ts = str(int(time.time()))\n        message = f\"{ts}\\n{method}\\n{path}\\n\".encode() + body\n        headers = {\n            \"Authorization\": f\"Bearer {self.token}\",\n            \"X-Aviedo-Timestamp\": ts,\n            \"X-Aviedo-Signature\": hmac.new(self.secret, message, hashlib.sha256).hexdigest(),\n            \"Accept\": \"application/json\",\n        }\n        if method != \"GET\":\n            headers[\"Content-Type\"] = \"application/json\"\n        try:\n            r = self.session.request(\n                method,\n                self.base + path,\n                data=body if method != \"GET\" else None,\n                headers=headers,\n                timeout=self.timeout,\n                allow_redirects=False,\n            )\n        except requests.RequestException as e:\n            return self._failure(\"network_error\", str(e), True, 0)\n        try:\n            payload = r.json()\n        except ValueError:\n            return self._failure(\"bad_response\", f\"HTTP {r.status_code}\", r.status_code >= 500, r.status_code)\n        payload[\"http_status\"] = r.status_code\n        return payload\n\n    def create_order(self, order, attempts=5):\n        last = None\n        for i in range(1, attempts + 1):\n            res = self.post(\"/v1/orders\", order)\n            if res[\"ok\"] or not res[\"error\"].get(\"retryable\"):\n                return res\n            last = res\n            if i < attempts:\n                time.sleep(max(res[\"error\"].get(\"retry_after\") or 0, 2 ** i))\n        params = {\"test\": 1} if order.get(\"test\") else None\n        found = self.get(\"/v1/orders/external/\" + urllib.parse.quote(order[\"external_id\"], safe=\"\"), params)\n        return found if found[\"ok\"] else last\n\n    @staticmethod\n    def _failure(code, message, retryable, status):\n        return {\n            \"ok\": False,\n            \"http_status\": status,\n            \"error\": {\"code\": code, \"message\": message, \"retryable\": retryable, \"retry_after\": None, \"details\": None},\n        }\n```\n\n`buy.py`:\n\n```python\nimport os\nimport secrets\nimport time\n\nfrom aviedo import AviedoClient\n\napi = AviedoClient(os.environ.get(\"AVIEDO_TOKEN\", \"rsl_ВАШ_ТОКЕН\"), os.environ.get(\"AVIEDO_SECRET\", \"ВАШ_SECRET\"))\n\nme = api.get(\"/v1/me\")\nif not me[\"ok\"]:\n    raise SystemExit(f\"Ключ не работает: {me['error']['code']} — {me['error']['message']}\")\nprint(\"Баланс: $\" + me[\"data\"][\"balance\"][\"available\"])\n\nproduct = api.get(\"/v1/products/853\")\nif not product[\"ok\"] or not product[\"data\"][\"available\"]:\n    raise SystemExit(\"Товар сейчас недоступен\")\n\norder = {\n    \"product_id\": 853,\n    \"external_id\": f\"shop-{time.strftime('%Y%m%d%H%M%S')}-{secrets.token_hex(2)}\",\n    \"max_total_usd\": product[\"data\"][\"price\"][\"unit_price\"],\n    \"fields\": {\"telegram_username\": \"durov\"},\n    \"test\": True,\n}\n\nquote = api.post(\"/v1/orders/quote\", order)\nif not quote[\"ok\"] or not quote[\"data\"][\"can_order\"]:\n    for p in quote[\"data\"][\"problems\"] if quote[\"ok\"] else [quote[\"error\"]]:\n        print(f\"Нельзя оформить: {p['code']} — {p['message']}\")\n    raise SystemExit(1)\n\nres = api.create_order(order)\nif not res[\"ok\"]:\n    e = res[\"error\"]\n    prefix = \"Повторите позже с тем же external_id\" if e[\"retryable\"] else \"Заказ не создан\"\n    raise SystemExit(f\"{prefix}: {e['code']} — {e['message']}\")\no = res[\"data\"]\nprint(f\"Заказ {o['id']} ({o['external_id']}): {o['status_text']}\")\n\ndeadline = time.time() + 180\nwhile o[\"status\"] not in (\"completed\", \"refunded\") and time.time() < deadline:\n    time.sleep(15)\n    r = api.get(f\"/v1/orders/{o['id']}\")\n    if r[\"ok\"] and r[\"data\"][\"revision\"] > o[\"revision\"]:\n        o = r[\"data\"]\n        print(\"Статус:\", o[\"status_text\"])\n        if o[\"status\"] == \"action_required\":\n            print(\"Передайте покупателю ссылку:\", o[\"action\"][\"url\"])\n\nif o[\"status\"] == \"completed\":\n    for item in o[\"delivery\"][\"items\"]:\n        print(f\"Выдать покупателю ({item['type']}): {item['value']}\")\n    if o[\"delivery\"][\"instructions\"]:\n        print(\"Инструкция:\", o[\"delivery\"][\"instructions\"][\"text\"])\nelif o[\"status\"] == \"refunded\":\n    print(f\"Возврат ${o['refund']['amount']}, причина: {o['refund']['reason']}\")\n```\n\n`poll_events.py` — получение событий без вебхука (опрос `GET /v1/events`):\n\n```python\nimport os\nimport time\n\nfrom aviedo import AviedoClient\n\napi = AviedoClient(os.environ[\"AVIEDO_TOKEN\"], os.environ[\"AVIEDO_SECRET\"])\nstate_file = \"last_event_id.txt\"\n\n\ndef load_last_id():\n    try:\n        with open(state_file) as f:\n            return int(f.read().strip() or 0)\n    except FileNotFoundError:\n        return 0\n\n\ndef handle_event(event):\n    kind = \"ТЕСТ \" if event[\"test\"] else \"\"\n    if event[\"type\"].startswith(\"order.\"):\n        order = event[\"data\"][\"order\"]\n        print(f\"{kind}{event['id']} {event['type']}: {order['id']} → {order['status']} (revision {order['revision']})\")\n    elif event[\"type\"] == \"message.created\":\n        message = event[\"data\"][\"message\"]\n        print(f\"{kind}{event['id']} сообщение по {event['data']['order_id']} от {message['from']}: {message['text']}\")\n\n\nlast_id = load_last_id()\nwhile True:\n    res = api.get(\"/v1/events\", {\"after_id\": last_id, \"limit\": 100})\n    if not res[\"ok\"]:\n        time.sleep(res[\"error\"].get(\"retry_after\") or 15)\n        continue\n    for event in res[\"data\"]:\n        handle_event(event)\n        last_id = event[\"id\"]\n    with open(state_file, \"w\") as f:\n        f.write(str(last_id))\n    if res[\"meta\"][\"gap\"]:\n        print(\"Пропущены события старше 30 дней: сверьтесь через GET /v1/orders?updated_since=…\")\n    if not res[\"pagination\"][\"has_more\"]:\n        if os.environ.get(\"AVIEDO_POLL_ONCE\"):\n            break\n        time.sleep(15)\n```\n\n`webhook_flask.py` — обработчик вебхука на Flask (`pip install flask`):\n\n```python\nimport hashlib\nimport hmac\nimport json\nimport os\nimport re\nimport threading\nimport time\n\nfrom flask import Flask, request\n\nSECRET = os.environ.get(\"AVIEDO_SECRET\", \"ВАШ_SECRET\").encode()\nSTORE = \"aviedo-store.json\"\nlock = threading.Lock()\napp = Flask(__name__)\n\n\ndef verify(header, raw, tolerance=300):\n    t, signatures = None, []\n    for part in header.split(\",\"):\n        key, _, value = part.strip().partition(\"=\")\n        if key == \"t\" and value.isdigit():\n            t = value\n        elif key == \"v1\" and re.fullmatch(r\"[0-9a-f]{64}\", value):\n            signatures.append(value)\n    if t is None or not signatures or abs(time.time() - int(t)) > tolerance:\n        return False\n    expected = hmac.new(SECRET, t.encode() + b\".\" + raw, hashlib.sha256).hexdigest()\n    return any(hmac.compare_digest(expected, s) for s in signatures)\n\n\ndef handle_event(event):\n    with lock:\n        try:\n            with open(STORE, encoding=\"utf-8\") as f:\n                db = json.load(f)\n        except FileNotFoundError:\n            db = {}\n        events = db.setdefault(\"events\", {})\n        if str(event[\"id\"]) in events:\n            return\n        events[str(event[\"id\"])] = event[\"type\"]\n        if event[\"type\"].startswith(\"order.\"):\n            order = event[\"data\"][\"order\"]\n            saved = db.setdefault(\"orders\", {}).get(order[\"id\"])\n            if saved is None or order[\"revision\"] > saved[\"revision\"]:\n                db[\"orders\"][order[\"id\"]] = order\n            if order[\"delivery\"] is not None:\n                db.setdefault(\"deliveries\", {})[order[\"id\"]] = order[\"delivery\"]\n        elif event[\"type\"] == \"message.created\":\n            db.setdefault(\"messages\", {}).setdefault(event[\"data\"][\"order_id\"], []).append(event[\"data\"][\"message\"])\n        with open(STORE, \"w\", encoding=\"utf-8\") as f:\n            json.dump(db, f, ensure_ascii=False, indent=2)\n\n\n@app.post(\"/aviedo/webhook\")\ndef aviedo_webhook():\n    raw = request.get_data()\n    if not verify(request.headers.get(\"X-Aviedo-Signature\", \"\"), raw):\n        return \"bad signature\", 401\n    try:\n        event = json.loads(raw)\n    except ValueError:\n        return \"bad payload\", 400\n    handle_event(event)\n    return \"ok\", 200\n\n\nif __name__ == \"__main__\":\n    app.run(host=\"127.0.0.1\", port=int(os.environ.get(\"PORT\", \"8096\")))\n```\n\nНе передавайте в `requests` параметры `params=` и `json=`: подписывается ровно та строка пути и те байты тела, которые уходят в запрос.\n\n### Node.js 18+ (fetch, без зависимостей)\n\n`aviedo.mjs`:\n\n```javascript\nimport crypto from \"node:crypto\";\n\nexport class AviedoClient {\n  constructor(token, secret, base = \"https://api.aviedo.net\", timeoutMs = 45000) {\n    this.token = token;\n    this.secret = secret;\n    this.base = base;\n    this.timeoutMs = timeoutMs;\n  }\n\n  get(path, params) {\n    if (params && Object.keys(params).length) {\n      path += \"?\" + new URLSearchParams(params).toString();\n    }\n    return this.request(\"GET\", path, \"\");\n  }\n\n  post(path, data = {}) {\n    return this.request(\"POST\", path, JSON.stringify(data));\n  }\n\n  async request(method, path, body) {\n    const ts = Math.floor(Date.now() / 1000).toString();\n    const signature = crypto\n      .createHmac(\"sha256\", this.secret)\n      .update(`${ts}\\n${method}\\n${path}\\n${body}`)\n      .digest(\"hex\");\n    const headers = {\n      Authorization: `Bearer ${this.token}`,\n      \"X-Aviedo-Timestamp\": ts,\n      \"X-Aviedo-Signature\": signature,\n      Accept: \"application/json\",\n    };\n    if (method !== \"GET\") headers[\"Content-Type\"] = \"application/json\";\n\n    let res;\n    try {\n      res = await fetch(this.base + path, {\n        method,\n        headers,\n        body: method === \"GET\" ? undefined : body,\n        redirect: \"manual\",\n        signal: AbortSignal.timeout(this.timeoutMs),\n      });\n    } catch (e) {\n      return AviedoClient.failure(\"network_error\", String(e), true, 0);\n    }\n    const text = await res.text();\n    try {\n      const json = JSON.parse(text);\n      json.http_status = res.status;\n      return json;\n    } catch {\n      return AviedoClient.failure(\"bad_response\", `HTTP ${res.status}`, res.status >= 500, res.status);\n    }\n  }\n\n  async createOrder(order, attempts = 5) {\n    let last = null;\n    for (let i = 1; i <= attempts; i++) {\n      const res = await this.post(\"/v1/orders\", order);\n      if (res.ok || !res.error.retryable) return res;\n      last = res;\n      if (i < attempts) {\n        const waitSec = Math.max(res.error.retry_after ?? 0, 2 ** i);\n        await new Promise((resolve) => setTimeout(resolve, waitSec * 1000));\n      }\n    }\n    const found = await this.get(\n      \"/v1/orders/external/\" + encodeURIComponent(order.external_id),\n      order.test ? { test: 1 } : undefined,\n    );\n    return found.ok ? found : last;\n  }\n\n  static failure(code, message, retryable, status) {\n    return {\n      ok: false,\n      http_status: status,\n      error: { code, message, retryable, retry_after: null, details: null },\n    };\n  }\n}\n```\n\n`buy.mjs`:\n\n```javascript\nimport crypto from \"node:crypto\";\nimport { AviedoClient } from \"./aviedo.mjs\";\n\nconst api = new AviedoClient(\n  process.env.AVIEDO_TOKEN ?? \"rsl_ВАШ_ТОКЕН\",\n  process.env.AVIEDO_SECRET ?? \"ВАШ_SECRET\",\n);\nconst sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst me = await api.get(\"/v1/me\");\nif (!me.ok) throw new Error(`Ключ не работает: ${me.error.code} — ${me.error.message}`);\nconsole.log(\"Баланс: $\" + me.data.balance.available);\n\nconst product = await api.get(\"/v1/products/853\");\nif (!product.ok || !product.data.available) throw new Error(\"Товар сейчас недоступен\");\n\nconst order = {\n  product_id: 853,\n  external_id: `shop-${Date.now()}-${crypto.randomBytes(2).toString(\"hex\")}`,\n  max_total_usd: product.data.price.unit_price,\n  fields: { telegram_username: \"durov\" },\n  test: true,\n};\n\nconst quote = await api.post(\"/v1/orders/quote\", order);\nif (!quote.ok || !quote.data.can_order) {\n  for (const p of quote.ok ? quote.data.problems : [quote.error]) {\n    console.log(`Нельзя оформить: ${p.code} — ${p.message}`);\n  }\n  process.exit(1);\n}\n\nconst res = await api.createOrder(order);\nif (!res.ok) {\n  const e = res.error;\n  throw new Error(`${e.retryable ? \"Повторите позже с тем же external_id\" : \"Заказ не создан\"}: ${e.code} — ${e.message}`);\n}\nlet o = res.data;\nconsole.log(`Заказ ${o.id} (${o.external_id}): ${o.status_text}`);\n\nconst deadline = Date.now() + 180_000;\nwhile (![\"completed\", \"refunded\"].includes(o.status) && Date.now() < deadline) {\n  await sleep(15_000);\n  const r = await api.get(`/v1/orders/${o.id}`);\n  if (r.ok && r.data.revision > o.revision) {\n    o = r.data;\n    console.log(\"Статус:\", o.status_text);\n    if (o.status === \"action_required\") console.log(\"Передайте покупателю ссылку:\", o.action.url);\n  }\n}\n\nif (o.status === \"completed\") {\n  for (const item of o.delivery.items) console.log(`Выдать покупателю (${item.type}): ${item.value}`);\n  if (o.delivery.instructions) console.log(\"Инструкция:\", o.delivery.instructions.text);\n} else if (o.status === \"refunded\") {\n  console.log(`Возврат $${o.refund.amount}, причина: ${o.refund.reason}`);\n}\n```\n\n`webhook.mjs` — обработчик вебхука на встроенном `node:http`:\n\n```javascript\nimport crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport http from \"node:http\";\n\nconst SECRET = process.env.AVIEDO_SECRET ?? \"ВАШ_SECRET\";\nconst STORE = \"aviedo-store.json\";\n\nfunction verify(header, raw, tolerance = 300) {\n  let t = null;\n  const signatures = [];\n  for (const part of header.split(\",\")) {\n    const [key, value = \"\"] = part.trim().split(\"=\", 2);\n    if (key === \"t\" && /^\\d+$/.test(value)) t = value;\n    else if (key === \"v1\" && /^[0-9a-f]{64}$/.test(value)) signatures.push(value);\n  }\n  if (t === null || !signatures.length || Math.abs(Date.now() / 1000 - Number(t)) > tolerance) return false;\n  const expected = crypto\n    .createHmac(\"sha256\", SECRET)\n    .update(Buffer.concat([Buffer.from(t + \".\"), raw]))\n    .digest();\n  return signatures.some((s) => crypto.timingSafeEqual(expected, Buffer.from(s, \"hex\")));\n}\n\nfunction handleEvent(event) {\n  const db = fs.existsSync(STORE) ? JSON.parse(fs.readFileSync(STORE, \"utf8\")) : {};\n  db.events ??= {};\n  if (db.events[event.id]) return;\n  db.events[event.id] = event.type;\n  if (event.type.startsWith(\"order.\")) {\n    const order = event.data.order;\n    db.orders ??= {};\n    const saved = db.orders[order.id];\n    if (!saved || order.revision > saved.revision) db.orders[order.id] = order;\n    if (order.delivery) (db.deliveries ??= {})[order.id] = order.delivery;\n  } else if (event.type === \"message.created\") {\n    db.messages ??= {};\n    (db.messages[event.data.order_id] ??= []).push(event.data.message);\n  }\n  fs.writeFileSync(STORE, JSON.stringify(db, null, 2));\n}\n\nhttp\n  .createServer((req, res) => {\n    if (req.method !== \"POST\" || req.url !== \"/aviedo/webhook\") {\n      res.writeHead(404).end();\n      return;\n    }\n    const chunks = [];\n    req.on(\"data\", (chunk) => chunks.push(chunk));\n    req.on(\"end\", () => {\n      const raw = Buffer.concat(chunks);\n      if (!verify(req.headers[\"x-aviedo-signature\"] ?? \"\", raw)) {\n        res.writeHead(401).end(\"bad signature\");\n        return;\n      }\n      let event;\n      try {\n        event = JSON.parse(raw.toString(\"utf8\"));\n      } catch {\n        res.writeHead(400).end(\"bad payload\");\n        return;\n      }\n      handleEvent(event);\n      res.writeHead(200).end(\"ok\");\n    });\n  })\n  .listen(Number(process.env.PORT ?? 8097), \"127.0.0.1\");\n```\n\n### curl и openssl\n\n`aviedo.sh` — функция `aviedo МЕТОД ПУТЬ [ТЕЛО]` для командной строки и скриптов. `source aviedo.sh` подключает функцию в текущую оболочку, а `bash aviedo.sh` выполняет демонстрационные запросы (проверка ключа, список тестовых заказов, `quote` и тестовый заказ):\n\n```bash\n#!/usr/bin/env bash\n\nAVIEDO_BASE=\"${AVIEDO_BASE:-https://api.aviedo.net}\"\n\naviedo() {\n  local method=\"$1\" path=\"$2\" body=\"${3:-}\"\n  : \"${AVIEDO_TOKEN:?укажите AVIEDO_TOKEN}\" \"${AVIEDO_SECRET:?укажите AVIEDO_SECRET}\"\n  if [ \"$method\" != \"GET\" ] && [ -z \"$body\" ]; then\n    body='{}'\n  fi\n  local ts sig\n  ts=\"$(date +%s)\"\n  sig=\"$(printf '%s\\n%s\\n%s\\n%s' \"$ts\" \"$method\" \"$path\" \"$body\" | openssl dgst -sha256 -hmac \"$AVIEDO_SECRET\" -r | cut -d' ' -f1)\"\n  local args=(-sS -X \"$method\" \"$AVIEDO_BASE$path\"\n    -H \"Authorization: Bearer $AVIEDO_TOKEN\"\n    -H \"X-Aviedo-Timestamp: $ts\"\n    -H \"X-Aviedo-Signature: $sig\")\n  if [ \"$method\" != \"GET\" ]; then\n    args+=(-H \"Content-Type: application/json\" --data-raw \"$body\")\n  fi\n  curl \"${args[@]}\"\n  echo\n}\n\nif [ \"${BASH_SOURCE[0]}\" = \"$0\" ]; then\n  set -euo pipefail\n  aviedo GET /v1/me\n  aviedo GET '/v1/orders?test=1&limit=1'\n  aviedo POST /v1/orders/quote '{\"product_id\":853,\"fields\":{\"telegram_username\":\"durov\"},\"test\":true}'\n  aviedo POST /v1/orders \"{\\\"product_id\\\":853,\\\"external_id\\\":\\\"shop-curl-$(date +%s)\\\",\\\"max_total_usd\\\":\\\"12.67\\\",\\\"fields\\\":{\\\"telegram_username\\\":\\\"durov\\\"},\\\"test\\\":true}\"\nfi\n```\n\nВ описании каждого метода ниже есть готовые вызовы для всех четырёх вариантов: `$api->…` (PHP), `api.…` (Python), `await api.…` (Node.js) и `aviedo …` (curl).\n\n## Чек-лист перед запуском\n\n- [ ] `GET /v1/me` отвечает `ok: true`, а ваша функция подписи проходит все тестовые векторы.\n- [ ] Каталог обновляется по расписанию с `If-None-Match`. Товары с `available: false` у вас скрыты.\n- [ ] Форма заказа строится из `fields` товара и перестраивается при смене `fields_version`. Количество ограничено `quantity.min/max`.\n- [ ] `external_id` создаётся до запроса и не меняется при повторах. `max_total_usd` передаётся всегда.\n- [ ] Таймаут HTTP-клиента — не меньше 45 секунд, повторы только при `retryable: true` и сетевых сбоях.\n- [ ] Обрабатываются все 5 статусов. Незнакомый статус считается `processing`.\n- [ ] При `action_required` ссылка сразу уходит покупателю.\n- [ ] `refunded` обрабатывается **в любой момент**, даже после `completed`.\n- [ ] Вебхук проверяет подпись и время, отвечает `2xx` быстрее 10 секунд, отбрасывает повторы по `id` из подписанного тела и сохраняет заказ только с большим `revision`. Если вебхука нет — работает опрос `GET /v1/events`.\n- [ ] Заказы хранятся по `order.id`. События с `\"test\": true` в боевой интеграции игнорируются и не приводят к выдаче настоящего товара.\n- [ ] `delivery.items` из `order.completed` сохраняются у вас: после возврата `delivery` в заказе становится `null`.\n- [ ] Для ручных товаров вы читаете сообщения продавца и отвечаете на них.\n- [ ] Фото из `delivery.attachments` и чата скачиваются и хранятся у вас.\n- [ ] Прогнаны все тестовые сценарии из раздела «Тестовый режим».\n- [ ] Секретный ключ хранится только на сервере.\n\n## Частые вопросы\n\n**Нужно ли отдельно оплачивать заказ?**\nНет. `POST /v1/orders` создаёт заказ и сразу списывает `price.total` с вашего долларового баланса. Если денег не хватает, заказ не создаётся (`402 insufficient_funds`).\n\n**В какой валюте цены? Как продавать за рубли?**\nВсе цены — в долларах, уже с вашей наценкой. Цену для своих покупателей вы назначаете сами. Если продаёте за рубли, можно ориентироваться на наш курс из `GET /v1/rate`.\n\n**Почему цена в заказе меньше, чем я передал в `max_total_usd`?**\n`max_total_usd` — верхняя граница. Списывается текущая цена; если она снизилась, вы платите меньше.\n\n**Заказ завис в `processing`. Что делать?**\nАвтоматические заказы обычно выполняются за 1–10 минут. Если у поставщика сбой, заказ получит `delayed: true` — поддержка уже разбирается и повторит отправку или вернёт деньги. Если заказ долго в работе без `delayed`, напишите в чат заказа или в поддержку с номером заказа и `request_id`.\n\n**Можно ли отменить заказ?**\nТолько ручной заказ в статусе `pending` (`cancellable: true`) — мгновенный полный возврат. Остальные — через чат заказа.\n\n**Пришёл `refunded` после `completed`. Это ошибка?**\nНет, это редкий случай спора или брака: деньги уже вернулись на ваш баланс. Обработайте как обычный возврат. `delivery` и `completed_at` в заказе после возврата — `null`, выданные коды берите из сохранённого `order.completed`.\n\n**Я не получил ответ на `POST /v1/orders`. Создался ли заказ?**\nПовторите тот же запрос с тем же `external_id` — второго списания не будет. Или проверьте `GET /v1/orders/external/{external_id}` (его `404` окончателен через 60 секунд после отправки).\n\n**Можно ли использовать один `external_id` повторно?**\nНет: он уникален навсегда в пределах аккаунта. Исключение — тестовые заказы, у них своё пространство номеров.\n\n**Зачем нужны и вебхук, и `GET /v1/events`?**\nЭто одна и та же лента. Вебхук быстрее, опрос не требует публичного адреса. Даже с вебхуком полезно раз в несколько минут сверяться с лентой — на случай простоя вашего сервера.\n\n**Вебхук перестал приходить.**\nПроверьте `GET /v1/me` → `webhook.status`. Если `paused`, исправьте сервер и вызовите `POST /v1/webhooks/test` — отправка возобновится. Пропущенные события заберите из `GET /v1/events`.\n\n**Почему `GET /v1/catalog` отвечает `429`?**\nУ каталога отдельный лимит — 6 запросов в минуту (сюда же входит `GET /v1/products` без `ids`). Обновляйте каталог раз в 15–60 минут с `If-None-Match`, а для отдельных товаров используйте `GET /v1/products?ids=…` или `GET /v1/products/{id}`.\n\n**Почему запрос отвечает `400 unknown_parameter`, хотя я ничего лишнего не передавал?**\nAPI строго проверяет параметры: например, библиотека могла добавить `_=1699999999` для обхода кэша. Уберите лишний параметр.\n\n**Как показать покупателю инструкцию?**\nВозьмите `order.delivery.instructions.text` (простой текст) или `.html` (безопасный набор тегов `b i u s a code pre br`).\n\n**Сколько хранятся заказы и события?**\nЗаказы — всегда (`GET /v1/orders`), события в ленте — 30 дней, тестовые заказы — 7 дней.\n\n**Можно ли получить заказы, сделанные на сайте?**\nНет, API показывает только заказы, созданные через API. В статистике (`GET /v1/stats`) можно выбрать `source=web` или `all`.\n\n**Куда писать?**\nВ Telegram: [t.me/av1de](https://t.me/av1de). Укажите `request_id` из ответа и номер заказа.\n\n## Журнал изменений\n\n| Дата | Версия | Изменения |\n|---|---|---|\n| 12.10.2026 | 1.0 | `quote` перечисляет в `problems` незаполненные обязательные поля и не переданное или неверное `quantity`, как `POST /v1/orders`; фильтр `test` в `GET /v1/events`; `quantity` не больше 1 000 000 000; в тестовом режиме остаток берётся из кэша; уточнены описания ошибок `POST /v1/webhooks/test` |\n| 12.10.2026 | 1.0 | Первая публичная версия: каталог с ценами реселлера, заказы с идемпотентностью по `external_id` и `max_total_usd`, события и подписанные вебхуки с повторами, чат заказа с фото, отмена ручных заказов, отправка кода Supercell ID, статистика, тестовый режим со сценариями `success`, `refund`, `delay`, `action_required`, `chat`, `completed_then_refunded`, `out_of_stock`, `account_not_found` |\n\n## Поддержка\n\nВопросы по интеграции, доступу и заказам — в Telegram: [t.me/av1de](https://t.me/av1de). Чтобы ответ был быстрым, укажите `request_id` из ответа API, номер заказа (`id` или `external_id`) и время запроса.\n\nОписание API в формате OpenAPI 3.1: [https://api.aviedo.net/docs/openapi.json](https://api.aviedo.net/docs/openapi.json) — его можно импортировать в Postman, Insomnia или генератор клиентов.\n","contact":{"name":"Поддержка Aviedo","url":"https://t.me/av1de"}},"servers":[{"url":"https://api.aviedo.net","description":"Боевой сервер. Тестовые заказы создаются на нём же с \"test\": true"}],"security":[{"AviedoToken":[],"AviedoTimestamp":[],"AviedoSignature":[]}],"tags":[{"name":"Сервис","description":"Состояние сервиса без авторизации."},{"name":"Аккаунт","description":"Проверка ключа, баланс, история операций и курс доллара."},{"name":"Каталог","description":"Разделы, категории и товары с вашими ценами в долларах; отправка кода Supercell ID для товаров «вход по коду». Как синхронизировать каталог — в разделе «Товары: автоматические, загруженные, ручные»."},{"name":"Заказы","description":"Проверка, создание и оплата заказа, получение, список и отмена. Обязательно прочитайте «Создание заказа и идемпотентность» и «Статусы заказа»."},{"name":"Чат","description":"Переписка с продавцом по заказу: для ручных товаров обязательна. Подробности — в разделе «Чат заказа»."},{"name":"События и вебхуки","description":"Лента событий и тестовая отправка вебхука. Формат вебхуков, подпись и повторы — в разделе «Вебхуки», тела событий — в блоке Webhooks."},{"name":"Статистика","description":"Ваша статистика по заказам."}],"paths":{"/v1/status":{"get":{"tags":["Сервис"],"operationId":"getStatus","summary":"Состояние сервиса","description":"Состояние сервиса и время сервера. **Без авторизации** — удобно для сверки часов и проверки, принимаются ли сейчас заказы.\n\n`orders_enabled: false` — идут технические работы или курс устарел; каталог при этом доступен. `announcement` — объявление для реселлеров (например, о плановых работах).\n\nОтветы `403 https_required` (запрос по `http://`), `404 not_found` (неизвестный путь, в том числе с `/` в конце) и `405 method_not_allowed` (неверный HTTP-метод, допустимые — в заголовке `Allow`) одинаковы для любого пути API.","security":[],"responses":{"200":{"description":"Сервис отвечает.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Status"},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"ok":{"summary":"Сервис работает","value":{"ok":true,"data":{"server_time":"2026-10-12T19:06:14+03:00","server_unix":1791821174,"orders_enabled":true,"maintenance":false,"rate_fresh":true,"announcement":null,"api_version":"1.0"},"request_id":"req_32c0a19e5bf5"}}}}}},"400":{"description":"- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"unknown_parameter":{"summary":"unknown_parameter: опечатка в query","value":{"ok":false,"error":{"code":"unknown_parameter","message":"Неизвестный параметр: statuss","retryable":false,"retry_after":null,"details":{"param":"statuss","allowed":["status","kind","product_id","from","to","updated_since","has_unread","delayed","test","limit","cursor"]}},"request_id":"req_f28a29e21c06"}}}}}},"403":{"description":"- `https_required` — запрос по http://","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}}}}}},"404":{"description":"- `not_found` — неизвестный путь","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"not_found":{"summary":"not_found","value":{"ok":false,"error":{"code":"not_found","message":"Неизвестный путь","retryable":false,"retry_after":null,"details":null},"request_id":"req_ba136242cee6"}}}}}},"405":{"description":"- `method_not_allowed` — неверный HTTP-метод (`details.allowed`, заголовок `Allow`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"Allow":{"$ref":"#/components/headers/Allow"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"method_not_allowed":{"summary":"method_not_allowed","value":{"ok":false,"error":{"code":"method_not_allowed","message":"Метод не поддерживается","retryable":false,"retry_after":null,"details":{"allowed":["POST","GET"]}},"request_id":"req_fdf73fa91e30"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl -s https://api.aviedo.net/v1/status"}]}},"/v1/me":{"get":{"tags":["Аккаунт"],"operationId":"getMe","summary":"Проверка ключа и сводка аккаунта","description":"Ваш «hello world»: если вызов прошёл, токен и подпись работают. Возвращает баланс, курс, состояние вебхука, срок старой пары ключей после перевыпуска, лимиты и число непрочитанных сообщений по боевым заказам.","responses":{"200":{"description":"Сводка аккаунта.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Me"},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"webhook":{"summary":"С вебхуком","value":{"ok":true,"data":{"reseller":{"id":"ab12-3456","username":"myshop","status":"approved","approved_at":"2026-10-12T19:06:06+03:00"},"balance":{"currency":"USD","available":"250.00"},"rate":{"usd_rub":"87.200000","fresh":true},"webhook":{"url":"https://shop.example.com/aviedo/webhook","status":"active"},"key":{"created_at":"2026-10-12T19:06:06+03:00","previous_key_valid_until":null},"limits":{"requests_per_minute":120,"orders_per_minute":30,"uploaded_max_per_order":20},"unread_messages":0,"server_time":"2026-10-12T19:06:14+03:00","api_version":"1.0"},"request_id":"req_544a477d8fce"}},"no_webhook":{"summary":"Без вебхука","value":{"ok":true,"data":{"reseller":{"id":"ab12-3456","username":"myshop","status":"approved","approved_at":"2026-10-12T19:06:06+03:00"},"balance":{"currency":"USD","available":"250.00"},"rate":{"usd_rub":"87.200000","fresh":true},"webhook":{"url":null,"status":"none"},"key":{"created_at":"2026-10-12T19:06:06+03:00","previous_key_valid_until":null},"limits":{"requests_per_minute":120,"orders_per_minute":30,"uploaded_max_per_order":20},"unread_messages":0,"server_time":"2026-10-12T19:06:14+03:00","api_version":"1.0"},"request_id":"req_e9466264c40c"}}}}}},"400":{"description":"- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"unknown_parameter":{"summary":"unknown_parameter: опечатка в query","value":{"ok":false,"error":{"code":"unknown_parameter","message":"Неизвестный параметр: statuss","retryable":false,"retry_after":null,"details":{"param":"statuss","allowed":["status","kind","product_id","from","to","updated_since","has_unread","delayed","test","limit","cursor"]}},"request_id":"req_f28a29e21c06"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials_err_missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"missing_credentials_err_missing_credentials_all":{"summary":"missing_credentials: нет всех заголовков","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: Authorization, X-Aviedo-Timestamp, X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["Authorization","X-Aviedo-Timestamp","X-Aviedo-Signature"]}},"request_id":"req_1b29bd77ba06"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo GET '/v1/me'"},{"lang":"PHP","label":"PHP","source":"$res = $api->get('/v1/me');"},{"lang":"Python","label":"Python","source":"res = api.get(\"/v1/me\")"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.get(\"/v1/me\");"}]}},"/v1/balance":{"get":{"tags":["Аккаунт"],"operationId":"getBalance","summary":"Баланс","description":"Долларовый баланс, с которого оплачиваются заказы. Пополнить его можно в магазине Aviedo в разделе «Пополнить» ($): USDT TRC20 / BEP20 / TON или Bybit UID. Через API пополнить нельзя.","responses":{"200":{"description":"Баланс.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Balance"},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"ok":{"summary":"Баланс","value":{"ok":true,"data":{"currency":"USD","available":"250.00","updated_at":"2026-10-12T18:06:06+03:00"},"request_id":"req_837c021befd6"}}}}}},"400":{"description":"- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"unknown_parameter":{"summary":"unknown_parameter: опечатка в query","value":{"ok":false,"error":{"code":"unknown_parameter","message":"Неизвестный параметр: statuss","retryable":false,"retry_after":null,"details":{"param":"statuss","allowed":["status","kind","product_id","from","to","updated_since","has_unread","delayed","test","limit","cursor"]}},"request_id":"req_f28a29e21c06"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo GET '/v1/balance'"},{"lang":"PHP","label":"PHP","source":"$res = $api->get('/v1/balance');"},{"lang":"Python","label":"Python","source":"res = api.get(\"/v1/balance\")"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.get(\"/v1/balance\");"}]}},"/v1/balance/history":{"get":{"tags":["Аккаунт"],"operationId":"getBalanceHistory","summary":"Движение средств","description":"Списания, возвраты, пополнения и корректировки долларового баланса, от новых к старым. Списания идут с минусом, зачисления с плюсом. У оплат и возвратов заказов заполнены `order_id` и `external_id`. Тестовые заказы сюда не попадают.","parameters":[{"name":"type","in":"query","required":false,"description":"Типы операций через запятую: `order_payment`, `order_refund`, `topup`, `adjustment`.","schema":{"type":"string"},"example":"order_payment,order_refund"},{"name":"from","in":"query","required":false,"description":"Начало периода: дата `YYYY-MM-DD` (с начала московских суток) или ISO-время со смещением.","schema":{"type":"string"},"example":"2026-10-01"},{"name":"to","in":"query","required":false,"description":"Конец периода: дата (до конца московских суток) или ISO-время.","schema":{"type":"string"},"example":"2026-10-31"},{"name":"limit","in":"query","required":false,"description":"Размер страницы, 1–100, по умолчанию 50.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"Курсор следующей страницы из `pagination.next_cursor`.","schema":{"type":"string"}}],"responses":{"200":{"description":"Операции.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","pagination","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/BalanceTransaction"}},"pagination":{"$ref":"#/components/schemas/CursorPagination"},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"ok":{"summary":"Пополнение баланса","value":{"ok":true,"data":[{"id":"7Q2M-9X4K-P8Z3","type":"topup","amount":"250.00","currency":"USD","order_id":null,"external_id":null,"created_at":"2026-10-12T18:06:06+03:00"}],"pagination":{"has_more":false,"next_cursor":null},"request_id":"req_daac2c4aa17a"}}}}}},"400":{"description":"- `invalid_request` — неверный тип или значение параметра (`details.param`), в том числе значение в `fields` не строка и не целое число\n- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"invalid_request":{"summary":"invalid_request: неверный limit","value":{"ok":false,"error":{"code":"invalid_request","message":"Параметр limit должен быть целым числом от 1 до 100","retryable":false,"retry_after":null,"details":{"param":"limit"}},"request_id":"req_cea3f4e084cc"}},"unknown_parameter":{"summary":"unknown_parameter: опечатка в query","value":{"ok":false,"error":{"code":"unknown_parameter","message":"Неизвестный параметр: statuss","retryable":false,"retry_after":null,"details":{"param":"statuss","allowed":["status","kind","product_id","from","to","updated_since","has_unread","delayed","test","limit","cursor"]}},"request_id":"req_f28a29e21c06"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo GET '/v1/balance/history?type=order_payment,order_refund&limit=50'"},{"lang":"PHP","label":"PHP","source":"$res = $api->get('/v1/balance/history', [\n    'type' => 'order_payment,order_refund',\n    'limit' => 50,\n]);"},{"lang":"Python","label":"Python","source":"res = api.get(\"/v1/balance/history\", {\n    \"type\": \"order_payment,order_refund\",\n    \"limit\": 50,\n})"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.get(\"/v1/balance/history\", {\n  type: \"order_payment,order_refund\",\n  limit: 50,\n});"}]}},"/v1/rate":{"get":{"tags":["Аккаунт"],"operationId":"getRate","summary":"Курс доллара","description":"Сколько рублей стоит 1 $. Нужен, только если вы продаёте за рубли и хотите ориентироваться на наш курс: все цены в API уже в долларах. Курс обновляется примерно раз в 30 минут; если он не обновлялся больше 120 минут, `fresh: false` и заказы временно не принимаются (`503 rate_unavailable`).","responses":{"200":{"description":"Курс.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Rate"},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"ok":{"summary":"Свежий курс","value":{"ok":true,"data":{"base":"USD","quote":"RUB","rate":"87.200000","updated_at":"2026-10-12T18:56:02+03:00","fresh":true,"age_minutes":10,"stale_after_minutes":120,"prices_currency":"USD","prices_include_your_markup":true},"request_id":"req_7ccb433424b9"}}}}}},"400":{"description":"- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"unknown_parameter":{"summary":"unknown_parameter: опечатка в query","value":{"ok":false,"error":{"code":"unknown_parameter","message":"Неизвестный параметр: statuss","retryable":false,"retry_after":null,"details":{"param":"statuss","allowed":["status","kind","product_id","from","to","updated_since","has_unread","delayed","test","limit","cursor"]}},"request_id":"req_f28a29e21c06"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}},"503":{"description":"- `rate_unavailable` — курс доллара устарел, заказы не принимаются","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_unavailable":{"summary":"rate_unavailable","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"rate_unavailable","message":"Курс доллара временно недоступен","retryable":true,"retry_after":300,"details":null},"request_id":"req_a4e7b1c0d935"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo GET '/v1/rate'"},{"lang":"PHP","label":"PHP","source":"$res = $api->get('/v1/rate');"},{"lang":"Python","label":"Python","source":"res = api.get(\"/v1/rate\")"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.get(\"/v1/rate\");"}]}},"/v1/catalog":{"get":{"tags":["Каталог"],"operationId":"getCatalog","summary":"Весь каталог","description":"Весь каталог одним запросом: разделы → категории → товары, с вашими ценами.\n\n- Скрытые, удалённые и истёкшие товары не отдаются, пустые разделы и категории тоже.\n- Закончившиеся товары отдаются с `available: false` и `unavailable_reason: \"out_of_stock\"`.\n- Разделы идут как на витрине: сначала игры, потом сервисы, внутри — по алфавиту.\n- Пагинации нет: ~800 товаров, ~1,2 МБ (≈80 КБ в gzip — передавайте `Accept-Encoding: gzip`).\n\n**Кэширование.** Сохраните `ETag` и передавайте его в `If-None-Match`: если ничего не изменилось, придёт `304 Not Modified` без тела. Подпись нужна и для такого запроса. ETag меняется при каждом обновлении курса и при любой правке каталога.\n\n**Лимит — 6 запросов в минуту** (ответы `304` тоже считаются). Обновляйте каталог раз в 15–60 минут.","parameters":[{"name":"kind","in":"query","required":false,"description":"Только эти виды товаров через запятую: `auto`, `uploaded`, `manual`.","schema":{"type":"string"},"example":"auto,uploaded"},{"name":"section_id","in":"query","required":false,"description":"Только один раздел.","schema":{"type":"integer","minimum":1},"example":8},{"name":"in_stock","in":"query","required":false,"description":"`1` — без закончившихся товаров.","schema":{"type":"string","enum":["1","0","true","false"]},"example":"1"},{"name":"If-None-Match","in":"header","required":false,"description":"ETag из прошлого ответа — как есть. Если ничего не изменилось, придёт `304` без тела.","schema":{"type":"string"},"example":"W/\"2367397b7c9a28379efbb74df61a1a44\""}],"responses":{"200":{"description":"Каталог. Пример сокращён до одной категории.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"ETag":{"$ref":"#/components/headers/ETag"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Catalog"},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"ok":{"summary":"Раздел Telegram, категория Премиум (сокращено)","value":{"ok":true,"data":{"generated_at":"2026-10-12T19:06:14+03:00","version":"831bb0ad","rate":{"usd_rub":"87.200000","fresh":true},"sections":[{"id":8,"name":"Telegram","type":"service","image_url":"https://aviedo.net/section/telegram_6692.png","position":8,"categories":[{"id":66,"section_id":8,"name":"Премиум ⚡️","image_url":null,"position":2,"description":"Спонсирование ...?","notice":"","eta":"Доставка после оплаты.","instructions":{"text":"Благодарим Вас за покупку!\nПриятной игры и хорошего дня! 💙","html":"Благодарим Вас за покупку!<br>Приятной игры и хорошего дня! 💙"},"faq":[{"title":"📍⠀Как всё происходит?","text":"− Выбираем желаемое количество и заполняем необходимую информацию;\n\n− Оплачиваем товар, после чего заказ будет принят в обработку;\n\n− После выполнения придёт уведомление о выполненной работе."},{"title":"⚡️⠀Сколько занимает доставка?","text":"Доставка занимает от 2 до 10 минут в любое время суток."},{"title":"🔰⠀Это безопасно?","text":"Безусловно, мы используем и покупаем только у официальных и проверенных дистрибьторов."},{"title":"🌍⠀Для каких стран доступно?","text":"Доступно для всех аккаунтов и стран."}],"tags":["Выгодно","Безопасно","Без задержек","Автоматическая доставка","Круглосуточно","Без комиссий"],"groups":[{"id":161,"name":"Премиум","position":1}],"products":[{"id":853,"name":"3 месяца","kind":"auto","type":"telegram_premium","result":"topup","section":{"id":8,"name":"Telegram"},"category":{"id":66,"name":"Премиум ⚡️"},"group":{"id":161,"name":"Премиум"},"image_url":"https://aviedo.net/tovars/products-78a1cdf7.webp","position":1,"price":{"currency":"USD","model":"fixed","unit_price":"12.67","unit":"pcs"},"quantity":{"min":1,"max":1,"step":1,"label":"Количество"},"stock":{"in_stock":true,"count":null,"checked_at":null},"available":true,"unavailable_reason":null,"available_until":null,"eta":"Доставка после оплаты.","requires":{"chat":false,"end_user_action":false,"email_code":false},"fields_version":"93f74da7","fields":[{"key":"telegram_username","label":"Username в Telegram","type":"telegram_username","required":true,"min_length":3,"max_length":32,"pattern":"^[A-Za-z0-9_]{3,32}$","options":null,"hint":"Можно с @ или ссылкой t.me/…","sensitive":false}]},{"id":854,"name":"6 месяцев","kind":"auto","type":"telegram_premium","result":"topup","section":{"id":8,"name":"Telegram"},"category":{"id":66,"name":"Премиум ⚡️"},"group":{"id":161,"name":"Премиум"},"image_url":"https://aviedo.net/tovars/products-b63fa9ab.webp","position":2,"price":{"currency":"USD","model":"fixed","unit_price":"16.89","unit":"pcs"},"quantity":{"min":1,"max":1,"step":1,"label":"Количество"},"stock":{"in_stock":true,"count":null,"checked_at":null},"available":true,"unavailable_reason":null,"available_until":null,"eta":"Доставка после оплаты.","requires":{"chat":false,"end_user_action":false,"email_code":false},"fields_version":"93f74da7","fields":[{"key":"telegram_username","label":"Username в Telegram","type":"telegram_username","required":true,"min_length":3,"max_length":32,"pattern":"^[A-Za-z0-9_]{3,32}$","options":null,"hint":"Можно с @ или ссылкой t.me/…","sensitive":false}]},{"id":855,"name":"1 год","kind":"manual","type":"manual","result":"service","section":{"id":8,"name":"Telegram"},"category":{"id":66,"name":"Премиум ⚡️"},"group":{"id":161,"name":"Премиум"},"image_url":"https://aviedo.net/tovars/products-912a6881.webp","position":3,"price":{"currency":"USD","model":"fixed","unit_price":"30.32","unit":"pcs"},"quantity":{"min":1,"max":1,"step":1,"label":"Количество"},"stock":{"in_stock":true,"count":null,"checked_at":null},"available":true,"unavailable_reason":null,"available_until":null,"eta":"Доставка после оплаты.","requires":{"chat":true,"end_user_action":false,"email_code":false},"fields_version":"2eed9004","fields":[{"key":"comment","label":"Комментарий","type":"text","required":false,"min_length":null,"max_length":1000,"pattern":null,"options":null,"hint":"Пожелания покупателя, необязательно","sensitive":false}]}]}]}]},"request_id":"req_71cca15f3c50"}}}}}},"304":{"description":"Каталог не изменился (передан актуальный `If-None-Match`). Тела нет.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"ETag":{"$ref":"#/components/headers/ETag"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"400":{"description":"- `invalid_request` — неверный тип или значение параметра (`details.param`), в том числе значение в `fields` не строка и не целое число\n- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"invalid_request":{"summary":"invalid_request: неизвестный kind","value":{"ok":false,"error":{"code":"invalid_request","message":"Параметр kind: допустимо auto, uploaded, manual","retryable":false,"retry_after":null,"details":{"param":"kind","allowed":["auto","uploaded","manual"]}},"request_id":"req_db3b6beff33e"}},"unknown_parameter":{"summary":"unknown_parameter: опечатка в query","value":{"ok":false,"error":{"code":"unknown_parameter","message":"Неизвестный параметр: statuss","retryable":false,"retry_after":null,"details":{"param":"statuss","allowed":["status","kind","product_id","from","to","updated_since","has_unread","delayed","test","limit","cursor"]}},"request_id":"req_f28a29e21c06"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}},"503":{"description":"- `rate_unavailable` — курс доллара устарел, заказы не принимаются","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_unavailable":{"summary":"rate_unavailable","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"rate_unavailable","message":"Курс доллара временно недоступен","retryable":true,"retry_after":300,"details":null},"request_id":"req_a4e7b1c0d935"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo GET '/v1/catalog'"},{"lang":"PHP","label":"PHP","source":"$res = $api->get('/v1/catalog');"},{"lang":"Python","label":"Python","source":"res = api.get(\"/v1/catalog\")"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.get(\"/v1/catalog\");"}]}},"/v1/products":{"get":{"tags":["Каталог"],"operationId":"listProducts","summary":"Товары списком","description":"Тот же объект Product, но плоским списком — удобно синхронизировать товары со своей базой.\n\n- С `ids` (до 200 через запятую) возвращает товары **даже скрытые** (`available: false` и причина) в порядке `ids`; несуществующие и удалённые ID перечисляются в `meta.not_found`. Такие запросы входят только в общий лимит.\n- Без `ids` возвращает видимые товары по фильтрам и считается в лимит каталога (**6 в минуту**).\n\nПоддерживает `ETag` / `If-None-Match`, как каталог.","parameters":[{"name":"ids","in":"query","required":false,"description":"До 200 ID товаров через запятую.","schema":{"type":"string"},"example":"853,29,1187"},{"name":"section_id","in":"query","required":false,"description":"Фильтр по разделу.","schema":{"type":"integer","minimum":1}},{"name":"category_id","in":"query","required":false,"description":"Фильтр по категории.","schema":{"type":"integer","minimum":1},"example":66},{"name":"kind","in":"query","required":false,"description":"Виды товаров через запятую.","schema":{"type":"string"}},{"name":"in_stock","in":"query","required":false,"description":"`1` — только в наличии.","schema":{"type":"string","enum":["1","0","true","false"]}},{"name":"If-None-Match","in":"header","required":false,"description":"ETag из прошлого ответа — как есть. Если ничего не изменилось, придёт `304` без тела.","schema":{"type":"string"},"example":"W/\"2367397b7c9a28379efbb74df61a1a44\""}],"responses":{"200":{"description":"Товары.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"ETag":{"$ref":"#/components/headers/ETag"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","meta","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Product"}},"meta":{"type":"object","properties":{"not_found":{"type":"array","items":{"type":"integer"},"description":"ID из `ids`, которых нет или которые удалены."}},"required":["not_found"],"additionalProperties":false},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"by_category":{"summary":"Товары категории (category_id=66)","value":{"ok":true,"data":[{"id":853,"name":"3 месяца","kind":"auto","type":"telegram_premium","result":"topup","section":{"id":8,"name":"Telegram"},"category":{"id":66,"name":"Премиум ⚡️"},"group":{"id":161,"name":"Премиум"},"image_url":"https://aviedo.net/tovars/products-78a1cdf7.webp","position":1,"price":{"currency":"USD","model":"fixed","unit_price":"12.67","unit":"pcs"},"quantity":{"min":1,"max":1,"step":1,"label":"Количество"},"stock":{"in_stock":true,"count":null,"checked_at":null},"available":true,"unavailable_reason":null,"available_until":null,"eta":"Доставка после оплаты.","requires":{"chat":false,"end_user_action":false,"email_code":false},"fields_version":"93f74da7","fields":[{"key":"telegram_username","label":"Username в Telegram","type":"telegram_username","required":true,"min_length":3,"max_length":32,"pattern":"^[A-Za-z0-9_]{3,32}$","options":null,"hint":"Можно с @ или ссылкой t.me/…","sensitive":false}]},{"id":854,"name":"6 месяцев","kind":"auto","type":"telegram_premium","result":"topup","section":{"id":8,"name":"Telegram"},"category":{"id":66,"name":"Премиум ⚡️"},"group":{"id":161,"name":"Премиум"},"image_url":"https://aviedo.net/tovars/products-b63fa9ab.webp","position":2,"price":{"currency":"USD","model":"fixed","unit_price":"16.89","unit":"pcs"},"quantity":{"min":1,"max":1,"step":1,"label":"Количество"},"stock":{"in_stock":true,"count":null,"checked_at":null},"available":true,"unavailable_reason":null,"available_until":null,"eta":"Доставка после оплаты.","requires":{"chat":false,"end_user_action":false,"email_code":false},"fields_version":"93f74da7","fields":[{"key":"telegram_username","label":"Username в Telegram","type":"telegram_username","required":true,"min_length":3,"max_length":32,"pattern":"^[A-Za-z0-9_]{3,32}$","options":null,"hint":"Можно с @ или ссылкой t.me/…","sensitive":false}]},{"id":855,"name":"1 год","kind":"manual","type":"manual","result":"service","section":{"id":8,"name":"Telegram"},"category":{"id":66,"name":"Премиум ⚡️"},"group":{"id":161,"name":"Премиум"},"image_url":"https://aviedo.net/tovars/products-912a6881.webp","position":3,"price":{"currency":"USD","model":"fixed","unit_price":"30.32","unit":"pcs"},"quantity":{"min":1,"max":1,"step":1,"label":"Количество"},"stock":{"in_stock":true,"count":null,"checked_at":null},"available":true,"unavailable_reason":null,"available_until":null,"eta":"Доставка после оплаты.","requires":{"chat":true,"end_user_action":false,"email_code":false},"fields_version":"2eed9004","fields":[{"key":"comment","label":"Комментарий","type":"text","required":false,"min_length":null,"max_length":1000,"pattern":null,"options":null,"hint":"Пожелания покупателя, необязательно","sensitive":false}]}],"meta":{"not_found":[]},"request_id":"req_d38a5dbfd4fd"}},"by_ids":{"summary":"По ids, со скрытым и несуществующим","value":{"ok":true,"data":[{"id":853,"name":"3 месяца","kind":"auto","type":"telegram_premium","result":"topup","section":{"id":8,"name":"Telegram"},"category":{"id":66,"name":"Премиум ⚡️"},"group":{"id":161,"name":"Премиум"},"image_url":"https://aviedo.net/tovars/products-78a1cdf7.webp","position":1,"price":{"currency":"USD","model":"fixed","unit_price":"12.67","unit":"pcs"},"quantity":{"min":1,"max":1,"step":1,"label":"Количество"},"stock":{"in_stock":true,"count":null,"checked_at":null},"available":true,"unavailable_reason":null,"available_until":null,"eta":"Доставка после оплаты.","requires":{"chat":false,"end_user_action":false,"email_code":false},"fields_version":"93f74da7","fields":[{"key":"telegram_username","label":"Username в Telegram","type":"telegram_username","required":true,"min_length":3,"max_length":32,"pattern":"^[A-Za-z0-9_]{3,32}$","options":null,"hint":"Можно с @ или ссылкой t.me/…","sensitive":false}]},{"id":29,"name":"50 - 100 000 звёзд","kind":"auto","type":"telegram_stars","result":"topup","section":{"id":8,"name":"Telegram"},"category":{"id":4,"name":"Звёзды ⚡️"},"group":{"id":8,"name":"Звёзды"},"image_url":"https://aviedo.net/tovars/product211-e7fac83c.webp","position":2,"price":{"currency":"USD","model":"per_unit","unit_price":"0.015960","unit":"star"},"quantity":{"min":50,"max":100000,"step":1,"label":"Количество звёзд"},"stock":{"in_stock":true,"count":null,"checked_at":null},"available":true,"unavailable_reason":null,"available_until":null,"eta":"Доставка после оплаты.","requires":{"chat":false,"end_user_action":false,"email_code":false},"fields_version":"93f74da7","fields":[{"key":"telegram_username","label":"Username в Telegram","type":"telegram_username","required":true,"min_length":3,"max_length":32,"pattern":"^[A-Za-z0-9_]{3,32}$","options":null,"hint":"Можно с @ или ссылкой t.me/…","sensitive":false}]},{"id":1187,"name":"Family • 1 месяц","kind":"uploaded","type":"digital_item","result":"item","section":{"id":43,"name":"Spotify"},"category":{"id":86,"name":"Подписки (EG) ⚡️"},"group":{"id":200,"name":"Family"},"image_url":"https://aviedo.net/tovars/products-49d74742.webp","position":0,"price":{"currency":"USD","model":"fixed","unit_price":"3.72","unit":"pcs"},"quantity":{"min":1,"max":4,"step":1,"label":"Количество"},"stock":{"in_stock":true,"count":4,"checked_at":null},"available":true,"unavailable_reason":null,"available_until":null,"eta":"Доставка до 2-х минут","requires":{"chat":false,"end_user_action":false,"email_code":false},"fields_version":"97d170e1","fields":[]},{"id":1259,"name":"Profile Package","kind":"manual","type":"manual","result":"service","section":{"id":14,"name":"CookieRun: Kingdom"},"category":{"id":31,"name":"Через Devplay"},"group":{"id":177,"name":"Cosmetics"},"image_url":"https://aviedo.net/tovars/2-0b072c9f.webp","position":0,"price":{"currency":"USD","model":"fixed","unit_price":"3.98","unit":"pcs"},"quantity":{"min":1,"max":1,"step":1,"label":"Количество"},"stock":{"in_stock":true,"count":null,"checked_at":null},"available":true,"unavailable_reason":null,"available_until":"2026-10-20T00:00:00+03:00","eta":"Выполнение до 2-х часов.","requires":{"chat":true,"end_user_action":false,"email_code":false},"fields_version":"f505abab","fields":[{"key":"privyazannaya_pochta","label":"Привязанная почта","type":"text","required":true,"min_length":null,"max_length":2000,"pattern":null,"options":null,"hint":null,"sensitive":false},{"key":"parol","label":"Пароль","type":"password","required":true,"min_length":null,"max_length":2000,"pattern":null,"options":null,"hint":null,"sensitive":true},{"key":"comment","label":"Комментарий","type":"text","required":false,"min_length":null,"max_length":1000,"pattern":null,"options":null,"hint":"Пожелания покупателя, необязательно","sensitive":false}]},{"id":171,"name":"80 робуксов","kind":"auto","type":"robux","result":"topup","section":{"id":18,"name":"Roblox"},"category":{"id":19,"name":"Через вход ⚡️"},"group":{"id":42,"name":"Набор робуксов"},"image_url":"https://aviedo.net/tovars/product212-934e3ed8.webp","position":2,"price":{"currency":"USD","model":"fixed","unit_price":"0.89","unit":"pcs"},"quantity":{"min":1,"max":1,"step":1,"label":"Количество"},"stock":{"in_stock":true,"count":null,"checked_at":null},"available":true,"unavailable_reason":null,"available_until":null,"eta":"Автоматическая доставка.","requires":{"chat":false,"end_user_action":true,"email_code":false},"fields_version":"8af1a140","fields":[{"key":"roblox_username","label":"Логин аккаунта Roblox","type":"text","required":true,"min_length":null,"max_length":64,"pattern":null,"options":null,"hint":null,"sensitive":false},{"key":"roblox_password","label":"Пароль Roblox","type":"password","required":false,"min_length":null,"max_length":200,"pattern":null,"options":null,"hint":null,"sensitive":true}]},{"id":1254,"name":"250 монет + эпик бокс","kind":"auto","type":"game_topup","result":"topup","section":{"id":47,"name":"Oxide: Survival Island"},"category":{"id":90,"name":"Через айди"},"group":{"id":208,"name":"Персональные акции"},"image_url":"https://aviedo.net/tovars/8-21adda58.webp","position":0,"price":{"currency":"USD","model":"fixed","unit_price":"6.01","unit":"pcs"},"quantity":{"min":1,"max":1,"step":1,"label":"Количество"},"stock":{"in_stock":true,"count":null,"checked_at":null},"available":true,"unavailable_reason":null,"available_until":null,"eta":"Доставка после оплаты.","requires":{"chat":false,"end_user_action":false,"email_code":false},"fields_version":"023bb612","fields":[{"key":"player_id","label":"Player ID","type":"text","required":true,"min_length":null,"max_length":2000,"pattern":null,"options":null,"hint":null,"sensitive":false}]},{"id":68,"name":"Пополнение RUB","kind":"auto","type":"steam_topup","result":"topup","section":{"id":7,"name":"Steam"},"category":{"id":9,"name":"Через логин ⚡️"},"group":{"id":21,"name":"Пополнение"},"image_url":"https://aviedo.net/tovars/product284-229a372d.webp","position":1,"price":{"currency":"USD","model":"per_unit","unit_price":"0.011569","unit":"RUB"},"quantity":{"min":20,"max":45000,"step":1,"label":"Сумма пополнения, RUB"},"stock":{"in_stock":true,"count":null,"checked_at":null},"available":true,"unavailable_reason":null,"available_until":null,"eta":"Доставка после оплаты.","requires":{"chat":false,"end_user_action":false,"email_code":false},"fields_version":"efd3fc27","fields":[{"key":"steam_login","label":"Логин Steam","type":"text","required":true,"min_length":null,"max_length":64,"pattern":null,"options":null,"hint":null,"sensitive":false}]},{"id":1141,"name":"190 гемов (если есть)","kind":"manual","type":"manual_login","result":"service","section":{"id":1,"name":"Brawl Stars"},"category":{"id":1,"name":"Через вход"},"group":{"id":3,"name":"Особые акции"},"image_url":"https://aviedo.net/tovars/products-86c10f2c.webp","position":0,"price":{"currency":"USD","model":"fixed","unit_price":"6.03","unit":"pcs"},"quantity":{"min":1,"max":1,"step":1,"label":"Количество"},"stock":{"in_stock":true,"count":null,"checked_at":null},"available":true,"unavailable_reason":null,"available_until":null,"eta":"Выполнение до 2-х часов.","requires":{"chat":true,"end_user_action":false,"email_code":true},"fields_version":"27169afe","fields":[{"key":"email","label":"Привязанная почта","type":"email","required":true,"min_length":null,"max_length":254,"pattern":null,"options":null,"hint":"Сначала отправьте код: POST /v1/products/{id}/send-code","sensitive":false},{"key":"code","label":"Код с почты","type":"text","required":true,"min_length":null,"max_length":32,"pattern":null,"options":null,"hint":"Код из письма Supercell","sensitive":false},{"key":"comment","label":"Комментарий","type":"text","required":false,"min_length":null,"max_length":1000,"pattern":null,"options":null,"hint":"Пожелания покупателя, необязательно","sensitive":false}]},{"id":1238,"name":"Лунная Лола","kind":"manual","type":"manual_login","result":"service","section":{"id":1,"name":"Brawl Stars"},"category":{"id":1,"name":"Через вход"},"group":{"id":3,"name":"Особые акции"},"image_url":"https://aviedo.net/tovars/logo2-52ef1028.webp","position":0,"price":{"currency":"USD","model":"fixed","unit_price":"7.74","unit":"pcs"},"quantity":{"min":1,"max":1,"step":1,"label":"Количество"},"stock":{"in_stock":true,"count":null,"checked_at":null},"available":false,"unavailable_reason":"hidden","available_until":null,"eta":"Выполнение до 2-х часов.","requires":{"chat":true,"end_user_action":false,"email_code":true},"fields_version":"27169afe","fields":[{"key":"email","label":"Привязанная почта","type":"email","required":true,"min_length":null,"max_length":254,"pattern":null,"options":null,"hint":"Сначала отправьте код: POST /v1/products/{id}/send-code","sensitive":false},{"key":"code","label":"Код с почты","type":"text","required":true,"min_length":null,"max_length":32,"pattern":null,"options":null,"hint":"Код из письма Supercell","sensitive":false},{"key":"comment","label":"Комментарий","type":"text","required":false,"min_length":null,"max_length":1000,"pattern":null,"options":null,"hint":"Пожелания покупателя, необязательно","sensitive":false}]}],"meta":{"not_found":[999999999]},"request_id":"req_2f5a2af1be9c"}}}}}},"304":{"description":"Список не изменился. Тела нет.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"ETag":{"$ref":"#/components/headers/ETag"},"Cache-Control":{"$ref":"#/components/headers/Cache-Control"}}},"400":{"description":"- `invalid_request` — неверный тип или значение параметра (`details.param`), в том числе значение в `fields` не строка и не целое число\n- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"invalid_request":{"summary":"invalid_request: неизвестный kind","value":{"ok":false,"error":{"code":"invalid_request","message":"Параметр kind: допустимо auto, uploaded, manual","retryable":false,"retry_after":null,"details":{"param":"kind","allowed":["auto","uploaded","manual"]}},"request_id":"req_db3b6beff33e"}},"unknown_parameter":{"summary":"unknown_parameter: опечатка в query","value":{"ok":false,"error":{"code":"unknown_parameter","message":"Неизвестный параметр: statuss","retryable":false,"retry_after":null,"details":{"param":"statuss","allowed":["status","kind","product_id","from","to","updated_since","has_unread","delayed","test","limit","cursor"]}},"request_id":"req_f28a29e21c06"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}},"503":{"description":"- `rate_unavailable` — курс доллара устарел, заказы не принимаются","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_unavailable":{"summary":"rate_unavailable","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"rate_unavailable","message":"Курс доллара временно недоступен","retryable":true,"retry_after":300,"details":null},"request_id":"req_a4e7b1c0d935"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo GET '/v1/products?ids=853,29,1187'"},{"lang":"PHP","label":"PHP","source":"$res = $api->get('/v1/products', [\n    'ids' => '853,29,1187',\n]);"},{"lang":"Python","label":"Python","source":"res = api.get(\"/v1/products\", {\n    \"ids\": \"853,29,1187\",\n})"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.get(\"/v1/products\", {\n  ids: \"853,29,1187\",\n});"}]}},"/v1/products/{id}":{"get":{"tags":["Каталог"],"operationId":"getProduct","summary":"Один товар со свежими ценой и наличием","description":"Один товар с **самыми свежими** ценой и наличием: остаток подарочных карт и ваучеров уточняется у поставщика (кэш до 2 минут). Вызывайте на странице товара и перед заказом.\n\n- Скрытый товар — `200` с `available: false` и `unavailable_reason`.\n- Удалённый или несуществующий — `404 product_not_found`.","parameters":[{"name":"id","in":"path","required":true,"description":"ID товара.","schema":{"type":"integer","minimum":1},"example":853}],"responses":{"200":{"description":"Товар.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Product"},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"auto":{"summary":"auto: Telegram Premium","value":{"ok":true,"data":{"id":853,"name":"3 месяца","kind":"auto","type":"telegram_premium","result":"topup","section":{"id":8,"name":"Telegram"},"category":{"id":66,"name":"Премиум ⚡️"},"group":{"id":161,"name":"Премиум"},"image_url":"https://aviedo.net/tovars/products-78a1cdf7.webp","position":1,"price":{"currency":"USD","model":"fixed","unit_price":"12.67","unit":"pcs"},"quantity":{"min":1,"max":1,"step":1,"label":"Количество"},"stock":{"in_stock":true,"count":null,"checked_at":null},"available":true,"unavailable_reason":null,"available_until":null,"eta":"Доставка после оплаты.","requires":{"chat":false,"end_user_action":false,"email_code":false},"fields_version":"93f74da7","fields":[{"key":"telegram_username","label":"Username в Telegram","type":"telegram_username","required":true,"min_length":3,"max_length":32,"pattern":"^[A-Za-z0-9_]{3,32}$","options":null,"hint":"Можно с @ или ссылкой t.me/…","sensitive":false}]},"request_id":"req_b1492a32d526"}},"uploaded":{"summary":"uploaded: с остатком","value":{"ok":true,"data":{"id":1187,"name":"Family • 1 месяц","kind":"uploaded","type":"digital_item","result":"item","section":{"id":43,"name":"Spotify"},"category":{"id":86,"name":"Подписки (EG) ⚡️"},"group":{"id":200,"name":"Family"},"image_url":"https://aviedo.net/tovars/products-49d74742.webp","position":0,"price":{"currency":"USD","model":"fixed","unit_price":"3.72","unit":"pcs"},"quantity":{"min":1,"max":4,"step":1,"label":"Количество"},"stock":{"in_stock":true,"count":4,"checked_at":null},"available":true,"unavailable_reason":null,"available_until":null,"eta":"Доставка до 2-х минут","requires":{"chat":false,"end_user_action":false,"email_code":false},"fields_version":"97d170e1","fields":[]},"request_id":"req_ad80be6067de"}},"manual":{"summary":"manual: поля формы и comment","value":{"ok":true,"data":{"id":1259,"name":"Profile Package","kind":"manual","type":"manual","result":"service","section":{"id":14,"name":"CookieRun: Kingdom"},"category":{"id":31,"name":"Через Devplay"},"group":{"id":177,"name":"Cosmetics"},"image_url":"https://aviedo.net/tovars/2-0b072c9f.webp","position":0,"price":{"currency":"USD","model":"fixed","unit_price":"3.98","unit":"pcs"},"quantity":{"min":1,"max":1,"step":1,"label":"Количество"},"stock":{"in_stock":true,"count":null,"checked_at":null},"available":true,"unavailable_reason":null,"available_until":"2026-10-20T00:00:00+03:00","eta":"Выполнение до 2-х часов.","requires":{"chat":true,"end_user_action":false,"email_code":false},"fields_version":"f505abab","fields":[{"key":"privyazannaya_pochta","label":"Привязанная почта","type":"text","required":true,"min_length":null,"max_length":2000,"pattern":null,"options":null,"hint":null,"sensitive":false},{"key":"parol","label":"Пароль","type":"password","required":true,"min_length":null,"max_length":2000,"pattern":null,"options":null,"hint":null,"sensitive":true},{"key":"comment","label":"Комментарий","type":"text","required":false,"min_length":null,"max_length":1000,"pattern":null,"options":null,"hint":"Пожелания покупателя, необязательно","sensitive":false}]},"request_id":"req_7b1373f17185"}},"manual_login":{"summary":"manual_login: Supercell ID","value":{"ok":true,"data":{"id":1141,"name":"190 гемов (если есть)","kind":"manual","type":"manual_login","result":"service","section":{"id":1,"name":"Brawl Stars"},"category":{"id":1,"name":"Через вход"},"group":{"id":3,"name":"Особые акции"},"image_url":"https://aviedo.net/tovars/products-86c10f2c.webp","position":0,"price":{"currency":"USD","model":"fixed","unit_price":"6.03","unit":"pcs"},"quantity":{"min":1,"max":1,"step":1,"label":"Количество"},"stock":{"in_stock":true,"count":null,"checked_at":null},"available":true,"unavailable_reason":null,"available_until":null,"eta":"Выполнение до 2-х часов.","requires":{"chat":true,"end_user_action":false,"email_code":true},"fields_version":"27169afe","fields":[{"key":"email","label":"Привязанная почта","type":"email","required":true,"min_length":null,"max_length":254,"pattern":null,"options":null,"hint":"Сначала отправьте код: POST /v1/products/{id}/send-code","sensitive":false},{"key":"code","label":"Код с почты","type":"text","required":true,"min_length":null,"max_length":32,"pattern":null,"options":null,"hint":"Код из письма Supercell","sensitive":false},{"key":"comment","label":"Комментарий","type":"text","required":false,"min_length":null,"max_length":1000,"pattern":null,"options":null,"hint":"Пожелания покупателя, необязательно","sensitive":false}]},"request_id":"req_4908025dc09b"}},"hidden":{"summary":"Скрытый товар","value":{"ok":true,"data":{"id":1238,"name":"Лунная Лола","kind":"manual","type":"manual_login","result":"service","section":{"id":1,"name":"Brawl Stars"},"category":{"id":1,"name":"Через вход"},"group":{"id":3,"name":"Особые акции"},"image_url":"https://aviedo.net/tovars/logo2-52ef1028.webp","position":0,"price":{"currency":"USD","model":"fixed","unit_price":"7.74","unit":"pcs"},"quantity":{"min":1,"max":1,"step":1,"label":"Количество"},"stock":{"in_stock":true,"count":null,"checked_at":null},"available":false,"unavailable_reason":"hidden","available_until":null,"eta":"Выполнение до 2-х часов.","requires":{"chat":true,"end_user_action":false,"email_code":true},"fields_version":"27169afe","fields":[{"key":"email","label":"Привязанная почта","type":"email","required":true,"min_length":null,"max_length":254,"pattern":null,"options":null,"hint":"Сначала отправьте код: POST /v1/products/{id}/send-code","sensitive":false},{"key":"code","label":"Код с почты","type":"text","required":true,"min_length":null,"max_length":32,"pattern":null,"options":null,"hint":"Код из письма Supercell","sensitive":false},{"key":"comment","label":"Комментарий","type":"text","required":false,"min_length":null,"max_length":1000,"pattern":null,"options":null,"hint":"Пожелания покупателя, необязательно","sensitive":false}]},"request_id":"req_052e478ee8d1"}}}}}},"400":{"description":"- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"unknown_parameter":{"summary":"unknown_parameter: опечатка в query","value":{"ok":false,"error":{"code":"unknown_parameter","message":"Неизвестный параметр: statuss","retryable":false,"retry_after":null,"details":{"param":"statuss","allowed":["status","kind","product_id","from","to","updated_since","has_unread","delayed","test","limit","cursor"]}},"request_id":"req_f28a29e21c06"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"404":{"description":"- `product_not_found` — товар удалён или не существовал","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"product_not_found":{"summary":"product_not_found","value":{"ok":false,"error":{"code":"product_not_found","message":"Товар не найден","retryable":false,"retry_after":null,"details":{"product_id":999999999}},"request_id":"req_fad9a45e409e"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}},"503":{"description":"- `rate_unavailable` — курс доллара устарел, заказы не принимаются","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_unavailable":{"summary":"rate_unavailable","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"rate_unavailable","message":"Курс доллара временно недоступен","retryable":true,"retry_after":300,"details":null},"request_id":"req_a4e7b1c0d935"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo GET '/v1/products/853'"},{"lang":"PHP","label":"PHP","source":"$res = $api->get('/v1/products/853');"},{"lang":"Python","label":"Python","source":"res = api.get(\"/v1/products/853\")"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.get(\"/v1/products/853\");"}]}},"/v1/products/{id}/send-code":{"post":{"tags":["Каталог"],"operationId":"sendSupercellCode","summary":"Отправить код Supercell ID","description":"Только для товаров с `requires.email_code: true` (`type: manual_login`). Supercell ID отправит покупателю письмо с кодом входа; затем **сразу** создайте заказ с `fields.email` и `fields.code`.\n\nПочта сравнивается в нормализованном виде: без пробелов по краям, в нижнем регистре, без `+метки` (`player+shop@example.com` = `player@example.com`), у Gmail — без точек в имени, `googlemail.com` = `gmail.com`. Supercell ID получает почту ровно в том виде, в каком её передали вы.\n\n**Лимиты:**\n- на одну почту — не чаще раза в 60 секунд и не больше 10 кодов за 24 часа, **общие для всех реселлеров** (`429 send_code_cooldown`, `details.reason` = `cooldown` / `email_daily_limit`; `provider_throttled` — если Supercell сам ограничил отправку);\n- на ваш аккаунт — 200 отправок за 24 часа (`429 rate_limited`, `bucket: send_code_day`) и одна отправка одновременно (`bucket: send_code_inflight`, `Retry-After: 5`);\n- 10 запросов в минуту (`bucket: send_code`).\n\nВ лимиты засчитываются только попытки, дошедшие до Supercell ID. Если сервис отправки занят или недоступен (`503 provider_unavailable`, `Retry-After` 5 или 30), попытка не засчитывается.","parameters":[{"name":"id","in":"path","required":true,"description":"ID товара с `requires.email_code: true`.","schema":{"type":"integer","minimum":1},"example":1141}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendCodeRequest"},"example":{"email":"player@example.com"}}}},"responses":{"200":{"description":"Код отправлен.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/SendCodeResult"},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"ok":{"summary":"Код отправлен","description":"Форма ответа (успешная отправка вызывает настоящий Supercell ID, поэтому в тестовом прогоне не выполнялась).","value":{"ok":true,"data":{"sent":true,"cooldown_seconds":60},"request_id":"req_2d7a9f4c1e60"}}}}}},"400":{"description":"- `invalid_json` — тело не является JSON-объектом\n- `invalid_request` — неверный тип или значение параметра (`details.param`), в том числе значение в `fields` не строка и не целое число\n- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"invalid_json":{"summary":"invalid_json","value":{"ok":false,"error":{"code":"invalid_json","message":"Тело запроса не является валидным JSON","retryable":false,"retry_after":null,"details":null},"request_id":"req_64e1e4cef951"}},"invalid_request":{"summary":"invalid_request: товару не нужен код","value":{"ok":false,"error":{"code":"invalid_request","message":"Этому товару не нужен код Supercell ID","retryable":false,"retry_after":null,"details":{"param":"product_id","reason":"email_code_not_required"}},"request_id":"req_50aee81548ab"}},"unknown_parameter":{"summary":"unknown_parameter: опечатка в теле","value":{"ok":false,"error":{"code":"unknown_parameter","message":"Неизвестный параметр: quantiy","retryable":false,"retry_after":null,"details":{"param":"quantiy","allowed":["product_id","quantity","external_id","max_total_usd","fields","meta","accept_chat","test","test_scenario"]}},"request_id":"req_5fe9d8284333"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"404":{"description":"- `product_not_found` — товар удалён или не существовал","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"product_not_found":{"summary":"product_not_found","value":{"ok":false,"error":{"code":"product_not_found","message":"Товар не найден","retryable":false,"retry_after":null,"details":{"product_id":999999999}},"request_id":"req_fad9a45e409e"}}}}}},"409":{"description":"- `product_unavailable` — товар скрыт или истёк (`details.reason`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"product_unavailable":{"summary":"product_unavailable: скрыт","value":{"ok":false,"error":{"code":"product_unavailable","message":"Товар временно скрыт","retryable":false,"retry_after":null,"details":{"reason":"hidden","product_id":1238}},"request_id":"req_0a2f0ac5721e"}}}}}},"413":{"description":"- `payload_too_large` — тело больше 8 МБ или картинка больше 5 МБ","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"payload_too_large":{"summary":"payload_too_large","value":{"ok":false,"error":{"code":"payload_too_large","message":"Тело запроса слишком большое","retryable":false,"retry_after":null,"details":{"max_bytes":8388608}},"request_id":"req_83c446683620"}}}}}},"415":{"description":"- `unsupported_media_type` — у POST нет Content-Type: application/json","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"unsupported_media_type":{"summary":"unsupported_media_type","value":{"ok":false,"error":{"code":"unsupported_media_type","message":"Нужен заголовок Content-Type: application/json","retryable":false,"retry_after":null,"details":null},"request_id":"req_aba6339e4cfa"}}}}}},"422":{"description":"- `validation_failed` — ошибки в полях (`details.errors[]`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"validation_failed":{"summary":"validation_failed: e-mail","value":{"ok":false,"error":{"code":"validation_failed","message":"Неверный формат e-mail","retryable":false,"retry_after":null,"details":{"errors":[{"field":"email","code":"invalid_format","message":"Неверный формат e-mail"}]}},"request_id":"req_ecae30bd704f"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)\n- `send_code_cooldown` — код на эту почту уже отправляли (`details.reason`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}},"send_code_cooldown":{"summary":"send_code_cooldown","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"send_code_cooldown","message":"Код на эту почту уже отправлен, повторить можно через 42 с","retryable":true,"retry_after":42,"details":{"retry_after":42,"reason":"cooldown"}},"request_id":"req_8d2b6e4f1a07"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}},"503":{"description":"- `provider_unavailable` — поставщик или сервис проверки недоступен\n- `maintenance` — технические работы","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"provider_unavailable":{"summary":"provider_unavailable","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"provider_unavailable","message":"Сервис Premium временно недоступен","retryable":true,"retry_after":60,"details":null},"request_id":"req_e2a95b7c3d10"}},"maintenance":{"summary":"maintenance","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"maintenance","message":"Идут технические работы","retryable":true,"retry_after":60,"details":null},"request_id":"req_0f6d2c8a4b19"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo POST /v1/products/1141/send-code '{\"email\":\"player@example.com\"}'"},{"lang":"PHP","label":"PHP","source":"$res = $api->post('/v1/products/1141/send-code', [\n    'email' => 'player@example.com',\n]);"},{"lang":"Python","label":"Python","source":"res = api.post(\"/v1/products/1141/send-code\", {\n    \"email\": \"player@example.com\",\n})"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.post(\"/v1/products/1141/send-code\", {\n  email: \"player@example.com\",\n});"}]}},"/v1/orders/quote":{"post":{"tags":["Заказы"],"operationId":"quoteOrder","summary":"Проверить заказ без покупки","description":"Тело такое же, как у создания заказа, но `external_id` и `max_total_usd` не обязательны. Проверяет поля, количество, наличие, баланс и — для Telegram Premium — существование получателя у поставщика. **Деньги не списываются, заказ не создаётся.**\n\nПричины, по которым заказ нельзя оформить, приходят не ошибкой, а списком `problems` — с теми же кодами, текстами и `details`, что вернул бы `POST /v1/orders` с этим телом: незаполненное обязательное поле — `validation_failed` с `errors[].code = \"required\"`, не переданное или неверное `quantity` — `quantity_out_of_range`. `can_order: true` только при пустом `problems`. Ошибкой метод отвечает только на битый запрос, несуществующий товар, технические работы и устаревший курс.\n\nЕсли количество не прошло проверку (не передано, вне диапазона, больше остатка), `quantity`, `total` и `balance_after` посчитаны для `quantity.min` товара — только для ориентира.\n\n`checks.*`: `ok`, `failed`, `skipped` (не проверялось) или `not_supported` (для товара проверки нет). С `\"test\": true` получатель у поставщика не проверяется, остаток берётся из кэша, как в каталоге, а сценарии `out_of_stock` и `account_not_found` попадают в `problems`. Лимит — 60 в минуту.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteRequest"},"examples":{"premium":{"summary":"Telegram Premium","value":{"product_id":853,"fields":{"telegram_username":"durov"},"test":true}},"problems":{"summary":"20 000 звёзд при балансе 250 $","value":{"product_id":29,"quantity":20000,"max_total_usd":"250.00","fields":{"telegram_username":"durov"},"test":true}},"missing":{"summary":"Звёзды без полей и количества","value":{"product_id":29,"test":true}}}}}},"responses":{"200":{"description":"Результат проверки.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Quote"},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"can_order":{"summary":"Можно заказать","value":{"ok":true,"data":{"can_order":true,"product_id":853,"quantity":1,"currency":"USD","unit_price":"12.67","total":"12.67","balance":"250.00","balance_after":"237.33","checks":{"fields":"ok","quantity":"ok","stock":"ok","account":"ok"},"problems":[]},"request_id":"req_28cad1daedaf"}},"problems":{"summary":"Нельзя: не хватает денег, сумма выше max_total_usd","value":{"ok":true,"data":{"can_order":false,"product_id":29,"quantity":20000,"currency":"USD","unit_price":"0.015960","total":"319.20","balance":"250.00","balance_after":"-69.20","checks":{"fields":"ok","quantity":"ok","stock":"ok","account":"not_supported"},"problems":[{"code":"insufficient_funds","message":"Недостаточно средств: не хватает 69.20 $","details":{"missing":"69.20"}},{"code":"price_changed","message":"Цена выше max_total_usd","details":{"total":"319.20"}}]},"request_id":"req_4f8896838a56"}},"missing":{"summary":"Нельзя: не заполнены поле и quantity","value":{"ok":true,"data":{"can_order":false,"product_id":29,"quantity":50,"currency":"USD","unit_price":"0.015960","total":"0.80","balance":"250.00","balance_after":"249.20","checks":{"fields":"failed","quantity":"failed","stock":"ok","account":"not_supported"},"problems":[{"code":"validation_failed","message":"Ошибки в полях заказа","details":{"errors":[{"field":"fields.telegram_username","code":"required","message":"Обязательное поле"}]}},{"code":"quantity_out_of_range","message":"Укажите quantity: от 50 до 100000","details":{"min":50,"max":100000,"step":1}}]},"request_id":"req_cc019831dc68"},"description":"Суммы посчитаны для quantity.min = 50 — только для ориентира."}}}}},"400":{"description":"- `invalid_json` — тело не является JSON-объектом\n- `invalid_request` — неверный тип или значение параметра (`details.param`), в том числе значение в `fields` не строка и не целое число\n- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"invalid_json":{"summary":"invalid_json","value":{"ok":false,"error":{"code":"invalid_json","message":"Тело запроса не является валидным JSON","retryable":false,"retry_after":null,"details":null},"request_id":"req_64e1e4cef951"}},"invalid_request":{"summary":"invalid_request: сценарий не подходит товару","value":{"ok":false,"error":{"code":"invalid_request","message":"test_scenario refund недоступен для товаров kind=uploaded. Допустимо: success, completed_then_refunded, out_of_stock, account_not_found","retryable":false,"retry_after":null,"details":{"param":"test_scenario","kind":"uploaded","allowed":["success","completed_then_refunded","out_of_stock","account_not_found"]}},"request_id":"req_d40ff40701b2"}},"unknown_parameter":{"summary":"unknown_parameter: опечатка в теле","value":{"ok":false,"error":{"code":"unknown_parameter","message":"Неизвестный параметр: quantiy","retryable":false,"retry_after":null,"details":{"param":"quantiy","allowed":["product_id","quantity","external_id","max_total_usd","fields","meta","accept_chat","test","test_scenario"]}},"request_id":"req_5fe9d8284333"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"404":{"description":"- `product_not_found` — товар удалён или не существовал","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"product_not_found":{"summary":"product_not_found","value":{"ok":false,"error":{"code":"product_not_found","message":"Товар не найден","retryable":false,"retry_after":null,"details":{"product_id":999999999}},"request_id":"req_491d08d1172b"}}}}}},"409":{"description":"- `product_unavailable` — товар скрыт или истёк (`details.reason`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"product_unavailable":{"summary":"product_unavailable: скрыт","value":{"ok":false,"error":{"code":"product_unavailable","message":"Товар временно скрыт","retryable":false,"retry_after":null,"details":{"reason":"hidden","product_id":1238}},"request_id":"req_0a2f0ac5721e"}}}}}},"413":{"description":"- `payload_too_large` — тело больше 8 МБ или картинка больше 5 МБ","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"payload_too_large":{"summary":"payload_too_large","value":{"ok":false,"error":{"code":"payload_too_large","message":"Тело запроса слишком большое","retryable":false,"retry_after":null,"details":{"max_bytes":8388608}},"request_id":"req_83c446683620"}}}}}},"415":{"description":"- `unsupported_media_type` — у POST нет Content-Type: application/json","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"unsupported_media_type":{"summary":"unsupported_media_type","value":{"ok":false,"error":{"code":"unsupported_media_type","message":"Нужен заголовок Content-Type: application/json","retryable":false,"retry_after":null,"details":null},"request_id":"req_aba6339e4cfa"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}},"503":{"description":"- `rate_unavailable` — курс доллара устарел, заказы не принимаются\n- `maintenance` — технические работы","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_unavailable":{"summary":"rate_unavailable","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"rate_unavailable","message":"Курс доллара временно недоступен","retryable":true,"retry_after":300,"details":null},"request_id":"req_a4e7b1c0d935"}},"maintenance":{"summary":"maintenance","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"maintenance","message":"Идут технические работы","retryable":true,"retry_after":60,"details":null},"request_id":"req_0f6d2c8a4b19"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo POST /v1/orders/quote '{\"product_id\":853,\"fields\":{\"telegram_username\":\"durov\"},\"test\":true}'"},{"lang":"PHP","label":"PHP","source":"$res = $api->post('/v1/orders/quote', [\n    'product_id' => 853,\n    'fields' => [\n        'telegram_username' => 'durov',\n    ],\n    'test' => true,\n]);"},{"lang":"Python","label":"Python","source":"res = api.post(\"/v1/orders/quote\", {\n    \"product_id\": 853,\n    \"fields\": {\n        \"telegram_username\": \"durov\",\n    },\n    \"test\": True,\n})"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.post(\"/v1/orders/quote\", {\n  product_id: 853,\n  fields: {\n    telegram_username: \"durov\",\n  },\n  test: true,\n});"}]}},"/v1/orders":{"post":{"tags":["Заказы"],"operationId":"createOrder","summary":"Создать и оплатить заказ","description":"Создаёт заказ и **сразу списывает** `price.total` с долларового баланса. Подробно — в разделах «Создание заказа и идемпотентность» и «Поля заказа».\n\n- `external_id` — ваш номер заказа, уникальный навсегда. Повтор с теми же параметрами вернёт `200` и тот же заказ (`meta.idempotent_replay: true`) без второго списания; с другими `product_id`, `quantity` или `fields` — `409 external_id_conflict`. Значения `fields` сравниваются в том виде, в каком переданы (обрезаются только пробелы по краям): `\"@durov\"` и `\"durov\"` — разные запросы.\n- `max_total_usd` — наибольшая сумма; если цена выросла, `409 price_changed`.\n- Статус после создания: `uploaded` — сразу `completed` с ключами в `delivery.items`, `auto` — `processing`, `manual` — `pending`.\n- Любой `4xx`, кроме `409 external_id_conflict`, — заказ не создан и деньги не списаны. При `5xx` и сетевой ошибке повторите тот же запрос с тем же `external_id`. Таймаут клиента — не меньше 45 секунд.\n- `\"test\": true` — тестовый заказ (раздел «Тестовый режим»).\n\nЛимит — 30 в минуту.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOrderRequest"},"examples":{"auto":{"summary":"auto: Telegram Premium","value":{"product_id":853,"quantity":1,"external_id":"shop-1001","max_total_usd":"12.67","fields":{"telegram_username":"durov"},"meta":{"customer":"client-42"},"test":true}},"uploaded":{"summary":"uploaded: 2 штуки","value":{"product_id":1187,"quantity":2,"external_id":"shop-1002","max_total_usd":"7.44","test":true}},"per_unit":{"summary":"per_unit: 100 звёзд","value":{"product_id":29,"quantity":100,"external_id":"shop-1003","max_total_usd":"1.60","fields":{"telegram_username":"@durov"},"test":true}},"manual_chat":{"summary":"manual с accept_chat, сценарий chat","value":{"product_id":1259,"external_id":"shop-1004","max_total_usd":"3.98","fields":{"privyazannaya_pochta":"player@example.com","parol":"S3cret-pass","comment":"Ник в игре: PlayerOne"},"accept_chat":true,"test":true,"test_scenario":"chat"}},"robux":{"summary":"Robux, сценарий action_required","value":{"product_id":171,"external_id":"shop-1006","max_total_usd":"0.89","fields":{"roblox_username":"builderman"},"test":true,"test_scenario":"action_required"}}}}}},"responses":{"201":{"description":"Заказ создан и оплачен.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","meta","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Order"},"meta":{"type":"object","properties":{"idempotent_replay":{"type":"boolean","const":false}},"required":["idempotent_replay"],"additionalProperties":false},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"auto_processing":{"summary":"auto: создан, processing","value":{"ok":true,"data":{"id":"T3088AD3A7FA","external_id":"shop-1001","status":"processing","status_text":"В процессе","delayed":false,"kind":"auto","type":"telegram_premium","test":true,"product":{"id":853,"name":"3 месяца","image_url":"https://aviedo.net/tovars/products-78a1cdf7.webp"},"category":{"id":66,"name":"Премиум ⚡️"},"section":{"id":8,"name":"Telegram"},"quantity":1,"price":{"currency":"USD","unit_price":"12.67","total":"12.67"},"fields":[{"key":"telegram_username","label":"Username в Telegram","value":"durov"}],"meta":{"customer":"client-42"},"delivery":null,"action":null,"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":0,"last_message_at":null},"created_at":"2026-10-12T19:06:15+03:00","updated_at":"2026-10-12T19:06:15+03:00","completed_at":null,"revision":1},"meta":{"idempotent_replay":false},"request_id":"req_f6a6111967eb"},"description":"Telegram Premium, тестовый заказ."},"uploaded_completed":{"summary":"uploaded: сразу completed с ключами","value":{"ok":true,"data":{"id":"TC655EADB878","external_id":"shop-1002","status":"completed","status_text":"Выполнен","delayed":false,"kind":"uploaded","type":"digital_item","test":true,"product":{"id":1187,"name":"Family • 1 месяц","image_url":"https://aviedo.net/tovars/products-49d74742.webp"},"category":{"id":86,"name":"Подписки (EG) ⚡️"},"section":{"id":43,"name":"Spotify"},"quantity":2,"price":{"currency":"USD","unit_price":"3.72","total":"7.44"},"fields":[],"meta":{},"delivery":{"items":[{"type":"item","value":"TEST-CHFH-STL9-87D6"},{"type":"item","value":"TEST-2PTX-YVQV-PSNY"}],"instructions":{"text":"📌 Активировать ключ можно на сайте партнёра: https://premiumcdk.com\n\nБлагодарим Вас за покупку!\nПриятной игры и хорошего дня! 💙","html":"📌 Активировать ключ можно на сайте партнёра: <b>https://premiumcdk.com</b><br><br>Благодарим Вас за покупку!<br>Приятной игры и хорошего дня! 💙"},"attachments":[],"delivered_at":"2026-10-12T19:06:16+03:00"},"action":null,"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":2,"last_message_at":"2026-10-12T19:06:16+03:00"},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:16+03:00","completed_at":"2026-10-12T19:06:16+03:00","revision":4},"meta":{"idempotent_replay":false},"request_id":"req_a06b6a77f477"}},"manual_pending":{"summary":"manual: pending","value":{"ok":true,"data":{"id":"TD0D8BE98162","external_id":"shop-1004","status":"pending","status_text":"Ожидание продавца","delayed":false,"kind":"manual","type":"manual","test":true,"product":{"id":1259,"name":"Profile Package","image_url":"https://aviedo.net/tovars/2-0b072c9f.webp"},"category":{"id":31,"name":"Через Devplay"},"section":{"id":14,"name":"CookieRun: Kingdom"},"quantity":1,"price":{"currency":"USD","unit_price":"3.98","total":"3.98"},"fields":[{"key":"privyazannaya_pochta","label":"Привязанная почта","value":"player@example.com"},{"key":"parol","label":"Пароль","value":"••••••"},{"key":"comment","label":"Комментарий","value":"Ник в игре: PlayerOne"}],"meta":{},"delivery":null,"action":null,"refund":null,"cancellable":true,"chat":{"can_write":true,"unread":0,"last_message_at":null},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:16+03:00","completed_at":null,"revision":1},"meta":{"idempotent_replay":false},"request_id":"req_6ec85c749cce"}},"per_unit":{"summary":"auto per_unit: Steam 1000 ₽","value":{"ok":true,"data":{"id":"TF4F377FAA13","external_id":"shop-1009","status":"processing","status_text":"В процессе","delayed":false,"kind":"auto","type":"steam_topup","test":true,"product":{"id":68,"name":"Пополнение RUB","image_url":"https://aviedo.net/tovars/product284-229a372d.webp"},"category":{"id":9,"name":"Через логин ⚡️"},"section":{"id":7,"name":"Steam"},"quantity":1000,"price":{"currency":"USD","unit_price":"0.011569","total":"11.57"},"fields":[{"key":"steam_login","label":"Логин Steam","value":"gaben"}],"meta":{},"delivery":null,"action":null,"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":0,"last_message_at":null},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:16+03:00","completed_at":null,"revision":1},"meta":{"idempotent_replay":false},"request_id":"req_0eae3096c591"}}}}}},"200":{"description":"Повтор с тем же `external_id` и теми же параметрами: тот же заказ в текущем состоянии, второго списания нет.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","meta","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Order"},"meta":{"type":"object","properties":{"idempotent_replay":{"type":"boolean","const":true}},"required":["idempotent_replay"],"additionalProperties":false},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"replay":{"summary":"Повтор запроса","value":{"ok":true,"data":{"id":"T3088AD3A7FA","external_id":"shop-1001","status":"processing","status_text":"В процессе","delayed":false,"kind":"auto","type":"telegram_premium","test":true,"product":{"id":853,"name":"3 месяца","image_url":"https://aviedo.net/tovars/products-78a1cdf7.webp"},"category":{"id":66,"name":"Премиум ⚡️"},"section":{"id":8,"name":"Telegram"},"quantity":1,"price":{"currency":"USD","unit_price":"12.67","total":"12.67"},"fields":[{"key":"telegram_username","label":"Username в Telegram","value":"durov"}],"meta":{"customer":"client-42"},"delivery":null,"action":null,"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":0,"last_message_at":null},"created_at":"2026-10-12T19:06:15+03:00","updated_at":"2026-10-12T19:06:15+03:00","completed_at":null,"revision":1},"meta":{"idempotent_replay":true},"request_id":"req_665589ca304b"}}}}}},"400":{"description":"- `invalid_json` — тело не является JSON-объектом\n- `invalid_request` — неверный тип или значение параметра (`details.param`), в том числе значение в `fields` не строка и не целое число\n- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"invalid_json":{"summary":"invalid_json","value":{"ok":false,"error":{"code":"invalid_json","message":"Тело запроса не является валидным JSON","retryable":false,"retry_after":null,"details":null},"request_id":"req_64e1e4cef951"}},"invalid_request_err_invalid_external_id":{"summary":"invalid_request: неверный external_id","value":{"ok":false,"error":{"code":"invalid_request","message":"external_id: 1–64 символа [A-Za-z0-9_.:-]","retryable":false,"retry_after":null,"details":{"param":"external_id"}},"request_id":"req_a5c5f0c07c7a"}},"invalid_request_err_missing_max_total":{"summary":"invalid_request: нет max_total_usd","value":{"ok":false,"error":{"code":"invalid_request","message":"Не передан max_total_usd","retryable":false,"retry_after":null,"details":{"param":"max_total_usd"}},"request_id":"req_476333557514"}},"invalid_request_err_scenario_not_allowed":{"summary":"invalid_request: сценарий не подходит товару","value":{"ok":false,"error":{"code":"invalid_request","message":"test_scenario refund недоступен для товаров kind=uploaded. Допустимо: success, completed_then_refunded, out_of_stock, account_not_found","retryable":false,"retry_after":null,"details":{"param":"test_scenario","kind":"uploaded","allowed":["success","completed_then_refunded","out_of_stock","account_not_found"]}},"request_id":"req_d40ff40701b2"}},"unknown_parameter":{"summary":"unknown_parameter: опечатка в теле","value":{"ok":false,"error":{"code":"unknown_parameter","message":"Неизвестный параметр: quantiy","retryable":false,"retry_after":null,"details":{"param":"quantiy","allowed":["product_id","quantity","external_id","max_total_usd","fields","meta","accept_chat","test","test_scenario"]}},"request_id":"req_5fe9d8284333"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"402":{"description":"- `insufficient_funds` — на балансе меньше суммы заказа","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"insufficient_funds":{"summary":"insufficient_funds","value":{"ok":false,"error":{"code":"insufficient_funds","message":"Недостаточно средств: нужно 319.20 $, на балансе 250.00 $","retryable":false,"retry_after":null,"details":{"required":"319.20","balance":"250.00","missing":"69.20"}},"request_id":"req_580d597eae6c"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"404":{"description":"- `product_not_found` — товар удалён или не существовал","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"product_not_found":{"summary":"product_not_found","value":{"ok":false,"error":{"code":"product_not_found","message":"Товар не найден","retryable":false,"retry_after":null,"details":{"product_id":999999999}},"request_id":"req_491d08d1172b"}}}}}},"409":{"description":"- `product_unavailable` — товар скрыт или истёк (`details.reason`)\n- `out_of_stock` — товара не хватает (`details.available`)\n- `price_changed` — сумма выше `max_total_usd` (`details.total`)\n- `external_id_conflict` — external_id уже использован с другими параметрами (`details.order_id`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"product_unavailable_err_product_hidden":{"summary":"product_unavailable: скрыт","value":{"ok":false,"error":{"code":"product_unavailable","message":"Товар временно скрыт","retryable":false,"retry_after":null,"details":{"reason":"hidden","product_id":1238}},"request_id":"req_0a2f0ac5721e"}},"product_unavailable_err_product_expired":{"summary":"product_unavailable: срок истёк","value":{"ok":false,"error":{"code":"product_unavailable","message":"Срок товара истёк","retryable":false,"retry_after":null,"details":{"reason":"expired","product_id":1256}},"request_id":"req_95e26ccce49c"}},"out_of_stock":{"summary":"out_of_stock","value":{"ok":false,"error":{"code":"out_of_stock","message":"Товара нет в наличии","retryable":false,"retry_after":null,"details":{"available":0}},"request_id":"req_1014fa71d66d"}},"price_changed":{"summary":"price_changed","value":{"ok":false,"error":{"code":"price_changed","message":"Цена изменилась: 12.67 $","retryable":false,"retry_after":null,"details":{"total":"12.67","max_total_usd":"10.00"}},"request_id":"req_f760454a8464"}},"external_id_conflict":{"summary":"external_id_conflict","value":{"ok":false,"error":{"code":"external_id_conflict","message":"Этот external_id уже использован с другими параметрами","retryable":false,"retry_after":null,"details":{"order_id":"T3088AD3A7FA","external_id":"shop-1001"}},"request_id":"req_9173a4d18518"}}}}}},"413":{"description":"- `payload_too_large` — тело больше 8 МБ или картинка больше 5 МБ","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"payload_too_large":{"summary":"payload_too_large","value":{"ok":false,"error":{"code":"payload_too_large","message":"Тело запроса слишком большое","retryable":false,"retry_after":null,"details":{"max_bytes":8388608}},"request_id":"req_83c446683620"}}}}}},"415":{"description":"- `unsupported_media_type` — у POST нет Content-Type: application/json","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"unsupported_media_type":{"summary":"unsupported_media_type","value":{"ok":false,"error":{"code":"unsupported_media_type","message":"Нужен заголовок Content-Type: application/json","retryable":false,"retry_after":null,"details":null},"request_id":"req_aba6339e4cfa"}}}}}},"422":{"description":"- `validation_failed` — ошибки в полях (`details.errors[]`)\n- `quantity_out_of_range` — количество вне диапазона (`details.min`, `max`, `step`)\n- `account_not_found` — получатель не найден у поставщика (`details.field`; `null`, если у товара нет полей)\n- `chat_required` — ручной товар без вебхука и без `accept_chat: true`","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"validation_failed":{"summary":"validation_failed: поля заказа","value":{"ok":false,"error":{"code":"validation_failed","message":"Ошибки в полях заказа","retryable":false,"retry_after":null,"details":{"errors":[{"field":"fields.colour","code":"unknown_field","message":"У товара нет такого поля","allowed":["telegram_username"]},{"field":"fields.telegram_username","code":"invalid_format","message":"Только латиница, цифры и _, 3–32 символа"}]}},"request_id":"req_1293639c8f96"}},"quantity_out_of_range_err_quantity_out_of_range":{"summary":"quantity_out_of_range: вне диапазона","value":{"ok":false,"error":{"code":"quantity_out_of_range","message":"Количество вне диапазона: от 50 до 100000","retryable":false,"retry_after":null,"details":{"min":50,"max":100000,"step":1}},"request_id":"req_34831d670de0"}},"quantity_out_of_range_err_quantity_missing":{"summary":"quantity_out_of_range: не передано","value":{"ok":false,"error":{"code":"quantity_out_of_range","message":"Укажите quantity: от 50 до 100000","retryable":false,"retry_after":null,"details":{"min":50,"max":100000,"step":1}},"request_id":"req_47526a2bebbe"}},"account_not_found":{"summary":"account_not_found (тестовый сценарий)","value":{"ok":false,"error":{"code":"account_not_found","message":"Получатель не найден (тестовый сценарий account_not_found)","retryable":false,"retry_after":null,"details":{"field":"fields.telegram_username"}},"request_id":"req_ad4ee3e4f297"}},"chat_required":{"summary":"chat_required","value":{"ok":false,"error":{"code":"chat_required","message":"Для ручного товара нужен вебхук или accept_chat: true","retryable":false,"retry_after":null,"details":null},"request_id":"req_74a339d2ca2e"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}},"503":{"description":"- `rate_unavailable` — курс доллара устарел, заказы не принимаются\n- `maintenance` — технические работы\n- `provider_unavailable` — поставщик или сервис проверки недоступен\n- `server_busy` — создание не уложилось в 30 секунд или запрос долго ждал в очереди","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_unavailable":{"summary":"rate_unavailable","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"rate_unavailable","message":"Курс доллара временно недоступен","retryable":true,"retry_after":300,"details":null},"request_id":"req_a4e7b1c0d935"}},"maintenance":{"summary":"maintenance","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"maintenance","message":"Идут технические работы","retryable":true,"retry_after":60,"details":null},"request_id":"req_0f6d2c8a4b19"}},"provider_unavailable":{"summary":"provider_unavailable","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"provider_unavailable","message":"Сервис Premium временно недоступен","retryable":true,"retry_after":60,"details":null},"request_id":"req_e2a95b7c3d10"}},"server_busy":{"summary":"server_busy","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"server_busy","message":"Сервер перегружен, повторите запрос","retryable":true,"retry_after":5,"details":null},"request_id":"req_7b3f0e9d5c21"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo POST /v1/orders '{\"product_id\":853,\"quantity\":1,\"external_id\":\"shop-1001\",\"max_total_usd\":\"12.67\",\"fields\":{\"telegram_username\":\"durov\"},\"meta\":{\"customer\":\"client-42\"},\"test\":true}'"},{"lang":"PHP","label":"PHP","source":"$res = $api->post('/v1/orders', [\n    'product_id' => 853,\n    'quantity' => 1,\n    'external_id' => 'shop-1001',\n    'max_total_usd' => '12.67',\n    'fields' => [\n        'telegram_username' => 'durov',\n    ],\n    'meta' => [\n        'customer' => 'client-42',\n    ],\n    'test' => true,\n]);"},{"lang":"Python","label":"Python","source":"res = api.post(\"/v1/orders\", {\n    \"product_id\": 853,\n    \"quantity\": 1,\n    \"external_id\": \"shop-1001\",\n    \"max_total_usd\": \"12.67\",\n    \"fields\": {\n        \"telegram_username\": \"durov\",\n    },\n    \"meta\": {\n        \"customer\": \"client-42\",\n    },\n    \"test\": True,\n})"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.post(\"/v1/orders\", {\n  product_id: 853,\n  quantity: 1,\n  external_id: \"shop-1001\",\n  max_total_usd: \"12.67\",\n  fields: {\n    telegram_username: \"durov\",\n  },\n  meta: {\n    customer: \"client-42\",\n  },\n  test: true,\n});"}]},"get":{"tags":["Заказы"],"operationId":"listOrders","summary":"Список заказов","description":"Заказы, созданные через API, от новых к старым. Для синхронизации используйте `updated_since`. С `test=1` — тестовые заказы вместо боевых (у тестового списка свой курсор).","parameters":[{"name":"status","in":"query","required":false,"description":"Статусы через запятую.","schema":{"type":"string"},"example":"pending,processing"},{"name":"kind","in":"query","required":false,"description":"Виды товаров через запятую.","schema":{"type":"string"},"example":"manual"},{"name":"product_id","in":"query","required":false,"description":"ID товара.","schema":{"type":"integer","minimum":1}},{"name":"from","in":"query","required":false,"description":"Создан не раньше: дата `YYYY-MM-DD` (московские сутки) или ISO-время.","schema":{"type":"string"},"example":"2026-10-01"},{"name":"to","in":"query","required":false,"description":"Создан не позже: дата или ISO-время.","schema":{"type":"string"},"example":"2026-10-31T23:59:59+03:00"},{"name":"updated_since","in":"query","required":false,"description":"Изменённые после этого момента.","schema":{"type":"string"},"example":"2026-10-12T15:00:00+03:00"},{"name":"has_unread","in":"query","required":false,"description":"`1` — только с непрочитанными сообщениями, `0` — без них.","schema":{"type":"string","enum":["1","0","true","false"]}},{"name":"delayed","in":"query","required":false,"description":"`1` — только с заминкой у поставщика.","schema":{"type":"string","enum":["1","0","true","false"]}},{"name":"test","in":"query","required":false,"description":"`1` — тестовые заказы.","schema":{"type":"string","enum":["1","0","true","false"]}},{"name":"limit","in":"query","required":false,"description":"1–100, по умолчанию 50.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"Курсор из `pagination.next_cursor` этого же списка.","schema":{"type":"string"}}],"responses":{"200":{"description":"Заказы.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","pagination","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Order"}},"pagination":{"$ref":"#/components/schemas/CursorPagination"},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"test":{"summary":"Тестовые заказы, limit=2","value":{"ok":true,"data":[{"id":"T20EFB948DDD","external_id":"shop-1010","status":"refunded","status_text":"Возврат","delayed":false,"kind":"uploaded","type":"digital_item","test":true,"product":{"id":1187,"name":"Family • 1 месяц","image_url":"https://aviedo.net/tovars/products-49d74742.webp"},"category":{"id":86,"name":"Подписки (EG) ⚡️"},"section":{"id":43,"name":"Spotify"},"quantity":1,"price":{"currency":"USD","unit_price":"3.72","total":"3.72"},"fields":[],"meta":{},"delivery":null,"action":null,"refund":{"amount":"3.72","currency":"USD","reason":"support_decision","refunded_at":"2026-10-12T19:06:46+03:00"},"cancellable":false,"chat":{"can_write":true,"unread":3,"last_message_at":"2026-10-12T19:06:46+03:00"},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:46+03:00","completed_at":null,"revision":6},{"id":"TF4F377FAA13","external_id":"shop-1009","status":"completed","status_text":"Выполнен","delayed":false,"kind":"auto","type":"steam_topup","test":true,"product":{"id":68,"name":"Пополнение RUB","image_url":"https://aviedo.net/tovars/product284-229a372d.webp"},"category":{"id":9,"name":"Через логин ⚡️"},"section":{"id":7,"name":"Steam"},"quantity":1000,"price":{"currency":"USD","unit_price":"0.011569","total":"11.57"},"fields":[{"key":"steam_login","label":"Логин Steam","value":"gaben"}],"meta":{},"delivery":{"items":[],"instructions":{"text":"Благодарим Вас за покупку!\nПриятной игры и хорошего дня! 💙","html":"Благодарим Вас за покупку!<br>Приятной игры и хорошего дня! 💙"},"attachments":[],"delivered_at":"2026-10-12T19:06:37+03:00"},"action":null,"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":1,"last_message_at":"2026-10-12T19:06:37+03:00"},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:38+03:00","completed_at":"2026-10-12T19:06:37+03:00","revision":3}],"pagination":{"has_more":true,"next_cursor":"dDoyMDQ"},"request_id":"req_458230063ae2"}},"empty":{"summary":"Боевых заказов нет","value":{"ok":true,"data":[],"pagination":{"has_more":false,"next_cursor":null},"request_id":"req_df88d0941c87"}}}}}},"400":{"description":"- `invalid_request` — неверный тип или значение параметра (`details.param`), в том числе значение в `fields` не строка и не целое число\n- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"invalid_request_err_invalid_limit":{"summary":"invalid_request: неверный limit","value":{"ok":false,"error":{"code":"invalid_request","message":"Параметр limit должен быть целым числом от 1 до 100","retryable":false,"retry_after":null,"details":{"param":"limit"}},"request_id":"req_cea3f4e084cc"}},"invalid_request_err_cursor_mismatch":{"summary":"invalid_request: чужой cursor","value":{"ok":false,"error":{"code":"invalid_request","message":"Неверный cursor","retryable":false,"retry_after":null,"details":{"param":"cursor"}},"request_id":"req_4ebc2dad6ac0"}},"unknown_parameter":{"summary":"unknown_parameter: опечатка в query","value":{"ok":false,"error":{"code":"unknown_parameter","message":"Неизвестный параметр: statuss","retryable":false,"retry_after":null,"details":{"param":"statuss","allowed":["status","kind","product_id","from","to","updated_since","has_unread","delayed","test","limit","cursor"]}},"request_id":"req_f28a29e21c06"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo GET '/v1/orders?status=processing&limit=50'"},{"lang":"PHP","label":"PHP","source":"$res = $api->get('/v1/orders', [\n    'status' => 'processing',\n    'limit' => 50,\n]);"},{"lang":"Python","label":"Python","source":"res = api.get(\"/v1/orders\", {\n    \"status\": \"processing\",\n    \"limit\": 50,\n})"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.get(\"/v1/orders\", {\n  status: \"processing\",\n  limit: 50,\n});"}]}},"/v1/orders/{id}":{"get":{"tags":["Заказы"],"operationId":"getOrder","summary":"Заказ по ID","description":"Заказ по нашему ID. Чужой или несуществующий заказ — `404 order_not_found`. Опрашивать один заказ имеет смысл не чаще раза в 15 секунд.","parameters":[{"name":"id","in":"path","required":true,"description":"ID заказа (`id` из ответа создания). Тестовые заказы начинаются с `T`.","schema":{"type":"string","pattern":"^[0-9A-Za-z]{12}$"},"example":"T3088AD3A7FA"}],"responses":{"200":{"description":"Заказ.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Order"},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"completed_topup":{"summary":"completed: пополнение (items пустой)","value":{"ok":true,"data":{"id":"T3088AD3A7FA","external_id":"shop-1001","status":"completed","status_text":"Выполнен","delayed":false,"kind":"auto","type":"telegram_premium","test":true,"product":{"id":853,"name":"3 месяца","image_url":"https://aviedo.net/tovars/products-78a1cdf7.webp"},"category":{"id":66,"name":"Премиум ⚡️"},"section":{"id":8,"name":"Telegram"},"quantity":1,"price":{"currency":"USD","unit_price":"12.67","total":"12.67"},"fields":[{"key":"telegram_username","label":"Username в Telegram","value":"durov"}],"meta":{"customer":"client-42"},"delivery":{"items":[],"instructions":{"text":"Благодарим Вас за покупку!\nПриятной игры и хорошего дня! 💙","html":"Благодарим Вас за покупку!<br>Приятной игры и хорошего дня! 💙"},"attachments":[],"delivered_at":"2026-10-12T19:06:35+03:00"},"action":null,"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":1,"last_message_at":"2026-10-12T19:06:35+03:00"},"created_at":"2026-10-12T19:06:15+03:00","updated_at":"2026-10-12T19:06:35+03:00","completed_at":"2026-10-12T19:06:35+03:00","revision":3},"request_id":"req_1a838f199801"}},"completed_items":{"summary":"completed: ключи","value":{"ok":true,"data":{"id":"TC655EADB878","external_id":"shop-1002","status":"completed","status_text":"Выполнен","delayed":false,"kind":"uploaded","type":"digital_item","test":true,"product":{"id":1187,"name":"Family • 1 месяц","image_url":"https://aviedo.net/tovars/products-49d74742.webp"},"category":{"id":86,"name":"Подписки (EG) ⚡️"},"section":{"id":43,"name":"Spotify"},"quantity":2,"price":{"currency":"USD","unit_price":"3.72","total":"7.44"},"fields":[],"meta":{},"delivery":{"items":[{"type":"item","value":"TEST-CHFH-STL9-87D6"},{"type":"item","value":"TEST-2PTX-YVQV-PSNY"}],"instructions":{"text":"📌 Активировать ключ можно на сайте партнёра: https://premiumcdk.com\n\nБлагодарим Вас за покупку!\nПриятной игры и хорошего дня! 💙","html":"📌 Активировать ключ можно на сайте партнёра: <b>https://premiumcdk.com</b><br><br>Благодарим Вас за покупку!<br>Приятной игры и хорошего дня! 💙"},"attachments":[],"delivered_at":"2026-10-12T19:06:16+03:00"},"action":null,"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":2,"last_message_at":"2026-10-12T19:06:16+03:00"},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:16+03:00","completed_at":"2026-10-12T19:06:16+03:00","revision":4},"request_id":"req_8adeaa1a3074"}},"completed_manual":{"summary":"completed: ручной, с фото","value":{"ok":true,"data":{"id":"TD0D8BE98162","external_id":"shop-1004","status":"completed","status_text":"Выполнен","delayed":false,"kind":"manual","type":"manual","test":true,"product":{"id":1259,"name":"Profile Package","image_url":"https://aviedo.net/tovars/2-0b072c9f.webp"},"category":{"id":31,"name":"Через Devplay"},"section":{"id":14,"name":"CookieRun: Kingdom"},"quantity":1,"price":{"currency":"USD","unit_price":"3.98","total":"3.98"},"fields":[{"key":"privyazannaya_pochta","label":"Привязанная почта","value":"player@example.com"},{"key":"parol","label":"Пароль","value":"••••••"},{"key":"comment","label":"Комментарий","value":"Ник в игре: PlayerOne"}],"meta":{},"delivery":{"items":[],"instructions":{"text":"Благодарим Вас за покупку!\nПриятной игры и хорошего дня! 💙","html":"Благодарим Вас за покупку!<br>Приятной игры и хорошего дня! 💙"},"attachments":[{"type":"photo","url":"https://aviedo.net/image/api-test-photo.jpg","mime":"image/jpeg"}],"delivered_at":"2026-10-12T19:07:01+03:00"},"action":null,"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":3,"last_message_at":"2026-10-12T19:07:01+03:00"},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:07:01+03:00","completed_at":"2026-10-12T19:07:01+03:00","revision":7},"request_id":"req_d33134942337"}},"action_required":{"summary":"action_required: Roblox","value":{"ok":true,"data":{"id":"TDC76B34FBF9","external_id":"shop-1006","status":"action_required","status_text":"Требуется действие","delayed":false,"kind":"auto","type":"robux","test":true,"product":{"id":171,"name":"80 робуксов","image_url":"https://aviedo.net/tovars/product212-934e3ed8.webp"},"category":{"id":19,"name":"Через вход ⚡️"},"section":{"id":18,"name":"Roblox"},"quantity":1,"price":{"currency":"USD","unit_price":"0.89","total":"0.89"},"fields":[{"key":"roblox_username","label":"Логин аккаунта Roblox","value":"builderman"}],"meta":{},"delivery":null,"action":{"type":"open_url","url":"https://example.com/aviedo-test/verify/TEST-VXYR-2BY9-MYDD","expires_at":null,"hint":"Откройте ссылку, войдите в аккаунт Roblox и подтвердите вход (2FA). После этого Robux будут зачислены автоматически."},"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":0,"last_message_at":null},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:27+03:00","completed_at":null,"revision":2},"request_id":"req_541287d38228"}},"delayed":{"summary":"processing с delayed: true","value":{"ok":true,"data":{"id":"T1B89A3A5685","external_id":"shop-1007","status":"processing","status_text":"В процессе","delayed":true,"kind":"auto","type":"game_topup","test":true,"product":{"id":1254,"name":"250 монет + эпик бокс","image_url":"https://aviedo.net/tovars/8-21adda58.webp"},"category":{"id":90,"name":"Через айди"},"section":{"id":47,"name":"Oxide: Survival Island"},"quantity":1,"price":{"currency":"USD","unit_price":"6.01","total":"6.01"},"fields":[{"key":"player_id","label":"Player ID","value":"123456789"}],"meta":{},"delivery":null,"action":null,"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":0,"last_message_at":null},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:31+03:00","completed_at":null,"revision":2},"request_id":"req_832cae5b45e2"}},"refunded":{"summary":"refunded: supplier_failed","value":{"ok":true,"data":{"id":"T20C81DF39B0","external_id":"shop-1008","status":"refunded","status_text":"Возврат","delayed":false,"kind":"auto","type":"telegram_premium","test":true,"product":{"id":853,"name":"3 месяца","image_url":"https://aviedo.net/tovars/products-78a1cdf7.webp"},"category":{"id":66,"name":"Премиум ⚡️"},"section":{"id":8,"name":"Telegram"},"quantity":1,"price":{"currency":"USD","unit_price":"12.67","total":"12.67"},"fields":[{"key":"telegram_username","label":"Username в Telegram","value":"durov"}],"meta":{},"delivery":null,"action":null,"refund":{"amount":"12.67","currency":"USD","reason":"supplier_failed","refunded_at":"2026-10-12T19:06:37+03:00"},"cancellable":false,"chat":{"can_write":true,"unread":1,"last_message_at":"2026-10-12T19:06:37+03:00"},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:37+03:00","completed_at":null,"revision":3},"request_id":"req_c1e34691c52f"}}}}}},"400":{"description":"- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"unknown_parameter":{"summary":"unknown_parameter: опечатка в query","value":{"ok":false,"error":{"code":"unknown_parameter","message":"Неизвестный параметр: statuss","retryable":false,"retry_after":null,"details":{"param":"statuss","allowed":["status","kind","product_id","from","to","updated_since","has_unread","delayed","test","limit","cursor"]}},"request_id":"req_f28a29e21c06"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"404":{"description":"- `order_not_found` — такого заказа у вас нет","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"order_not_found":{"summary":"order_not_found","value":{"ok":false,"error":{"code":"order_not_found","message":"Заказ не найден","retryable":false,"retry_after":null,"details":null},"request_id":"req_47072bcbf62d"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo GET '/v1/orders/T3088AD3A7FA'"},{"lang":"PHP","label":"PHP","source":"$res = $api->get('/v1/orders/T3088AD3A7FA');"},{"lang":"Python","label":"Python","source":"res = api.get(\"/v1/orders/T3088AD3A7FA\")"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.get(\"/v1/orders/T3088AD3A7FA\");"}]}},"/v1/orders/external/{external_id}":{"get":{"tags":["Заказы"],"operationId":"getOrderByExternalId","summary":"Заказ по вашему external_id","description":"Ищет заказ по вашему номеру. Ищутся боевые заказы; тестовый — с `?test=1`.\n\n**`404 order_not_found` — окончательное доказательство, что заказ не создан и деньги не списаны, если исходный `POST /v1/orders` с этим `external_id` уже вернул любой ответ, кроме `5xx` и сетевой ошибки, или с его отправки прошло больше 60 секунд.** Раньше `404` не окончателен: заказ может появиться через несколько секунд. После окончательного `404` можно создавать заказ с тем же `external_id`.\n\nЕсли в `external_id` есть `:`, его можно передать как есть или как `%3A` — подписывайте путь ровно в том виде, в каком отправляете.","parameters":[{"name":"external_id","in":"path","required":true,"description":"Ваш `external_id`.","schema":{"type":"string","pattern":"^[A-Za-z0-9_.:%-]{1,192}$"},"example":"shop-1001"},{"name":"test","in":"query","required":false,"description":"`1` — искать среди тестовых заказов.","schema":{"type":"string","enum":["1","0","true","false"]},"example":"1"}],"responses":{"200":{"description":"Заказ.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Order"},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"test":{"summary":"Тестовый заказ по external_id","value":{"ok":true,"data":{"id":"T3088AD3A7FA","external_id":"shop-1001","status":"completed","status_text":"Выполнен","delayed":false,"kind":"auto","type":"telegram_premium","test":true,"product":{"id":853,"name":"3 месяца","image_url":"https://aviedo.net/tovars/products-78a1cdf7.webp"},"category":{"id":66,"name":"Премиум ⚡️"},"section":{"id":8,"name":"Telegram"},"quantity":1,"price":{"currency":"USD","unit_price":"12.67","total":"12.67"},"fields":[{"key":"telegram_username","label":"Username в Telegram","value":"durov"}],"meta":{"customer":"client-42"},"delivery":{"items":[],"instructions":{"text":"Благодарим Вас за покупку!\nПриятной игры и хорошего дня! 💙","html":"Благодарим Вас за покупку!<br>Приятной игры и хорошего дня! 💙"},"attachments":[],"delivered_at":"2026-10-12T19:06:35+03:00"},"action":null,"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":1,"last_message_at":"2026-10-12T19:06:35+03:00"},"created_at":"2026-10-12T19:06:15+03:00","updated_at":"2026-10-12T19:06:35+03:00","completed_at":"2026-10-12T19:06:35+03:00","revision":3},"request_id":"req_c72810368f92"}}}}}},"400":{"description":"- `invalid_request` — неверный тип или значение параметра (`details.param`), в том числе значение в `fields` не строка и не целое число\n- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"unknown_parameter":{"summary":"unknown_parameter: опечатка в query","value":{"ok":false,"error":{"code":"unknown_parameter","message":"Неизвестный параметр: statuss","retryable":false,"retry_after":null,"details":{"param":"statuss","allowed":["status","kind","product_id","from","to","updated_since","has_unread","delayed","test","limit","cursor"]}},"request_id":"req_f28a29e21c06"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"404":{"description":"- `order_not_found` — такого заказа у вас нет","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"order_not_found":{"summary":"order_not_found по external_id","value":{"ok":false,"error":{"code":"order_not_found","message":"Заказ не найден","retryable":false,"retry_after":null,"details":{"external_id":"shop-1001"}},"request_id":"req_2fef30809158"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo GET '/v1/orders/external/shop-1001?test=1'"},{"lang":"PHP","label":"PHP","source":"$res = $api->get('/v1/orders/external/shop-1001', [\n    'test' => 1,\n]);"},{"lang":"Python","label":"Python","source":"res = api.get(\"/v1/orders/external/shop-1001\", {\n    \"test\": 1,\n})"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.get(\"/v1/orders/external/shop-1001\", {\n  test: 1,\n});"}]}},"/v1/orders/{id}/cancel":{"post":{"tags":["Заказы"],"operationId":"cancelOrder","summary":"Отменить заказ","description":"Отменяет **ручной** заказ, пока продавец его не взял (`status: pending`, `cancellable: true`): мгновенный полный возврат на баланс, `refund.reason: \"cancelled_by_reseller\"`.\n\n| Ситуация | Результат |\n|---|---|\n| `manual` в `pending` | `200`, заказ в `refunded` |\n| `manual` в `processing` | `409 not_cancellable` — напишите в чат заказа |\n| `auto`, `uploaded` | `409 not_cancellable` |\n| уже `refunded` | `200` и тот же заказ (повтор безопасен) |\n\nПричина (`reason`, до 200 символов) сохраняется одной строкой: управляющие символы удаляются, переносы заменяются пробелами, `«»` — на `\"`, `<` и `>` — на `‹` и `›`. В чате появится системное сообщение «Заказ отменён реселлером до начала работы…» со строкой `Причина (реселлер): «…»`.","parameters":[{"name":"id","in":"path","required":true,"description":"ID заказа.","schema":{"type":"string","pattern":"^[0-9A-Za-z]{12}$"},"example":"T78C203C2802"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelRequest"},"example":{"reason":"customer_request"}}}},"responses":{"200":{"description":"Заказ отменён (или уже был отменён).","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Order"},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"refunded":{"summary":"Отменён, деньги возвращены","value":{"ok":true,"data":{"id":"T78C203C2802","external_id":"shop-1005","status":"refunded","status_text":"Возврат","delayed":false,"kind":"manual","type":"manual","test":true,"product":{"id":1259,"name":"Profile Package","image_url":"https://aviedo.net/tovars/2-0b072c9f.webp"},"category":{"id":31,"name":"Через Devplay"},"section":{"id":14,"name":"CookieRun: Kingdom"},"quantity":1,"price":{"currency":"USD","unit_price":"3.98","total":"3.98"},"fields":[{"key":"privyazannaya_pochta","label":"Привязанная почта","value":"player@example.com"},{"key":"parol","label":"Пароль","value":"••••••"},{"key":"comment","label":"Комментарий","value":"Ник в игре: PlayerOne"}],"meta":{},"delivery":null,"action":null,"refund":{"amount":"3.98","currency":"USD","reason":"cancelled_by_reseller","refunded_at":"2026-10-12T19:06:16+03:00"},"cancellable":false,"chat":{"can_write":true,"unread":1,"last_message_at":"2026-10-12T19:06:16+03:00"},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:16+03:00","completed_at":null,"revision":3},"request_id":"req_5f61a28a2dcc"}}}}}},"400":{"description":"- `invalid_json` — тело не является JSON-объектом\n- `invalid_request` — неверный тип или значение параметра (`details.param`), в том числе значение в `fields` не строка и не целое число\n- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"invalid_json":{"summary":"invalid_json","value":{"ok":false,"error":{"code":"invalid_json","message":"Тело запроса не является валидным JSON","retryable":false,"retry_after":null,"details":null},"request_id":"req_64e1e4cef951"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"404":{"description":"- `order_not_found` — такого заказа у вас нет","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"order_not_found":{"summary":"order_not_found","value":{"ok":false,"error":{"code":"order_not_found","message":"Заказ не найден","retryable":false,"retry_after":null,"details":null},"request_id":"req_47072bcbf62d"}}}}}},"409":{"description":"- `not_cancellable` — заказ нельзя отменить (`details.status`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"not_cancellable":{"summary":"not_cancellable","value":{"ok":false,"error":{"code":"not_cancellable","message":"Заказ уже нельзя отменить","retryable":false,"retry_after":null,"details":{"status":"processing"}},"request_id":"req_3a248b91fe8c"}}}}}},"413":{"description":"- `payload_too_large` — тело больше 8 МБ или картинка больше 5 МБ","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"payload_too_large":{"summary":"payload_too_large","value":{"ok":false,"error":{"code":"payload_too_large","message":"Тело запроса слишком большое","retryable":false,"retry_after":null,"details":{"max_bytes":8388608}},"request_id":"req_83c446683620"}}}}}},"415":{"description":"- `unsupported_media_type` — у POST нет Content-Type: application/json","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"unsupported_media_type":{"summary":"unsupported_media_type","value":{"ok":false,"error":{"code":"unsupported_media_type","message":"Нужен заголовок Content-Type: application/json","retryable":false,"retry_after":null,"details":null},"request_id":"req_aba6339e4cfa"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}},"503":{"description":"- `maintenance` — технические работы","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"maintenance":{"summary":"maintenance","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"maintenance","message":"Идут технические работы","retryable":true,"retry_after":60,"details":null},"request_id":"req_0f6d2c8a4b19"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo POST /v1/orders/T78C203C2802/cancel '{\"reason\":\"customer_request\"}'"},{"lang":"PHP","label":"PHP","source":"$res = $api->post('/v1/orders/T78C203C2802/cancel', [\n    'reason' => 'customer_request',\n]);"},{"lang":"Python","label":"Python","source":"res = api.post(\"/v1/orders/T78C203C2802/cancel\", {\n    \"reason\": \"customer_request\",\n})"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.post(\"/v1/orders/T78C203C2802/cancel\", {\n  reason: \"customer_request\",\n});"}]}},"/v1/orders/{id}/messages":{"get":{"tags":["Чат"],"operationId":"listMessages","summary":"Сообщения чата заказа","description":"Сообщения по возрастанию `id`. Вложения: `[{\"type\": \"photo\", \"url\", \"mime\"}]` — скачивайте их и храните у себя.","parameters":[{"name":"id","in":"path","required":true,"description":"ID заказа.","schema":{"type":"string","pattern":"^[0-9A-Za-z]{12}$"},"example":"TD0D8BE98162"},{"name":"after_id","in":"query","required":false,"description":"Вернуть сообщения с `id` больше этого; по умолчанию 0.","schema":{"type":"integer","minimum":0,"default":0}},{"name":"limit","in":"query","required":false,"description":"1–200, по умолчанию 100.","schema":{"type":"integer","minimum":1,"maximum":200,"default":100}}],"responses":{"200":{"description":"Сообщения.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","pagination","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Message"}},"pagination":{"$ref":"#/components/schemas/AfterIdPagination"},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"conversation":{"summary":"Переписка тестового заказа (сценарий chat)","value":{"ok":true,"data":[{"id":331,"order_id":"TD0D8BE98162","from":"support","text":"Тест: пришлите код","attachments":[],"read":true,"client_message_id":null,"created_at":"2026-10-12T19:06:50+03:00"},{"id":332,"order_id":"TD0D8BE98162","from":"reseller","text":"Код: 482913","attachments":[],"read":true,"client_message_id":"msg-77","created_at":"2026-10-12T19:06:50+03:00"},{"id":333,"order_id":"TD0D8BE98162","from":"reseller","text":"Скриншот профиля","attachments":[{"type":"photo","url":"https://aviedo.net/image/api-test-photo.jpg","mime":"image/jpeg"}],"read":true,"client_message_id":"msg-78","created_at":"2026-10-12T19:06:50+03:00"},{"id":334,"order_id":"TD0D8BE98162","from":"support","text":"Тест: код получен, спасибо! Завершаем заказ.","attachments":[],"read":false,"client_message_id":null,"created_at":"2026-10-12T19:06:54+03:00"},{"id":335,"order_id":"TD0D8BE98162","from":"support","text":"Тест: фото выполнения","attachments":[{"type":"photo","url":"https://aviedo.net/image/api-test-photo.jpg","mime":"image/jpeg"}],"read":false,"client_message_id":null,"created_at":"2026-10-12T19:07:01+03:00"},{"id":336,"order_id":"TD0D8BE98162","from":"system","text":"Тест: заказ выполнен! 🤝","attachments":[],"read":false,"client_message_id":null,"created_at":"2026-10-12T19:07:01+03:00"}],"pagination":{"has_more":false,"next_after_id":336},"request_id":"req_e193a376011b"}}}}}},"400":{"description":"- `invalid_request` — неверный тип или значение параметра (`details.param`), в том числе значение в `fields` не строка и не целое число\n- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"unknown_parameter":{"summary":"unknown_parameter: опечатка в query","value":{"ok":false,"error":{"code":"unknown_parameter","message":"Неизвестный параметр: statuss","retryable":false,"retry_after":null,"details":{"param":"statuss","allowed":["status","kind","product_id","from","to","updated_since","has_unread","delayed","test","limit","cursor"]}},"request_id":"req_f28a29e21c06"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"404":{"description":"- `order_not_found` — такого заказа у вас нет","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"order_not_found":{"summary":"order_not_found","value":{"ok":false,"error":{"code":"order_not_found","message":"Заказ не найден","retryable":false,"retry_after":null,"details":null},"request_id":"req_47072bcbf62d"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo GET '/v1/orders/TD0D8BE98162/messages?after_id=0'"},{"lang":"PHP","label":"PHP","source":"$res = $api->get('/v1/orders/TD0D8BE98162/messages', [\n    'after_id' => 0,\n]);"},{"lang":"Python","label":"Python","source":"res = api.get(\"/v1/orders/TD0D8BE98162/messages\", {\n    \"after_id\": 0,\n})"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.get(\"/v1/orders/TD0D8BE98162/messages\", {\n  after_id: 0,\n});"}]},"post":{"tags":["Чат"],"operationId":"postMessage","summary":"Написать продавцу","description":"Отправляет сообщение продавцу: `text` (до 4000 символов) и/или `image`.\n\n- **Фото:** JPG, PNG или WEBP в base64, до 5 МБ после декодирования, каждая сторона до 8000 px и не больше 16 Мп. Проверяется по содержимому и всегда перекодируется (до 2560 px, поворот по EXIF, JPEG качества 85; PNG и WEBP остаются только с прозрачностью; метаданные удаляются). Ошибки картинки — `422 validation_failed` с `details.errors[0].field = \"image\"`; неверный base64 — `400 invalid_request`; больше 5 МБ — `413 payload_too_large`.\n- **Дубли** отсекаются только по `client_message_id`: повтор с тем же значением вернёт `200`, `meta.idempotent_replay: true` и уже созданное сообщение. Без `client_message_id` каждый запрос, в том числе повтор после таймаута, создаёт новое сообщение.\n- **Лимиты:** 30 сообщений в минуту, из них с фото — 10 (каждая попытка с картинкой); на заказ — 20 фото и 50 МБ (`400 invalid_request`); на аккаунт — 200 фото и 200 МБ за 24 часа (`429 rate_limited`, `bucket` = `chat_photo_day` / `chat_photo_bytes_day`). Если на сервере мало места — `507 insufficient_storage` (текст при этом принимается).\n- Писать можно, пока `order.chat.can_write = true`, иначе `409 chat_closed`.","parameters":[{"name":"id","in":"path","required":true,"description":"ID заказа.","schema":{"type":"string","pattern":"^[0-9A-Za-z]{12}$"},"example":"TD0D8BE98162"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageRequest"},"examples":{"text":{"summary":"Текст","value":{"text":"Код: 482913","client_message_id":"msg-77"}},"photo":{"summary":"Текст и фото","value":{"text":"Скриншот профиля","image":{"filename":"screenshot.jpg","content_base64":"/9j/4AAQSkZJRgABAQEAYABgAAD…"},"client_message_id":"msg-78"}}}}}},"responses":{"201":{"description":"Сообщение отправлено.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","meta","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Message"},"meta":{"type":"object","properties":{"idempotent_replay":{"type":"boolean","const":false}},"required":["idempotent_replay"],"additionalProperties":false},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"text":{"summary":"Текст","value":{"ok":true,"data":{"id":332,"order_id":"TD0D8BE98162","from":"reseller","text":"Код: 482913","attachments":[],"read":true,"client_message_id":"msg-77","created_at":"2026-10-12T19:06:50+03:00"},"meta":{"idempotent_replay":false},"request_id":"req_28dd686d4f0c"}},"photo":{"summary":"С фото","value":{"ok":true,"data":{"id":333,"order_id":"TD0D8BE98162","from":"reseller","text":"Скриншот профиля","attachments":[{"type":"photo","url":"https://aviedo.net/image/api-test-photo.jpg","mime":"image/jpeg"}],"read":true,"client_message_id":"msg-78","created_at":"2026-10-12T19:06:50+03:00"},"meta":{"idempotent_replay":false},"request_id":"req_fa8a1f872056"}}}}}},"200":{"description":"Повтор с тем же `client_message_id`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","meta","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Message"},"meta":{"type":"object","properties":{"idempotent_replay":{"type":"boolean","const":true}},"required":["idempotent_replay"],"additionalProperties":false},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"replay":{"summary":"Повтор","value":{"ok":true,"data":{"id":332,"order_id":"TD0D8BE98162","from":"reseller","text":"Код: 482913","attachments":[],"read":true,"client_message_id":"msg-77","created_at":"2026-10-12T19:06:50+03:00"},"meta":{"idempotent_replay":true},"request_id":"req_4eaba90bcbed"}}}}}},"400":{"description":"- `invalid_json` — тело не является JSON-объектом\n- `invalid_request` — неверный тип или значение параметра (`details.param`), в том числе значение в `fields` не строка и не целое число\n- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"invalid_json":{"summary":"invalid_json","value":{"ok":false,"error":{"code":"invalid_json","message":"Тело запроса не является валидным JSON","retryable":false,"retry_after":null,"details":null},"request_id":"req_64e1e4cef951"}},"invalid_request":{"summary":"invalid_request: нет text и image","value":{"ok":false,"error":{"code":"invalid_request","message":"Нужно передать text или image","retryable":false,"retry_after":null,"details":{"param":"text"}},"request_id":"req_d4de5797fb24"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"404":{"description":"- `order_not_found` — такого заказа у вас нет","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"order_not_found":{"summary":"order_not_found","value":{"ok":false,"error":{"code":"order_not_found","message":"Заказ не найден","retryable":false,"retry_after":null,"details":null},"request_id":"req_47072bcbf62d"}}}}}},"409":{"description":"- `chat_closed` — переписка по заказу закрыта","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"chat_closed":{"summary":"chat_closed","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"chat_closed","message":"Переписка по заказу закрыта","retryable":false,"retry_after":null,"details":{"status":"completed"}},"request_id":"req_3c9e1f0a7b52"}}}}}},"413":{"description":"- `payload_too_large` — тело больше 8 МБ или картинка больше 5 МБ","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"payload_too_large":{"summary":"payload_too_large","value":{"ok":false,"error":{"code":"payload_too_large","message":"Тело запроса слишком большое","retryable":false,"retry_after":null,"details":{"max_bytes":8388608}},"request_id":"req_83c446683620"}}}}}},"415":{"description":"- `unsupported_media_type` — у POST нет Content-Type: application/json","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"unsupported_media_type":{"summary":"unsupported_media_type","value":{"ok":false,"error":{"code":"unsupported_media_type","message":"Нужен заголовок Content-Type: application/json","retryable":false,"retry_after":null,"details":null},"request_id":"req_aba6339e4cfa"}}}}}},"422":{"description":"- `validation_failed` — ошибки в полях (`details.errors[]`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"validation_failed":{"summary":"validation_failed: картинка","value":{"ok":false,"error":{"code":"validation_failed","message":"Поддерживаются только JPG, PNG и WEBP","retryable":false,"retry_after":null,"details":{"errors":[{"field":"image","code":"invalid_format","message":"Поддерживаются только JPG, PNG и WEBP"}]}},"request_id":"req_4bcea4220272"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}},"507":{"description":"- `insufficient_storage` — мало места для файлов, фото не принимаются","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"insufficient_storage":{"summary":"insufficient_storage","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"insufficient_storage","message":"На сервере не хватает места для файлов, повторите позже","retryable":true,"retry_after":600,"details":null},"request_id":"req_c81d4a6f2e93"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo POST /v1/orders/TD0D8BE98162/messages '{\"text\":\"Код: 482913\",\"client_message_id\":\"msg-77\"}'"},{"lang":"PHP","label":"PHP","source":"$res = $api->post('/v1/orders/TD0D8BE98162/messages', [\n    'text' => 'Код: 482913',\n    'client_message_id' => 'msg-77',\n]);"},{"lang":"Python","label":"Python","source":"res = api.post(\"/v1/orders/TD0D8BE98162/messages\", {\n    \"text\": \"Код: 482913\",\n    \"client_message_id\": \"msg-77\",\n})"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.post(\"/v1/orders/TD0D8BE98162/messages\", {\n  text: \"Код: 482913\",\n  client_message_id: \"msg-77\",\n});"}]}},"/v1/orders/{id}/messages/read":{"post":{"tags":["Чат"],"operationId":"markMessagesRead","summary":"Отметить сообщения прочитанными","description":"Отмечает прочитанными сообщения до `up_to_id` включительно; без параметра (`{}`) — все. Отметка только растёт: меньший `up_to_id` ничего не меняет, а значение больше последнего сообщения ограничивается им. Возвращает, сколько непрочитанных осталось.","parameters":[{"name":"id","in":"path","required":true,"description":"ID заказа.","schema":{"type":"string","pattern":"^[0-9A-Za-z]{12}$"},"example":"TD0D8BE98162"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkReadRequest"},"examples":{"all":{"summary":"Все","value":{}},"up_to":{"summary":"До сообщения","value":{"up_to_id":121}}}}}},"responses":{"200":{"description":"Готово.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/UnreadResult"},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"ok":{"summary":"Все прочитаны","value":{"ok":true,"data":{"unread":0},"request_id":"req_1197e80629a5"}}}}}},"400":{"description":"- `invalid_json` — тело не является JSON-объектом\n- `invalid_request` — неверный тип или значение параметра (`details.param`), в том числе значение в `fields` не строка и не целое число\n- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"invalid_json":{"summary":"invalid_json","value":{"ok":false,"error":{"code":"invalid_json","message":"Тело запроса не является валидным JSON","retryable":false,"retry_after":null,"details":null},"request_id":"req_64e1e4cef951"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"404":{"description":"- `order_not_found` — такого заказа у вас нет","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"order_not_found":{"summary":"order_not_found","value":{"ok":false,"error":{"code":"order_not_found","message":"Заказ не найден","retryable":false,"retry_after":null,"details":null},"request_id":"req_47072bcbf62d"}}}}}},"413":{"description":"- `payload_too_large` — тело больше 8 МБ или картинка больше 5 МБ","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"payload_too_large":{"summary":"payload_too_large","value":{"ok":false,"error":{"code":"payload_too_large","message":"Тело запроса слишком большое","retryable":false,"retry_after":null,"details":{"max_bytes":8388608}},"request_id":"req_83c446683620"}}}}}},"415":{"description":"- `unsupported_media_type` — у POST нет Content-Type: application/json","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"unsupported_media_type":{"summary":"unsupported_media_type","value":{"ok":false,"error":{"code":"unsupported_media_type","message":"Нужен заголовок Content-Type: application/json","retryable":false,"retry_after":null,"details":null},"request_id":"req_aba6339e4cfa"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo POST /v1/orders/TD0D8BE98162/messages/read '{}'"},{"lang":"PHP","label":"PHP","source":"$res = $api->post('/v1/orders/TD0D8BE98162/messages/read');"},{"lang":"Python","label":"Python","source":"res = api.post(\"/v1/orders/TD0D8BE98162/messages/read\")"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.post(\"/v1/orders/TD0D8BE98162/messages/read\");"}]}},"/v1/events":{"get":{"tags":["События и вебхуки"],"operationId":"listEvents","summary":"Лента событий","description":"Лента событий по вашим API-заказам — та же, что приходит вебхуками (кроме `ping`). Используйте её вместо вебхука или как страховку.\n\n- События идут по возрастанию `id` и хранятся 30 дней. События тестовых заказов — в той же ленте с `\"test\": true`; `test=0` оставляет только боевые, `test=1` — только тестовые.\n- Сохраняйте `pagination.next_after_id` и передавайте его в следующем запросе; пока `has_more: true`, запрашивайте сразу.\n- Если `after_id` старше 30 дней, придут первые доступные события и `meta.gap: true` — пересинхронизируйтесь через `GET /v1/orders?updated_since=…`.\n\nОпрашивайте раз в 10–30 секунд.","parameters":[{"name":"after_id","in":"query","required":false,"description":"ID последнего обработанного события; в первый раз `0`.","schema":{"type":"integer","minimum":0,"default":0},"example":0},{"name":"types","in":"query","required":false,"description":"Типы через запятую: `order.processing`, `order.action_required`, `order.delayed`, `order.completed`, `order.refunded`, `message.created`.","schema":{"type":"string"},"example":"order.completed,order.refunded"},{"name":"test","in":"query","required":false,"description":"`0` — только события боевых заказов, `1` — только тестовых. Без параметра — все.","schema":{"type":"string","enum":["1","0","true","false"]},"example":"0"},{"name":"limit","in":"query","required":false,"description":"1–500, по умолчанию 100.","schema":{"type":"integer","minimum":1,"maximum":500,"default":100}}],"responses":{"200":{"description":"События.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","pagination","meta","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"pagination":{"$ref":"#/components/schemas/AfterIdPagination"},"meta":{"type":"object","properties":{"gap":{"type":"boolean","description":"Часть событий после `after_id` уже удалена (старше 30 дней)."}},"required":["gap"],"additionalProperties":false},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"first":{"summary":"Первые события (limit=5)","value":{"ok":true,"data":[{"id":1096,"type":"message.created","created_at":"2026-10-12T19:06:16+03:00","test":true,"data":{"order_id":"TC655EADB878","external_id":"shop-1002","message":{"id":321,"order_id":"TC655EADB878","from":"system","text":"Ваши товары:\nTEST-CHFH-STL9-87D6\nTEST-2PTX-YVQV-PSNY","attachments":[],"read":false,"client_message_id":null,"created_at":"2026-10-12T19:06:16+03:00"}}},{"id":1097,"type":"message.created","created_at":"2026-10-12T19:06:16+03:00","test":true,"data":{"order_id":"TC655EADB878","external_id":"shop-1002","message":{"id":322,"order_id":"TC655EADB878","from":"system","text":"📌 Активировать ключ можно на сайте партнёра: https://premiumcdk.com\n\nБлагодарим Вас за покупку!\nПриятной игры и хорошего дня! 💙","attachments":[],"read":false,"client_message_id":null,"created_at":"2026-10-12T19:06:16+03:00"}}},{"id":1098,"type":"order.completed","created_at":"2026-10-12T19:06:16+03:00","test":true,"data":{"order":{"id":"TC655EADB878","external_id":"shop-1002","status":"completed","status_text":"Выполнен","delayed":false,"kind":"uploaded","type":"digital_item","test":true,"product":{"id":1187,"name":"Family • 1 месяц","image_url":"https://aviedo.net/tovars/products-49d74742.webp"},"category":{"id":86,"name":"Подписки (EG) ⚡️"},"section":{"id":43,"name":"Spotify"},"quantity":2,"price":{"currency":"USD","unit_price":"3.72","total":"7.44"},"fields":[],"meta":{},"delivery":{"items":[{"type":"item","value":"TEST-CHFH-STL9-87D6"},{"type":"item","value":"TEST-2PTX-YVQV-PSNY"}],"instructions":{"text":"📌 Активировать ключ можно на сайте партнёра: https://premiumcdk.com\n\nБлагодарим Вас за покупку!\nПриятной игры и хорошего дня! 💙","html":"📌 Активировать ключ можно на сайте партнёра: <b>https://premiumcdk.com</b><br><br>Благодарим Вас за покупку!<br>Приятной игры и хорошего дня! 💙"},"attachments":[],"delivered_at":"2026-10-12T19:06:16+03:00"},"action":null,"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":2,"last_message_at":"2026-10-12T19:06:16+03:00"},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:16+03:00","completed_at":"2026-10-12T19:06:16+03:00","revision":4}}},{"id":1099,"type":"message.created","created_at":"2026-10-12T19:06:16+03:00","test":true,"data":{"order_id":"T78C203C2802","external_id":"shop-1005","message":{"id":323,"order_id":"T78C203C2802","from":"system","text":"Заказ отменён реселлером до начала работы. Средства возвращены на долларовый баланс.\nПричина (реселлер): «customer_request»","attachments":[],"read":false,"client_message_id":null,"created_at":"2026-10-12T19:06:16+03:00"}}},{"id":1100,"type":"order.refunded","created_at":"2026-10-12T19:06:16+03:00","test":true,"data":{"order":{"id":"T78C203C2802","external_id":"shop-1005","status":"refunded","status_text":"Возврат","delayed":false,"kind":"manual","type":"manual","test":true,"product":{"id":1259,"name":"Profile Package","image_url":"https://aviedo.net/tovars/2-0b072c9f.webp"},"category":{"id":31,"name":"Через Devplay"},"section":{"id":14,"name":"CookieRun: Kingdom"},"quantity":1,"price":{"currency":"USD","unit_price":"3.98","total":"3.98"},"fields":[{"key":"privyazannaya_pochta","label":"Привязанная почта","value":"player@example.com"},{"key":"parol","label":"Пароль","value":"••••••"},{"key":"comment","label":"Комментарий","value":"Ник в игре: PlayerOne"}],"meta":{},"delivery":null,"action":null,"refund":{"amount":"3.98","currency":"USD","reason":"cancelled_by_reseller","refunded_at":"2026-10-12T19:06:16+03:00"},"cancellable":false,"chat":{"can_write":true,"unread":1,"last_message_at":"2026-10-12T19:06:16+03:00"},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:16+03:00","completed_at":null,"revision":3}}}],"pagination":{"has_more":true,"next_after_id":1100},"meta":{"gap":false},"request_id":"req_ea331ae674da"}},"filtered":{"summary":"Только order.completed и order.refunded","value":{"ok":true,"data":[{"id":1098,"type":"order.completed","created_at":"2026-10-12T19:06:16+03:00","test":true,"data":{"order":{"id":"TC655EADB878","external_id":"shop-1002","status":"completed","status_text":"Выполнен","delayed":false,"kind":"uploaded","type":"digital_item","test":true,"product":{"id":1187,"name":"Family • 1 месяц","image_url":"https://aviedo.net/tovars/products-49d74742.webp"},"category":{"id":86,"name":"Подписки (EG) ⚡️"},"section":{"id":43,"name":"Spotify"},"quantity":2,"price":{"currency":"USD","unit_price":"3.72","total":"7.44"},"fields":[],"meta":{},"delivery":{"items":[{"type":"item","value":"TEST-CHFH-STL9-87D6"},{"type":"item","value":"TEST-2PTX-YVQV-PSNY"}],"instructions":{"text":"📌 Активировать ключ можно на сайте партнёра: https://premiumcdk.com\n\nБлагодарим Вас за покупку!\nПриятной игры и хорошего дня! 💙","html":"📌 Активировать ключ можно на сайте партнёра: <b>https://premiumcdk.com</b><br><br>Благодарим Вас за покупку!<br>Приятной игры и хорошего дня! 💙"},"attachments":[],"delivered_at":"2026-10-12T19:06:16+03:00"},"action":null,"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":2,"last_message_at":"2026-10-12T19:06:16+03:00"},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:16+03:00","completed_at":"2026-10-12T19:06:16+03:00","revision":4}}},{"id":1100,"type":"order.refunded","created_at":"2026-10-12T19:06:16+03:00","test":true,"data":{"order":{"id":"T78C203C2802","external_id":"shop-1005","status":"refunded","status_text":"Возврат","delayed":false,"kind":"manual","type":"manual","test":true,"product":{"id":1259,"name":"Profile Package","image_url":"https://aviedo.net/tovars/2-0b072c9f.webp"},"category":{"id":31,"name":"Через Devplay"},"section":{"id":14,"name":"CookieRun: Kingdom"},"quantity":1,"price":{"currency":"USD","unit_price":"3.98","total":"3.98"},"fields":[{"key":"privyazannaya_pochta","label":"Привязанная почта","value":"player@example.com"},{"key":"parol","label":"Пароль","value":"••••••"},{"key":"comment","label":"Комментарий","value":"Ник в игре: PlayerOne"}],"meta":{},"delivery":null,"action":null,"refund":{"amount":"3.98","currency":"USD","reason":"cancelled_by_reseller","refunded_at":"2026-10-12T19:06:16+03:00"},"cancellable":false,"chat":{"can_write":true,"unread":1,"last_message_at":"2026-10-12T19:06:16+03:00"},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:16+03:00","completed_at":null,"revision":3}}},{"id":1103,"type":"order.completed","created_at":"2026-10-12T19:06:16+03:00","test":true,"data":{"order":{"id":"T20EFB948DDD","external_id":"shop-1010","status":"completed","status_text":"Выполнен","delayed":false,"kind":"uploaded","type":"digital_item","test":true,"product":{"id":1187,"name":"Family • 1 месяц","image_url":"https://aviedo.net/tovars/products-49d74742.webp"},"category":{"id":86,"name":"Подписки (EG) ⚡️"},"section":{"id":43,"name":"Spotify"},"quantity":1,"price":{"currency":"USD","unit_price":"3.72","total":"3.72"},"fields":[],"meta":{},"delivery":{"items":[{"type":"item","value":"TEST-YBXE-T8CC-5TSB"}],"instructions":{"text":"📌 Активировать ключ можно на сайте партнёра: https://premiumcdk.com\n\nБлагодарим Вас за покупку!\nПриятной игры и хорошего дня! 💙","html":"📌 Активировать ключ можно на сайте партнёра: <b>https://premiumcdk.com</b><br><br>Благодарим Вас за покупку!<br>Приятной игры и хорошего дня! 💙"},"attachments":[],"delivered_at":"2026-10-12T19:06:16+03:00"},"action":null,"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":2,"last_message_at":"2026-10-12T19:06:16+03:00"},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:16+03:00","completed_at":"2026-10-12T19:06:16+03:00","revision":4}}}],"pagination":{"has_more":true,"next_after_id":1103},"meta":{"gap":false},"request_id":"req_9bf6680c5125"}},"test_only":{"summary":"Только тестовые order.completed (test=1)","value":{"ok":true,"data":[{"id":1098,"type":"order.completed","created_at":"2026-10-12T19:06:16+03:00","test":true,"data":{"order":{"id":"TC655EADB878","external_id":"shop-1002","status":"completed","status_text":"Выполнен","delayed":false,"kind":"uploaded","type":"digital_item","test":true,"product":{"id":1187,"name":"Family • 1 месяц","image_url":"https://aviedo.net/tovars/products-49d74742.webp"},"category":{"id":86,"name":"Подписки (EG) ⚡️"},"section":{"id":43,"name":"Spotify"},"quantity":2,"price":{"currency":"USD","unit_price":"3.72","total":"7.44"},"fields":[],"meta":{},"delivery":{"items":[{"type":"item","value":"TEST-CHFH-STL9-87D6"},{"type":"item","value":"TEST-2PTX-YVQV-PSNY"}],"instructions":{"text":"📌 Активировать ключ можно на сайте партнёра: https://premiumcdk.com\n\nБлагодарим Вас за покупку!\nПриятной игры и хорошего дня! 💙","html":"📌 Активировать ключ можно на сайте партнёра: <b>https://premiumcdk.com</b><br><br>Благодарим Вас за покупку!<br>Приятной игры и хорошего дня! 💙"},"attachments":[],"delivered_at":"2026-10-12T19:06:16+03:00"},"action":null,"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":2,"last_message_at":"2026-10-12T19:06:16+03:00"},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:16+03:00","completed_at":"2026-10-12T19:06:16+03:00","revision":4}}},{"id":1103,"type":"order.completed","created_at":"2026-10-12T19:06:16+03:00","test":true,"data":{"order":{"id":"T20EFB948DDD","external_id":"shop-1010","status":"completed","status_text":"Выполнен","delayed":false,"kind":"uploaded","type":"digital_item","test":true,"product":{"id":1187,"name":"Family • 1 месяц","image_url":"https://aviedo.net/tovars/products-49d74742.webp"},"category":{"id":86,"name":"Подписки (EG) ⚡️"},"section":{"id":43,"name":"Spotify"},"quantity":1,"price":{"currency":"USD","unit_price":"3.72","total":"3.72"},"fields":[],"meta":{},"delivery":{"items":[{"type":"item","value":"TEST-YBXE-T8CC-5TSB"}],"instructions":{"text":"📌 Активировать ключ можно на сайте партнёра: https://premiumcdk.com\n\nБлагодарим Вас за покупку!\nПриятной игры и хорошего дня! 💙","html":"📌 Активировать ключ можно на сайте партнёра: <b>https://premiumcdk.com</b><br><br>Благодарим Вас за покупку!<br>Приятной игры и хорошего дня! 💙"},"attachments":[],"delivered_at":"2026-10-12T19:06:16+03:00"},"action":null,"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":2,"last_message_at":"2026-10-12T19:06:16+03:00"},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:16+03:00","completed_at":"2026-10-12T19:06:16+03:00","revision":4}}}],"pagination":{"has_more":true,"next_after_id":1103},"meta":{"gap":false},"request_id":"req_5d1874824a50"}}}}}},"400":{"description":"- `invalid_request` — неверный тип или значение параметра (`details.param`), в том числе значение в `fields` не строка и не целое число\n- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"invalid_request":{"summary":"invalid_request: неверный limit (лента событий)","value":{"ok":false,"error":{"code":"invalid_request","message":"Параметр limit должен быть целым числом от 1 до 500","retryable":false,"retry_after":null,"details":{"param":"limit"}},"request_id":"req_e053c46515b1"}},"unknown_parameter":{"summary":"unknown_parameter: опечатка в query","value":{"ok":false,"error":{"code":"unknown_parameter","message":"Неизвестный параметр: statuss","retryable":false,"retry_after":null,"details":{"param":"statuss","allowed":["status","kind","product_id","from","to","updated_since","has_unread","delayed","test","limit","cursor"]}},"request_id":"req_f28a29e21c06"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo GET '/v1/events?after_id=0&limit=100'"},{"lang":"PHP","label":"PHP","source":"$res = $api->get('/v1/events', [\n    'after_id' => 0,\n    'limit' => 100,\n]);"},{"lang":"Python","label":"Python","source":"res = api.get(\"/v1/events\", {\n    \"after_id\": 0,\n    \"limit\": 100,\n})"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.get(\"/v1/events\", {\n  after_id: 0,\n  limit: 100,\n});"}]}},"/v1/webhooks/test":{"post":{"tags":["События и вебхуки"],"operationId":"testWebhook","summary":"Отправить тестовый вебхук","description":"Сразу отправляет событие `ping` на ваш Webhook URL и возвращает результат доставки. Тело — `{}`. Если отправка вебхуков была приостановлена и тест прошёл успешно, она возобновляется. Если URL не указан, придёт `200` с `delivered: false` и `error: \"webhook_not_configured\"`.\n\nКоды `error`: `invalid_url` — ссылка не прошла проверку (не `https://`, логин и пароль в ссылке, часть после `#`, порт не 443/8443, `localhost` и внутренние зоны, IP-адрес из запрещённого диапазона прямо в ссылке, адреса Aviedo); `address_not_allowed` — имя хоста по DNS указывает на частный, служебный или зарезервированный IP или на сервер Aviedo; `dns_error`, `connection_failed`, `tls_error`, `timeout`, `redirect_not_followed`, `http_error`, `request_failed` — ошибки доставки. `port_not_allowed` зарезервирован и сейчас не возвращается. Лимит — 5 в минуту.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","maxProperties":0},"example":{}}}},"responses":{"200":{"description":"Результат доставки.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/WebhookTestResult"},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"delivered":{"summary":"Доставлено","description":"Форма успешного ответа: ваш сервер ответил 200.","value":{"ok":true,"data":{"url":"https://shop.example.com/aviedo/webhook","delivered":true,"http_status":200,"duration_ms":143,"error":null},"request_id":"req_6e0b3d9a2f41"}},"dns_error":{"summary":"Не доставлено: домен не найден","value":{"ok":true,"data":{"url":"https://shop.example.com/aviedo/webhook","delivered":false,"http_status":null,"duration_ms":12,"error":"dns_error"},"request_id":"req_eec47a2917b1"}},"not_configured":{"summary":"URL не указан","value":{"ok":true,"data":{"url":null,"delivered":false,"http_status":null,"duration_ms":0,"error":"webhook_not_configured"},"request_id":"req_f332a906eca1"}}}}}},"400":{"description":"- `invalid_json` — тело не является JSON-объектом\n- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"invalid_json":{"summary":"invalid_json","value":{"ok":false,"error":{"code":"invalid_json","message":"Тело запроса не является валидным JSON","retryable":false,"retry_after":null,"details":null},"request_id":"req_64e1e4cef951"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"413":{"description":"- `payload_too_large` — тело больше 8 МБ или картинка больше 5 МБ","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"payload_too_large":{"summary":"payload_too_large","value":{"ok":false,"error":{"code":"payload_too_large","message":"Тело запроса слишком большое","retryable":false,"retry_after":null,"details":{"max_bytes":8388608}},"request_id":"req_83c446683620"}}}}}},"415":{"description":"- `unsupported_media_type` — у POST нет Content-Type: application/json","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"unsupported_media_type":{"summary":"unsupported_media_type","value":{"ok":false,"error":{"code":"unsupported_media_type","message":"Нужен заголовок Content-Type: application/json","retryable":false,"retry_after":null,"details":null},"request_id":"req_aba6339e4cfa"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo POST /v1/webhooks/test '{}'"},{"lang":"PHP","label":"PHP","source":"$res = $api->post('/v1/webhooks/test');"},{"lang":"Python","label":"Python","source":"res = api.post(\"/v1/webhooks/test\")"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.post(\"/v1/webhooks/test\");"}]}},"/v1/stats":{"get":{"tags":["Статистика"],"operationId":"getStats","summary":"Статистика","description":"Ваша статистика за период — теми же формулами, что в кабинете реселлера, поэтому за одинаковый период числа совпадают.\n\n- `spent` — сумма выполненных заказов (как «Оборот» в кабинете); заказы в работе и возвраты в неё не входят.\n- В топах `orders` — число выполненных заказов, до 10 позиций.\n- `avg_completion_minutes` — среднее время от создания до выполнения, всегда число с одной цифрой после точки.\n- Тестовые заказы не учитываются.","parameters":[{"name":"from","in":"query","required":false,"description":"Начало периода `YYYY-MM-DD` (московские сутки). По умолчанию — 30 дней назад.","schema":{"type":"string","format":"date"},"example":"2026-10-01"},{"name":"to","in":"query","required":false,"description":"Конец периода `YYYY-MM-DD`; период не больше 366 дней. По умолчанию — сегодня.","schema":{"type":"string","format":"date"},"example":"2026-10-31"},{"name":"group","in":"query","required":false,"description":"Шаг ряда `series`: `day` (по умолчанию) или `month`.","schema":{"type":"string","enum":["day","month"],"default":"day"}},{"name":"source","in":"query","required":false,"description":"`all` — все долларовые заказы (по умолчанию, как в кабинете), `api` — только API, `web` — только сайт.","schema":{"type":"string","enum":["all","api","web"],"default":"all"}}],"responses":{"200":{"description":"Статистика.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","required":["ok","data","request_id"],"properties":{"ok":{"type":"boolean","const":true},"data":{"$ref":"#/components/schemas/Stats"},"request_id":{"$ref":"#/components/schemas/RequestId"}}},"examples":{"week":{"summary":"Неделя без заказов (тестовые заказы не учитываются)","value":{"ok":true,"data":{"period":{"from":"2026-10-06","to":"2026-10-12","timezone":"Europe/Moscow"},"totals":{"orders":0,"completed":0,"refunded":0,"in_progress":0,"spent":"0.00","avg_completion_minutes":0.0},"series":[{"date":"2026-10-06","orders":0,"completed":0,"refunded":0,"spent":"0.00"},{"date":"2026-10-07","orders":0,"completed":0,"refunded":0,"spent":"0.00"},{"date":"2026-10-08","orders":0,"completed":0,"refunded":0,"spent":"0.00"},{"date":"2026-10-09","orders":0,"completed":0,"refunded":0,"spent":"0.00"},{"date":"2026-10-10","orders":0,"completed":0,"refunded":0,"spent":"0.00"},{"date":"2026-10-11","orders":0,"completed":0,"refunded":0,"spent":"0.00"},{"date":"2026-10-12","orders":0,"completed":0,"refunded":0,"spent":"0.00"}],"top_products":[],"top_categories":[],"top_sections":[]},"request_id":"req_d8f3f2f6f8b4"}}}}}},"400":{"description":"- `invalid_request` — неверный тип или значение параметра (`details.param`), в том числе значение в `fields` не строка и не целое число\n- `unknown_parameter` — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"unknown_parameter":{"summary":"unknown_parameter: опечатка в query","value":{"ok":false,"error":{"code":"unknown_parameter","message":"Неизвестный параметр: statuss","retryable":false,"retry_after":null,"details":{"param":"statuss","allowed":["status","kind","product_id","from","to","updated_since","has_unread","delayed","test","limit","cursor"]}},"request_id":"req_f28a29e21c06"}}}}}},"401":{"description":"- `missing_credentials` — нет одного из заголовков авторизации (`details.missing`)\n- `unauthorized` — токен неизвестен или отозван\n- `invalid_signature` — подпись не совпала (подсказки в `details`)\n- `timestamp_out_of_window` — расхождение часов больше 300 секунд (`details.server_time`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_credentials":{"summary":"missing_credentials: нет подписи","value":{"ok":false,"error":{"code":"missing_credentials","message":"Не хватает заголовков авторизации: X-Aviedo-Signature","retryable":false,"retry_after":null,"details":{"missing":["X-Aviedo-Signature"]}},"request_id":"req_3c6d95b439ce"}},"unauthorized":{"summary":"unauthorized","value":{"ok":false,"error":{"code":"unauthorized","message":"Токен неизвестен или отозван","retryable":false,"retry_after":null,"details":null},"request_id":"req_116ccdf168a7"}},"invalid_signature":{"summary":"invalid_signature","value":{"ok":false,"error":{"code":"invalid_signature","message":"Подпись не совпала","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"string_to_sign_prefix":"1791821251\nPOST\n/v1/orders/quote\n","body_sha256":"75b1111c8fcd7489cb0db7ac92457ef1626952c261ee6ff4a1649636908c916d","body_length":30}},"request_id":"req_acfe62169ede"}},"timestamp_out_of_window":{"summary":"timestamp_out_of_window","value":{"ok":false,"error":{"code":"timestamp_out_of_window","message":"Время запроса расходится с временем сервера больше чем на 300 секунд","retryable":false,"retry_after":null,"details":{"server_time":1791821251,"window_seconds":300}},"request_id":"req_540e95d86233"}}}}}},"403":{"description":"- `https_required` — запрос по http://\n- `reseller_not_approved` — статус реселлера не «одобрен»\n- `account_banned` — аккаунт заблокирован","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"https_required":{"summary":"https_required","value":{"ok":false,"error":{"code":"https_required","message":"Используйте HTTPS","retryable":false,"retry_after":null,"details":null},"request_id":"req_4e1e6bb7cfdd"}},"reseller_not_approved":{"summary":"reseller_not_approved","value":{"ok":false,"error":{"code":"reseller_not_approved","message":"Статус реселлера не «одобрен»","retryable":false,"retry_after":null,"details":null},"request_id":"req_af201674ff1c"}},"account_banned":{"summary":"account_banned","value":{"ok":false,"error":{"code":"account_banned","message":"Аккаунт заблокирован","retryable":false,"retry_after":null,"details":null},"request_id":"req_c9ba6cfdcd59"}}}}}},"429":{"description":"- `rate_limited` — превышен лимит запросов (`details.bucket`)","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"rate_limited":{"summary":"rate_limited","value":{"ok":false,"error":{"code":"rate_limited","message":"Превышен лимит запросов: 5 в минуту","retryable":true,"retry_after":29,"details":{"bucket":"webhook_test","limit":5,"reset":1791821280}},"request_id":"req_3da0ffffad67"}}}}}},"500":{"description":"- `internal_error` — ошибка на нашей стороне","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-Aviedo-Server-Time":{"$ref":"#/components/headers/X-Aviedo-Server-Time"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"internal_error":{"summary":"internal_error","description":"Форма ответа; значения `message`, `retry_after` и `details` зависят от ситуации.","value":{"ok":false,"error":{"code":"internal_error","message":"Внутренняя ошибка сервера","retryable":true,"retry_after":5,"details":null},"request_id":"req_51f0c3a9e6d2"}}}}}}},"x-codeSamples":[{"lang":"Shell","label":"curl (aviedo.sh)","source":"aviedo GET '/v1/stats?from=2026-10-01&to=2026-10-31&group=day'"},{"lang":"PHP","label":"PHP","source":"$res = $api->get('/v1/stats', [\n    'from' => '2026-10-01',\n    'to' => '2026-10-31',\n    'group' => 'day',\n]);"},{"lang":"Python","label":"Python","source":"res = api.get(\"/v1/stats\", {\n    \"from\": \"2026-10-01\",\n    \"to\": \"2026-10-31\",\n    \"group\": \"day\",\n})"},{"lang":"JavaScript","label":"Node.js","source":"const res = await api.get(\"/v1/stats\", {\n  from: \"2026-10-01\",\n  to: \"2026-10-31\",\n  group: \"day\",\n});"}]}}},"webhooks":{"order.processing":{"post":{"tags":["События и вебхуки"],"operationId":"webhook_order_processing","summary":"order.processing — Заказ в работе","description":"Продавец взял ручной заказ, или авто-заказ вернулся в работу после действия покупателя или повторной отправки.\n\nПроверьте подпись по сырому телу, ответьте `2xx` в течение 10 секунд, отбросьте повтор по `id`. Тело — объект Event; оно же приходит в `GET /v1/events`.","security":[],"parameters":[{"name":"X-Aviedo-Signature","in":"header","required":true,"description":"`t=<unix-время>,v1=<hex HMAC-SHA256(секретный_ключ, t + \".\" + сырое_тело)>`. После перевыпуска ключей 24 часа приходят два `v1`.","schema":{"type":"string"},"example":"t=1791810000,v1=9368001464b1e7ef2e2dc6b735ed4e317f2d79b845e00db0dfee62486f87d70b"},{"name":"X-Aviedo-Event","in":"header","required":true,"description":"Тип события (копия `type`).","schema":{"type":"string"}},{"name":"X-Aviedo-Event-Id","in":"header","required":true,"description":"ID события (копия `id`, не входит в подпись).","schema":{"type":"string"}},{"name":"X-Aviedo-Attempt","in":"header","required":true,"description":"Номер попытки доставки, 1–7.","schema":{"type":"string"}},{"name":"User-Agent","in":"header","required":true,"description":"`Aviedo-Webhooks/1.0`","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"},"example":{"id":1114,"type":"order.processing","created_at":"2026-10-12T19:06:46+03:00","test":true,"data":{"order":{"id":"TD0D8BE98162","external_id":"shop-1004","status":"processing","status_text":"В процессе","delayed":false,"kind":"manual","type":"manual","test":true,"product":{"id":1259,"name":"Profile Package","image_url":"https://aviedo.net/tovars/2-0b072c9f.webp"},"category":{"id":31,"name":"Через Devplay"},"section":{"id":14,"name":"CookieRun: Kingdom"},"quantity":1,"price":{"currency":"USD","unit_price":"3.98","total":"3.98"},"fields":[{"key":"privyazannaya_pochta","label":"Привязанная почта","value":"player@example.com"},{"key":"parol","label":"Пароль","value":"••••••"},{"key":"comment","label":"Комментарий","value":"Ник в игре: PlayerOne"}],"meta":{},"delivery":null,"action":null,"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":0,"last_message_at":null},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:46+03:00","completed_at":null,"revision":2}}}}}},"responses":{"200":{"description":"Любой код 2xx в течение 10 секунд — событие доставлено. Иначе повторим через 1 мин, 5 мин, 30 мин, 2 ч, 6 ч и 24 ч."}}}},"order.action_required":{"post":{"tags":["События и вебхуки"],"operationId":"webhook_order_action_required","summary":"order.action_required — Нужно действие покупателя","description":"Покупателю нужно открыть `order.action.url` (Roblox); в том числе выдана новая ссылка.\n\nПроверьте подпись по сырому телу, ответьте `2xx` в течение 10 секунд, отбросьте повтор по `id`. Тело — объект Event; оно же приходит в `GET /v1/events`.","security":[],"parameters":[{"name":"X-Aviedo-Signature","in":"header","required":true,"description":"`t=<unix-время>,v1=<hex HMAC-SHA256(секретный_ключ, t + \".\" + сырое_тело)>`. После перевыпуска ключей 24 часа приходят два `v1`.","schema":{"type":"string"},"example":"t=1791810000,v1=9368001464b1e7ef2e2dc6b735ed4e317f2d79b845e00db0dfee62486f87d70b"},{"name":"X-Aviedo-Event","in":"header","required":true,"description":"Тип события (копия `type`).","schema":{"type":"string"}},{"name":"X-Aviedo-Event-Id","in":"header","required":true,"description":"ID события (копия `id`, не входит в подпись).","schema":{"type":"string"}},{"name":"X-Aviedo-Attempt","in":"header","required":true,"description":"Номер попытки доставки, 1–7.","schema":{"type":"string"}},{"name":"User-Agent","in":"header","required":true,"description":"`Aviedo-Webhooks/1.0`","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"},"example":{"id":1104,"type":"order.action_required","created_at":"2026-10-12T19:06:27+03:00","test":true,"data":{"order":{"id":"TDC76B34FBF9","external_id":"shop-1006","status":"action_required","status_text":"Требуется действие","delayed":false,"kind":"auto","type":"robux","test":true,"product":{"id":171,"name":"80 робуксов","image_url":"https://aviedo.net/tovars/product212-934e3ed8.webp"},"category":{"id":19,"name":"Через вход ⚡️"},"section":{"id":18,"name":"Roblox"},"quantity":1,"price":{"currency":"USD","unit_price":"0.89","total":"0.89"},"fields":[{"key":"roblox_username","label":"Логин аккаунта Roblox","value":"builderman"}],"meta":{},"delivery":null,"action":{"type":"open_url","url":"https://example.com/aviedo-test/verify/TEST-VXYR-2BY9-MYDD","expires_at":null,"hint":"Откройте ссылку, войдите в аккаунт Roblox и подтвердите вход (2FA). После этого Robux будут зачислены автоматически."},"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":0,"last_message_at":null},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:27+03:00","completed_at":null,"revision":2}}}}}},"responses":{"200":{"description":"Любой код 2xx в течение 10 секунд — событие доставлено. Иначе повторим через 1 мин, 5 мин, 30 мин, 2 ч, 6 ч и 24 ч."}}}},"order.delayed":{"post":{"tags":["События и вебхуки"],"operationId":"webhook_order_delayed","summary":"order.delayed — Заминка у поставщика","description":"У авто-заказа сбой у поставщика (`delayed: true`), поддержка разбирается.\n\nПроверьте подпись по сырому телу, ответьте `2xx` в течение 10 секунд, отбросьте повтор по `id`. Тело — объект Event; оно же приходит в `GET /v1/events`.","security":[],"parameters":[{"name":"X-Aviedo-Signature","in":"header","required":true,"description":"`t=<unix-время>,v1=<hex HMAC-SHA256(секретный_ключ, t + \".\" + сырое_тело)>`. После перевыпуска ключей 24 часа приходят два `v1`.","schema":{"type":"string"},"example":"t=1791810000,v1=9368001464b1e7ef2e2dc6b735ed4e317f2d79b845e00db0dfee62486f87d70b"},{"name":"X-Aviedo-Event","in":"header","required":true,"description":"Тип события (копия `type`).","schema":{"type":"string"}},{"name":"X-Aviedo-Event-Id","in":"header","required":true,"description":"ID события (копия `id`, не входит в подпись).","schema":{"type":"string"}},{"name":"X-Aviedo-Attempt","in":"header","required":true,"description":"Номер попытки доставки, 1–7.","schema":{"type":"string"}},{"name":"User-Agent","in":"header","required":true,"description":"`Aviedo-Webhooks/1.0`","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"},"example":{"id":1105,"type":"order.delayed","created_at":"2026-10-12T19:06:31+03:00","test":true,"data":{"order":{"id":"T1B89A3A5685","external_id":"shop-1007","status":"processing","status_text":"В процессе","delayed":true,"kind":"auto","type":"game_topup","test":true,"product":{"id":1254,"name":"250 монет + эпик бокс","image_url":"https://aviedo.net/tovars/8-21adda58.webp"},"category":{"id":90,"name":"Через айди"},"section":{"id":47,"name":"Oxide: Survival Island"},"quantity":1,"price":{"currency":"USD","unit_price":"6.01","total":"6.01"},"fields":[{"key":"player_id","label":"Player ID","value":"123456789"}],"meta":{},"delivery":null,"action":null,"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":0,"last_message_at":null},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:31+03:00","completed_at":null,"revision":2}}}}}},"responses":{"200":{"description":"Любой код 2xx в течение 10 секунд — событие доставлено. Иначе повторим через 1 мин, 5 мин, 30 мин, 2 ч, 6 ч и 24 ч."}}}},"order.completed":{"post":{"tags":["События и вебхуки"],"operationId":"webhook_order_completed","summary":"order.completed — Заказ выполнен","description":"Результат в `order.delivery`.\n\nПроверьте подпись по сырому телу, ответьте `2xx` в течение 10 секунд, отбросьте повтор по `id`. Тело — объект Event; оно же приходит в `GET /v1/events`.","security":[],"parameters":[{"name":"X-Aviedo-Signature","in":"header","required":true,"description":"`t=<unix-время>,v1=<hex HMAC-SHA256(секретный_ключ, t + \".\" + сырое_тело)>`. После перевыпуска ключей 24 часа приходят два `v1`.","schema":{"type":"string"},"example":"t=1791810000,v1=9368001464b1e7ef2e2dc6b735ed4e317f2d79b845e00db0dfee62486f87d70b"},{"name":"X-Aviedo-Event","in":"header","required":true,"description":"Тип события (копия `type`).","schema":{"type":"string"}},{"name":"X-Aviedo-Event-Id","in":"header","required":true,"description":"ID события (копия `id`, не входит в подпись).","schema":{"type":"string"}},{"name":"X-Aviedo-Attempt","in":"header","required":true,"description":"Номер попытки доставки, 1–7.","schema":{"type":"string"}},{"name":"User-Agent","in":"header","required":true,"description":"`Aviedo-Webhooks/1.0`","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"},"example":{"id":1098,"type":"order.completed","created_at":"2026-10-12T19:06:16+03:00","test":true,"data":{"order":{"id":"TC655EADB878","external_id":"shop-1002","status":"completed","status_text":"Выполнен","delayed":false,"kind":"uploaded","type":"digital_item","test":true,"product":{"id":1187,"name":"Family • 1 месяц","image_url":"https://aviedo.net/tovars/products-49d74742.webp"},"category":{"id":86,"name":"Подписки (EG) ⚡️"},"section":{"id":43,"name":"Spotify"},"quantity":2,"price":{"currency":"USD","unit_price":"3.72","total":"7.44"},"fields":[],"meta":{},"delivery":{"items":[{"type":"item","value":"TEST-CHFH-STL9-87D6"},{"type":"item","value":"TEST-2PTX-YVQV-PSNY"}],"instructions":{"text":"📌 Активировать ключ можно на сайте партнёра: https://premiumcdk.com\n\nБлагодарим Вас за покупку!\nПриятной игры и хорошего дня! 💙","html":"📌 Активировать ключ можно на сайте партнёра: <b>https://premiumcdk.com</b><br><br>Благодарим Вас за покупку!<br>Приятной игры и хорошего дня! 💙"},"attachments":[],"delivered_at":"2026-10-12T19:06:16+03:00"},"action":null,"refund":null,"cancellable":false,"chat":{"can_write":true,"unread":2,"last_message_at":"2026-10-12T19:06:16+03:00"},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:16+03:00","completed_at":"2026-10-12T19:06:16+03:00","revision":4}}}}}},"responses":{"200":{"description":"Любой код 2xx в течение 10 секунд — событие доставлено. Иначе повторим через 1 мин, 5 мин, 30 мин, 2 ч, 6 ч и 24 ч."}}}},"order.refunded":{"post":{"tags":["События и вебхуки"],"operationId":"webhook_order_refunded","summary":"order.refunded — Деньги возвращены","description":"Возврат на баланс, в том числе после выполнения. Сумма и причина — в `order.refund`.\n\nПроверьте подпись по сырому телу, ответьте `2xx` в течение 10 секунд, отбросьте повтор по `id`. Тело — объект Event; оно же приходит в `GET /v1/events`.","security":[],"parameters":[{"name":"X-Aviedo-Signature","in":"header","required":true,"description":"`t=<unix-время>,v1=<hex HMAC-SHA256(секретный_ключ, t + \".\" + сырое_тело)>`. После перевыпуска ключей 24 часа приходят два `v1`.","schema":{"type":"string"},"example":"t=1791810000,v1=9368001464b1e7ef2e2dc6b735ed4e317f2d79b845e00db0dfee62486f87d70b"},{"name":"X-Aviedo-Event","in":"header","required":true,"description":"Тип события (копия `type`).","schema":{"type":"string"}},{"name":"X-Aviedo-Event-Id","in":"header","required":true,"description":"ID события (копия `id`, не входит в подпись).","schema":{"type":"string"}},{"name":"X-Aviedo-Attempt","in":"header","required":true,"description":"Номер попытки доставки, 1–7.","schema":{"type":"string"}},{"name":"User-Agent","in":"header","required":true,"description":"`Aviedo-Webhooks/1.0`","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"},"example":{"id":1100,"type":"order.refunded","created_at":"2026-10-12T19:06:16+03:00","test":true,"data":{"order":{"id":"T78C203C2802","external_id":"shop-1005","status":"refunded","status_text":"Возврат","delayed":false,"kind":"manual","type":"manual","test":true,"product":{"id":1259,"name":"Profile Package","image_url":"https://aviedo.net/tovars/2-0b072c9f.webp"},"category":{"id":31,"name":"Через Devplay"},"section":{"id":14,"name":"CookieRun: Kingdom"},"quantity":1,"price":{"currency":"USD","unit_price":"3.98","total":"3.98"},"fields":[{"key":"privyazannaya_pochta","label":"Привязанная почта","value":"player@example.com"},{"key":"parol","label":"Пароль","value":"••••••"},{"key":"comment","label":"Комментарий","value":"Ник в игре: PlayerOne"}],"meta":{},"delivery":null,"action":null,"refund":{"amount":"3.98","currency":"USD","reason":"cancelled_by_reseller","refunded_at":"2026-10-12T19:06:16+03:00"},"cancellable":false,"chat":{"can_write":true,"unread":1,"last_message_at":"2026-10-12T19:06:16+03:00"},"created_at":"2026-10-12T19:06:16+03:00","updated_at":"2026-10-12T19:06:16+03:00","completed_at":null,"revision":3}}}}}},"responses":{"200":{"description":"Любой код 2xx в течение 10 секунд — событие доставлено. Иначе повторим через 1 мин, 5 мин, 30 мин, 2 ч, 6 ч и 24 ч."}}}},"message.created":{"post":{"tags":["События и вебхуки"],"operationId":"webhook_message_created","summary":"message.created — Новое сообщение","description":"Сообщение от продавца или системное в чате заказа.\n\nПроверьте подпись по сырому телу, ответьте `2xx` в течение 10 секунд, отбросьте повтор по `id`. Тело — объект Event; оно же приходит в `GET /v1/events`.","security":[],"parameters":[{"name":"X-Aviedo-Signature","in":"header","required":true,"description":"`t=<unix-время>,v1=<hex HMAC-SHA256(секретный_ключ, t + \".\" + сырое_тело)>`. После перевыпуска ключей 24 часа приходят два `v1`.","schema":{"type":"string"},"example":"t=1791810000,v1=9368001464b1e7ef2e2dc6b735ed4e317f2d79b845e00db0dfee62486f87d70b"},{"name":"X-Aviedo-Event","in":"header","required":true,"description":"Тип события (копия `type`).","schema":{"type":"string"}},{"name":"X-Aviedo-Event-Id","in":"header","required":true,"description":"ID события (копия `id`, не входит в подпись).","schema":{"type":"string"}},{"name":"X-Aviedo-Attempt","in":"header","required":true,"description":"Номер попытки доставки, 1–7.","schema":{"type":"string"}},{"name":"User-Agent","in":"header","required":true,"description":"`Aviedo-Webhooks/1.0`","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"},"example":{"id":1117,"type":"message.created","created_at":"2026-10-12T19:06:50+03:00","test":true,"data":{"order_id":"TD0D8BE98162","external_id":"shop-1004","message":{"id":331,"order_id":"TD0D8BE98162","from":"support","text":"Тест: пришлите код","attachments":[],"read":false,"client_message_id":null,"created_at":"2026-10-12T19:06:50+03:00"}}}}}},"responses":{"200":{"description":"Любой код 2xx в течение 10 секунд — событие доставлено. Иначе повторим через 1 мин, 5 мин, 30 мин, 2 ч, 6 ч и 24 ч."}}}},"ping":{"post":{"tags":["События и вебхуки"],"operationId":"webhook_ping","summary":"ping — Тестовое событие","description":"Отправляется методом `POST /v1/webhooks/test`. В ленте событий его нет.\n\nПроверьте подпись по сырому телу, ответьте `2xx` в течение 10 секунд, отбросьте повтор по `id`. Тело — объект Event; оно же приходит в `GET /v1/events`.","security":[],"parameters":[{"name":"X-Aviedo-Signature","in":"header","required":true,"description":"`t=<unix-время>,v1=<hex HMAC-SHA256(секретный_ключ, t + \".\" + сырое_тело)>`. После перевыпуска ключей 24 часа приходят два `v1`.","schema":{"type":"string"},"example":"t=1791810000,v1=9368001464b1e7ef2e2dc6b735ed4e317f2d79b845e00db0dfee62486f87d70b"},{"name":"X-Aviedo-Event","in":"header","required":true,"description":"Тип события (копия `type`).","schema":{"type":"string"}},{"name":"X-Aviedo-Event-Id","in":"header","required":true,"description":"ID события (копия `id`, не входит в подпись).","schema":{"type":"string"}},{"name":"X-Aviedo-Attempt","in":"header","required":true,"description":"Номер попытки доставки, 1–7.","schema":{"type":"string"}},{"name":"User-Agent","in":"header","required":true,"description":"`Aviedo-Webhooks/1.0`","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"},"example":{"id":1042,"type":"ping","created_at":"2026-10-12T16:00:00+03:00","test":false,"data":{}}}}},"responses":{"200":{"description":"Любой код 2xx в течение 10 секунд — событие доставлено. Иначе повторим через 1 мин, 5 мин, 30 мин, 2 ч, 6 ч и 24 ч."}}}}},"components":{"securitySchemes":{"AviedoToken":{"type":"http","scheme":"bearer","bearerFormat":"rsl_…","description":"API токен из кабинета реселлера: `Authorization: Bearer rsl_…`. Передаётся вместе с `X-Aviedo-Timestamp` и `X-Aviedo-Signature`."},"AviedoTimestamp":{"type":"apiKey","in":"header","name":"X-Aviedo-Timestamp","description":"Текущее unix-время в секундах; допустимое расхождение с сервером ±300 секунд."},"AviedoSignature":{"type":"apiKey","in":"header","name":"X-Aviedo-Signature","description":"`hex(HMAC-SHA256(секретный_ключ, ts + \"\\n\" + METHOD + \"\\n\" + PATH_WITH_QUERY + \"\\n\" + BODY))` — 64 символа в нижнем регистре. Подробно — в разделе «Авторизация и подпись»."}},"headers":{"X-Request-Id":{"description":"ID запроса, то же значение, что `request_id` в теле. Указывайте его, когда пишете в поддержку.","schema":{"type":"string","pattern":"^req_[0-9a-f]{12}$","example":"req_63f28101673f"}},"X-Aviedo-Server-Time":{"description":"Unix-время сервера в секундах — для сверки часов (окно подписи ±300 с). Приходит во всех ответах API, кроме ошибок, которые формирует прокси (nginx): `403 https_required`, `429 rate_limited` по IP, `400 invalid_request` у повреждённого HTTP-запроса, `413 payload_too_large` у тела больше 10 МБ, `500 internal_error` при сбое шлюза и `404 not_found` для путей вне `/v1/`.","schema":{"type":"string","pattern":"^[0-9]+$","example":"1791815974"}},"X-RateLimit-Limit":{"description":"Лимит самой «узкой» из корзин, в которые засчитан запрос, на текущую минуту.","schema":{"type":"string","example":"120"}},"X-RateLimit-Remaining":{"description":"Сколько запросов осталось в этой корзине до конца минуты.","schema":{"type":"string","example":"119"}},"X-RateLimit-Reset":{"description":"Unix-время начала следующей минуты, когда счётчики обнулятся.","schema":{"type":"string","example":"1791816000"}},"Retry-After":{"description":"Через сколько секунд можно повторить запрос (у ошибок с `retryable: true`).","schema":{"type":"string","example":"17"}},"ETag":{"description":"Версия ответа. Передайте его как есть в `If-None-Match` следующего запроса — при неизменном каталоге придёт `304`. При сжатии gzip приходит в слабой форме `W/\"…\"`, это нормально.","schema":{"type":"string","example":"W/\"2367397b7c9a28379efbb74df61a1a44\""}},"Cache-Control":{"description":"`no-store` у всех ответов, `private, no-cache` у каталога и списка товаров.","schema":{"type":"string","example":"no-store"}},"Allow":{"description":"Допустимые методы для этого пути (у `405 method_not_allowed`).","schema":{"type":"string","example":"POST, GET"}}},"schemas":{"RequestId":{"type":"string","description":"ID запроса для поддержки, совпадает с заголовком `X-Request-Id`.","pattern":"^req_[0-9a-f]{12}$","examples":["req_63f28101673f"]},"Money":{"type":"string","description":"Сумма в долларах, строка с двумя знаками после точки.","pattern":"^-?[0-9]+\\.[0-9]{2}$","examples":["12.67"]},"DateTime":{"type":"string","description":"Время ISO-8601 с московским смещением.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]},"OrderId":{"type":"string","description":"ID заказа: 12 символов `[0-9A-F]` у боевых заказов, `T` + 11 символов у тестовых. Регистр не важен.","pattern":"^(?:[0-9A-Fa-f]{12}|[Tt][0-9A-Fa-f]{11})$","examples":["T3088AD3A7FA","4A04D6B650FB"]},"ErrorCode":{"type":"string","description":"Машиночитаемый код ошибки. Список может расширяться: незнакомый код обрабатывайте по HTTP-статусу и `retryable`.","enum":["invalid_json","invalid_request","unknown_parameter","missing_credentials","unauthorized","invalid_signature","timestamp_out_of_window","insufficient_funds","https_required","reseller_not_approved","account_banned","not_found","product_not_found","order_not_found","method_not_allowed","product_unavailable","out_of_stock","price_changed","external_id_conflict","not_cancellable","chat_closed","payload_too_large","unsupported_media_type","validation_failed","quantity_out_of_range","account_not_found","chat_required","rate_limited","send_code_cooldown","internal_error","rate_unavailable","maintenance","provider_unavailable","server_busy","insufficient_storage"],"x-enumDescriptions":{"invalid_json":"HTTP 400 — тело не является JSON-объектом","invalid_request":"HTTP 400 — неверный тип или значение параметра (`details.param`), в том числе значение в `fields` не строка и не целое число","unknown_parameter":"HTTP 400 — неизвестный параметр в теле или query (`details.param`, `details.allowed`)","missing_credentials":"HTTP 401 — нет одного из заголовков авторизации (`details.missing`)","unauthorized":"HTTP 401 — токен неизвестен или отозван","invalid_signature":"HTTP 401 — подпись не совпала (подсказки в `details`)","timestamp_out_of_window":"HTTP 401 — расхождение часов больше 300 секунд (`details.server_time`)","insufficient_funds":"HTTP 402 — на балансе меньше суммы заказа","https_required":"HTTP 403 — запрос по http://","reseller_not_approved":"HTTP 403 — статус реселлера не «одобрен»","account_banned":"HTTP 403 — аккаунт заблокирован","not_found":"HTTP 404 — неизвестный путь","product_not_found":"HTTP 404 — товар удалён или не существовал","order_not_found":"HTTP 404 — такого заказа у вас нет","method_not_allowed":"HTTP 405 — неверный HTTP-метод (`details.allowed`, заголовок `Allow`)","product_unavailable":"HTTP 409 — товар скрыт или истёк (`details.reason`)","out_of_stock":"HTTP 409 — товара не хватает (`details.available`)","price_changed":"HTTP 409 — сумма выше `max_total_usd` (`details.total`)","external_id_conflict":"HTTP 409 — external_id уже использован с другими параметрами (`details.order_id`)","not_cancellable":"HTTP 409 — заказ нельзя отменить (`details.status`)","chat_closed":"HTTP 409 — переписка по заказу закрыта","payload_too_large":"HTTP 413 — тело больше 8 МБ или картинка больше 5 МБ","unsupported_media_type":"HTTP 415 — у POST нет Content-Type: application/json","validation_failed":"HTTP 422 — ошибки в полях (`details.errors[]`)","quantity_out_of_range":"HTTP 422 — количество вне диапазона (`details.min`, `max`, `step`)","account_not_found":"HTTP 422 — получатель не найден у поставщика (`details.field`; `null`, если у товара нет полей)","chat_required":"HTTP 422 — ручной товар без вебхука и без `accept_chat: true`","rate_limited":"HTTP 429, можно повторить — превышен лимит запросов (`details.bucket`)","send_code_cooldown":"HTTP 429, можно повторить — код на эту почту уже отправляли (`details.reason`)","internal_error":"HTTP 500, можно повторить — ошибка на нашей стороне","rate_unavailable":"HTTP 503, можно повторить — курс доллара устарел, заказы не принимаются","maintenance":"HTTP 503, можно повторить — технические работы","provider_unavailable":"HTTP 503, можно повторить — поставщик или сервис проверки недоступен","server_busy":"HTTP 503, можно повторить — создание не уложилось в 30 секунд или запрос долго ждал в очереди","insufficient_storage":"HTTP 507, можно повторить — мало места для файлов, фото не принимаются"}},"FieldError":{"type":"object","properties":{"field":{"type":"string","description":"Где ошибка: `fields.<key>`, `email` или `image`.","examples":["fields.telegram_username"]},"code":{"type":"string","description":"Код ошибки поля.","enum":["required","too_long","too_short","invalid_format","invalid_option","out_of_range","unknown_field"]},"message":{"type":"string","description":"Текст для человека."},"allowed":{"type":"array","items":{"type":"string"},"description":"Допустимые значения или ключи (у `invalid_option` и `unknown_field`)."}},"required":["field","code","message"],"description":"Ошибка одного поля в `details.errors[]` у `422 validation_failed`.","additionalProperties":false},"Error":{"type":"object","properties":{"code":{"$ref":"#/components/schemas/ErrorCode"},"message":{"type":"string","description":"Описание для человека. Текст может меняться — логику стройте на `code`."},"retryable":{"type":"boolean","description":"`true` — запрос можно повторить не раньше чем через `retry_after` секунд."},"retry_after":{"type":["integer","null"],"description":"Сколько секунд ждать перед повтором; то же значение в заголовке `Retry-After`.","minimum":1},"details":{"type":["object","null"],"description":"Подробности, зависят от кода: `param`, `allowed`, `errors[]`, `available`, `total`, `order_id`, `bucket` и т. д.","additionalProperties":true}},"required":["code","message","retryable","retry_after","details"],"description":"Описание ошибки.","additionalProperties":false},"ErrorResponse":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"error":{"$ref":"#/components/schemas/Error"},"request_id":{"$ref":"#/components/schemas/RequestId"}},"required":["ok","error","request_id"],"description":"Ответ с ошибкой. Приходит с HTTP-статусом 4xx/5xx.","additionalProperties":false},"CursorPagination":{"type":"object","properties":{"has_more":{"type":"boolean","description":"Есть ли следующая страница."},"next_cursor":{"type":["string","null"],"description":"Курсор следующей страницы — передайте в `cursor`. `null`, если страниц больше нет."}},"required":["has_more","next_cursor"],"description":"Пагинация по курсору (от новых к старым).","additionalProperties":false},"AfterIdPagination":{"type":"object","properties":{"has_more":{"type":"boolean","description":"Есть ли ещё записи после последней в ответе."},"next_after_id":{"type":"integer","description":"ID последней записи в ответе — передайте его в `after_id`. Если записей нет, равен переданному `after_id`.","minimum":0}},"required":["has_more","next_after_id"],"description":"Пагинация по возрастанию ID (от старых к новым).","additionalProperties":false},"Status":{"type":"object","properties":{"server_time":{"type":"string","description":"Время ISO-8601 с московским смещением.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]},"server_unix":{"type":"integer","description":"Unix-время сервера в секундах."},"orders_enabled":{"type":"boolean","description":"Принимаются ли сейчас заказы: `false` во время технических работ или пока курс устарел."},"maintenance":{"type":"boolean","description":"Идут технические работы."},"rate_fresh":{"type":"boolean","description":"Курс доллара свежий (обновлялся не позже 120 минут назад)."},"announcement":{"type":["string","null"],"description":"Объявление для реселлеров (плановые работы и т. п.) или `null`."},"api_version":{"type":"string","description":"Версия API.","examples":["1.0"]}},"required":["server_time","server_unix","orders_enabled","maintenance","rate_fresh","announcement","api_version"],"additionalProperties":false},"Me":{"type":"object","properties":{"reseller":{"type":"object","properties":{"id":{"type":"string","description":"ID аккаунта Aviedo (строка вида \"ab12-3456\"). Храните как строку.","examples":["ab12-3456"]},"username":{"type":["string","null"],"description":"Логин без `@`."},"status":{"type":"string","description":"Статус реселлера: здесь всегда `approved` — иначе запрос не пройдёт авторизацию.","enum":["approved"]},"approved_at":{"type":["string","null"],"description":"Время ISO-8601 с московским смещением.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]}},"required":["id","username","status","approved_at"],"additionalProperties":false},"balance":{"type":"object","properties":{"currency":{"type":"string","enum":["USD"]},"available":{"type":"string","description":"Сумма в долларах, строка с двумя знаками после точки.","pattern":"^-?[0-9]+\\.[0-9]{2}$","examples":["12.67"]}},"required":["currency","available"],"description":"Долларовый баланс.","additionalProperties":false},"rate":{"type":"object","properties":{"usd_rub":{"type":["string","null"],"description":"Курс: рублей за 1 $, шесть знаков.","examples":["87.270000"]},"fresh":{"type":"boolean","description":"Курс свежий."}},"required":["usd_rub","fresh"],"additionalProperties":false},"webhook":{"type":"object","properties":{"url":{"type":["string","null"],"description":"Webhook URL из кабинета.","format":"uri"},"status":{"type":"string","description":"`active` — отправка работает, `paused` — приостановлена после 3 суток сбоев, `none` — URL не указан.","enum":["active","paused","none"]}},"required":["url","status"],"additionalProperties":false},"key":{"type":"object","properties":{"created_at":{"type":["string","null"],"description":"Время ISO-8601 с московским смещением.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]},"previous_key_valid_until":{"type":["string","null"],"description":"До какого момента после перевыпуска ещё работает старая пара ключей; `null`, если старой пары нет.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]}},"required":["created_at","previous_key_valid_until"],"additionalProperties":false},"limits":{"type":"object","properties":{"requests_per_minute":{"type":"integer","description":"Общий лимит запросов в минуту."},"orders_per_minute":{"type":"integer","description":"Лимит `POST /v1/orders` в минуту."},"uploaded_max_per_order":{"type":"integer","description":"Сколько штук загруженного товара можно купить одним заказом."}},"required":["requests_per_minute","orders_per_minute","uploaded_max_per_order"],"additionalProperties":false},"unread_messages":{"type":"integer","description":"Непрочитанные сообщения продавца и системные по боевым заказам.","minimum":0},"server_time":{"type":"string","description":"Время ISO-8601 с московским смещением.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]},"api_version":{"type":"string","examples":["1.0"]}},"required":["reseller","balance","rate","webhook","key","limits","unread_messages","server_time","api_version"],"additionalProperties":false},"Balance":{"type":"object","properties":{"currency":{"type":"string","enum":["USD"]},"available":{"type":"string","description":"Сумма в долларах, строка с двумя знаками после точки.","pattern":"^-?[0-9]+\\.[0-9]{2}$","examples":["12.67"]},"updated_at":{"type":["string","null"],"description":"Время последней операции по балансу.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]}},"required":["currency","available","updated_at"],"additionalProperties":false},"BalanceTransaction":{"type":"object","properties":{"id":{"type":"string","description":"Код операции.","examples":["7Q2M-9X4K-P8Z3"]},"type":{"type":"string","description":"Тип операции.","enum":["order_payment","order_refund","topup","adjustment"],"x-enumDescriptions":{"order_payment":"оплата заказа (сумма со знаком минус)","order_refund":"возврат за заказ","topup":"пополнение баланса","adjustment":"ручная корректировка, начисление, вывод, реферальное начисление"}},"amount":{"type":"string","description":"Сумма: списания с минусом, зачисления с плюсом.","pattern":"^-?[0-9]+\\.[0-9]{2}$","examples":["12.67"]},"currency":{"type":"string","enum":["USD"]},"order_id":{"type":["string","null"],"description":"ID заказа для `order_payment` и `order_refund`."},"external_id":{"type":["string","null"],"description":"Ваш `external_id` заказа, если заказ создан через API."},"created_at":{"type":"string","description":"Время ISO-8601 с московским смещением.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]}},"required":["id","type","amount","currency","order_id","external_id","created_at"],"additionalProperties":false},"Rate":{"type":"object","properties":{"base":{"type":"string","enum":["USD"]},"quote":{"type":"string","enum":["RUB"]},"rate":{"type":"string","description":"Сколько рублей стоит 1 $, шесть знаков.","examples":["87.270000"]},"updated_at":{"type":["string","null"],"description":"Когда курс в последний раз проверялся.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]},"fresh":{"type":"boolean","description":"`false`, если курс не обновлялся больше `stale_after_minutes` минут — тогда заказы не принимаются."},"age_minutes":{"type":["integer","null"],"description":"Сколько минут назад курс обновлялся."},"stale_after_minutes":{"type":"integer","description":"Через сколько минут без обновления курс считается устаревшим.","examples":[120]},"prices_currency":{"type":"string","description":"Валюта всех цен в API.","enum":["USD"]},"prices_include_your_markup":{"type":"boolean","description":"Цены в API уже включают вашу наценку.","const":true}},"required":["base","quote","rate","updated_at","fresh","age_minutes","stale_after_minutes","prices_currency","prices_include_your_markup"],"additionalProperties":false},"IdName":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"Instructions":{"type":"object","properties":{"text":{"type":"string","description":"Простой текст, переносы строк — `\\n`."},"html":{"type":"string","description":"HTML с тегами `b i u s a code pre br`."}},"required":["text","html"],"description":"Инструкция для покупателя после выполнения.","additionalProperties":false},"FieldOption":{"type":"object","properties":{"value":{"type":"string","description":"Что передавать в `fields`."},"label":{"type":"string","description":"Что показывать покупателю."}},"required":["value","label"],"additionalProperties":false},"Field":{"type":"object","properties":{"key":{"type":"string","description":"Ключ в объекте `fields` заказа. Стабилен.","examples":["telegram_username"]},"label":{"type":"string","description":"Подпись для покупателя.","examples":["Username в Telegram"]},"type":{"type":"string","description":"Тип поля. Список может расширяться — незнакомый тип показывайте как `text`.","enum":["text","password","email","select","telegram_username","ipv4","number"],"x-enumDescriptions":{"text":"строка","password":"пароль, в ответах маскируется","email":"e-mail до 254 символов","select":"одно из `options[].value`","telegram_username":"username Telegram: можно с @ или t.me/…","ipv4":"IPv4-адрес вашего покупателя","number":"целое число строкой (зарезервировано)"}},"required":{"type":"boolean","description":"Обязательное поле."},"min_length":{"type":["integer","null"],"description":"Минимальная длина."},"max_length":{"type":["integer","null"],"description":"Максимальная длина."},"pattern":{"type":["string","null"],"description":"Регулярное выражение (PCRE и JS) или `null`."},"options":{"type":["array","null"],"items":{"$ref":"#/components/schemas/FieldOption"},"description":"Варианты для `select`."},"hint":{"type":["string","null"],"description":"Подсказка для покупателя."},"sensitive":{"type":"boolean","description":"`true` у паролей: значение маскируется в ответах как `••••••`."}},"required":["key","label","type","required","min_length","max_length","pattern","options","hint","sensitive"],"description":"Описание поля, которое нужно передать в заказе.","additionalProperties":false},"Price":{"type":"object","properties":{"currency":{"type":"string","enum":["USD"]},"model":{"type":"string","description":"`fixed` — цена за штуку, `per_unit` — цена единицы (звезды, рубля/гривны/тенге кошелька Steam).","enum":["fixed","per_unit"]},"unit_price":{"type":"string","description":"Цена за единицу с вашей наценкой: два знака у `fixed`, шесть у `per_unit`.","pattern":"^[0-9]+\\.([0-9]{2}|[0-9]{6})$","examples":["12.67","0.015960"]},"unit":{"type":"string","description":"Единица: `pcs` — штука, `star` — звезда, `RUB`/`UAH`/`KZT` — валюта кошелька Steam.","enum":["pcs","star","RUB","UAH","KZT"]}},"required":["currency","model","unit_price","unit"],"additionalProperties":false},"Quantity":{"type":"object","properties":{"min":{"type":"integer","description":"Минимальное количество.","minimum":1},"max":{"type":["integer","null"],"description":"Максимальное количество с учётом остатка и лимитов; `0` — купить нельзя; `null` — без верхней границы (технический предел — 1 000 000 000).","minimum":0},"step":{"type":"integer","description":"Шаг.","const":1},"label":{"type":"string","description":"Подпись для поля ввода.","examples":["Количество звёзд"]}},"required":["min","max","step","label"],"additionalProperties":false},"Stock":{"type":"object","properties":{"in_stock":{"type":"boolean","description":"Можно ли заказывать."},"count":{"type":["integer","null"],"description":"Остаток в штуках; `null` — без ограничений или неизвестно.","minimum":0},"checked_at":{"type":["string","null"],"description":"Когда остаток сверяли с поставщиком.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]}},"required":["in_stock","count","checked_at"],"additionalProperties":false},"Product":{"type":"object","properties":{"id":{"type":"integer","description":"ID товара."},"name":{"type":"string","description":"Название как на витрине."},"kind":{"type":"string","description":"Вид товара.","enum":["auto","uploaded","manual"],"x-enumDescriptions":{"auto":"автоматическая выдача поставщиком","uploaded":"загруженные заранее ключи и аккаунты, выдаются сразу","manual":"выполняет продавец"}},"type":{"type":"string","description":"Подтип. Список может расширяться.","enum":["game_topup","gift_card","voucher","telegram_stars","telegram_premium","telegram_gift","steam_topup","robux","spotify","digital_item","manual","manual_login"]},"result":{"type":"string","description":"Что получит покупатель.","enum":["code","item","topup","link","service"],"x-enumDescriptions":{"code":"код карты или ваучера","item":"ключ или аккаунт строкой","topup":"зачисление на аккаунт, показывать нечего","link":"ссылка","service":"работу выполнит продавец"}},"section":{"$ref":"#/components/schemas/IdName"},"category":{"$ref":"#/components/schemas/IdName"},"group":{"anyOf":[{"$ref":"#/components/schemas/IdName"},{"type":"null"}]},"image_url":{"type":["string","null"],"format":"uri"},"position":{"type":"integer","description":"Порядок внутри категории."},"price":{"$ref":"#/components/schemas/Price"},"quantity":{"$ref":"#/components/schemas/Quantity"},"stock":{"$ref":"#/components/schemas/Stock"},"available":{"type":"boolean","description":"Можно ли купить прямо сейчас."},"unavailable_reason":{"type":["string","null"],"description":"Почему нельзя купить.","enum":["out_of_stock","hidden","expired",null]},"available_until":{"type":["string","null"],"description":"Когда исчезнет временный товар.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]},"eta":{"type":"string","description":"Ориентир по срокам для покупателя."},"requires":{"type":"object","properties":{"chat":{"type":"boolean","description":"Ручной товар: продавец может писать в чат заказа; нужен вебхук или `accept_chat: true`."},"end_user_action":{"type":"boolean","description":"После оплаты покупатель должен открыть ссылку (Roblox)."},"email_code":{"type":"boolean","description":"Перед заказом нужно отправить код на почту (`send-code`)."}},"required":["chat","end_user_action","email_code"],"additionalProperties":false},"fields_version":{"type":"string","description":"Хеш набора полей: меняется при любом изменении `fields`.","examples":["f3a91c0e"]},"fields":{"type":"array","items":{"$ref":"#/components/schemas/Field"},"description":"Что передать в заказе."}},"required":["id","name","kind","type","result","section","category","group","image_url","position","price","quantity","stock","available","unavailable_reason","available_until","eta","requires","fields_version","fields"],"description":"Товар с вашей ценой.","additionalProperties":false},"Group":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"position":{"type":"integer"}},"required":["id","name","position"],"additionalProperties":false},"FaqItem":{"type":"object","properties":{"title":{"type":"string"},"text":{"type":"string"}},"required":["title","text"],"additionalProperties":false},"Category":{"type":"object","properties":{"id":{"type":"integer"},"section_id":{"type":"integer"},"name":{"type":"string"},"image_url":{"type":"null","description":"У категорий пока нет своих картинок — показывайте картинку раздела или товара."},"position":{"type":"integer"},"description":{"type":"string","description":"Описание категории (простой текст)."},"notice":{"type":"string","description":"Важное предупреждение для покупателя (может быть пустым)."},"eta":{"type":"string","description":"Ориентир по срокам."},"instructions":{"$ref":"#/components/schemas/Instructions"},"faq":{"type":"array","items":{"$ref":"#/components/schemas/FaqItem"}},"tags":{"type":"array","items":{"type":"string"}},"groups":{"type":"array","items":{"$ref":"#/components/schemas/Group"},"description":"Группы товаров внутри категории."},"products":{"type":"array","items":{"$ref":"#/components/schemas/Product"}}},"required":["id","section_id","name","image_url","position","description","notice","eta","instructions","faq","tags","groups","products"],"additionalProperties":false},"Section":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"type":{"type":"string","description":"`game` — игры, `service` — сервисы.","enum":["game","service"]},"image_url":{"type":["string","null"],"format":"uri"},"position":{"type":"integer"},"categories":{"type":"array","items":{"$ref":"#/components/schemas/Category"}}},"required":["id","name","type","image_url","position","categories"],"additionalProperties":false},"Catalog":{"type":"object","properties":{"generated_at":{"type":"string","description":"Время ISO-8601 с московским смещением.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]},"version":{"type":"string","description":"Короткий хеш содержимого.","examples":["2367397b"]},"rate":{"type":"object","properties":{"usd_rub":{"type":"string","examples":["87.270000"]},"fresh":{"type":"boolean"}},"required":["usd_rub","fresh"],"additionalProperties":false},"sections":{"type":"array","items":{"$ref":"#/components/schemas/Section"}}},"required":["generated_at","version","rate","sections"],"additionalProperties":false},"DeliveryItem":{"type":"object","properties":{"type":{"type":"string","description":"`code` — код карты или ваучера, `item` — ключ или аккаунт, `link` — ссылка.","enum":["code","item","link"]},"value":{"type":"string","description":"Значение для покупателя."}},"required":["type","value"],"additionalProperties":false},"Attachment":{"type":"object","properties":{"type":{"type":"string","enum":["photo"]},"url":{"type":"string","description":"Ссылка на файл. Скачайте и храните у себя.","format":"uri"},"mime":{"type":"string","examples":["image/jpeg"]}},"required":["type","url","mime"],"additionalProperties":false},"Delivery":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/DeliveryItem"},"description":"Выданные значения по порядку; у пополнений пусто."},"instructions":{"anyOf":[{"$ref":"#/components/schemas/Instructions"},{"type":"null"}]},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Attachment"},"description":"Фото от продавца."},"delivered_at":{"type":["string","null"],"description":"Время ISO-8601 с московским смещением.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]}},"required":["items","instructions","attachments","delivered_at"],"description":"Результат заказа, заполняется при `completed`.","additionalProperties":false},"Action":{"type":"object","properties":{"type":{"type":"string","enum":["open_url"]},"url":{"type":"string","description":"Ссылку нужно сразу передать покупателю.","format":"uri"},"expires_at":{"type":["string","null"],"description":"Срок действия ссылки, если поставщик его сообщил.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]},"hint":{"type":"string","description":"Готовая подсказка для покупателя."}},"required":["type","url","expires_at","hint"],"description":"Что должен сделать покупатель (при `action_required`).","additionalProperties":false},"Refund":{"type":"object","properties":{"amount":{"type":"string","description":"Сумма возврата, всегда равна `price.total`.","pattern":"^-?[0-9]+\\.[0-9]{2}$","examples":["12.67"]},"currency":{"type":"string","enum":["USD"]},"reason":{"type":"string","description":"Причина возврата.","enum":["cancelled_by_reseller","out_of_stock","supplier_failed","support_decision"],"x-enumDescriptions":{"cancelled_by_reseller":"вы отменили ручной заказ","out_of_stock":"товар закончился у поставщика","supplier_failed":"поставщик не смог выполнить заказ","support_decision":"решение поддержки"}},"refunded_at":{"type":["string","null"],"description":"Время ISO-8601 с московским смещением.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]}},"required":["amount","currency","reason","refunded_at"],"additionalProperties":false},"OrderField":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"value":{"type":"string","description":"Введённое значение; у `sensitive` полей — `••••••`."}},"required":["key","label","value"],"additionalProperties":false},"Order":{"type":"object","properties":{"id":{"$ref":"#/components/schemas/OrderId"},"external_id":{"type":["string","null"],"description":"Ваш номер заказа."},"status":{"type":"string","description":"Статус заказа. Незнакомый статус считайте `processing`.","enum":["pending","processing","action_required","completed","refunded"],"x-enumDescriptions":{"pending":"ручной заказ ждёт продавца","processing":"выполняется","action_required":"покупатель должен открыть `action.url`","completed":"выполнен, результат в `delivery`","refunded":"деньги возвращены"}},"status_text":{"type":"string","description":"Готовый русский текст статуса.","examples":["В процессе"]},"delayed":{"type":"boolean","description":"Заминка у поставщика: поддержка уже разбирается (статус остаётся `processing`)."},"kind":{"type":"string","enum":["auto","uploaded","manual"]},"type":{"type":"string","examples":["telegram_premium"]},"test":{"type":"boolean","description":"Тестовый заказ."},"product":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"image_url":{"type":["string","null"],"format":"uri"}},"required":["id","name","image_url"],"additionalProperties":false},"category":{"$ref":"#/components/schemas/IdName"},"section":{"$ref":"#/components/schemas/IdName"},"quantity":{"type":"integer","minimum":1},"price":{"type":"object","properties":{"currency":{"type":"string","enum":["USD"]},"unit_price":{"type":"string","description":"Цена за единицу на момент покупки."},"total":{"type":"string","description":"Списанная сумма.","pattern":"^-?[0-9]+\\.[0-9]{2}$","examples":["12.67"]}},"required":["currency","unit_price","total"],"additionalProperties":false},"fields":{"type":"array","items":{"$ref":"#/components/schemas/OrderField"},"description":"Переданные данные."},"meta":{"type":"object","additionalProperties":{"type":"string"},"description":"Ваши метки из запроса, как есть."},"delivery":{"anyOf":[{"$ref":"#/components/schemas/Delivery"},{"type":"null"}],"description":"Результат заказа при `completed`, иначе `null`. После возврата (в том числе после выполнения) снова `null` — сохраняйте `delivery.items` из `order.completed`."},"action":{"anyOf":[{"$ref":"#/components/schemas/Action"},{"type":"null"}]},"refund":{"anyOf":[{"$ref":"#/components/schemas/Refund"},{"type":"null"}]},"cancellable":{"type":"boolean","description":"Можно ли отменить заказ прямо сейчас (ручной заказ в `pending`)."},"chat":{"type":"object","properties":{"can_write":{"type":"boolean","description":"Можно ли писать продавцу: пока заказ не завершён и 14 дней после."},"unread":{"type":"integer","description":"Непрочитанные сообщения продавца и системные.","minimum":0},"last_message_at":{"type":["string","null"],"description":"Время ISO-8601 с московским смещением.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]}},"required":["can_write","unread","last_message_at"],"additionalProperties":false},"created_at":{"type":"string","description":"Время ISO-8601 с московским смещением.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]},"updated_at":{"type":"string","description":"Время ISO-8601 с московским смещением.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]},"completed_at":{"type":["string","null"],"description":"Когда заказ выполнен; `null`, пока заказ не `completed`, и снова `null` после возврата.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]},"revision":{"type":"integer","description":"Растёт при каждом изменении. Сохраняйте заказ, только если `revision` больше сохранённого.","minimum":0}},"required":["id","external_id","status","status_text","delayed","kind","type","test","product","category","section","quantity","price","fields","meta","delivery","action","refund","cancellable","chat","created_at","updated_at","completed_at","revision"],"description":"Заказ. Один и тот же объект приходит из всех методов, событий и вебхуков.","additionalProperties":false},"Message":{"type":"object","properties":{"id":{"type":"integer","description":"ID сообщения (растёт)."},"order_id":{"$ref":"#/components/schemas/OrderId"},"from":{"type":"string","description":"`reseller` — вы, `support` — продавец или поддержка, `system` — служебное сообщение.","enum":["reseller","support","system"]},"text":{"type":"string","description":"Текст; у сообщения только с фото — пустая строка."},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Attachment"}},"read":{"type":"boolean","description":"Прочитано вами (у ваших сообщений всегда `true`)."},"client_message_id":{"type":["string","null"],"description":"Ваш ID сообщения (только у ваших сообщений)."},"created_at":{"type":"string","description":"Время ISO-8601 с московским смещением.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]}},"required":["id","order_id","from","text","attachments","read","client_message_id","created_at"],"description":"Сообщение чата заказа.","additionalProperties":false},"OrderEventData":{"type":"object","properties":{"order":{"$ref":"#/components/schemas/Order"}},"required":["order"],"description":"Данные событий `order.*`.","additionalProperties":false},"MessageEventData":{"type":"object","properties":{"order_id":{"$ref":"#/components/schemas/OrderId"},"external_id":{"type":["string","null"]},"message":{"$ref":"#/components/schemas/Message"}},"required":["order_id","external_id","message"],"description":"Данные события `message.created`.","additionalProperties":false},"Event":{"type":"object","properties":{"id":{"type":"integer","description":"ID события, растёт. По нему отбрасывайте повторы."},"type":{"type":"string","description":"Тип события. Список может расширяться.","enum":["order.processing","order.action_required","order.delayed","order.completed","order.refunded","message.created","ping"]},"created_at":{"type":"string","description":"Время ISO-8601 с московским смещением.","format":"date-time","examples":["2026-10-12T17:39:35+03:00"]},"test":{"type":"boolean","description":"Событие тестового заказа. В боевой интеграции такие события не должны приводить к выдаче товара."},"data":{"oneOf":[{"$ref":"#/components/schemas/OrderEventData"},{"$ref":"#/components/schemas/MessageEventData"},{"type":"object","maxProperties":0,"description":"У `ping` — пустой объект."}]}},"required":["id","type","created_at","test","data"],"description":"Событие. То же тело приходит вебхуком.","additionalProperties":false},"CreateOrderRequest":{"type":"object","properties":{"product_id":{"type":["integer","string"],"description":"ID товара.","examples":[853]},"quantity":{"type":["integer","string","null"],"description":"Количество. Обязательно, если `quantity.max` у товара больше 1.","examples":[1]},"external_id":{"type":"string","description":"Ваш номер заказа: уникален навсегда в пределах аккаунта. Не меняйте его при повторах.","pattern":"^[A-Za-z0-9_.:-]{1,64}$","examples":["shop-1001"]},"max_total_usd":{"type":["string","number"],"description":"Наибольшая сумма, которую вы согласны заплатить (до двух знаков).","examples":["12.67"]},"fields":{"type":["object","null"],"additionalProperties":{"type":["string","integer"]},"description":"Поля заказа «ключ → строка» по описанию `fields` товара. Целые числа превращаются в строку; другой тип значения или `fields` не объектом — `400 invalid_request` (`details.param`)."},"meta":{"type":["object","null"],"maxProperties":10,"additionalProperties":{"type":"string","maxLength":200},"propertyNames":{"minLength":1,"maxLength":40},"description":"Ваши метки: до 10 пар, ключ до 40 символов, значение до 200."},"accept_chat":{"type":["boolean","null"],"description":"Для ручных товаров без вебхука: вы подтверждаете, что читаете события и отвечаете продавцу."},"test":{"type":["boolean","null"],"description":"Тестовый заказ: баланс не списывается."},"test_scenario":{"type":["string","null"],"description":"Сценарий тестового заказа (только с `test: true`).","enum":["success","refund","delay","action_required","chat","completed_then_refunded","out_of_stock","account_not_found",null]}},"required":["product_id","external_id","max_total_usd"],"description":"Тело создания заказа. Неизвестные поля дают `400 unknown_parameter`.","additionalProperties":false},"QuoteRequest":{"type":"object","properties":{"product_id":{"type":["integer","string"],"description":"ID товара.","examples":[853]},"quantity":{"type":["integer","string","null"],"description":"Количество. Обязательно, если `quantity.max` у товара больше 1.","examples":[1]},"external_id":{"type":"string","description":"Ваш номер заказа: уникален навсегда в пределах аккаунта. Не меняйте его при повторах.","pattern":"^[A-Za-z0-9_.:-]{1,64}$","examples":["shop-1001"]},"max_total_usd":{"type":["string","number"],"description":"Наибольшая сумма, которую вы согласны заплатить (до двух знаков).","examples":["12.67"]},"fields":{"type":["object","null"],"additionalProperties":{"type":["string","integer"]},"description":"Поля заказа «ключ → строка» по описанию `fields` товара. Целые числа превращаются в строку; другой тип значения или `fields` не объектом — `400 invalid_request` (`details.param`)."},"meta":{"type":["object","null"],"maxProperties":10,"additionalProperties":{"type":"string","maxLength":200},"propertyNames":{"minLength":1,"maxLength":40},"description":"Ваши метки: до 10 пар, ключ до 40 символов, значение до 200."},"accept_chat":{"type":["boolean","null"],"description":"Для ручных товаров без вебхука: вы подтверждаете, что читаете события и отвечаете продавцу."},"test":{"type":["boolean","null"],"description":"Тестовый заказ: баланс не списывается."},"test_scenario":{"type":["string","null"],"description":"Сценарий тестового заказа (только с `test: true`).","enum":["success","refund","delay","action_required","chat","completed_then_refunded","out_of_stock","account_not_found",null]}},"required":["product_id"],"description":"То же тело, что у создания заказа; `external_id` и `max_total_usd` необязательны. Незаполненные обязательные поля и `quantity` попадают в `problems`, как ошибки у `POST /v1/orders`.","additionalProperties":false},"QuoteProblem":{"type":"object","properties":{"code":{"type":"string","description":"Код как у ошибок API.","enum":["product_unavailable","chat_required","validation_failed","quantity_out_of_range","out_of_stock","account_not_found","provider_unavailable","insufficient_funds","price_changed"]},"message":{"type":"string"},"details":{"type":["object","null"],"additionalProperties":true}},"required":["code","message","details"],"additionalProperties":false},"Quote":{"type":"object","properties":{"can_order":{"type":"boolean","description":"Можно ли оформить заказ прямо сейчас."},"product_id":{"type":"integer"},"quantity":{"type":"integer","description":"Количество, по которому посчитаны `total` и `balance_after`: переданное, а если оно не прошло проверку (не передано, вне диапазона, больше остатка) — `quantity.min` товара. Во втором случае суммы только для ориентира."},"currency":{"type":"string","enum":["USD"]},"unit_price":{"type":"string","examples":["12.67"]},"total":{"type":"string","description":"Сумма в долларах, строка с двумя знаками после точки.","pattern":"^-?[0-9]+\\.[0-9]{2}$","examples":["12.67"]},"balance":{"type":"string","description":"Сумма в долларах, строка с двумя знаками после точки.","pattern":"^-?[0-9]+\\.[0-9]{2}$","examples":["12.67"]},"balance_after":{"type":"string","description":"Баланс после заказа (может быть отрицательным).","pattern":"^-?[0-9]+\\.[0-9]{2}$","examples":["12.67"]},"checks":{"type":"object","properties":{"fields":{"type":"string","enum":["ok","failed","skipped","not_supported"]},"quantity":{"type":"string","enum":["ok","failed","skipped","not_supported"]},"stock":{"type":"string","enum":["ok","failed","skipped","not_supported"]},"account":{"type":"string","enum":["ok","failed","skipped","not_supported"]}},"required":["fields","quantity","stock","account"],"description":"`ok`, `failed`, `skipped` (не проверялось: например, `account` без получателя или `quantity` у закончившегося товара) или `not_supported` (для товара проверки нет). `fields` проверяются всегда, даже если `fields` не передан.","additionalProperties":false},"problems":{"type":"array","items":{"$ref":"#/components/schemas/QuoteProblem"},"description":"Причины, по которым заказ нельзя оформить."}},"required":["can_order","product_id","quantity","currency","unit_price","total","balance","balance_after","checks","problems"],"additionalProperties":false},"CancelRequest":{"type":"object","properties":{"reason":{"type":["string","null"],"description":"Причина отмены, до 200 символов. Сохраняется одной строкой.","maxLength":200}},"additionalProperties":false},"MessageRequest":{"type":"object","properties":{"text":{"type":["string","null"],"description":"Текст до 4000 символов.","maxLength":4000},"image":{"type":["object","null"],"properties":{"filename":{"type":["string","null"],"description":"Не используется, файл сохраняется под случайным именем.","maxLength":255},"content_base64":{"type":"string","description":"JPG, PNG или WEBP в base64, до 5 МБ после декодирования; можно с префиксом `data:image/…;base64,`."}},"required":["content_base64"],"additionalProperties":false},"client_message_id":{"type":["string","null"],"description":"Ваш ID сообщения для защиты от дублей.","pattern":"^[A-Za-z0-9_.:-]{1,64}$"}},"description":"Нужно передать `text` или `image` (можно оба).","additionalProperties":false},"MarkReadRequest":{"type":"object","properties":{"up_to_id":{"type":["integer","null"],"description":"Отметить прочитанными сообщения до этого ID включительно. Без параметра — все.","minimum":1}},"additionalProperties":false},"SendCodeRequest":{"type":"object","properties":{"email":{"type":"string","description":"Почта Supercell ID покупателя (до 254 символов).","format":"email","maxLength":254}},"required":["email"],"additionalProperties":false},"SendCodeResult":{"type":"object","properties":{"sent":{"type":"boolean","const":true},"cooldown_seconds":{"type":"integer","description":"Через сколько секунд можно отправить код на эту почту снова.","examples":[60]}},"required":["sent","cooldown_seconds"],"additionalProperties":false},"UnreadResult":{"type":"object","properties":{"unread":{"type":"integer","description":"Сколько непрочитанных осталось.","minimum":0}},"required":["unread"],"additionalProperties":false},"WebhookTestResult":{"type":"object","properties":{"url":{"type":["string","null"],"format":"uri"},"delivered":{"type":"boolean","description":"Получен ответ 2xx."},"http_status":{"type":["integer","null"],"description":"HTTP-код ответа вашего сервера."},"duration_ms":{"type":"integer","description":"Время запроса в миллисекундах."},"error":{"type":["string","null"],"description":"Почему не доставлено. Список может расширяться.","enum":["webhook_not_configured","invalid_url","address_not_allowed","dns_error","connection_failed","tls_error","timeout","redirect_not_followed","http_error","request_failed","port_not_allowed",null],"x-enumDescriptions":{"webhook_not_configured":"Webhook URL не указан в кабинете","invalid_url":"ссылка не прошла проверку: не `https://`, логин или пароль в ссылке, часть после `#`, порт не 443 и не 8443, точка в конце имени, `localhost`, `*.local`, `*.internal`, IP-адрес из запрещённого диапазона прямо в ссылке, адрес Aviedo","address_not_allowed":"имя хоста по DNS указывает на частный, служебный или зарезервированный IP или на сервер Aviedo","dns_error":"имя хоста не найдено в DNS","connection_failed":"не удалось подключиться","tls_error":"ошибка TLS: сертификат недействителен, не совпадает имя и т. п.","timeout":"нет ответа за 10 секунд","redirect_not_followed":"сервер ответил `3xx`; редиректы не выполняются","http_error":"сервер ответил кодом не `2xx`","request_failed":"другая ошибка соединения","port_not_allowed":"зарезервировано, сейчас не возвращается: недопустимый порт даёт `invalid_url`"}}},"required":["url","delivered","http_status","duration_ms","error"],"additionalProperties":false},"StatsTop":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"orders":{"type":"integer","description":"Выполненные заказы."},"spent":{"type":"string","description":"Сумма в долларах, строка с двумя знаками после точки.","pattern":"^-?[0-9]+\\.[0-9]{2}$","examples":["12.67"]}},"required":["id","name","orders","spent"],"additionalProperties":false},"Stats":{"type":"object","properties":{"period":{"type":"object","properties":{"from":{"type":"string","format":"date"},"to":{"type":"string","format":"date"},"timezone":{"type":"string","enum":["Europe/Moscow"]}},"required":["from","to","timezone"],"additionalProperties":false},"totals":{"type":"object","properties":{"orders":{"type":"integer","description":"Все заказы за период."},"completed":{"type":"integer"},"refunded":{"type":"integer"},"in_progress":{"type":"integer"},"spent":{"type":"string","description":"Сумма выполненных заказов (как «Оборот» в кабинете).","pattern":"^-?[0-9]+\\.[0-9]{2}$","examples":["12.67"]},"avg_completion_minutes":{"type":"number","description":"Среднее время выполнения в минутах, одна цифра после точки."}},"required":["orders","completed","refunded","in_progress","spent","avg_completion_minutes"],"additionalProperties":false},"series":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","description":"`YYYY-MM-DD` или `YYYY-MM` при `group=month`."},"orders":{"type":"integer"},"completed":{"type":"integer"},"refunded":{"type":"integer"},"spent":{"type":"string","description":"Сумма в долларах, строка с двумя знаками после точки.","pattern":"^-?[0-9]+\\.[0-9]{2}$","examples":["12.67"]}},"required":["date","orders","completed","refunded","spent"],"additionalProperties":false}},"top_products":{"type":"array","items":{"$ref":"#/components/schemas/StatsTop"},"description":"До 10 позиций."},"top_categories":{"type":"array","items":{"$ref":"#/components/schemas/StatsTop"}},"top_sections":{"type":"array","items":{"$ref":"#/components/schemas/StatsTop"}}},"required":["period","totals","series","top_products","top_categories","top_sections"],"additionalProperties":false}}}}
