{
  "openapi": "3.1.0",
  "jsonSchemaDialect": "https://spec.openapis.org/oas/3.1/dialect/base",
  "info": {
    "title": "MaxCheck API",
    "version": "1.0.0",
    "summary": "Проверка наличия номеров в мессенджере MAX (через MAX241).",
    "description": "MaxCheck API проверяет, зарегистрированы ли российские мобильные номера в мессенджере **MAX**, и возвращает\nдоступные данные профиля. Проверку выполняет система **MAX241**; других провайдеров API не использует.\n\n## 1. Введение\n\nAPI асинхронный: заказ создаётся одним запросом, проверка выполняется в фоне, результат забирается отдельно.\n\n- **Расчёт стоимости** без списания — `POST /v1/quote`.\n- **Создание и оплата заказа** — `POST /v1/orders`. Деньги списываются сразу при создании, ровно один раз.\n- **Статус заказа** и список своих заказов — `GET /v1/orders/{order_id}`, `GET /v1/orders`.\n- **Полный результат** одним JSON — `GET /v1/orders/{order_id}/result`.\n- **Баланс и тариф** — `GET /v1/balance`.\n\nБаланс общий с Telegram-ботом MaxCheck: заказы API и бота списываются с одного счёта по одной цене\n(индивидуальной, если она назначена). Все суммы — в **USDT**.\n\nФормат обмена — JSON в UTF-8. Суммы передаются **строками** (`\"0.8440\"`), чтобы не терять точность.\nВремя — ISO 8601 в UTC с суффиксом `Z` (`\"2026-11-14T19:36:24.439015Z\"`).\n\n## 2. Быстрый старт\n\n1. Сохраните свой API-ключ в переменную окружения `MAXCHECK_API_KEY` (раздел 3).\n2. Проверьте ключ и баланс:\n   ```bash\n   curl -s https://maxapi.work/v1/balance -H \"Authorization: Bearer $MAXCHECK_API_KEY\"\n   ```\n3. Рассчитайте стоимость (ничего не списывается):\n   ```bash\n   curl -s https://maxapi.work/v1/quote -H \"Authorization: Bearer $MAXCHECK_API_KEY\" \\\n     -H \"Content-Type: application/json\" -d @order.json\n   ```\n4. Создайте заказ с уникальным `Idempotency-Key` и сохраните `order_id`:\n   ```bash\n   curl -s https://maxapi.work/v1/orders -H \"Authorization: Bearer $MAXCHECK_API_KEY\" \\\n     -H \"Content-Type: application/json\" -H \"Idempotency-Key: $(uuidgen)\" -d @order.json\n   ```\n5. Опрашивайте `GET /v1/orders/{order_id}` раз в 5–15 секунд, пока `state` не станет `done`\n   (или `refunded` / `delayed`).\n6. Заберите результат: `GET /v1/orders/{order_id}/result`.\n\nФайл `order.json`: `{\"phones\": [\"79001234567\", \"79001234568\", \"…\"], \"name\": \"Моя база\"}` —\nв заказе должно быть не меньше 1 000 уникальных валидных номеров.\n\n## 3. Авторизация через API-ключ\n\n- Каждый запрос передаёт ключ **только** в заголовке `Authorization: Bearer <ключ>`.\n- Формат ключа: `mcak_` и 43 символа `A–Z a–z 0–9 _ -` (всего 48 символов).\n- Ключ в параметрах URL (`api_key`, `apikey`, `key`, `token`, `access_token`, `authorization`) отклоняется с\n  `400 key_in_url`.\n- Нет ключа, ключ неверный или отозван — `401 unauthorized`. Отзыв действует сразу, со следующего запроса.\n- У пользователя один действующий ключ. Заказы, баланс и результаты принадлежат пользователю, а не ключу:\n  с новым ключом видны все прежние заказы.\n- Храните ключ как пароль: не пишите его в журналы, не передавайте в URL, не вставляйте в код в открытом виде.\n\n## 4. Проверка баланса\n\n`GET /v1/balance` возвращает баланс, цену одного номера и цену за 1 000 номеров. Если сервис проверки временно\nне настроен, `price_per_number` и `price_per_1000` равны `null`.\n\n## 5. Расчёт стоимости\n\n`POST /v1/quote` принимает тот же JSON, что и создание заказа, и ничего не списывает.\n\nКак обрабатываются номера (одинаково для расчёта и заказа):\n\n- Пустые строки отбрасываются. Если в первой строке нет ни одной цифры (например, `\"Телефон\"`), а дальше есть\n  валидные номера, первая строка считается заголовком и тоже отбрасывается.\n- Из строки удаляются все символы, кроме цифр. Принимаются только российские мобильные номера:\n  10 цифр, начинающиеся с `9` (`9001234567`), или 11 цифр, начинающиеся с `79` или `89`. Результат нормализации —\n  `79XXXXXXXXX`. Остальное — неверные номера (`invalid_count`).\n- Повторы после нормализации — дубли (`duplicates_count`). В заказ попадает первое вхождение номера.\n- Оплачиваются только уникальные валидные номера: `total_cost = valid_count × unit_price`, округление до 4 знаков\n  (половина — вверх).\n- `valid_count` должен быть от **1 000** до **300 000**.\n\nПоле `can_order` показывает, можно ли сейчас создать такой заказ, а `reason` — почему нельзя.\n\n## 6. Создание заказа\n\n`POST /v1/orders` с обязательным заголовком `Idempotency-Key`.\n\n- В одной транзакции происходит расчёт, **списание ровно `total_cost`** и создание заказа. Оплаченного заказа без\n  номеров и заказа без списания не бывает.\n- Цена фиксируется в момент создания: последующее изменение тарифа на заказ не влияет.\n- Новый заказ — `201`, повтор того же запроса с тем же `Idempotency-Key` — `200` с тем же `order_id`\n  без нового списания (раздел 9).\n- Одновременно у пользователя может быть не больше **5 незавершённых** заказов (`created`, `submitting`, `processing`).\n\nСостояния заказа (`state`):\n\n| Состояние | Что значит | Что делать клиенту |\n|---|---|---|\n| `created` | заказ оплачен, ожидает отправки на проверку | ждать |\n| `submitting` | заказ передаётся в систему проверки | ждать |\n| `processing` | номера проверяются | ждать |\n| `done` | проверка завершена, результат готов | забрать результат |\n| `refunded` | проверка не выполнена, **полная сумма возвращена** на баланс; причина — `refund_reason` | при необходимости создать новый заказ |\n| `delayed` | автоматически завершить не удалось (`error: \"manual_review\"`), заказ на ручном разборе; деньги **автоматически не возвращаются** | продолжать опрашивать статус реже (например, раз в несколько минут); новый заказ на те же номера не создавать |\n\n`delayed` не окончательное: после ручного разбора заказ может перейти в `done` или `refunded`.\n\n## 7. Получение статуса\n\n`GET /v1/orders/{order_id}` — состояние, счётчики (`max_count` и `not_max_count` заполняются после `done`)\nи признак готовности результата `result_available`.\n\n`GET /v1/orders` — свои заказы от новых к старым, постранично (`limit` 1–100, по умолчанию 20; следующая страница —\nпо `next_cursor`).\n\nЧужой заказ неотличим от несуществующего: в обоих случаях `404 not_found`.\n\nРекомендуемый интервал опроса — **5–15 секунд**. Время выполнения зависит от объёма заказа и загрузки системы проверки.\n\n## 8. Получение результатов\n\n`GET /v1/orders/{order_id}/result` возвращает **один JSON со всеми проверенными номерами** — найденными и\nненайденными. Параметров у метода нет; `filter` и `format` не поддерживаются (`400 unsupported_parameter`).\n\n```json\n{\n  \"order_id\": \"6f1c2a7e-3b5d-4c8e-9a10-2d4b6e8f0a12\",\n  \"total\": 2,\n  \"results\": [\n    {\"phone\": \"79001234567\", \"in_max\": true, \"max_user_id\": \"123456789\", \"name\": \"Иван\",\n     \"last_name\": \"Иванов\", \"activity\": \"недавно\", \"reg_date\": \"12:30 05.11.2025\",\n     \"photo_url\": \"https://i.oneme.ru/i?r=EXAMPLE\"},\n    {\"phone\": \"79001234568\", \"in_max\": false, \"max_user_id\": null, \"name\": null,\n     \"last_name\": null, \"activity\": null, \"reg_date\": null, \"photo_url\": null}\n  ]\n}\n```\n\n- Порядок строк — порядок номеров в заказе после нормализации и удаления дублей; `total` = `valid_count`\n  заказа = числу строк в `results`.\n- У каждой строки ровно 8 полей. Нет значения — `null` (пустых строк нет). У ненайденных номеров\n  (`in_max: false`) все поля, кроме `phone` и `in_max`, равны `null`.\n- `activity` — `\"недавно\"` или `\"давно\"`; `reg_date` — дата регистрации в MAX, строка `ЧЧ:ММ дд.мм.ГГГГ` по\n  московскому времени; `photo_url` — ссылка `https://` на фото профиля (у многих пользователей фото нет).\n- Результат хранится **60 суток** после завершения, затем — `410 result_expired`.\n- Скачивание бесплатное и повторяемое: оно не списывает деньги и не запускает новую проверку.\n- Ответ отдаётся потоком; на 300 000 номеров это около 55 МБ. Читайте ответ целиком и разбирайте JSON\n  только после получения всего тела. Если соединение оборвалось, ответ неполный — повторите запрос.\n\n## 9. Idempotency-Key\n\n- `Idempotency-Key` обязателен для `POST /v1/orders`: 1–255 печатных ASCII-символов. Используйте UUID и\n  генерируйте его **один раз на заказ**, до первой отправки, и сохраняйте вместе с данными заказа.\n- Повтор с тем же ключом и **точно тем же телом** (тот же список `phones` в том же порядке и тот же `name`)\n  возвращает `200` и тот же заказ (`created: false`, `balance_after: null`). Повторного списания нет.\n- Тот же ключ с другим телом — `409 idempotency_conflict`, новый заказ не создаётся.\n- При таймауте, обрыве соединения или ответе `5xx` на создание заказа **повторяйте запрос с тем же ключом** —\n  не создавайте новый ключ, иначе можно оплатить заказ дважды.\n- Ключ идемпотентности действует в пределах API-ключа: после смены API-ключа тот же `Idempotency-Key` создаст\n  новый заказ.\n- Повторы тоже учитываются в лимите 20 `POST /v1/orders` в минуту.\n- Два разных ключа идемпотентности с одинаковыми номерами — два разных заказа и два списания.\n\n## 10. Лимиты и ограничения\n\n| Ограничение | Значение |\n|---|---|\n| Все запросы одного API-ключа | 120 в минуту (скользящее окно) |\n| `POST /v1/quote` | 30 в минуту на ключ |\n| `POST /v1/orders` (включая повторы и конфликты) | 20 в минуту на ключ |\n| Незавершённых заказов у пользователя | не больше 5 |\n| Тело запроса | до 8 МиБ, только `application/json` |\n| Строк в `phones` | до 1 000 000; каждая — строка до 64 символов |\n| Уникальных валидных номеров в заказе | от 1 000 до 300 000 |\n| `name` заказа | 1–255 символов без управляющих; по умолчанию `api_<8 символов>` |\n| Время обработки запроса | 30 секунд (выдача результата — 600 секунд) |\n| Хранение результата | 60 суток после завершения |\n\nПри превышении лимита частоты — `429 rate_limited` с заголовком `Retry-After` (секунды). Входной прокси может\nдополнительно ограничивать частоту и число одновременных соединений с одного IP-адреса.\n\n## 11. Ошибки API\n\nОшибки API — JSON вида `{\"error\": \"<код>\", \"message\": \"<текст>\"}`, иногда с дополнительными полями\n(`min_valid`, `max_valid`, `valid_count`, `invalid_count`, `total_cost`, `max_active_orders`, `max_rows`,\n`retry_after`, `state`). Опирайтесь на **код** `error`, а не на текст `message`.\n\n| HTTP | `error` | Значение и что делать |\n|---|---|---|\n| 400 | `invalid_json` | тело — не JSON-объект в UTF-8 |\n| 400 | `invalid_idempotency_key` | нет `Idempotency-Key` или он неверного формата |\n| 400 | `key_in_url` | API-ключ передан в URL — передавайте в `Authorization` |\n| 400 | `unsupported_parameter` | у `…/result` переданы `filter` или `format` — уберите их |\n| 401 | `unauthorized` | нет ключа, неверный или отозванный ключ |\n| 401 | `invalid_api_key` | ключ отозван во время создания заказа (редко); ничего не списано |\n| 402 | `insufficient_balance` | не хватает средств (`total_cost` — нужная сумма); пополните баланс |\n| 403 | `banned` | пользователь заблокирован |\n| 404 | `not_found` | заказ не найден (или чужой) |\n| 404 / 405 | `http_error` | неизвестный путь или метод |\n| 409 | `idempotency_conflict` | `Idempotency-Key` уже использован с другим телом |\n| 409 | `not_ready` | результат ещё не готов (`state` — текущее состояние); опрашивайте статус |\n| 409 | `order_refunded` | заказ возвращён, результата нет |\n| 410 | `result_expired` | срок хранения результата (60 суток) истёк |\n| 413 | `body_too_large` | тело больше 8 МиБ — разбейте заказ |\n| 415 | `unsupported_media_type` | нужен `Content-Type: application/json` |\n| 422 | `invalid_phones`, `too_many_rows`, `invalid_name`, `unknown_fields` | неверная структура тела |\n| 422 | `empty`, `no_valid_phones`, `below_min_valid`, `too_many_phones` | заказ не проходит по номерам; деньги не списаны |\n| 422 | `invalid_limit`, `invalid_cursor` | неверные параметры списка заказов |\n| 429 | `rate_limited` | превышен лимит частоты — ждите `Retry-After` |\n| 429 | `too_many_active_orders` | уже 5 незавершённых заказов — дождитесь завершения |\n| 500 | `internal_error` | внутренняя ошибка — повторите позже |\n| 503 | `service_unavailable` | сервис проверки временно недоступен; деньги не списаны |\n| 503 | `result_unavailable` | результат временно недоступен — повторите через `Retry-After` |\n| 504 | `timeout` | запрос не уложился во время; для `POST /v1/orders` повторите с тем же `Idempotency-Key` |\n\nОтветы `413`, `429`, `502`, `504` может вернуть и входной прокси — тогда тело **не JSON**. Обрабатывайте их по\nHTTP-коду.\n\nРекомендации:\n\n- `5xx`, `429` и сетевые ошибки — повторять с паузой (не чаще `Retry-After`), для создания заказа — только с тем же\n  `Idempotency-Key`.\n- `4xx`, кроме `409 not_ready` и `429`, — исправить запрос, повтор без изменений не поможет.\n- Ошибки на этапе создания (`402`, `422`, `503 service_unavailable`) означают, что деньги **не списаны**.\n\n## 12. Примеры интеграции на cURL и Python\n\n### cURL\n\n```bash\nAPI=https://maxapi.work\nAUTH=\"Authorization: Bearer $MAXCHECK_API_KEY\"\n\ncurl -s \"$API/v1/balance\" -H \"$AUTH\"\n\ncurl -s \"$API/v1/quote\" -H \"$AUTH\" -H \"Content-Type: application/json\" -d @order.json\n\nIDEM=$(uuidgen)            # сохраните вместе с заказом\ncurl -s \"$API/v1/orders\" -H \"$AUTH\" -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $IDEM\" -d @order.json\n\ncurl -s \"$API/v1/orders/$ORDER_ID\" -H \"$AUTH\"\ncurl -s \"$API/v1/orders/$ORDER_ID/result\" -H \"$AUTH\" -o result.json\n```\n\n### Python\n\n```python\nimport os, time, uuid\nimport requests  # pip install requests\n\nAPI = \"https://maxapi.work\"\nS = requests.Session()\nS.headers[\"Authorization\"] = f\"Bearer {os.environ['MAXCHECK_API_KEY']}\"\n\ndef call(method, path, **kw):\n    while True:\n        r = S.request(method, API + path, timeout=(10, 660), **kw)\n        if r.status_code == 429 or r.status_code >= 500:\n            time.sleep(int(r.headers.get(\"Retry-After\", 10)))\n            continue\n        return r\n\nphones = [line.strip() for line in open(\"phones.txt\", encoding=\"utf-8\") if line.strip()]\nbody = {\"phones\": phones, \"name\": \"Моя база\"}\n\nquote = call(\"POST\", \"/v1/quote\", json=body).json()\nif not quote[\"can_order\"]:\n    raise SystemExit(f\"заказ невозможен: {quote['reason']}\")\n\nidem = str(uuid.uuid4())     # один ключ на заказ; при повторах — тот же\nwhile True:\n    try:\n        r = call(\"POST\", \"/v1/orders\", json=body, headers={\"Idempotency-Key\": idem})\n        break\n    except requests.RequestException:\n        time.sleep(10)        # сеть: повторяем с ТЕМ ЖЕ idem\nr.raise_for_status()\norder_id = r.json()[\"order_id\"]\n\nwhile True:\n    st = call(\"GET\", f\"/v1/orders/{order_id}\").json()\n    if st[\"state\"] in (\"done\", \"refunded\"):\n        break\n    time.sleep(10 if st[\"state\"] != \"delayed\" else 300)   # delayed — ручной разбор, опрашивать реже\n\nif st[\"state\"] == \"done\":\n    result = call(\"GET\", f\"/v1/orders/{order_id}/result\").json()\n    found = [x for x in result[\"results\"] if x[\"in_max\"]]\n    print(result[\"total\"], \"номеров, найдено в MAX:\", len(found))\nelse:\n    print(\"возврат:\", st[\"refund_reason\"])\n```"
  },
  "servers": [
    {
      "url": "https://maxapi.work",
      "description": "MaxCheck API"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Баланс",
      "description": "Баланс и тариф пользователя."
    },
    {
      "name": "Заказы",
      "description": "Расчёт, создание, статус и список заказов."
    },
    {
      "name": "Результаты",
      "description": "Полный результат проверки в JSON."
    }
  ],
  "paths": {
    "/v1/balance": {
      "get": {
        "tags": [
          "Баланс"
        ],
        "operationId": "getBalance",
        "summary": "Баланс и тариф",
        "description": "Баланс пользователя и действующая цена. Ничего не меняет.",
        "responses": {
          "200": {
            "description": "Баланс и цена.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Balance"
                },
                "examples": {
                  "balance": {
                    "value": {
                      "balance": "172.6928",
                      "currency": "USDT",
                      "price_per_number": "0.00080000",
                      "price_per_1000": "0.8"
                    }
                  },
                  "service_unavailable": {
                    "summary": "Сервис проверки не настроен",
                    "value": {
                      "balance": "172.6928",
                      "currency": "USDT",
                      "price_per_number": null,
                      "price_per_1000": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/KeyInUrl"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "504": {
            "$ref": "#/components/responses/Timeout"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -s https://maxapi.work/v1/balance \\\n  -H \"Authorization: Bearer $MAXCHECK_API_KEY\""
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\nAPI = \"https://maxapi.work\"\nH = {\"Authorization\": f\"Bearer {os.environ['MAXCHECK_API_KEY']}\"}\nprint(requests.get(f\"{API}/v1/balance\", headers=H, timeout=30).json())"
          }
        ]
      }
    },
    "/v1/quote": {
      "post": {
        "tags": [
          "Заказы"
        ],
        "operationId": "quoteOrder",
        "summary": "Расчёт стоимости",
        "description": "Нормализует номера, считает дубли и неверные, стоимость и достаточность баланса. **Ничего не списывает и не создаёт.** Причины невозможности заказа возвращаются полем `reason` с HTTP 200; ошибки структуры тела — 4xx.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderRequest"
              },
              "examples": {
                "order": {
                  "summary": "Номера в разных записях (в реальном заказе — от 1 000 уникальных)",
                  "value": {
                    "phones": [
                      "79001234567",
                      "+7 (900) 123-45-68",
                      "89001234569",
                      "9001234570",
                      "79001234567",
                      "нет номера"
                    ],
                    "name": "Моя база"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Расчёт.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Quote"
                },
                "examples": {
                  "ok": {
                    "summary": "Заказ возможен",
                    "value": {
                      "total_rows": 1055,
                      "valid_count": 1055,
                      "duplicates_count": 0,
                      "invalid_count": 0,
                      "min_valid": 1000,
                      "max_valid": 300000,
                      "unit_price": "0.00080000",
                      "total_cost": "0.8440",
                      "balance": "173.5368",
                      "currency": "USDT",
                      "balance_sufficient": true,
                      "can_order": true,
                      "reason": null
                    }
                  },
                  "below_min_valid": {
                    "summary": "Меньше 1 000 валидных номеров",
                    "value": {
                      "total_rows": 6,
                      "valid_count": 4,
                      "duplicates_count": 1,
                      "invalid_count": 1,
                      "min_valid": 1000,
                      "max_valid": 300000,
                      "unit_price": null,
                      "total_cost": null,
                      "balance": "173.5368",
                      "currency": "USDT",
                      "balance_sufficient": null,
                      "can_order": false,
                      "reason": "below_min_valid"
                    }
                  },
                  "insufficient_balance": {
                    "summary": "Не хватает средств",
                    "value": {
                      "total_rows": 300000,
                      "valid_count": 300000,
                      "duplicates_count": 0,
                      "invalid_count": 0,
                      "min_valid": 1000,
                      "max_valid": 300000,
                      "unit_price": "0.00080000",
                      "total_cost": "240.0000",
                      "balance": "173.5368",
                      "currency": "USDT",
                      "balance_sufficient": false,
                      "can_order": false,
                      "reason": "insufficient_balance"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Тело — не JSON-объект в UTF-8, или ключ в URL.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_json": {
                    "value": {
                      "error": "invalid_json",
                      "message": "тело запроса — не корректный JSON в UTF-8"
                    }
                  },
                  "key_in_url": {
                    "value": {
                      "error": "key_in_url",
                      "message": "API-ключ передаётся только в заголовке Authorization"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Тело больше 8 МиБ.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "body_too_large": {
                    "value": {
                      "error": "body_too_large",
                      "message": "тело запроса больше 8388608 байт"
                    }
                  }
                }
              }
            }
          },
          "415": {
            "description": "Нужен `Content-Type: application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unsupported_media_type": {
                    "value": {
                      "error": "unsupported_media_type",
                      "message": "ожидается application/json"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Неверная структура тела.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_phones": {
                    "value": {
                      "error": "invalid_phones",
                      "message": "каждый номер — строка до 64 символов"
                    }
                  },
                  "too_many_rows": {
                    "value": {
                      "error": "too_many_rows",
                      "message": "не больше 1000000 строк",
                      "max_rows": 1000000
                    }
                  },
                  "invalid_name": {
                    "value": {
                      "error": "invalid_name",
                      "message": "name — строка 1..255 символов без управляющих"
                    }
                  },
                  "unknown_fields": {
                    "value": {
                      "error": "unknown_fields",
                      "message": "неизвестные поля: ['x']"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "504": {
            "$ref": "#/components/responses/Timeout"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -s https://maxapi.work/v1/quote \\\n  -H \"Authorization: Bearer $MAXCHECK_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"phones\": [\"79001234567\", \"79001234568\"], \"name\": \"Моя база\"}'"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\nAPI = \"https://maxapi.work\"\nH = {\"Authorization\": f\"Bearer {os.environ['MAXCHECK_API_KEY']}\"}\nbody = {\"phones\": [\"79001234567\", \"79001234568\"], \"name\": \"Моя база\"}\nprint(requests.post(f\"{API}/v1/quote\", json=body, headers=H, timeout=60).json())"
          }
        ]
      }
    },
    "/v1/orders": {
      "post": {
        "tags": [
          "Заказы"
        ],
        "operationId": "createOrder",
        "summary": "Создать и оплатить заказ",
        "description": "Списывает ровно `total_cost` и создаёт заказ в одной транзакции. Заголовок `Idempotency-Key` обязателен (раздел 9). Повтор с тем же ключом и тем же телом возвращает тот же заказ без списания. Не больше 5 незавершённых заказов пользователя.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Уникальный ключ заказа: 1–255 печатных ASCII-символов (рекомендуется UUID). При повторах — тот же. Например: `b3f1c0de-5a7e-4b2a-9c1d-0e8f7a6b5c4d`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[\\x20-\\x7e]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderRequest"
              },
              "examples": {
                "order": {
                  "summary": "Номера в разных записях (в реальном заказе — от 1 000 уникальных)",
                  "value": {
                    "phones": [
                      "79001234567",
                      "+7 (900) 123-45-68",
                      "89001234569",
                      "9001234570",
                      "79001234567",
                      "нет номера"
                    ],
                    "name": "Моя база"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Заказ создан и оплачен.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderCreated"
                },
                "examples": {
                  "created": {
                    "value": {
                      "order_id": "6f1c2a7e-3b5d-4c8e-9a10-2d4b6e8f0a12",
                      "created": true,
                      "state": "created",
                      "total_rows": 1055,
                      "valid_count": 1055,
                      "duplicates_count": 0,
                      "invalid_count": 0,
                      "unit_price": "0.00080000",
                      "total_cost": "0.8440",
                      "balance_after": "172.6928",
                      "currency": "USDT"
                    }
                  }
                }
              }
            }
          },
          "200": {
            "description": "Повтор с тем же `Idempotency-Key`: тот же заказ, без нового списания.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderCreated"
                },
                "examples": {
                  "replayed": {
                    "value": {
                      "order_id": "6f1c2a7e-3b5d-4c8e-9a10-2d4b6e8f0a12",
                      "created": false,
                      "state": "processing",
                      "total_rows": 1055,
                      "valid_count": 1055,
                      "duplicates_count": 0,
                      "invalid_count": 0,
                      "unit_price": "0.00080000",
                      "total_cost": "0.8440",
                      "balance_after": null,
                      "currency": "USDT"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Нет или неверный `Idempotency-Key`; тело — не JSON; ключ в URL.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_idempotency_key": {
                    "value": {
                      "error": "invalid_idempotency_key",
                      "message": "заголовок Idempotency-Key обязателен: 1..255 печатных ASCII-символов"
                    }
                  },
                  "invalid_json": {
                    "value": {
                      "error": "invalid_json",
                      "message": "тело запроса — не корректный JSON в UTF-8"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Нет ключа, ключ неверный или отозван (в том числе во время создания — `invalid_api_key`). Ничего не списано.",
            "headers": {
              "WWW-Authenticate": {
                "schema": {
                  "type": "string",
                  "const": "Bearer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "value": {
                      "error": "unauthorized",
                      "message": "нужен действующий API-ключ"
                    }
                  },
                  "invalid_api_key": {
                    "value": {
                      "error": "invalid_api_key",
                      "message": "API-ключ не найден или отозван"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Недостаточно средств. Ничего не списано.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_balance": {
                    "value": {
                      "error": "insufficient_balance",
                      "message": "недостаточно средств",
                      "total_cost": "240.0000"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "`Idempotency-Key` уже использован с другим телом. Новый заказ не создан.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "idempotency_conflict": {
                    "value": {
                      "error": "idempotency_conflict",
                      "message": "Idempotency-Key уже использован с другим запросом"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "Тело больше 8 МиБ.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "body_too_large": {
                    "value": {
                      "error": "body_too_large",
                      "message": "тело запроса больше 8388608 байт"
                    }
                  }
                }
              }
            }
          },
          "415": {
            "description": "Нужен `Content-Type: application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unsupported_media_type": {
                    "value": {
                      "error": "unsupported_media_type",
                      "message": "ожидается application/json"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Неверное тело или заказ не проходит по номерам. Ничего не списано.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_phones": {
                    "value": {
                      "error": "invalid_phones",
                      "message": "каждый номер — строка до 64 символов"
                    }
                  },
                  "too_many_rows": {
                    "value": {
                      "error": "too_many_rows",
                      "message": "не больше 1000000 строк",
                      "max_rows": 1000000
                    }
                  },
                  "invalid_name": {
                    "value": {
                      "error": "invalid_name",
                      "message": "name — строка 1..255 символов без управляющих"
                    }
                  },
                  "unknown_fields": {
                    "value": {
                      "error": "unknown_fields",
                      "message": "неизвестные поля: ['x']"
                    }
                  },
                  "empty": {
                    "value": {
                      "error": "empty",
                      "message": "нет строк с номерами"
                    }
                  },
                  "no_valid_phones": {
                    "value": {
                      "error": "no_valid_phones",
                      "message": "ни один номер не распознан"
                    }
                  },
                  "below_min_valid": {
                    "value": {
                      "error": "below_min_valid",
                      "message": "недостаточно валидных номеров",
                      "min_valid": 1000,
                      "valid_count": 999,
                      "invalid_count": 0
                    }
                  },
                  "too_many_phones": {
                    "value": {
                      "error": "too_many_phones",
                      "message": "больше номеров, чем допускает MAX241",
                      "max_valid": 300000,
                      "valid_count": 300001
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Лимит частоты или уже 5 незавершённых заказов. Ничего не списано.",
            "headers": {
              "Retry-After": {
                "description": "Через сколько секунд повторить запрос.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "value": {
                      "error": "rate_limited",
                      "message": "слишком много запросов",
                      "retry_after": 37
                    }
                  },
                  "too_many_active_orders": {
                    "value": {
                      "error": "too_many_active_orders",
                      "message": "слишком много незавершённых заказов",
                      "max_active_orders": 5
                    }
                  }
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "description": "Сервис проверки временно недоступен. Ничего не списано.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "service_unavailable": {
                    "value": {
                      "error": "service_unavailable",
                      "message": "сервис проверки недоступен"
                    }
                  }
                }
              }
            }
          },
          "504": {
            "description": "Ответ не уложился в 30 секунд. Заказ мог быть создан — повторите запрос с тем же `Idempotency-Key`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "timeout": {
                    "value": {
                      "error": "timeout",
                      "message": "время обработки запроса истекло"
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -s https://maxapi.work/v1/orders \\\n  -H \"Authorization: Bearer $MAXCHECK_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: b3f1c0de-5a7e-4b2a-9c1d-0e8f7a6b5c4d\" \\\n  -d @order.json"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\nAPI = \"https://maxapi.work\"\nH = {\"Authorization\": f\"Bearer {os.environ['MAXCHECK_API_KEY']}\"}\nimport json, uuid\nbody = json.load(open(\"order.json\", encoding=\"utf-8\"))\nidem = str(uuid.uuid4())  # сохраните; при повторе — тот же\nr = requests.post(f\"{API}/v1/orders\", json=body, headers={**H, \"Idempotency-Key\": idem}, timeout=60)\nprint(r.status_code, r.json())"
          }
        ]
      },
      "get": {
        "tags": [
          "Заказы"
        ],
        "operationId": "listOrders",
        "summary": "Список своих заказов",
        "description": "Заказы пользователя от новых к старым, постранично.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Размер страницы.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Значение `next_cursor` предыдущей страницы.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Страница заказов.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderList"
                },
                "examples": {
                  "page": {
                    "value": {
                      "orders": [
                        {
                          "order_id": "6f1c2a7e-3b5d-4c8e-9a10-2d4b6e8f0a12",
                          "name": "Моя база",
                          "state": "done",
                          "total_rows": 1055,
                          "valid_count": 1055,
                          "duplicates_count": 0,
                          "invalid_count": 0,
                          "max_count": 573,
                          "not_max_count": 482,
                          "unit_price": "0.00080000",
                          "total_cost": "0.8440",
                          "currency": "USDT",
                          "created_at": "2026-11-14T19:36:24.439015Z",
                          "completed_at": "2026-11-14T19:36:31.750232Z",
                          "refund_reason": null,
                          "error": null
                        },
                        {
                          "order_id": "0b9e8d7c-6a5f-4e3d-8c2b-1a0f9e8d7c6b",
                          "name": "Моя база",
                          "state": "refunded",
                          "total_rows": 1055,
                          "valid_count": 1055,
                          "duplicates_count": 0,
                          "invalid_count": 0,
                          "max_count": null,
                          "not_max_count": null,
                          "unit_price": "0.00080000",
                          "total_cost": "0.8440",
                          "currency": "USDT",
                          "created_at": "2026-11-14T19:36:24.439015Z",
                          "completed_at": "2026-11-14T19:36:31.750232Z",
                          "refund_reason": "service_unavailable",
                          "error": null
                        }
                      ],
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/KeyInUrl"
          },
          "422": {
            "description": "Неверный `limit` или `cursor`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_limit": {
                    "value": {
                      "error": "invalid_limit",
                      "message": "limit — от 1 до 100"
                    }
                  },
                  "invalid_cursor": {
                    "value": {
                      "error": "invalid_cursor",
                      "message": "некорректный cursor"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "504": {
            "$ref": "#/components/responses/Timeout"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -s \"https://maxapi.work/v1/orders?limit=20\" \\\n  -H \"Authorization: Bearer $MAXCHECK_API_KEY\""
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\nAPI = \"https://maxapi.work\"\nH = {\"Authorization\": f\"Bearer {os.environ['MAXCHECK_API_KEY']}\"}\ncursor = None\nwhile True:\n    p = {\"limit\": 100} | ({\"cursor\": cursor} if cursor else {})\n    page = requests.get(f\"{API}/v1/orders\", params=p, headers=H, timeout=30).json()\n    for o in page[\"orders\"]:\n        print(o[\"order_id\"], o[\"state\"])\n    cursor = page[\"next_cursor\"]\n    if not cursor:\n        break"
          }
        ]
      }
    },
    "/v1/orders/{order_id}": {
      "get": {
        "tags": [
          "Заказы"
        ],
        "operationId": "getOrder",
        "summary": "Статус заказа",
        "description": "Состояние, счётчики и готовность результата. Опрашивайте раз в 5–15 секунд до `done`, `refunded` или `delayed`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderId"
          }
        ],
        "responses": {
          "200": {
            "description": "Заказ.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderStatus"
                },
                "examples": {
                  "done": {
                    "value": {
                      "order_id": "6f1c2a7e-3b5d-4c8e-9a10-2d4b6e8f0a12",
                      "name": "Моя база",
                      "state": "done",
                      "total_rows": 1055,
                      "valid_count": 1055,
                      "duplicates_count": 0,
                      "invalid_count": 0,
                      "max_count": 573,
                      "not_max_count": 482,
                      "unit_price": "0.00080000",
                      "total_cost": "0.8440",
                      "currency": "USDT",
                      "created_at": "2026-11-14T19:36:24.439015Z",
                      "completed_at": "2026-11-14T19:36:31.750232Z",
                      "refund_reason": null,
                      "error": null,
                      "result_available": true,
                      "result_unavailable_reason": null
                    }
                  },
                  "processing": {
                    "value": {
                      "order_id": "6f1c2a7e-3b5d-4c8e-9a10-2d4b6e8f0a12",
                      "name": "Моя база",
                      "state": "processing",
                      "total_rows": 1055,
                      "valid_count": 1055,
                      "duplicates_count": 0,
                      "invalid_count": 0,
                      "max_count": null,
                      "not_max_count": null,
                      "unit_price": "0.00080000",
                      "total_cost": "0.8440",
                      "currency": "USDT",
                      "created_at": "2026-11-14T19:36:24.439015Z",
                      "completed_at": null,
                      "refund_reason": null,
                      "error": null,
                      "result_available": false,
                      "result_unavailable_reason": null
                    }
                  },
                  "refunded": {
                    "value": {
                      "order_id": "0b9e8d7c-6a5f-4e3d-8c2b-1a0f9e8d7c6b",
                      "name": "Моя база",
                      "state": "refunded",
                      "total_rows": 1055,
                      "valid_count": 1055,
                      "duplicates_count": 0,
                      "invalid_count": 0,
                      "max_count": null,
                      "not_max_count": null,
                      "unit_price": "0.00080000",
                      "total_cost": "0.8440",
                      "currency": "USDT",
                      "created_at": "2026-11-14T19:36:24.439015Z",
                      "completed_at": "2026-11-14T19:36:31.750232Z",
                      "refund_reason": "service_unavailable",
                      "error": null,
                      "result_available": false,
                      "result_unavailable_reason": null
                    }
                  },
                  "delayed": {
                    "value": {
                      "order_id": "6f1c2a7e-3b5d-4c8e-9a10-2d4b6e8f0a12",
                      "name": "Моя база",
                      "state": "delayed",
                      "total_rows": 1055,
                      "valid_count": 1055,
                      "duplicates_count": 0,
                      "invalid_count": 0,
                      "max_count": null,
                      "not_max_count": null,
                      "unit_price": "0.00080000",
                      "total_cost": "0.8440",
                      "currency": "USDT",
                      "created_at": "2026-11-14T19:36:24.439015Z",
                      "completed_at": null,
                      "refund_reason": null,
                      "error": "manual_review",
                      "result_available": false,
                      "result_unavailable_reason": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/KeyInUrl"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "504": {
            "$ref": "#/components/responses/Timeout"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -s https://maxapi.work/v1/orders/6f1c2a7e-3b5d-4c8e-9a10-2d4b6e8f0a12 \\\n  -H \"Authorization: Bearer $MAXCHECK_API_KEY\""
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\nAPI = \"https://maxapi.work\"\nH = {\"Authorization\": f\"Bearer {os.environ['MAXCHECK_API_KEY']}\"}\nimport time\norder_id = \"6f1c2a7e-3b5d-4c8e-9a10-2d4b6e8f0a12\"\nwhile True:\n    st = requests.get(f\"{API}/v1/orders/{order_id}\", headers=H, timeout=30).json()\n    if st[\"state\"] in (\"done\", \"refunded\", \"delayed\"):\n        break\n    time.sleep(10)\nprint(st[\"state\"], st[\"max_count\"], st[\"not_max_count\"])"
          }
        ]
      }
    },
    "/v1/orders/{order_id}/result": {
      "get": {
        "tags": [
          "Результаты"
        ],
        "operationId": "getOrderResult",
        "summary": "Полный результат",
        "description": "Все проверенные номера заказа одним JSON (раздел 8). Параметров нет: `filter` и `format` отклоняются с `400 unsupported_parameter`. Бесплатно и повторяемо; результат хранится 60 суток. Ответ потоковый — при обрыве соединения повторите запрос.",
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderId"
          }
        ],
        "responses": {
          "200": {
            "description": "Полный результат.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Result"
                },
                "examples": {
                  "result": {
                    "value": {
                      "order_id": "6f1c2a7e-3b5d-4c8e-9a10-2d4b6e8f0a12",
                      "total": 2,
                      "results": [
                        {
                          "phone": "79001234567",
                          "in_max": true,
                          "max_user_id": "123456789",
                          "name": "Иван",
                          "last_name": "Иванов",
                          "activity": "недавно",
                          "reg_date": "12:30 05.11.2025",
                          "photo_url": "https://i.oneme.ru/i?r=EXAMPLE"
                        },
                        {
                          "phone": "79001234568",
                          "in_max": false,
                          "max_user_id": null,
                          "name": null,
                          "last_name": null,
                          "activity": null,
                          "reg_date": null,
                          "photo_url": null
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Переданы `filter`/`format` или ключ в URL.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unsupported_parameter": {
                    "value": {
                      "error": "unsupported_parameter",
                      "message": "параметры filter не поддерживаются: результат всегда полный, в JSON"
                    }
                  },
                  "key_in_url": {
                    "value": {
                      "error": "key_in_url",
                      "message": "API-ключ передаётся только в заголовке Authorization"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Результата нет: заказ ещё выполняется или возвращён.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_ready": {
                    "value": {
                      "error": "not_ready",
                      "message": "результат ещё не готов",
                      "state": "processing"
                    }
                  },
                  "order_refunded": {
                    "value": {
                      "error": "order_refunded",
                      "message": "заказ не выполнен, средства возвращены",
                      "state": "refunded"
                    }
                  }
                }
              }
            }
          },
          "410": {
            "description": "Срок хранения результата (60 суток) истёк.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "result_expired": {
                    "value": {
                      "error": "result_expired",
                      "message": "срок хранения результата истёк"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Результат временно недоступен.",
            "headers": {
              "Retry-After": {
                "description": "Через сколько секунд повторить запрос.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "result_unavailable": {
                    "value": {
                      "error": "result_unavailable",
                      "message": "результат временно недоступен, повторите позже"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "504": {
            "description": "Подготовка ответа не уложилась в 600 секунд — повторите позже.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "timeout": {
                    "value": {
                      "error": "timeout",
                      "message": "время обработки запроса истекло"
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -s https://maxapi.work/v1/orders/6f1c2a7e-3b5d-4c8e-9a10-2d4b6e8f0a12/result \\\n  -H \"Authorization: Bearer $MAXCHECK_API_KEY\" \\\n  -o result.json"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\nAPI = \"https://maxapi.work\"\nH = {\"Authorization\": f\"Bearer {os.environ['MAXCHECK_API_KEY']}\"}\norder_id = \"6f1c2a7e-3b5d-4c8e-9a10-2d4b6e8f0a12\"\nr = requests.get(f\"{API}/v1/orders/{order_id}/result\", headers=H, timeout=(10, 660))\nr.raise_for_status()\nres = r.json()\nfound = [x for x in res[\"results\"] if x[\"in_max\"]]\nprint(res[\"total\"], len(found))"
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "mcak_…",
        "description": "API-ключ в заголовке `Authorization: Bearer <ключ>`. Формат: `mcak_` + 43 символа, например `mcak_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`."
      }
    },
    "parameters": {
      "OrderId": {
        "name": "order_id",
        "in": "path",
        "required": true,
        "description": "ID заказа (UUID) из ответа `POST /v1/orders`. Например: `6f1c2a7e-3b5d-4c8e-9a10-2d4b6e8f0a12`.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    },
    "schemas": {
      "OrderRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "phones"
        ],
        "properties": {
          "phones": {
            "type": "array",
            "maxItems": 1000000,
            "items": {
              "type": "string",
              "maxLength": 64
            },
            "description": "Номера телефонов — строки (не числа), до 64 символов. Нормализация: раздел 5."
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "pattern": "^[^\\x00-\\x1f]+$",
            "description": "Название заказа (необязательно, без управляющих символов). По умолчанию — `api_<первые 8 символов order_id>`. В `POST /v1/quote` принимается, но не используется."
          }
        }
      },
      "Quote": {
        "type": "object",
        "required": [
          "total_rows",
          "valid_count",
          "duplicates_count",
          "invalid_count",
          "min_valid",
          "max_valid",
          "unit_price",
          "total_cost",
          "balance",
          "currency",
          "balance_sufficient",
          "can_order",
          "reason"
        ],
        "properties": {
          "total_rows": {
            "type": "integer",
            "minimum": 0,
            "description": "Строк с номерами (без пустых строк и заголовка)."
          },
          "valid_count": {
            "type": "integer",
            "minimum": 0,
            "description": "Уникальных валидных номеров — столько будет оплачено."
          },
          "duplicates_count": {
            "type": "integer",
            "minimum": 0
          },
          "invalid_count": {
            "type": "integer",
            "minimum": 0
          },
          "min_valid": {
            "type": "integer",
            "description": "Минимум уникальных валидных номеров в заказе (1 000)."
          },
          "max_valid": {
            "type": "integer",
            "description": "Максимум уникальных валидных номеров в заказе (300 000)."
          },
          "unit_price": {
            "oneOf": [
              {
                "type": "string",
                "pattern": "^-?\\d+(\\.\\d+)?$",
                "description": "Сумма в USDT строкой (десятичная запись)."
              },
              {
                "type": "null"
              }
            ],
            "description": "Цена одного номера; `null`, если расчёт остановлен раньше (нет номеров, меньше минимума, сервис недоступен)."
          },
          "total_cost": {
            "oneOf": [
              {
                "type": "string",
                "pattern": "^-?\\d+(\\.\\d+)?$",
                "description": "Сумма в USDT строкой (десятичная запись)."
              },
              {
                "type": "null"
              }
            ],
            "description": "Стоимость заказа (4 знака); `null` — как у `unit_price`."
          },
          "balance": {
            "oneOf": [
              {
                "type": "string",
                "pattern": "^-?\\d+(\\.\\d+)?$",
                "description": "Сумма в USDT строкой (десятичная запись)."
              },
              {
                "type": "null"
              }
            ],
            "description": "Текущий баланс."
          },
          "currency": {
            "const": "USDT"
          },
          "balance_sufficient": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Хватает ли баланса; `null`, если стоимость не рассчитана."
          },
          "can_order": {
            "type": "boolean",
            "description": "Можно ли создать такой заказ сейчас."
          },
          "reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "empty",
              "no_valid_phones",
              "below_min_valid",
              "too_many_phones",
              "insufficient_balance",
              "service_unavailable",
              "banned",
              null
            ],
            "description": "Почему заказ невозможен; `null`, если возможен."
          }
        }
      },
      "OrderCreated": {
        "type": "object",
        "required": [
          "order_id",
          "created",
          "state",
          "total_rows",
          "valid_count",
          "duplicates_count",
          "invalid_count",
          "unit_price",
          "total_cost",
          "balance_after",
          "currency"
        ],
        "properties": {
          "order_id": {
            "type": "string",
            "format": "uuid"
          },
          "created": {
            "type": "boolean",
            "description": "`true` — новый заказ (HTTP 201); `false` — повтор с тем же `Idempotency-Key` (HTTP 200)."
          },
          "state": {
            "$ref": "#/components/schemas/OrderState"
          },
          "total_rows": {
            "type": "integer"
          },
          "valid_count": {
            "type": "integer"
          },
          "duplicates_count": {
            "type": "integer"
          },
          "invalid_count": {
            "type": "integer"
          },
          "unit_price": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Сумма в USDT строкой (десятичная запись)."
          },
          "total_cost": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Сумма в USDT строкой (десятичная запись)."
          },
          "balance_after": {
            "oneOf": [
              {
                "type": "string",
                "pattern": "^-?\\d+(\\.\\d+)?$",
                "description": "Сумма в USDT строкой (десятичная запись)."
              },
              {
                "type": "null"
              }
            ],
            "description": "Баланс сразу после списания; у повтора — `null`."
          },
          "currency": {
            "const": "USDT"
          }
        }
      },
      "OrderState": {
        "type": "string",
        "enum": [
          "created",
          "submitting",
          "processing",
          "done",
          "refunded",
          "delayed"
        ],
        "description": "`created`, `submitting`, `processing` — в работе; `done` — результат готов; `refunded` — полный возврат; `delayed` — ручной разбор, без автоматического возврата (раздел 6)."
      },
      "Order": {
        "type": "object",
        "required": [
          "order_id",
          "name",
          "state",
          "total_rows",
          "valid_count",
          "duplicates_count",
          "invalid_count",
          "max_count",
          "not_max_count",
          "unit_price",
          "total_cost",
          "currency",
          "created_at",
          "completed_at",
          "refund_reason",
          "error"
        ],
        "properties": {
          "order_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "state": {
            "$ref": "#/components/schemas/OrderState"
          },
          "total_rows": {
            "type": "integer"
          },
          "valid_count": {
            "type": "integer",
            "description": "Проверяемых (и оплаченных) номеров."
          },
          "duplicates_count": {
            "type": "integer"
          },
          "invalid_count": {
            "type": "integer"
          },
          "max_count": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Найдено в MAX; заполняется после `done`."
          },
          "not_max_count": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Не найдено в MAX; заполняется после `done`."
          },
          "unit_price": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Сумма в USDT строкой (десятичная запись)."
          },
          "total_cost": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Сумма в USDT строкой (десятичная запись)."
          },
          "currency": {
            "const": "USDT"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "ISO 8601, UTC, суффикс `Z`."
          },
          "completed_at": {
            "oneOf": [
              {
                "type": "string",
                "format": "date-time",
                "description": "ISO 8601, UTC, суффикс `Z`."
              },
              {
                "type": "null"
              }
            ],
            "description": "Время перехода в `done` или `refunded`."
          },
          "refund_reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "service_unavailable",
              "check_failed",
              null
            ],
            "description": "Только для `refunded`: `service_unavailable` — проверка не началась; `check_failed` — проверка завершилась ошибкой."
          },
          "error": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "manual_review",
              null
            ],
            "description": "`manual_review` — только для `delayed`."
          }
        }
      },
      "OrderStatus": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Order"
          },
          {
            "type": "object",
            "required": [
              "result_available",
              "result_unavailable_reason"
            ],
            "properties": {
              "result_available": {
                "type": "boolean",
                "description": "Можно ли сейчас скачать результат."
              },
              "result_unavailable_reason": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "expired",
                  "temporarily_unavailable",
                  null
                ],
                "description": "Для `done` без доступного результата: истёк срок или временно недоступен."
              }
            }
          }
        ]
      },
      "OrderList": {
        "type": "object",
        "required": [
          "orders",
          "next_cursor"
        ],
        "properties": {
          "orders": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Order"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Курсор следующей страницы; `null` — страниц больше нет."
          }
        }
      },
      "ResultRow": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "phone",
          "in_max",
          "max_user_id",
          "name",
          "last_name",
          "activity",
          "reg_date",
          "photo_url"
        ],
        "properties": {
          "phone": {
            "type": "string",
            "pattern": "^79\\d{9}$",
            "description": "Номер после нормализации."
          },
          "in_max": {
            "type": "boolean",
            "description": "Зарегистрирован ли номер в MAX."
          },
          "max_user_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^\\d+$",
            "description": "ID пользователя MAX (строка цифр)."
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Имя в профиле MAX."
          },
          "last_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Фамилия в профиле MAX."
          },
          "activity": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "недавно",
              "давно",
              null
            ],
            "description": "Активность: `недавно` или `давно`; `null` — неизвестна."
          },
          "reg_date": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^\\d{2}:\\d{2} \\d{2}\\.\\d{2}\\.\\d{4}$",
            "description": "Дата регистрации в MAX, `ЧЧ:ММ дд.мм.ГГГГ`, московское время."
          },
          "photo_url": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^https://",
            "description": "Ссылка на фото профиля; `null` — фото нет."
          }
        }
      },
      "Result": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "order_id",
          "total",
          "results"
        ],
        "properties": {
          "order_id": {
            "type": "string",
            "format": "uuid"
          },
          "total": {
            "type": "integer",
            "description": "Число проверенных номеров = `valid_count` заказа = длина `results`."
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResultRow"
            },
            "description": "Все проверенные номера (найденные и ненайденные) в порядке заказа."
          }
        }
      },
      "Balance": {
        "type": "object",
        "required": [
          "balance",
          "currency",
          "price_per_number",
          "price_per_1000"
        ],
        "properties": {
          "balance": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Сумма в USDT строкой (десятичная запись)."
          },
          "currency": {
            "const": "USDT"
          },
          "price_per_number": {
            "oneOf": [
              {
                "type": "string",
                "pattern": "^-?\\d+(\\.\\d+)?$",
                "description": "Сумма в USDT строкой (десятичная запись)."
              },
              {
                "type": "null"
              }
            ],
            "description": "Цена одного номера (индивидуальная, если назначена)."
          },
          "price_per_1000": {
            "oneOf": [
              {
                "type": "string",
                "pattern": "^-?\\d+(\\.\\d+)?$",
                "description": "Сумма в USDT строкой (десятичная запись)."
              },
              {
                "type": "null"
              }
            ],
            "description": "Цена за 1 000 номеров."
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error",
          "message"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Машиночитаемый код (раздел 11)."
          },
          "message": {
            "type": "string",
            "description": "Пояснение для человека; может меняться."
          },
          "state": {
            "$ref": "#/components/schemas/OrderState"
          },
          "retry_after": {
            "type": "integer",
            "description": "Через сколько секунд повторить (для `rate_limited`)."
          },
          "min_valid": {
            "type": "integer"
          },
          "max_valid": {
            "type": "integer"
          },
          "valid_count": {
            "type": "integer"
          },
          "invalid_count": {
            "type": "integer"
          },
          "max_rows": {
            "type": "integer"
          },
          "max_active_orders": {
            "type": "integer"
          },
          "total_cost": {
            "type": "string",
            "pattern": "^-?\\d+(\\.\\d+)?$",
            "description": "Сумма в USDT строкой (десятичная запись)."
          }
        },
        "additionalProperties": true
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Нет ключа, ключ неверный или отозван.",
        "headers": {
          "WWW-Authenticate": {
            "schema": {
              "type": "string",
              "const": "Bearer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "unauthorized": {
                "value": {
                  "error": "unauthorized",
                  "message": "нужен действующий API-ключ"
                }
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "Пользователь заблокирован.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "banned": {
                "value": {
                  "error": "banned",
                  "message": "пользователь заблокирован"
                }
              }
            }
          }
        }
      },
      "KeyInUrl": {
        "description": "Ключ передан в URL.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "key_in_url": {
                "value": {
                  "error": "key_in_url",
                  "message": "API-ключ передаётся только в заголовке Authorization"
                }
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "Превышен лимит частоты (или лимит незавершённых заказов для `POST /v1/orders`).",
        "headers": {
          "Retry-After": {
            "description": "Через сколько секунд повторить запрос.",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "rate_limited": {
                "value": {
                  "error": "rate_limited",
                  "message": "слишком много запросов",
                  "retry_after": 37
                }
              }
            }
          }
        }
      },
      "Timeout": {
        "description": "Запрос не уложился во время обработки.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "timeout": {
                "value": {
                  "error": "timeout",
                  "message": "время обработки запроса истекло"
                }
              }
            }
          }
        }
      },
      "InternalError": {
        "description": "Внутренняя ошибка (без подробностей).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "internal_error": {
                "value": {
                  "error": "internal_error",
                  "message": "внутренняя ошибка"
                }
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "Заказ не найден или принадлежит другому пользователю.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "not_found": {
                "value": {
                  "error": "not_found",
                  "message": "заказ не найден"
                }
              }
            }
          }
        }
      }
    }
  }
}
