# История статусов

Изменения статусов лидов, кампаний и аккаунтов, начальный снимок и полнота доступной истории.

Базовый адрес: https://api.melioralab.io/v1. Ключ передается в заголовке `Authorization: Bearer mel_live_...`.

Маршруты:

- `GET /v1/leads/{id}/status-history`: История статусов лида
- `GET /v1/campaigns/{id}/status-history`: История статусов кампании
- `GET /v1/campaigns/{id}/accounts/{account_id}/status-history`: История статусов аккаунта кампании

## Объект LeadStatusTransition

Фактическое изменение статуса. Набор статусов зависит от `entity_kind`.

| Поле | Тип | Описание |
|---|---|---|
| `object` | string | Тип объекта, всегда `message`. |
| `id` | string (uuid) | Непрозрачный устойчивый идентификатор сообщения. Не разбирайте его формат. |
| `workspace_id` | string (uuid) | Идентификатор пространства. |
| `campaign_id` | string (uuid) | Идентификатор кампании. |
| `lead_id` | string (uuid) или null | Идентификатор участия лида в кампании. В истории кампании или аккаунта может быть `null`. |
| `entity_kind` | string | Вид объекта: лид, кампания или аккаунт. Всегда `"lead"`. |
| `entity_id` | string (uuid) | Идентификатор объекта, статус которого изменился. |
| `entity_revision` | integer | Порядковый номер записи для объекта. Переходы начинаются с 1, начальный снимок может иметь номер 0. |
| `from_status` | string | Предыдущий публичный статус. Неизвестное значение передается как `unknown`. Значения: `new`, `contacted`, `completed`, `replied`, `blocked`, `failed`, `suspended`, `deleted`, `opted_out`, `unknown`. |
| `to_status` | string | Новый публичный статус. Неизвестное значение передается как `unknown`. Значения: `new`, `contacted`, `completed`, `replied`, `blocked`, `failed`, `suspended`, `deleted`, `opted_out`, `unknown`. |
| `reason_code` | string | Причина изменения статуса. `unspecified`, если причина неизвестна. Значения: `operator_action`, `schedule`, `queue_exhausted`, `recipient_not_found`, `telegram_auth`, `subscription`, `recovery`, `unspecified`. |
| `source` | string | Источник записи. `unknown`, если он неизвестен. У статистики всегда `task_states`. Значения: `user`, `system`, `support`, `unknown`. |
| `occurred_at` | string (date-time) | Когда произошло изменение. |
| `recorded_at` | string (date-time) | Когда изменение или начальный снимок были сохранены. |

Пример:

```json
{
  "object": "status_transition",
  "id": "00000000-0000-4000-8000-000000000001",
  "workspace_id": "3f6a9d21-8b4c-4e7f-a102-5c9e8d7b6a43",
  "campaign_id": "4d8b2f73-6e1a-4c95-b7d0-8a3f5e2c9b14",
  "lead_id": "5a7c3e92-1f4b-4d68-9c2e-7b0a6d4f8e31",
  "entity_kind": "lead",
  "entity_id": "5a7c3e92-1f4b-4d68-9c2e-7b0a6d4f8e31",
  "entity_revision": 1,
  "from_status": "new",
  "to_status": "contacted",
  "reason_code": "operator_action",
  "source": "user",
  "occurred_at": "2026-10-27T09:15:42.000Z",
  "recorded_at": "2026-10-27T09:15:42.000Z"
}
```

## Объект CampaignStatusTransition

Фактическое изменение статуса. Набор статусов зависит от `entity_kind`.

| Поле | Тип | Описание |
|---|---|---|
| `object` | string | Тип объекта, всегда `message`. |
| `id` | string (uuid) | Непрозрачный устойчивый идентификатор сообщения. Не разбирайте его формат. |
| `workspace_id` | string (uuid) | Идентификатор пространства. |
| `campaign_id` | string (uuid) | Идентификатор кампании. |
| `lead_id` | string (uuid) или null | Идентификатор участия лида в кампании. В истории кампании или аккаунта может быть `null`. |
| `entity_kind` | string | Вид объекта: лид, кампания или аккаунт. Всегда `"campaign"`. |
| `entity_id` | string (uuid) | Идентификатор объекта, статус которого изменился. |
| `entity_revision` | integer | Порядковый номер записи для объекта. Переходы начинаются с 1, начальный снимок может иметь номер 0. |
| `from_status` | string | Предыдущий публичный статус. Неизвестное значение передается как `unknown`. Значения: `draft`, `scheduled`, `active`, `paused`, `stopped`, `completed`, `archived`, `launching`, `failed`, `paused_no_credits`, `unknown`. |
| `to_status` | string | Новый публичный статус. Неизвестное значение передается как `unknown`. Значения: `draft`, `scheduled`, `active`, `paused`, `stopped`, `completed`, `archived`, `launching`, `failed`, `paused_no_credits`, `unknown`. |
| `reason_code` | string | Причина изменения статуса. `unspecified`, если причина неизвестна. Значения: `operator_action`, `schedule`, `queue_exhausted`, `recipient_not_found`, `telegram_auth`, `subscription`, `recovery`, `unspecified`. |
| `source` | string | Источник записи. `unknown`, если он неизвестен. У статистики всегда `task_states`. Значения: `user`, `system`, `support`, `unknown`. |
| `occurred_at` | string (date-time) | Когда произошло изменение. |
| `recorded_at` | string (date-time) | Когда изменение или начальный снимок были сохранены. |

Пример:

```json
{
  "object": "status_transition",
  "id": "00000000-0000-4000-8000-000000000002",
  "workspace_id": "3f6a9d21-8b4c-4e7f-a102-5c9e8d7b6a43",
  "campaign_id": "4d8b2f73-6e1a-4c95-b7d0-8a3f5e2c9b14",
  "lead_id": null,
  "entity_kind": "campaign",
  "entity_id": "4d8b2f73-6e1a-4c95-b7d0-8a3f5e2c9b14",
  "entity_revision": 1,
  "from_status": "draft",
  "to_status": "active",
  "reason_code": "operator_action",
  "source": "user",
  "occurred_at": "2026-10-27T09:15:42.000Z",
  "recorded_at": "2026-10-27T09:15:42.000Z"
}
```

## Объект AccountStatusTransition

Фактическое изменение статуса. Набор статусов зависит от `entity_kind`.

| Поле | Тип | Описание |
|---|---|---|
| `object` | string | Тип объекта, всегда `message`. |
| `id` | string (uuid) | Непрозрачный устойчивый идентификатор сообщения. Не разбирайте его формат. |
| `workspace_id` | string (uuid) | Идентификатор пространства. |
| `campaign_id` | string (uuid) | Идентификатор кампании. |
| `lead_id` | string (uuid) или null | Идентификатор участия лида в кампании. В истории кампании или аккаунта может быть `null`. |
| `entity_kind` | string | Вид объекта: лид, кампания или аккаунт. Всегда `"account"`. |
| `entity_id` | string (uuid) | Идентификатор объекта, статус которого изменился. |
| `entity_revision` | integer | Порядковый номер записи для объекта. Переходы начинаются с 1, начальный снимок может иметь номер 0. |
| `from_status` | string | Предыдущий публичный статус. Неизвестное значение передается как `unknown`. Значения: `online`, `offline`, `limited`, `banned`, `deleted`, `locked`, `unauthorized`, `paused`, `unknown`. |
| `to_status` | string | Новый публичный статус. Неизвестное значение передается как `unknown`. Значения: `online`, `offline`, `limited`, `banned`, `deleted`, `locked`, `unauthorized`, `paused`, `unknown`. |
| `reason_code` | string | Причина изменения статуса. `unspecified`, если причина неизвестна. Значения: `operator_action`, `schedule`, `queue_exhausted`, `recipient_not_found`, `telegram_auth`, `subscription`, `recovery`, `unspecified`. |
| `source` | string | Источник записи. `unknown`, если он неизвестен. У статистики всегда `task_states`. Значения: `user`, `system`, `support`, `unknown`. |
| `occurred_at` | string (date-time) | Когда произошло изменение. |
| `recorded_at` | string (date-time) | Когда изменение или начальный снимок были сохранены. |

Пример:

```json
{
  "object": "status_transition",
  "id": "00000000-0000-4000-8000-000000000003",
  "workspace_id": "3f6a9d21-8b4c-4e7f-a102-5c9e8d7b6a43",
  "campaign_id": "4d8b2f73-6e1a-4c95-b7d0-8a3f5e2c9b14",
  "lead_id": null,
  "entity_kind": "account",
  "entity_id": "1d9f6b28-4c3e-4a75-8b19-5e7a2c0f6d83",
  "entity_revision": 1,
  "from_status": "online",
  "to_status": "paused",
  "reason_code": "operator_action",
  "source": "user",
  "occurred_at": "2026-10-27T09:15:42.000Z",
  "recorded_at": "2026-10-27T09:15:42.000Z"
}
```

## Объект StatusBaseline

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

| Поле | Тип | Описание |
|---|---|---|
| `Вариант 1: object` | string | Тип объекта, всегда `message`. |
| `Вариант 1: workspace_id` | string (uuid) | Идентификатор пространства. |
| `Вариант 1: campaign_id` | string (uuid) | Идентификатор кампании. |
| `Вариант 1: lead_id` | string (uuid) или null | Идентификатор участия лида в кампании. В истории кампании или аккаунта может быть `null`. |
| `Вариант 1: entity_kind` | string | Вид объекта: лид, кампания или аккаунт. Всегда `"lead"`. |
| `Вариант 1: entity_id` | string (uuid) | Идентификатор объекта, статус которого изменился. |
| `Вариант 1: entity_revision` | integer | Порядковый номер записи для объекта. Переходы начинаются с 1, начальный снимок может иметь номер 0. |
| `Вариант 1: status` | string | Публичный статус или состояние полноты. Неизвестное значение передается как `unknown`. Значения: `new`, `contacted`, `completed`, `replied`, `blocked`, `failed`, `suspended`, `deleted`, `opted_out`, `unknown`. |
| `Вариант 1: recorded_at` | string (date-time) | Когда изменение или начальный снимок были сохранены. |
| `Вариант 1: provenance` | string | Всегда `baseline`: начальный снимок, а не изменение статуса. |
| `Вариант 2: object` | string | Тип объекта, всегда `message`. |
| `Вариант 2: workspace_id` | string (uuid) | Идентификатор пространства. |
| `Вариант 2: campaign_id` | string (uuid) | Идентификатор кампании. |
| `Вариант 2: lead_id` | string (uuid) или null | Идентификатор участия лида в кампании. В истории кампании или аккаунта может быть `null`. |
| `Вариант 2: entity_kind` | string | Вид объекта: лид, кампания или аккаунт. Всегда `"campaign"`. |
| `Вариант 2: entity_id` | string (uuid) | Идентификатор объекта, статус которого изменился. |
| `Вариант 2: entity_revision` | integer | Порядковый номер записи для объекта. Переходы начинаются с 1, начальный снимок может иметь номер 0. |
| `Вариант 2: status` | string | Публичный статус или состояние полноты. Неизвестное значение передается как `unknown`. Значения: `draft`, `scheduled`, `active`, `paused`, `stopped`, `completed`, `archived`, `launching`, `failed`, `paused_no_credits`, `unknown`. |
| `Вариант 2: recorded_at` | string (date-time) | Когда изменение или начальный снимок были сохранены. |
| `Вариант 2: provenance` | string | Всегда `baseline`: начальный снимок, а не изменение статуса. |
| `Вариант 3: object` | string | Тип объекта, всегда `message`. |
| `Вариант 3: workspace_id` | string (uuid) | Идентификатор пространства. |
| `Вариант 3: campaign_id` | string (uuid) | Идентификатор кампании. |
| `Вариант 3: lead_id` | string (uuid) или null | Идентификатор участия лида в кампании. В истории кампании или аккаунта может быть `null`. |
| `Вариант 3: entity_kind` | string | Вид объекта: лид, кампания или аккаунт. Всегда `"account"`. |
| `Вариант 3: entity_id` | string (uuid) | Идентификатор объекта, статус которого изменился. |
| `Вариант 3: entity_revision` | integer | Порядковый номер записи для объекта. Переходы начинаются с 1, начальный снимок может иметь номер 0. |
| `Вариант 3: status` | string | Публичный статус или состояние полноты. Неизвестное значение передается как `unknown`. Значения: `online`, `offline`, `limited`, `banned`, `deleted`, `locked`, `unauthorized`, `paused`, `unknown`. |
| `Вариант 3: recorded_at` | string (date-time) | Когда изменение или начальный снимок были сохранены. |
| `Вариант 3: provenance` | string | Всегда `baseline`: начальный снимок, а не изменение статуса. |

Пример:

```json
{
  "object": "status_baseline",
  "workspace_id": "3f6a9d21-8b4c-4e7f-a102-5c9e8d7b6a43",
  "campaign_id": "4d8b2f73-6e1a-4c95-b7d0-8a3f5e2c9b14",
  "lead_id": "5a7c3e92-1f4b-4d68-9c2e-7b0a6d4f8e31",
  "entity_kind": "lead",
  "entity_id": "5a7c3e92-1f4b-4d68-9c2e-7b0a6d4f8e31",
  "entity_revision": 0,
  "status": "new",
  "recorded_at": "2026-10-26T07:30:00.000Z",
  "provenance": "baseline"
}
```

## История статусов лида

`GET /v1/leads/{id}/status-history`

Фактические изменения статуса лида по возрастанию `entity_revision`. Начальный снимок находится отдельно в `meta.baseline`. Новые возможности включаются для кабинета по запросу.

Право: `leads:read`. Вес запроса: 2.

### Параметры

| Параметр | Где | Тип | Обязательный | Описание |
|---|---|---|---|---|
| `id` | путь | string (uuid) | да | Идентификатор лида. |
| `limit` | строка запроса | integer | нет | Сколько объектов вернуть на странице. От 1 до 100. По умолчанию `50`. |
| `cursor` | строка запроса | string | нет | Значение `next_cursor` из предыдущего ответа. Остальные фильтры должны совпадать с первым запросом. |

### Ответ

Список: `object`, `data`, `has_more`, `next_cursor`, `meta`. Пагинация: https://docs.melioralab.io/md/pagination.md

Поле `meta`:

| Поле | Тип | Описание |
|---|---|---|
| `meta.baseline` | object или null | Начальный снимок статуса или `null`. Это не переход и не доказательство более ранней истории. |
| `meta.baseline.object` | string | Тип объекта, всегда `message`. |
| `meta.baseline.workspace_id` | string (uuid) | Идентификатор пространства. |
| `meta.baseline.campaign_id` | string (uuid) | Идентификатор кампании. |
| `meta.baseline.lead_id` | string (uuid) или null | Идентификатор участия лида в кампании. В истории кампании или аккаунта может быть `null`. |
| `meta.baseline.entity_kind` | string | Вид объекта: лид, кампания или аккаунт. Всегда `"lead"`. |
| `meta.baseline.entity_id` | string (uuid) | Идентификатор объекта, статус которого изменился. |
| `meta.baseline.entity_revision` | integer | Порядковый номер записи для объекта. Переходы начинаются с 1, начальный снимок может иметь номер 0. |
| `meta.baseline.status` | string | Публичный статус или состояние полноты. Неизвестное значение передается как `unknown`. Значения: `new`, `contacted`, `completed`, `replied`, `blocked`, `failed`, `suspended`, `deleted`, `opted_out`, `unknown`. |
| `meta.baseline.recorded_at` | string (date-time) | Когда изменение или начальный снимок были сохранены. |
| `meta.baseline.provenance` | string | Всегда `baseline`: начальный снимок, а не изменение статуса. |
| `meta.available_from` | string (date-time) или null | Начало периода, за который есть данные. `null`, если неизвестно. |
| `meta.history_started_at` | string (date-time) или null | Когда началось ведение истории. Более ранние изменения не восстанавливаются. |
| `meta.retained_from` | string (date-time) или null | Начало сохраненного периода истории или `null`, если неизвестно. |
| `meta.completeness` | object | Полнота данных. `has_more=false` означает конец страниц, а не полноту истории. |
| `meta.completeness.status` | string | `complete`, `partial` или `unknown`. Значения: `complete`, `partial`, `unknown`. |
| `meta.completeness.gaps` | array of object | До 50 интервалов возможной неполноты. |
| `meta.completeness.gaps[].id` | string (uuid) | Идентификатор интервала. |
| `meta.completeness.gaps[].from` | string (date-time) | Начало интервала. |
| `meta.completeness.gaps[].to` | string (date-time) или null | Конец интервала. `null`, если интервал еще не закрыт. |
| `meta.completeness.gaps[].state` | string | `open`, `recovering`, `recovered`, `unrecoverable` или `unknown`. Значения: `open`, `recovering`, `recovered`, `unrecoverable`, `unknown`. |
| `meta.completeness.gaps_truncated` | boolean | `true`, если интервалов больше 50. |
| `meta.completeness.incomplete_from` | string (date-time) или null | Самая ранняя граница скрытых неполных интервалов. `null`, если таких нет. |
| `meta.observed_at` | string (date-time) | Время чтения данных сервером. |

### Особые ошибки

- `cursor_mismatch` (400): Курсор поврежден, выдан для другого маршрута или фильтров, либо права и охват ключа изменились.
- `scope_required` (403): Ключ не разрешает операцию. Для команды нужно право ее вида.
- `not_found` (404): Объект не найден или находится вне охвата ключа. Неизвестный путь тоже дает 404.
- `cursor_expired` (410): Срок курсора истек: 15 минут для списков, 30 суток для ленты событий.

Общие ошибки: https://docs.melioralab.io/md/errors.md

### Пример запроса

```bash
curl https://api.melioralab.io/v1/leads/5a7c3e92-1f4b-4d68-9c2e-7b0a6d4f8e31/status-history \
  -H "Authorization: Bearer $MELIORA_API_KEY"
```

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

```json
{
  "object": "list",
  "data": [
    {
      "object": "status_transition",
      "id": "00000000-0000-4000-8000-000000000001",
      "workspace_id": "3f6a9d21-8b4c-4e7f-a102-5c9e8d7b6a43",
      "campaign_id": "4d8b2f73-6e1a-4c95-b7d0-8a3f5e2c9b14",
      "lead_id": "5a7c3e92-1f4b-4d68-9c2e-7b0a6d4f8e31",
      "entity_kind": "lead",
      "entity_id": "5a7c3e92-1f4b-4d68-9c2e-7b0a6d4f8e31",
      "entity_revision": 1,
      "from_status": "new",
      "to_status": "contacted",
      "reason_code": "operator_action",
      "source": "user",
      "occurred_at": "2026-10-27T09:15:42.000Z",
      "recorded_at": "2026-10-27T09:15:42.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null,
  "meta": {
    "baseline": {
      "object": "status_baseline",
      "workspace_id": "3f6a9d21-8b4c-4e7f-a102-5c9e8d7b6a43",
      "campaign_id": "4d8b2f73-6e1a-4c95-b7d0-8a3f5e2c9b14",
      "lead_id": "5a7c3e92-1f4b-4d68-9c2e-7b0a6d4f8e31",
      "entity_kind": "lead",
      "entity_id": "5a7c3e92-1f4b-4d68-9c2e-7b0a6d4f8e31",
      "entity_revision": 0,
      "status": "new",
      "recorded_at": "2026-10-26T07:30:00.000Z",
      "provenance": "baseline"
    },
    "available_from": "2026-10-26T07:30:00.000Z",
    "history_started_at": "2026-10-26T07:30:00.000Z",
    "retained_from": "2026-10-26T07:30:00.000Z",
    "completeness": {
      "status": "complete",
      "gaps": [],
      "gaps_truncated": false,
      "incomplete_from": null
    },
    "observed_at": "2026-10-27T09:15:42.000Z"
  }
}
```

## История статусов кампании

`GET /v1/campaigns/{id}/status-history`

Фактические изменения статуса кампании по возрастанию `entity_revision`. Новые возможности включаются для кабинета по запросу.

Право: `campaigns:read`. Вес запроса: 2.

### Параметры

| Параметр | Где | Тип | Обязательный | Описание |
|---|---|---|---|---|
| `id` | путь | string (uuid) | да | Идентификатор кампании. |
| `limit` | строка запроса | integer | нет | Сколько объектов вернуть на странице. От 1 до 100. По умолчанию `50`. |
| `cursor` | строка запроса | string | нет | Значение `next_cursor` из предыдущего ответа. Остальные фильтры должны совпадать с первым запросом. |

### Ответ

Список: `object`, `data`, `has_more`, `next_cursor`, `meta`. Пагинация: https://docs.melioralab.io/md/pagination.md

Поле `meta`:

| Поле | Тип | Описание |
|---|---|---|
| `meta.baseline` | object или null | Начальный снимок статуса или `null`. Это не переход и не доказательство более ранней истории. |
| `meta.baseline.object` | string | Тип объекта, всегда `message`. |
| `meta.baseline.workspace_id` | string (uuid) | Идентификатор пространства. |
| `meta.baseline.campaign_id` | string (uuid) | Идентификатор кампании. |
| `meta.baseline.lead_id` | string (uuid) или null | Идентификатор участия лида в кампании. В истории кампании или аккаунта может быть `null`. |
| `meta.baseline.entity_kind` | string | Вид объекта: лид, кампания или аккаунт. Всегда `"campaign"`. |
| `meta.baseline.entity_id` | string (uuid) | Идентификатор объекта, статус которого изменился. |
| `meta.baseline.entity_revision` | integer | Порядковый номер записи для объекта. Переходы начинаются с 1, начальный снимок может иметь номер 0. |
| `meta.baseline.status` | string | Публичный статус или состояние полноты. Неизвестное значение передается как `unknown`. Значения: `draft`, `scheduled`, `active`, `paused`, `stopped`, `completed`, `archived`, `launching`, `failed`, `paused_no_credits`, `unknown`. |
| `meta.baseline.recorded_at` | string (date-time) | Когда изменение или начальный снимок были сохранены. |
| `meta.baseline.provenance` | string | Всегда `baseline`: начальный снимок, а не изменение статуса. |
| `meta.available_from` | string (date-time) или null | Начало периода, за который есть данные. `null`, если неизвестно. |
| `meta.history_started_at` | string (date-time) или null | Когда началось ведение истории. Более ранние изменения не восстанавливаются. |
| `meta.retained_from` | string (date-time) или null | Начало сохраненного периода истории или `null`, если неизвестно. |
| `meta.completeness` | object | Полнота данных. `has_more=false` означает конец страниц, а не полноту истории. |
| `meta.completeness.status` | string | `complete`, `partial` или `unknown`. Значения: `complete`, `partial`, `unknown`. |
| `meta.completeness.gaps` | array of object | До 50 интервалов возможной неполноты. |
| `meta.completeness.gaps[].id` | string (uuid) | Идентификатор интервала. |
| `meta.completeness.gaps[].from` | string (date-time) | Начало интервала. |
| `meta.completeness.gaps[].to` | string (date-time) или null | Конец интервала. `null`, если интервал еще не закрыт. |
| `meta.completeness.gaps[].state` | string | `open`, `recovering`, `recovered`, `unrecoverable` или `unknown`. Значения: `open`, `recovering`, `recovered`, `unrecoverable`, `unknown`. |
| `meta.completeness.gaps_truncated` | boolean | `true`, если интервалов больше 50. |
| `meta.completeness.incomplete_from` | string (date-time) или null | Самая ранняя граница скрытых неполных интервалов. `null`, если таких нет. |
| `meta.observed_at` | string (date-time) | Время чтения данных сервером. |

### Особые ошибки

- `cursor_mismatch` (400): Курсор поврежден, выдан для другого маршрута или фильтров, либо права и охват ключа изменились.
- `scope_required` (403): Ключ не разрешает операцию. Для команды нужно право ее вида.
- `not_found` (404): Объект не найден или находится вне охвата ключа. Неизвестный путь тоже дает 404.
- `cursor_expired` (410): Срок курсора истек: 15 минут для списков, 30 суток для ленты событий.

Общие ошибки: https://docs.melioralab.io/md/errors.md

### Пример запроса

```bash
curl https://api.melioralab.io/v1/campaigns/4d8b2f73-6e1a-4c95-b7d0-8a3f5e2c9b14/status-history \
  -H "Authorization: Bearer $MELIORA_API_KEY"
```

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

```json
{
  "object": "list",
  "data": [
    {
      "object": "status_transition",
      "id": "00000000-0000-4000-8000-000000000002",
      "workspace_id": "3f6a9d21-8b4c-4e7f-a102-5c9e8d7b6a43",
      "campaign_id": "4d8b2f73-6e1a-4c95-b7d0-8a3f5e2c9b14",
      "lead_id": null,
      "entity_kind": "campaign",
      "entity_id": "4d8b2f73-6e1a-4c95-b7d0-8a3f5e2c9b14",
      "entity_revision": 1,
      "from_status": "draft",
      "to_status": "active",
      "reason_code": "operator_action",
      "source": "user",
      "occurred_at": "2026-10-27T09:15:42.000Z",
      "recorded_at": "2026-10-27T09:15:42.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null,
  "meta": {
    "baseline": {
      "object": "status_baseline",
      "workspace_id": "3f6a9d21-8b4c-4e7f-a102-5c9e8d7b6a43",
      "campaign_id": "4d8b2f73-6e1a-4c95-b7d0-8a3f5e2c9b14",
      "lead_id": null,
      "entity_kind": "campaign",
      "entity_id": "4d8b2f73-6e1a-4c95-b7d0-8a3f5e2c9b14",
      "entity_revision": 0,
      "status": "draft",
      "recorded_at": "2026-10-26T07:30:00.000Z",
      "provenance": "baseline"
    },
    "available_from": "2026-10-26T07:30:00.000Z",
    "history_started_at": "2026-10-26T07:30:00.000Z",
    "retained_from": "2026-10-26T07:30:00.000Z",
    "completeness": {
      "status": "complete",
      "gaps": [],
      "gaps_truncated": false,
      "incomplete_from": null
    },
    "observed_at": "2026-10-27T09:15:42.000Z"
  }
}
```

## История статусов аккаунта кампании

`GET /v1/campaigns/{id}/accounts/{account_id}/status-history`

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

Право: `accounts:read`. Вес запроса: 2.

### Параметры

| Параметр | Где | Тип | Обязательный | Описание |
|---|---|---|---|---|
| `id` | путь | string (uuid) | да | Идентификатор кампании. |
| `account_id` | путь | string (uuid) | да | Идентификатор аккаунта. |
| `limit` | строка запроса | integer | нет | Сколько объектов вернуть на странице. От 1 до 100. По умолчанию `50`. |
| `cursor` | строка запроса | string | нет | Значение `next_cursor` из предыдущего ответа. Остальные фильтры должны совпадать с первым запросом. |

### Ответ

Список: `object`, `data`, `has_more`, `next_cursor`, `meta`. Пагинация: https://docs.melioralab.io/md/pagination.md

Поле `meta`:

| Поле | Тип | Описание |
|---|---|---|
| `meta.baseline` | object или null | Начальный снимок статуса или `null`. Это не переход и не доказательство более ранней истории. |
| `meta.baseline.object` | string | Тип объекта, всегда `message`. |
| `meta.baseline.workspace_id` | string (uuid) | Идентификатор пространства. |
| `meta.baseline.campaign_id` | string (uuid) | Идентификатор кампании. |
| `meta.baseline.lead_id` | string (uuid) или null | Идентификатор участия лида в кампании. В истории кампании или аккаунта может быть `null`. |
| `meta.baseline.entity_kind` | string | Вид объекта: лид, кампания или аккаунт. Всегда `"account"`. |
| `meta.baseline.entity_id` | string (uuid) | Идентификатор объекта, статус которого изменился. |
| `meta.baseline.entity_revision` | integer | Порядковый номер записи для объекта. Переходы начинаются с 1, начальный снимок может иметь номер 0. |
| `meta.baseline.status` | string | Публичный статус или состояние полноты. Неизвестное значение передается как `unknown`. Значения: `online`, `offline`, `limited`, `banned`, `deleted`, `locked`, `unauthorized`, `paused`, `unknown`. |
| `meta.baseline.recorded_at` | string (date-time) | Когда изменение или начальный снимок были сохранены. |
| `meta.baseline.provenance` | string | Всегда `baseline`: начальный снимок, а не изменение статуса. |
| `meta.available_from` | string (date-time) или null | Начало периода, за который есть данные. `null`, если неизвестно. |
| `meta.history_started_at` | string (date-time) или null | Когда началось ведение истории. Более ранние изменения не восстанавливаются. |
| `meta.retained_from` | string (date-time) или null | Начало сохраненного периода истории или `null`, если неизвестно. |
| `meta.completeness` | object | Полнота данных. `has_more=false` означает конец страниц, а не полноту истории. |
| `meta.completeness.status` | string | `complete`, `partial` или `unknown`. Значения: `complete`, `partial`, `unknown`. |
| `meta.completeness.gaps` | array of object | До 50 интервалов возможной неполноты. |
| `meta.completeness.gaps[].id` | string (uuid) | Идентификатор интервала. |
| `meta.completeness.gaps[].from` | string (date-time) | Начало интервала. |
| `meta.completeness.gaps[].to` | string (date-time) или null | Конец интервала. `null`, если интервал еще не закрыт. |
| `meta.completeness.gaps[].state` | string | `open`, `recovering`, `recovered`, `unrecoverable` или `unknown`. Значения: `open`, `recovering`, `recovered`, `unrecoverable`, `unknown`. |
| `meta.completeness.gaps_truncated` | boolean | `true`, если интервалов больше 50. |
| `meta.completeness.incomplete_from` | string (date-time) или null | Самая ранняя граница скрытых неполных интервалов. `null`, если таких нет. |
| `meta.observed_at` | string (date-time) | Время чтения данных сервером. |

### Особые ошибки

- `cursor_mismatch` (400): Курсор поврежден, выдан для другого маршрута или фильтров, либо права и охват ключа изменились.
- `scope_required` (403): Ключ не разрешает операцию. Для команды нужно право ее вида.
- `not_found` (404): Объект не найден или находится вне охвата ключа. Неизвестный путь тоже дает 404.
- `cursor_expired` (410): Срок курсора истек: 15 минут для списков, 30 суток для ленты событий.

Общие ошибки: https://docs.melioralab.io/md/errors.md

### Пример запроса

```bash
curl https://api.melioralab.io/v1/campaigns/4d8b2f73-6e1a-4c95-b7d0-8a3f5e2c9b14/accounts/1d9f6b28-4c3e-4a75-8b19-5e7a2c0f6d83/status-history \
  -H "Authorization: Bearer $MELIORA_API_KEY"
```

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

```json
{
  "object": "list",
  "data": [
    {
      "object": "status_transition",
      "id": "00000000-0000-4000-8000-000000000003",
      "workspace_id": "3f6a9d21-8b4c-4e7f-a102-5c9e8d7b6a43",
      "campaign_id": "4d8b2f73-6e1a-4c95-b7d0-8a3f5e2c9b14",
      "lead_id": null,
      "entity_kind": "account",
      "entity_id": "1d9f6b28-4c3e-4a75-8b19-5e7a2c0f6d83",
      "entity_revision": 1,
      "from_status": "online",
      "to_status": "paused",
      "reason_code": "operator_action",
      "source": "user",
      "occurred_at": "2026-10-27T09:15:42.000Z",
      "recorded_at": "2026-10-27T09:15:42.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null,
  "meta": {
    "baseline": {
      "object": "status_baseline",
      "workspace_id": "3f6a9d21-8b4c-4e7f-a102-5c9e8d7b6a43",
      "campaign_id": "4d8b2f73-6e1a-4c95-b7d0-8a3f5e2c9b14",
      "lead_id": null,
      "entity_kind": "account",
      "entity_id": "1d9f6b28-4c3e-4a75-8b19-5e7a2c0f6d83",
      "entity_revision": 0,
      "status": "online",
      "recorded_at": "2026-10-26T07:30:00.000Z",
      "provenance": "baseline"
    },
    "available_from": "2026-10-26T07:30:00.000Z",
    "history_started_at": "2026-10-26T07:30:00.000Z",
    "retained_from": "2026-10-26T07:30:00.000Z",
    "completeness": {
      "status": "complete",
      "gaps": [],
      "gaps_truncated": false,
      "incomplete_from": null
    },
    "observed_at": "2026-10-27T09:15:42.000Z"
  }
}
```
