[ OData4 ]

Имена объектов в примерах взяты из типовых конфигураций — в вашей базе они будут свои, а форма запроса останется той же. Каждый пример заканчивается ссылкой в тот раздел документации, где он разобран целиком: эта страница нужна, чтобы увидеть, на что это похоже, а не чтобы заменить документацию.

Первые запросы

После установки расширения сервис отвечает по адресу публикации базы. Эти три запроса показывают, что он поднялся и что в нём есть.

Корень сервиса

Отдаёт список наборов, которые вошли в состав публикации и доступны этому пользователю.

В документацию

Запрос

GET /base/hs/odata/v4/

Ответ

{
  "@odata.context": "/base/hs/odata/v4/$metadata",
  "value": [
    { "name": "Catalog_Номенклатура", "kind": "EntitySet", "url": "Catalog_Номенклатура" },
    { "name": "Document_РеализацияТоваровУслуг", "kind": "EntitySet", "url": "Document_РеализацияТоваровУслуг" }
  ]
}

Описание модели

CSDL в XML — его читают Power BI и Excel. CSDL JSON отдаётся тем же запросом с $format=json; у штатного интерфейса такого формата нет вовсе.

В документацию

Запрос

GET /base/hs/odata/v4/$metadata
GET /base/hs/odata/v4/$metadata?$format=json

Один объект по ключу

Ключ — тот же Ref_Key, что у штатного интерфейса, в том же виде.

В документацию

Запрос

GET /base/hs/odata/v4/Catalog_Номенклатура(guid'0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9')

Отбор, поля и порядок

Чем точнее запрос, тем меньше 1С поднимает из базы и тем меньше едет по сети. Три поля вместо всех — это разница между десятью мегабайтами и тремя гигабайтами.

Отбор по датам и трём полям

$select режет состав ответа, $orderby задаёт порядок, $top — сколько вернуть. Даты в OData v4 пишутся без обёрток: 2026-01-01T00:00:00Z.

В документацию

Запрос

GET /base/hs/odata/v4/Document_РеализацияТоваровУслуг
    ?$filter=Date ge 2026-01-01T00:00:00Z and Date lt 2026-02-01T00:00:00Z
    &$select=Ref_Key,Number,Date,СуммаДокумента
    &$orderby=Date desc
    &$top=50

Ответ

{
  "@odata.context": "/base/hs/odata/v4/$metadata#Document_РеализацияТоваровУслуг",
  "value": [
    {
      "Ref_Key": "0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9",
      "Number": "РТУ-000184",
      "Date": "2026-01-31T17:42:11Z",
      "СуммаДокумента": 12480.5
    }
  ]
}

Отбор по полю связанного объекта

В $filter можно идти через ссылку: условие ставится на реквизит контрагента, а не на его ключ, и подбирать guid заранее не нужно.

В документацию

Запрос

GET /base/hs/odata/v4/Document_РеализацияТоваровУслуг
    ?$filter=Контрагент/ИНН eq '7701234567' and Posted eq true and DeletionMark eq false
    &$select=Number,Date,СуммаДокумента

Отбор по строкам табличной части

any и all проверяют условие по строкам: вернуть документы, где хоть одна строка дороже порога. Штатный интерфейс так не умеет.

В документацию

Запрос

GET /base/hs/odata/v4/Document_РеализацияТоваровУслуг
    ?$filter=Товары/any(t: t/Сумма gt 100000)
    &$select=Number,Date,СуммаДокумента

Сколько записей

$count отдаёт одно число, без выгрузки самих записей.

В документацию

Запрос

GET /base/hs/odata/v4/Catalog_Номенклатура/$count
GET /base/hs/odata/v4/Catalog_Номенклатура?$count=true&$top=0

Связи и табличные части

$expand вкладывает связанные данные в тот же ответ — до трёх уровней. У вложенного набора свои $select и $orderby, через точку с запятой.

Документ вместе со строками

Табличная часть приходит массивом внутри документа, а не отдельным запросом на каждую строку.

В документацию

Запрос

GET /base/hs/odata/v4/Document_РеализацияТоваровУслуг
    ?$filter=Date ge 2026-01-01T00:00:00Z
    &$select=Number,Date,СуммаДокумента
    &$expand=Товары($select=Номенклатура_Key,Количество,Сумма;$orderby=НомерСтроки)

Ссылки вместо ключей

Вместо Контрагент_Key в ответе будет сам контрагент с нужными полями — отчёту не придётся подтягивать справочник вторым запросом.

В документацию

Запрос

GET /base/hs/odata/v4/Document_РеализацияТоваровУслуг
    ?$select=Number,Date,СуммаДокумента
    &$expand=Контрагент($select=Code,Description),Организация($select=Description)

Регистры

Записи регистров доступны как обычные наборы, а остатки, обороты и срезы — как связанные функции: считает их 1С, а не отчёт на стороне клиента.

Записи регистра накопления

Набор записей целиком, с обычными $filter и $select.

В документацию

Запрос

GET /base/hs/odata/v4/AccumulationRegister_ТоварыНаСкладах_RecordType
    ?$filter=Period ge 2026-01-01T00:00:00Z
    &$select=Period,Склад_Key,Номенклатура_Key,Количество

Обороты по месяцам

Periodicity задаёт шаг: месяц, квартал и дальше. Считает платформа — в ответ приезжают уже свёрнутые обороты.

В документацию

Запрос

GET /base/hs/odata/v4/AccumulationRegister_ТоварыНаСкладах/Turnovers(StartPeriod=2026-01-01T00:00:00Z,EndPeriod=2026-07-01T00:00:00Z,Periodicity='Month')

Остатки регистра бухгалтерии

Та же форма вызова: функция у набора, параметры в скобках.

В документацию

Запрос

GET /base/hs/odata/v4/AccountingRegister_Хозрасчетный/Balance()

Агрегация на стороне 1С

$apply сворачивает данные до того, как они уедут по сети. В замерах группировка с суммой по миллиону записей вернула 338 байт за секунду с небольшим — вместо полутора гигабайт, которые пришлось бы качать, чтобы посчитать то же самое в Power BI. Штатный интерфейс $apply не поддерживает.

Группировка с суммой

groupby задаёт разрезы, aggregate — что считать. Поля перечисляются во внутренних скобках.

В документацию

Запрос

GET /base/hs/odata/v4/AccumulationRegister_ТоварыНаСкладах_RecordType
    ?$apply=groupby((Склад_Key,Номенклатура_Key),aggregate(Количество with sum as Итого))

Ответ

{
  "@odata.context": "/base/hs/odata/v4/$metadata#AccumulationRegister_ТоварыНаСкладах_RecordType",
  "value": [
    { "Склад_Key": "…", "Номенклатура_Key": "…", "Итого": 1842 }
  ]
}

Отбор до группировки

Шаги соединяются косой чертой и выполняются слева направо: сначала отобрать, потом свернуть.

В документацию

Запрос

GET /base/hs/odata/v4/AccumulationRegister_ТоварыНаСкладах_RecordType
    ?$apply=filter(Period ge 2026-01-01T00:00:00Z)/groupby((Склад_Key),aggregate(Количество with sum as Итого))

Большие выгрузки

По умолчанию ответ приходит страницами: в конце каждой лежит @odata.nextLink. Размер страницы и выдача одним ответом решают, сколько займёт полная выгрузка, — на миллионе записей разница была четырёхкратной.

Страница побольше

Заголовок Prefer просит страницы по 5000 записей. На миллионе записей это 145 секунд вместо 493.

В документацию

Запрос

GET /base/hs/odata/v4/AccumulationRegister_ТоварыНаСкладах_RecordType
Prefer: odata.maxpagesize=5000

Ответ

{
  "value": [ … ],
  "@odata.nextLink": "/base/hs/odata/v4/AccumulationRegister_ТоварыНаСкладах_RecordType?$skiptoken=…"
}

Одним ответом

Режим «Выдача коллекций» в настройках отдаёт набор одним потоком, без продолжений: 134 секунды на полтора гигабайта, при пике памяти рабочего процесса 1,4–1,7 ГБ.

В документацию

Запрос

GET /base/hs/odata/v4/AccumulationRegister_ТоварыНаСкладах_RecordType

Запись

POST, PATCH, PUT и DELETE идут через объектную модель 1С: срабатывают обработчики заполнения и записи, проверка реквизитов и подписки на события. Это не прямая запись в таблицы, а то же, что сделал бы пользователь в форме.

Создать элемент

В ответ приходит созданный объект целиком — с ключом, кодом и всем, что проставила 1С.

В документацию

Запрос

POST /base/hs/odata/v4/Catalog_Контрагенты
Content-Type: application/json

{
  "Description": "Ромашка",
  "ИНН": "7701234567",
  "ЮридическоеФизическоеЛицо": "ЮридическоеЛицо"
}

Изменить без гонки

ETag из предыдущего ответа и заголовок If-Match: если объект успели изменить, запрос вернёт 412 и ничего не испортит. У штатного интерфейса такой защиты нет.

В документацию

Запрос

PATCH /base/hs/odata/v4/Catalog_Контрагенты(guid'0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9')
If-Match: W/"AAAAAgAAAAE="
Content-Type: application/json

{ "Description": "Ромашка, ООО" }

Пометить на удаление

DELETE ставит пометку удаления, а не стирает объект из базы — так же, как это делает сама 1С.

В документацию

Запрос

DELETE /base/hs/odata/v4/Catalog_Контрагенты(guid'0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9')

Несколько операций одним запросом

$batch отправляет пачку операций за один заход, а набор изменений внутри пачки выполняется одной транзакцией: либо всё, либо ничего. Штатный интерфейс на $batch отвечает 501.

JSON batch

Один запрос вместо десятка. Операции в наборе изменений выполняются одной транзакцией: если вторая не прошла, первая откатится вместе с ней.

В документацию

Запрос

POST /base/hs/odata/v4/$batch
Content-Type: application/json

{
  "requests": [
    { "id": "1", "method": "PATCH",
      "url": "Catalog_Контрагенты(guid'0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9')",
      "body": { "Description": "Ромашка, ООО" } },
    { "id": "2", "method": "POST", "url": "Catalog_Контрагенты",
      "body": { "Description": "Василёк", "ИНН": "7709876543" } }
  ]
}

Power BI, Excel и код

Для Power BI и Excel нужен адрес канала и вход. Пароль 1С клиенту можно не давать: сервис умеет пускать по токену — со сроком, отзывом и ограничением по IP.

Power BI

«Получить данные → Канал OData», адрес — корень сервиса. Готовый адрес показывает форма «Настройки OData4» в самой базе, вместе со списком выпущенных токенов.

В документацию

Запрос

Получить данные → Канал OData
Адрес: https://сервер/base/hs/odata/v4/

Excel

Power Query видит наборы списком и подтягивает их как таблицы.

В документацию

Запрос

Данные → Получить данные → Из других источников → Из канала OData
Адрес: https://сервер/base/hs/odata/v4/

curl

Проверить сервис после установки проще всего так.

В документацию

Запрос

curl -u odata:пароль \
  "https://сервер/base/hs/odata/v4/Catalog_Номенклатура?\$top=1"

Дальше — документация.

Там разобраны все параметры запроса, формат ошибок, профили доступа и токены, настройки выдачи и ограничения, о которых лучше знать заранее.