# API для работы с отчётами

Источник: https://docs.dataforce.io/articles/api-working-with-reports

API отдаёт те же данные, что вы видите на экранах Dataforce ADS: SOI Динамика, SOI Конкуренты, SOI Товары, Товары и цены, SOI Статистика, Тренды и Объявления. Данные можно забирать в свои отчёты, BI-системы и таблицы без ручных выгрузок.

Раздел состоит из трёх статей:

- **API для работы с отчётами** (эта статья): как устроен запрос, параметры, фильтры, сортировка, сравнение периодов, форматы и ошибки.
- «**[Справочники API](https://docs.dataforce.io/articles/api-reference-guides)**»: как получить допустимые значения фильтров (проекты, регионы, домены, категории и т. д.).
- «**[Запросы для экранов](https://docs.dataforce.io/articles/api-requests-for-screens)**»: готовые запросы, которые воспроизводят каждый экран кабинета.

---

## Получение доступа

Для работы с API нужен токен. Он создаётся самостоятельно в интерфейсе Dataforce:

1. Нажмите на аватар в правом верхнем углу и выберите **Подключить MCP и API**.
2. В окне «Ключи доступа к API и MCP» нажмите **`+ Создать токен`**.
3. Укажите название токена (например, «Выгрузка в BI») и нажмите **`Создать`**.
4. Скопируйте токен, подтвердите чекбоксом, что сохранили его, и нажмите **`Готово`**.

**Внимание:** токен показывается только один раз. Если потеряли его, создайте новый и удалите старый.

Один токен работает и в API, и в MCP, в продуктах ADS и AI. Если вы уже подключали Dataforce по MCP, используйте тот же токен. Подробнее — в статье «**[Подключение Dataforce через MCP](https://docs.dataforce.io/articles/dataforce-mcp)**».

Токен привязан к пользователю и наследует все его права: API вернёт данные только тех пространств и проектов, которые этот пользователь видит в кабинете. Подробнее о правах см. в статье «**[Права доступа](https://docs.dataforce.io/articles/access)**».

> **Важно:** Храните токен как пароль: не публикуйте его в репозиториях, не вставляйте в ссылки и не показывайте на скриншотах.

## Авторизация

Во всех запросах передавайте токен в заголовке:

```
Authorization: Bearer ВАШ_ТОКЕН
```

Пример на `curl`:

```
curl -H "Authorization: Bearer ВАШ_ТОКЕН" \
  "https://direct.dataforce.io/public-api/reporting/projects/123/dictionaries/projects"
```

---

## Endpoint

```
GET https://direct.dataforce.io/public-api/reporting/spaces/{space_id}/reports/{report}
```

- `space_id` — идентификатор пространства. Его видно в адресной строке кабинета: `direct.dataforce.io/spaces/{space_id}/...`
- `report` — имя отчёта (таблица ниже).

### Отчёты

| Отчёт | Что внутри | Экраны |
| --- | --- | --- |
| `context.ads` | Конкуренты в блоке «Контекст» (поисковая реклама Директа) | SOI Конкуренты, SOI Динамика |
| `context.dm` | Конкуренты в блоке «Динамические места» | SOI Динамика |
| `context.all` | Оба блока вместе | SOI Динамика, блок «Мои площадки» на SOI Конкуренты |
| `products` | Товарная галерея: доли, позиции, цены | SOI Товары, Товары и цены |
| `statistics` | Наличие и объём рекламы в выдаче | SOI Статистика |
| `trends` | Спрос по категориям проекта | Тренды |
| `soi_competitors.all_data` | Тексты объявлений: заголовки, тексты, посадочные, UTM-метки | Объявления |

> **Важно:** Не путайте `soi_competitors.all_data` с экраном SOI Конкуренты. Этот отчёт отдаёт **тексты объявлений** (экран «Объявления»), а данные экрана SOI Конкуренты лежат в `context.ads`.

---

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

Все параметры передаются в строке запроса. Имена пишутся **через подчёркивание** (`order_by`, `with_diff`, `with_totals`, `pivot_dimensions`).

> **Важно:** Параметры в стиле `orderBy` или `withDiff` API **молча игнорирует**: ошибки не будет, но и сортировки или сравнения тоже.

| Параметр | Тип | Обязательный | Описание |
| --- | --- | --- | --- |
| `periods` | string | да\* | Дата `YYYY-MM-DD`, диапазон `YYYY-MM-DD:YYYY-MM-DD` или несколько периодов через запятую (см. «Сравнение периодов») |
| `dimensions` | string | да\*\* | Измерения (группировка) через запятую |
| `metrics` | string | да\*\* | Метрики через запятую |
| `filters` | string | нет | Фильтры (см. раздел «Фильтры») |
| `order_by` | string | рекомендуется | Сортировка (см. раздел «Сортировка»). Поле сортировки должно быть в `dimensions` или `metrics` |
| `limit` | integer | нет | Количество строк, от 1 до 1 000 000 |
| `offset` | integer | нет | Смещение для постраничной выгрузки |
| `with_totals` | boolean | нет | `1` или `true` — добавить в ответ итоговую строку `totals` |
| `with_diff` | boolean | нет | `1` или `true` — добавить разницу с предыдущим отрезком времени (см. «Динамика внутри периода») |
| `pivot_dimensions` | string | нет | Измерения, которые нужно развернуть в колонки (см. «Сводная таблица») |
| `format` | string | нет | `JSON` (по умолчанию), `XLSX`, `CSVWithNames` или `TabSeparatedWithNames` (см. «Формат ответа») |

\* Если `periods` не передан, данные берутся **за сегодняшний день**. Всегда указывайте период явно.
\*\* Нужно передать хотя бы одно из двух: `dimensions` или `metrics`. Вместе — не больше 30 полей.

---

## Фильтры

Фильтры передаются одной строкой в параметре `filters`:

- `;` — условие **И**;
- `,` — условие **ИЛИ**.

```
project_id=123;serp_region=213;serp_device=desktop
```

Если вызываете API из кода, кодируйте значение `filters` (URL-encode): символы `<`, `>`, `|`, `;` и кириллица должны быть закодированы.

Почти в каждом запросе нужен фильтр `project_id`. Без него отчёт посчитает данные по всем проектам пространства сразу.

### Операторы

| Оператор | Пример | Описание |
| --- | --- | --- |
| `=` | `serp_region=213` | Равно |
| `<>` | `path_1_id<>0` | Не равно |
| `<`, `<=`, `>`, `>=` | `position<=4` | Сравнение |
| `<in>` | `domain<in>example.ru\\|competitor.ru` | Одно из значений; значения разделяются `\\|` |
| `<!in>` | `domain<!in>example.ru` | Ни одно из значений |
| `<like>` | `query<like>%отель%` | Шаблон, `%` — любые символы |
| `<has>` | `serp_platform<has>desktop` | Значение есть в массиве (только для полей-массивов) |
| `<null>`, `<!null>` | `utm_campaign<!null>` | Пусто / не пусто; значение после оператора не пишется |

Значения фильтров берите из справочников. В фильтр подставляется `value` элемента справочника, а не его название. Подробнее — в статье «**[Справочники API](https://docs.dataforce.io/articles/api-reference-guides)**».

> Шаблоны, начинающиеся с `%` (`<like>%текст%`), заметно замедляют запрос. Если можно перечислить значения через `<in>`, используйте `<in>`.

### Частые фильтры

| Фильтр | Пример | Описание |
| --- | --- | --- |
| `project_id` | `project_id=123` | Проект |
| `serp_region` | `serp_region=213` | Регион выдачи |
| `serp_device` | `serp_device=desktop` | Устройство: `desktop` или `mobile` |
| `serp_platform` | `serp_platform<has>desktop` | Платформа (в отчётах `products` и `soi_competitors.all_data`) |
| `domain` | `domain<in>example.ru` | Домен |
| `is_premium_position` | `is_premium_position=1` | `1` — премиум-показы, `0` — прочие |
| `path_1_id` | `path_1_id<in>1001\\|1002` | Категория первого уровня |

---

## Сортировка

| Значение `order_by` | Порядок |
| --- | --- |
| `+prc_ws` | По убыванию |
| `prc_ws` | По убыванию |
| `-prc_ws` | По возрастанию |

> **Важно:** Обратите внимание: `+` означает **убывание**, `-` — **возрастание**. Это противоположно привычной записи во многих других API.

Можно сортировать по нескольким полям через запятую: `order_by=-week,+prc_ws` (сначала недели по возрастанию, внутри недели — по убыванию доли).

Сортировать можно только по полям, которые есть в `dimensions` или `metrics` этого запроса. Иначе API вернёт ошибку `400` с текстом `The field … does not participate in the selections`.

**Всегда передавайте `order_by`.** Без него порядок строк не гарантирован, и постраничная выгрузка через `offset` может пропускать или дублировать строки.

---

## Постраничная выгрузка

Используйте `limit` и `offset` вместе с `order_by`:

```
&order_by=+ws&limit=1000&offset=0
&order_by=+ws&limit=1000&offset=1000
...
```

Выгрузка закончена, когда в `data` пришло меньше строк, чем указано в `limit`.

> Не используйте `total_rows` как признак конца выгрузки: в запросах без `dimensions` и при сортировке по измерению (например, `order_by=-week`) поле приходит равным `0`.

---

## Итоги

`with_totals=1` добавляет в ответ массив `totals` с итогами по метрикам в том же порядке, что и `metrics`. Итоги по целочисленным метрикам (например, `ws`) приходят строками: `"1654091232"`; по долям и процентам — числами.

---

## Динамика внутри периода

`with_diff=1` добавляет к каждой метрике поле `<метрика>_diff` — разницу с предыдущим отрезком времени. Для этого в `dimensions` должно быть измерение времени: `date`, `week`, `month` или `hour`.

```
&periods=2026-09-01:2026-09-30
&dimensions=week
&metrics=prc_ws
&with_diff=1
```

В ответе появятся метрики `prc_ws` и `prc_ws_diff`. Для первого отрезка периода сравнивать не с чем, поэтому его `_diff` не информативен.

Номера недель (`week`) имеют вид `202638` (год и номер недели). Крайние недели периода могут быть неполными — точные границы приходят в `date_from` / `date_to` (в отчёте `trends` — в `start_of_week_from` / `end_of_week_to`).

---

## Сравнение периодов

Чтобы сравнить два или больше периодов, перечислите их через запятую:

```
&periods=2026-09-01:2026-09-30,2026-08-01:2026-08-31
&dimensions=path_1,path_1_id
&metrics=prc_ws
```

Для каждой метрики в ответе появятся поля:

| Поле | Значение |
| --- | --- |
| `prc_ws_period_0` | Значение за первый период в списке |
| `prc_ws_period_1` | Значение за второй период |
| `prc_ws_diff_1` | Разница: `period_0` − `period_1` |
| `prc_ws_gain_1` | Изменение в % относительно `period_0` |
| `prc_ws_gain_reverse_1` | Изменение в % относительно `period_1` |

**Совет:** ставьте текущий период первым, а прошлый — вторым. Тогда `diff_1` покажет прирост, а `gain_reverse_1` — привычное изменение в процентах относительно прошлого периода.

Поля с суффиксами можно использовать в `order_by` и `filters`, например `order_by=+prc_ws_diff_1` или `filters=...;prc_ws_diff_1<0`.

> **Важно:** Для сравнения периодов нужно хотя бы одно измерение в `dimensions`: запрос только с метриками не выполнится.

---

## Сводная таблица

`pivot_dimensions` разворачивает выбранные измерения в колонки. Каждое поле из `pivot_dimensions` должно быть и в `dimensions`, и хотя бы одно измерение должно остаться строкой.

```
&dimensions=path_1,week
&pivot_dimensions=week
&metrics=prc_ws
```

В ответе появится массив `pivot_data` с описанием колонок (недель), а в `data[].metrics` — значения в том же порядке.

---

## Формат ответа

| Формат | Описание |
| --- | --- |
| `JSON` | По умолчанию. Структура описана ниже |
| `XLSX` | Файл Excel |
| `CSVWithNames` | CSV со строкой заголовков |
| `TabSeparatedWithNames` | TSV (разделитель — табуляция) со строкой заголовков. Удобен для Excel и Google Таблиц |

Значение `format` пишется точно как в таблице, с учётом регистра. Варианты `CSV`, `TSV`, `csv`, `json` не принимаются.

В `CSVWithNames` и `TabSeparatedWithNames`:

- в заголовках — названия полей на русском (`Неделя`, `Путь 1`), а не их идентификаторы;
- дробные числа записаны с десятичной запятой: `"45,53"`.

```
"Путь 1",Неделя,"Доля ""WS"""
посуточно,202635,"6,54"
```

### Структура JSON

```json
{
  "request": { "attributes": { "space": 42, "report": "context.ads" }, "query": { ... } },
  "meta": {
    "dimensions": { "week": { "meta": { "name": "Неделя", "value_type": "string" } } },
    "metrics": { "prc_ws": { "meta": { "name": "%WS Общий", "value_type": "percent" } } }
  },
  "data": [
    {
      "dimensions": [ { "value": 202638, "attributes": { "display_name": "202638" } } ],
      "metrics": [ 37.8 ]
    }
  ],
  "total_rows": 5,
  "totals": []
}
```

- `request.query` — основные параметры запроса (`periods`, `dimensions`, `metrics`, `filters`, `order_by`, `limit`, `offset`, `format`) в том виде, в каком их принял API. Удобно для проверки опечаток.
- `meta` — названия и типы полей.
- `data` — строки. Значения в `dimensions` и `metrics` идут в том же порядке, что в запросе.
- `display_name` — название для показа. Например, свой домен в группировке «Вместе» приходит как `Мой проект`.

Другие поля ответа служебные и могут меняться: не опирайтесь на них в своих интеграциях.

---

## Ошибки

| Код | Когда возникает |
| --- | --- |
| `400` | Не переданы ни `dimensions`, ни `metrics`; поле из `order_by` не участвует в запросе; неверное значение `format`; `limit` справочника вне диапазона. Ответ — JSON с полями `message` и `details` |
| `401` | Токен не передан, неверный или удалён (`Full authentication is required to access this resource.`) |
| `403` | Неверное имя отчёта в адресе запроса (`Access Denied`). Проверьте его по таблице «Отчёты» |
| `404` | Неизвестный справочник или проект |
| `500` | Ошибка в составе запроса: неизвестное поле в `metrics` или `dimensions`, ошибка в синтаксисе `filters`, сравнение периодов без измерений. Ответ в этом случае может прийти не в формате JSON |

> **Важно:** Если у вас нет доступа к пространству или в фильтре указан чужой `project_id`, API вернёт `200` с пустым `data`, а не ошибку. Если пришёл пустой ответ, сначала проверьте `space_id` и `project_id`.

---

## Что дальше?

- Подберите значения фильтров в статье «[Справочники API](https://docs.dataforce.io/articles/api-reference-guides)».
- Возьмите готовый запрос под нужный экран в статье «[Запросы для экранов](https://docs.dataforce.io/articles/api-requests-for-screens)».
- Если работаете через AI-агента, удобнее подключиться по MCP: «[Подключение Dataforce через MCP](https://docs.dataforce.io/articles/dataforce-mcp)».
