> ## Documentation Index
> Fetch the complete documentation index at: https://docs.exode.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Запрос на генерацию

> Создание запроса на выгрузку данных в формате XLSX, CSV или JSON

## Заголовки запроса

<ParamField header="Authorization" type="string" required>
  API токен сервисного пользователя в формате Bearer. Получите токен в панели администратора школы. Формат: `Bearer YOUR_TOKEN`.
</ParamField>

<ParamField header="Seller-Id" type="string" required>
  Уникальный идентификатор продавца в системе. Используется для разграничения доступа между разными продавцами.
</ParamField>

<ParamField header="School-Id" type="string" required>
  Уникальный идентификатор школы в системе. Определяет контекст выполнения операции.
</ParamField>

## Как это работает

Генерация отчета выполняется через асинхронный workflow. Процесс состоит из двух шагов:

<Steps>
  <Step title="Создание задачи на генерацию">
    Отправьте `POST` запрос на `/saas/v2/query-export/generate` с указанием типа отчета, переменных фильтрации и
    формата.
    В ответ вы получите объект с полем `payload`, содержащим `uuid` — идентификатор для отслеживания результата.
  </Step>

  <Step title="Получение результата">
    Отправляйте `GET` запрос
    на <br />[`/saas/v2/workflow-execution/:executionUuid/result`](/ru/exode-api/school/query-export/result), <br />подставив
    `uuid` из первого шага.
    Повторяйте запрос до тех пор, пока `status` не станет `Completed` (или `Failed`).
  </Step>
</Steps>

***

## Создание запроса на выгрузку

```
POST /saas/v2/query-export/generate
```

<Info>
  Rate limit: **100 запросов в час**.
</Info>

### Параметры запроса

<ParamField body="type" type="string" required>
  Тип отчета. Определяет, какие данные будут выгружены. Доступные значения:

  * `QUERY_EXPORT_TYPE_GROUP_MEMBER_FIND_MANY` — [участники группы](/ru/exode-api/school/query-export/group-member-find-many)
  * `QUERY_EXPORT_TYPE_COURSE_LESSON_PRACTICE_ATTEMPT_FIND_MANY` — [попытки практических заданий](/ru/exode-api/school/query-export/practice-attempt-find-many)
</ParamField>

<ParamField body="variables" type="object" required>
  Переменные для запроса: фильтры и сортировка. Структура зависит от выбранного `type`.
  Подробнее — на странице конкретного [типа отчета](/ru/exode-api/school/query-export/group-member-find-many).
</ParamField>

<ParamField body="format" type="string">
  Формат выходного файла. По умолчанию — `Xlsx`.

  * `Xlsx` — Excel (.xlsx)
  * `Csv` — CSV (.csv)
  * `Json` — JSON (.json)
</ParamField>

### Поля ответа

<ResponseField name="success" type="boolean">
  Результат выполнения запроса.
</ResponseField>

<ResponseField name="code" type="number">
  HTTP-код ответа (например, `201`).
</ResponseField>

<ResponseField name="payload" type="object">
  Объект задачи генерации.

  <Expandable title="Свойства payload">
    <ResponseField name="uuid" type="string">
      UUID задачи — используется для [получения результата](/ru/exode-api/school/query-export/result).
    </ResponseField>

    <ResponseField name="flow" type="string">
      Тип процесса. Для выгрузок — `QueryExport`.
    </ResponseField>

    <ResponseField name="status" type="string">
      Статус задачи: `Waiting`, `Processing`, `Failed`, `Canceled`, `Completed`. При создании — `Processing`.
    </ResponseField>

    <ResponseField name="isCompleted" type="boolean">
      Флаг завершения задачи. При создании — `false`.
    </ResponseField>

    <ResponseField name="userId" type="number | null">
      ID инициатора задачи.
    </ResponseField>

    <ResponseField name="createdAt" type="string">
      Дата создания задачи (ISO 8601).
    </ResponseField>

    <ResponseField name="updatedAt" type="string | null">
      Дата последнего обновления задачи (ISO 8601).
    </ResponseField>
  </Expandable>
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl --location 'https://api.exode.biz/saas/v2/query-export/generate' \
    --header 'Seller-Id: {{ sellerId }}' \
    --header 'School-Id: {{ schoolId }}' \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Bearer YOUR_TOKEN' \
    --data '{
      "type": "QUERY_EXPORT_TYPE_GROUP_MEMBER_FIND_MANY",
      "variables": {
        "filter": { "groupIds": [1, 2, 3] }
      }
    }'
  ```

  ```javascript Node.js theme={null}
  const axios = require('axios');

  const generateReport = async () => {
    try {
      const response = await axios.post('https://api.exode.biz/saas/v2/query-export/generate', {
        type: 'QUERY_EXPORT_TYPE_GROUP_MEMBER_FIND_MANY',
        variables: {
          filter: { groupIds: [1, 2, 3] }
        }
      }, {
        headers: {
          'Seller-Id': '{{ sellerId }}',
          'School-Id': '{{ schoolId }}',
          'Content-Type': 'application/json',
          'Authorization': 'Bearer YOUR_TOKEN'
        }
      });

      const { uuid } = response.data.payload;
      console.log('Execution UUID:', uuid);
    } catch (error) {
      console.error('Error:', error.response?.data || error.message);
    }
  };

  generateReport();
  ```

  ```php PHP theme={null}
  <?php

  $url = 'https://api.exode.biz/saas/v2/query-export/generate';
  $data = [
    'type' => 'QUERY_EXPORT_TYPE_GROUP_MEMBER_FIND_MANY',
    'variables' => [
      'filter' => ['groupIds' => [1, 2, 3]]
    ]
  ];

  $headers = [
    'Seller-Id: {{ sellerId }}',
    'School-Id: {{ schoolId }}',
    'Content-Type: application/json',
    'Authorization: Bearer YOUR_TOKEN'
  ];

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

  $response = curl_exec($ch);
  $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  curl_close($ch);

  if ($httpCode === 200 || $httpCode === 201) {
    $result = json_decode($response, true);
    echo "Execution UUID: " . $result['payload']['uuid'] . "\n";
  } else {
    echo "Error: HTTP $httpCode\n";
    echo $response;
  }
  ?>
  ```

  ```python Python theme={null}
  import requests

  url = 'https://api.exode.biz/saas/v2/query-export/generate'

  data = {
    'type': 'QUERY_EXPORT_TYPE_GROUP_MEMBER_FIND_MANY',
    'variables': {
      'filter': {'groupIds': [1, 2, 3]}
    }
  }

  headers = {
    'Seller-Id': '{{ sellerId }}',
    'School-Id': '{{ schoolId }}',
    'Content-Type': 'application/json',
    'Authorization': 'Bearer YOUR_TOKEN'
  }

  try:
    response = requests.post(url, json=data, headers=headers)
    response.raise_for_status()

    result = response.json()
    print(f"Execution UUID: {result['payload']['uuid']}")

  except requests.exceptions.RequestException as e:
    print(f'Error: {e}')
  ```

  ```bsl 1С theme={null}
  ИдентификаторыГрупп = Новый Массив;
  ИдентификаторыГрупп.Добавить(1);
  ИдентификаторыГрупп.Добавить(2);
  ИдентификаторыГрупп.Добавить(3);

  Фильтр = Новый Структура;
  Фильтр.Вставить("groupIds", ИдентификаторыГрупп);

  Переменные = Новый Структура;
  Переменные.Вставить("filter", Фильтр);

  Данные = Новый Структура;
  Данные.Вставить("type", "QUERY_EXPORT_TYPE_GROUP_MEMBER_FIND_MANY");
  Данные.Вставить("variables", Переменные);

  // Serialize body to JSON
  ЗаписьJSON = Новый ЗаписьJSON;
  ЗаписьJSON.УстановитьСтроку();
  ЗаписатьJSON(ЗаписьJSON, Данные);
  ТелоЗапроса = ЗаписьJSON.Закрыть();

  Соединение = Новый HTTPСоединение("api.exode.biz", 443, , , , 30, Новый OpenSSLSecureConnection);

  Запрос = Новый HTTPЗапрос("/saas/v2/query-export/generate");
  Запрос.Заголовки.Вставить("Seller-Id", "{{ sellerId }}");
  Запрос.Заголовки.Вставить("School-Id", "{{ schoolId }}");
  Запрос.Заголовки.Вставить("Content-Type", "application/json");
  Запрос.Заголовки.Вставить("Authorization", "Bearer YOUR_TOKEN");
  Запрос.УстановитьТелоИзСтроки(ТелоЗапроса);

  Ответ = Соединение.ВызватьHTTPМетод("POST", Запрос);

  Если Ответ.КодСостояния = 200 Тогда
      ЧтениеJSON = Новый ЧтениеJSON;
      ЧтениеJSON.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
      Результат = ПрочитатьJSON(ЧтениеJSON);
      Сообщить("Экспорт запущен");
  Иначе
      Сообщить("Ошибка: HTTP " + Ответ.КодСостояния);
      Сообщить(Ответ.ПолучитьТелоКакСтроку());
  КонецЕсли;
  ```
</RequestExample>

<ResponseExample>
  ```json Success theme={null}
  {
    "success": true,
    "code": 201,
    "payload": {
      "uuid": "ac4140c9-12d3-4c1f-a7aa-d12f16c7bbdd",
      "flow": "QueryExport",
      "status": "Processing",
      "isCompleted": false,
      "userId": 5562,
      "createdAt": "2025-01-18T12:44:55.812Z"
    }
  }
  ```
</ResponseExample>

***

## Требования к правам доступа

<Check>
  Для генерации отчетов требуется **авторизация** и **доступ к SaaS API** школы.
</Check>

<Warning>
  Сервисный пользователь должен быть аутентифицирован по токену и иметь соответствующие права доступа к указанной школе.
</Warning>
