
## Получить результат операции 1С

`GET /v1/onec/operations/{operationId}`

Отдаёт состояние операции, поставленной этим же ключом, и её результат, когда 1С прислала данные. Пока чтение идёт, ответ несёт только состояние.

Операции других ключей, пользователей и порталов отвечают так же, как неизвестный идентификатор.

## Параметры

| Параметр | Тип | Обяз. | Описание |
|----------|-----|:-----:|---------|
| `operationId` (path) | string | да | Идентификатор из ответа [`POST /v1/onec/tools/{method}/call`](/docs/onec/call) — поле `data.operationId`, а заголовок `Location` — путь чтения этой операции, идентификатор стоит его последним сегментом |

## Примеры

### curl — личный ключ

```bash
curl https://vibecode.bitrix24.tech/v1/onec/operations/cl9x2k4t70000qz8h3m1vb7ry \
  -H "X-Api-Key: YOUR_API_KEY"
```

### curl — OAuth-приложение

```bash
curl https://vibecode.bitrix24.tech/v1/onec/operations/cl9x2k4t70000qz8h3m1vb7ry \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"
```

### JavaScript — личный ключ

```javascript
const operationId = 'cl9x2k4t70000qz8h3m1vb7ry'

const res = await fetch(`https://vibecode.bitrix24.tech/v1/onec/operations/${operationId}`, {
  headers: { 'X-Api-Key': 'YOUR_API_KEY' },
})

const { data } = await res.json()
console.log(data.status, data.result?.rows?.length)
```

### JavaScript — OAuth-приложение

```javascript
const operationId = 'cl9x2k4t70000qz8h3m1vb7ry'

const res = await fetch(`https://vibecode.bitrix24.tech/v1/onec/operations/${operationId}`, {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

const { data } = await res.json()
```

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

| Поле | Тип | Описание |
|------|-----|---------|
| `success` | boolean | Всегда `true` при успехе |
| `data.operationId` | string | Идентификатор операции |
| `data.type` | string | Вид операции. Для чтения данных — `getData` |
| `data.status` | string | `pending`, `running`, `succeeded`, `failed`, `cancelled` или `expired` |
| `data.createdAt` | string | Когда операция создана, ISO 8601 |
| `data.finishedAt` | string \| null | Когда операция завершилась, ISO 8601. `null`, пока она не в терминальном состоянии |
| `data.expiresAt` | string | До какого момента операция ждёт выполнения, ISO 8601 |
| `data.result` | object | Данные из 1С. Приходит только при `status: "succeeded"` |
| `data.result.columns` | array | Имена колонок в порядке, в котором их вернула 1С |
| `data.result.rows` | array | Строки выборки, объект на строку с колонками в ключах |
| `data.result.truncated` | boolean | Выборка оборвана по `limit` — за ней есть ещё строки |
| `data.result.nextOffset` | integer \| null | Позиция для следующего вызова при `truncated: true`, иначе `null` |
| `data.result.total` | integer | Всего строк под фильтром. Приходит, когда 1С отдала это число |
| `data.error` | object | Отказ. Приходит только при `status: "failed"` |
| `data.error.code` | string | Код отказа от 1С, например `ACCESS_DENIED` или `UNKNOWN_FILTER` |
| `data.error.message` | string | Текст отказа от 1С |

## Пример ответа

Чтение выполнено:

```json
{
  "success": true,
  "data": {
    "operationId": "cl9x2k4t70000qz8h3m1vb7ry",
    "type": "getData",
    "status": "succeeded",
    "createdAt": "2026-09-14T12:00:00.000Z",
    "finishedAt": "2026-09-14T12:00:04.000Z",
    "expiresAt": "2026-09-14T12:15:00.000Z",
    "result": {
      "columns": ["Код"],
      "rows": [{ "Код": "000012" }],
      "truncated": false,
      "nextOffset": null
    }
  }
}
```

1С ещё не взяла операцию в работу:

```json
{
  "success": true,
  "data": {
    "operationId": "cl9x2k4t70000qz8h3m1vb7ry",
    "type": "getData",
    "status": "pending",
    "createdAt": "2026-09-14T12:00:00.000Z",
    "finishedAt": null,
    "expiresAt": "2026-09-14T12:15:00.000Z"
  }
}
```

1С отказала в чтении:

```json
{
  "success": true,
  "data": {
    "operationId": "cl9x2k4t70000qz8h3m1vb7ry",
    "type": "getData",
    "status": "failed",
    "createdAt": "2026-09-14T12:00:00.000Z",
    "finishedAt": "2026-09-14T12:00:03.000Z",
    "expiresAt": "2026-09-14T12:15:00.000Z",
    "error": {
      "code": "ACCESS_DENIED",
      "message": "Нет прав"
    }
  }
}
```

## Пример ответа при ошибке

404 — идентификатор неизвестен либо операция создана другим ключом, пользователем или порталом:

```json
{
  "success": false,
  "error": {
    "code": "ONEC_OPERATION_NOT_FOUND",
    "message": "Operation not found."
  }
}
```

## Ошибки

| HTTP | Код | Описание |
|------|-----|---------|
| 404 | `ONEC_OPERATION_NOT_FOUND` | Операции с таким идентификатором нет, либо она создана другим ключом, пользователем или порталом |
| 404 | `ONEC_OPERATION_NOT_FOUND` | Идентификатор не той формы — от 20 до 40 строчных латинских букв и цифр |
| 404 | `ROUTE_NOT_FOUND` | Интеграция 1С на портале недоступна — ответ совпадает с ответом на неизвестный путь |
| 410 | `ONEC_OPERATION_GONE` | Результат уже не хранится: с момента завершения прошло больше суток |
| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |
| 429 | `RATE_LIMITED` | Превышен лимит запросов — повторите после времени из заголовка `Retry-After` |
| 503 | `user_self_deletion_pending` | Владелец ключа удаляет свою учётную запись на портале. Заголовок `Retry-After` равен `604800` — столько длится отсрочка удаления |

Полный список общих ошибок API — [Ошибки](/docs/errors).

## Известные особенности

**Терминальных состояний четыре, и клиент обязан разобрать все.** `succeeded` несёт `result`, `failed` несёт `error`, а `cancelled` и `expired` не несут ни того, ни другого: первое означает, что операцию снял портал — отключение 1С, смена настроек или потеря доступа к учётной записи, второе — что 1С не прислала данные до `expiresAt`.

**Статус `expired` вычисляется на чтении.** Операция, которая осталась незавершённой и перешагнула `expiresAt`, читается как `expired`, даже если в этот момент её состояние в очереди ещё не обновилось.

**Результат не переживает сутки.** Данные, которые нужны дольше, сохраняйте у себя при первом успешном чтении.

**Интервал опроса считается от лимита.** На чтение операций отведено 120 запросов в минуту, поэтому опрос раз в секунду в одном потоке укладывается в лимит. Действующее для ключа значение приходит в заголовке ответа `x-ratelimit-limit` — оно ниже суммарного, потому что лимит делится между репликами. Общие правила — [Лимиты и оптимизация](/docs/optimization).

**Ответ не кэшируется.** Каждый ответ приходит с `Cache-Control: no-store`, поэтому промежуточные кэши не отдадут устаревшее состояние операции.

**Готовый цикл опроса.** Ниже — чтение одной операции до терминального состояния с растущей паузой и разбором всех четырёх исходов.

```javascript
const BASE = 'https://vibecode.bitrix24.tech/v1'
const headers = { 'X-Api-Key': 'YOUR_API_KEY' }

async function waitForOperation(operationId, { firstDelayMs = 1000, maxDelayMs = 5000 } = {}) {
  let delay = firstDelayMs

  for (;;) {
    const res = await fetch(`${BASE}/onec/operations/${operationId}`, { headers })

    if (res.status === 410) {
      throw new Error('Результат операции больше не хранится')
    }
    if (res.status === 429) {
      const retryAfter = Number(res.headers.get('Retry-After') ?? 5)
      await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000))
      continue
    }
    if (!res.ok) {
      const { error } = await res.json()
      throw new Error(`${res.status} ${error.code}`)
    }

    const { data } = await res.json()

    if (data.status === 'succeeded') return data.result
    if (data.status === 'failed') throw new Error(`1С отказала: ${data.error.code}`)
    if (data.status === 'cancelled') throw new Error('Операцию снял портал')
    if (data.status === 'expired') throw new Error('1С не прислала данные до expiresAt')

    await new Promise((resolve) => setTimeout(resolve, delay))
    delay = Math.min(delay * 2, maxDelayMs)
  }
}

const result = await waitForOperation('cl9x2k4t70000qz8h3m1vb7ry')
console.log(result.columns, result.rows.length, result.nextOffset)
```

## Смотрите также

- [Запросить данные из 1С](/docs/onec/call)
- [Каталог инструментов 1С](/docs/onec/tools)
- [Интеграция 1С](/docs/onec)
- [Лимиты и оптимизация](/docs/optimization)
- [Ошибки](/docs/errors)
