{
  "info": {
    "name": "O·LESA — публичный API",
    "description": "Модели, агенты, расписания и вебхуки. Документация: https://o-lesa.ru/ru/docs/api/api-postman. Укажите base_url и api_key. Платные и изменяющие запросы отключены, пока allow_writes=false; DELETE дополнительно требует allow_delete=true. Запускайте отдельные запросы осознанно, не всю коллекцию целиком. Идемпотентности POST нет. Grok, tools и мультимодальность не поддерживаются. Ключи не включены в файл; не публикуйте экспорт с заполненными секретами.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{api_key}}",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://api.o-lesa.ru/v1",
      "type": "string",
      "description": "API-хост экземпляра без завершающего слеша. Для .com: https://api.o-lesa.com/v1"
    },
    {
      "key": "api_key",
      "value": "",
      "type": "string",
      "description": "Ключ из Настройки → API. Задайте локально, храните как секрет; не публикуйте значение."
    },
    {
      "key": "allow_writes",
      "value": "false",
      "type": "string",
      "description": "true разрешает POST/PATCH, включая платные запросы и создание активных расписаний."
    },
    {
      "key": "allow_delete",
      "value": "false",
      "type": "string",
      "description": "true дополнительно разрешает DELETE. Не включайте для массового запуска."
    },
    {
      "key": "model",
      "value": "gpt-5.5",
      "type": "string",
      "description": "Выберите актуальный ID из GET /models."
    },
    {
      "key": "run_id",
      "value": "",
      "type": "string",
      "description": "ID сохраняется после создания запуска; можно указать свой."
    },
    {
      "key": "schedule_id",
      "value": "",
      "type": "string",
      "description": "ID сохраняется после создания расписания."
    },
    {
      "key": "draft_id",
      "value": "",
      "type": "string",
      "description": "ID проверенного процесса из кабинета или списка drafts."
    },
    {
      "key": "webhook_id",
      "value": "",
      "type": "string",
      "description": "ID сохраняется после подключения получателя."
    },
    {
      "key": "webhook_url",
      "value": "https://your-service.example/hooks/olesa",
      "type": "string",
      "description": "Замените публичным HTTPS-адресом собственного сервера."
    }
  ],
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          "if (!pm.variables.get('api_key')) {",
          "  console.warn('Укажите локальную переменную api_key.');",
          "  pm.execution.skipRequest();",
          "}",
          "if (!['GET', 'HEAD', 'OPTIONS'].includes(pm.request.method) && pm.variables.get('allow_writes') !== 'true') {",
          "  console.warn('Запрос пропущен: allow_writes=false. Он может менять данные или расходовать баланс.');",
          "  pm.execution.skipRequest();",
          "}",
          "if (pm.request.method === 'DELETE' && pm.variables.get('allow_delete') !== 'true') {",
          "  console.warn('Удаление пропущено: allow_delete=false.');",
          "  pm.execution.skipRequest();",
          "}"
        ]
      }
    }
  ],
  "item": [
    {
      "name": "01 · Модели",
      "item": [
        {
          "name": "Каталог моделей",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/models",
            "description": "Право models. Используйте ID из data."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });"
                ]
              }
            }
          ]
        },
        {
          "name": "Текстовый ответ · платно",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{base_url}}/chat/completions",
            "description": "Право models. Расход с общего баланса; ограничение ответа — 256 токенов.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"model\": \"{{model}}\",\n  \"messages\": [\n    {\n      \"role\": \"user\",\n      \"content\": \"Предложи три коротких заголовка для сайта\"\n    }\n  ],\n  \"max_tokens\": 256\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });"
                ]
              }
            }
          ]
        },
        {
          "name": "Потоковый ответ SSE · платно",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{base_url}}/chat/completions",
            "description": "Право models. SSE с chunk-объектами, usage и [DONE]. Не JSON-документ целиком.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"model\": \"{{model}}\",\n  \"messages\": [\n    {\n      \"role\": \"user\",\n      \"content\": \"Составь краткий план запуска продукта\"\n    }\n  ],\n  \"max_tokens\": 256,\n  \"stream\": true,\n  \"stream_options\": {\n    \"include_usage\": true\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "02 · Агенты",
      "item": [
        {
          "name": "Каталог агентов",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/agents/",
            "description": "Право agents. Входные поля зависят от kind."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });"
                ]
              }
            }
          ]
        },
        {
          "name": "Запустить SEO-аудит · платно",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{base_url}}/agents/runs",
            "description": "Создаёт фоновую задачу и сохраняет run_id. Измените URL на страницу, которую хотите проверить. Повтор POST создаёт новый запуск.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"kind\": \"seo_audit\",\n  \"input\": {\n    \"url\": \"https://example.com\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  const data = pm.response.json();",
                  "  if (data.id) pm.collectionVariables.set('run_id', data.id);",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "История запусков",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/agents/runs?limit=20&offset=0",
            "description": "Только запуски вашего аккаунта. Дополнительно доступны kind и status."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });"
                ]
              }
            }
          ]
        },
        {
          "name": "Статус и результат",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/agents/runs/{{run_id}}",
            "description": "После завершения: output, cost. Проверяйте не чаще раза в 5–10 секунд."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });"
                ]
              }
            }
          ]
        },
        {
          "name": "Удалить запись запуска · удаление",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": "{{base_url}}/agents/runs/{{run_id}}",
            "description": "Удаляет запись и связанные данные. Это не гарантированная отмена вычислений. Не выполняйте для незавершённого запуска."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "03 · Расписания",
      "item": [
        {
          "name": "Список расписаний",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/agents/schedules",
            "description": "Право agents. Только ваш аккаунт."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });"
                ]
              }
            }
          ]
        },
        {
          "name": "Создать одноразовое расписание · будущий расход",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{base_url}}/agents/schedules",
            "description": "Создаёт АКТИВНОЕ расписание: ближайший понедельник 09:00 UTC, один запуск (one_shot). Задача при выполнении расходует баланс. Отключите или удалите тестовое расписание.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"kind\": \"seo_audit\",\n  \"input\": {\n    \"url\": \"https://example.com\"\n  },\n  \"cron\": \"0 9 * * 1\",\n  \"delivery_channels\": [],\n  \"one_shot\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  const data = pm.response.json();",
                  "  if (data.id) pm.collectionVariables.set('schedule_id', data.id);",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Отключить расписание",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{base_url}}/agents/schedules/{{schedule_id}}",
            "description": "Останавливает будущие срабатывания, но не уже запущенные задачи.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"enabled\": false\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });"
                ]
              }
            }
          ]
        },
        {
          "name": "Удалить расписание · удаление",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": "{{base_url}}/agents/schedules/{{schedule_id}}",
            "description": "Удаляет расписание и связанные данные. Для временной остановки используйте PATCH."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "04 · Собственные процессы",
      "item": [
        {
          "name": "Список процессов",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/agents/drafts",
            "description": "Выберите ID процесса и задайте draft_id. Создание и проверка графа — в конструкторе."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });"
                ]
              }
            }
          ]
        },
        {
          "name": "Получить процесс",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/agents/drafts/{{draft_id}}",
            "description": "Возвращает название и сохранённый граф процесса."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });"
                ]
              }
            }
          ]
        },
        {
          "name": "Запустить процесс · платно",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{base_url}}/agents/drafts/{{draft_id}}/run",
            "description": "Использует сохранённый граф: он может обращаться к вашим подключённым сервисам и выполнять действия. Перед запуском проверьте его в кабинете. Сохраняет новый run_id.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"input\": \"Подготовь краткий отчёт по настроенным источникам\",\n  \"attachment_ids\": []\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  const data = pm.response.json();",
                  "  if (data.id) pm.collectionVariables.set('run_id', data.id);",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Память процесса",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/agents/drafts/{{draft_id}}/memory",
            "description": "Память и история могут содержать конфиденциальные данные; не публикуйте ответы."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "05 · Вебхуки",
      "item": [
        {
          "name": "Получатели вебхуков",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/webhooks",
            "description": "Право agents. Секреты в списке не возвращаются."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });"
                ]
              }
            }
          ]
        },
        {
          "name": "Подключить получателя",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{base_url}}/webhooks",
            "description": "Все новые завершения агентов аккаунта будут отправляться на этот URL. Разрешён публичный HTTPS:443. Сохраните secret из ответа вручную: он показывается один раз, коллекция не копирует его в переменные или логи.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"url\": \"{{webhook_url}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  const data = pm.response.json();",
                  "  if (data.id) pm.collectionVariables.set('webhook_id', data.id);",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Журнал доставок",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/webhooks/{{webhook_id}}/deliveries?limit=50&offset=0",
            "description": "Показывает статусы, число попыток и HTTP-код; проверьте подпись на стороне получателя по инструкции wiki."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });"
                ]
              }
            }
          ]
        },
        {
          "name": "Отключить получателя",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": "{{base_url}}/webhooks/{{webhook_id}}",
            "description": "Новые отправки останавливаются. Уже выполняющаяся доставка может завершиться. Отзыв API-ключа сам по себе не отключает вебхуки."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('HTTP 2xx', function () { pm.expect(pm.response.code).to.be.within(200, 299); });"
                ]
              }
            }
          ]
        }
      ]
    }
  ]
}
