{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/akeda-ru/json-schema/akeda-ru-docflow-message-schema.json",
  "title": "DocflowMessage",
  "description": "Пакет документов у оператора — конверт, а не учётный документ Акеды.",
  "x-generated": "2026-11-01",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/akeda-ru-openapi.yaml#/components/schemas/DocflowMessage",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "id",
    "connection",
    "external_id",
    "external_revision",
    "direction",
    "doc_type",
    "doc_subtype",
    "doc_regulation",
    "number",
    "date",
    "amount",
    "currency",
    "counterparty",
    "state_code",
    "state_name",
    "our_org_external_id",
    "created_at",
    "updated_at",
    "connection_name",
    "connection_provider",
    "company_name",
    "attachments_total",
    "signatures_total",
    "actions_due",
    "stage_name",
    "sign_required",
    "notice_sign_required",
    "draft",
    "deleted_reason",
    "viewed",
    "state_category",
    "operator_link",
    "print_form"
  ],
  "properties": {
    "id": {
      "$ref": "#/$defs/UUID"
    },
    "connection": {
      "$ref": "#/$defs/UUID"
    },
    "external_id": {
      "type": "string",
      "description": "Идентификатор пакета у оператора"
    },
    "external_revision": {
      "type": "string",
      "description": "Редакция пакета: оператор меняет содержимое конверта, не меняя его идентификатор"
    },
    "direction": {
      "type": "string",
      "enum": [
        "incoming",
        "outgoing"
      ]
    },
    "doc_type": {
      "type": "string",
      "description": "Слова оператора, а не наша классификация"
    },
    "doc_subtype": {
      "type": "string"
    },
    "doc_regulation": {
      "type": "string"
    },
    "number": {
      "type": "string"
    },
    "date": {
      "type": "string",
      "description": "Календарная дата документа ГГГГ-ММ-ДД; пусто означает, что даты нет вовсе"
    },
    "amount": {
      "type": "string",
      "description": "Сумма строкой ровно так, как её прислал оператор; пусто означает «суммы нет», а не ноль"
    },
    "currency": {
      "type": "string"
    },
    "counterparty": {
      "$ref": "#/$defs/DocflowCounterparty"
    },
    "state_code": {
      "type": "string",
      "description": "Код состояния документооборота у оператора"
    },
    "state_name": {
      "type": "string",
      "description": "Состояние словами оператора: своего перевода состояний у нас нет и быть не должно"
    },
    "our_org_external_id": {
      "type": "string"
    },
    "received_at": {
      "type": "string",
      "format": "date-time"
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time"
    },
    "connection_name": {
      "type": "string"
    },
    "connection_provider": {
      "type": "string"
    },
    "stage_repeat": {
      "type": "boolean",
      "description": "Оператор подключения умеет «Повторить этап» утверждения входящего документа (Saby). У Контур.Диадока такого действия нет"
    },
    "company": {
      "$ref": "#/$defs/UUID"
    },
    "company_name": {
      "type": "string"
    },
    "attachments_total": {
      "type": "integer"
    },
    "signatures_total": {
      "type": "integer"
    },
    "actions_due": {
      "type": "integer",
      "description": "Сколько незакрытых этапов у пакета. Ноль означает «ход не за нами»"
    },
    "stage_name": {
      "type": "string",
      "description": "Название ближайшего незакрытого этапа словами оператора"
    },
    "sign_required": {
      "type": "boolean",
      "description": "У пакета открыт этап, который закрывается нашей подписью под самим документом. Отдельно от actions_due и stage_name: счётчик говорит «ход за нами», а название этапа — слова оператора, и отличить по ним подпись от согласования нельзя. Пока признак поднят, приёмка к учёту отказывает кодом docflow.edo.sign_first"
    },
    "notice_sign_required": {
      "type": "boolean",
      "description": "Открытый подписной этап служебный: извещение о получении, подтверждение даты, квитанция. Отдельным признаком, потому что человеку это другое дело — «Подписать извещение» подтверждает технологию обмена, а не содержание документа. Приёмку к учёту служебный этап НЕ держит"
    },
    "attachments": {
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/$defs/DocflowAttachment"
      },
      "description": "Состав пакета. Наполняется ТОЛЬКО в карточке одного пакета; в списке остаётся null. null означает «не спрашивали», пустой массив — «спросили, и там пусто»"
    },
    "signatures": {
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/$defs/DocflowSignature"
      }
    },
    "stages": {
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/$defs/DocflowStage"
      }
    },
    "events": {
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/$defs/DocflowEvent"
      }
    },
    "flow_documents": {
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/$defs/DocflowMessageFlowLink"
      },
      "description": "Карточки документооборота, которые вёз этот конверт. Как и весь состав, наполняется ТОЛЬКО в карточке одного пакета; в списке остаётся null"
    },
    "cancellation": {
      "oneOf": [
        {
          "$ref": "#/$defs/DocflowCancellation"
        },
        {
          "type": "null"
        }
      ],
      "description": "Соглашение сторон об аннулировании. Наполняется ТОЛЬКО в карточке одного пакета; в списке остаётся null — null означает «не спрашивали»"
    },
    "accounting_document": {
      "oneOf": [
        {
          "$ref": "#/$defs/UUID"
        },
        {
          "type": "null"
        }
      ],
      "description": "Учётный документ, которым пакет принят к учёту. Пусто означает «не принимали» и делает пакет принимаемым; обнулиться поле может и после приёмки, когда учётный документ удалили"
    },
    "accepted_at": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "description": "Когда пакет приняли к учёту. Переживает удаление учётного документа: приёмка была"
    },
    "accepted_by": {
      "type": [
        "integer",
        "null"
      ],
      "format": "int64",
      "description": "Кто принял пакет к учёту"
    },
    "accounting_number": {
      "type": "string",
      "description": "Номер учётного документа приёмки для строки «В учёте: … № …»; пусто — не принят или документ не прочитан"
    },
    "accounting_type": {
      "type": "string",
      "description": "Вид учётного документа приёмки (ключ вида документа ядра), например finance_purchase"
    },
    "draft": {
      "type": "boolean",
      "description": "Пакет записан оператору и наружу ещё не ушёл. Выводится из состава пакета при чтении: исходящий, без единого события обмена и без единой подписи"
    },
    "deleted_at": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "description": "Корзина НАШЕГО зеркала: контрагент её не видит, и пакет у оператора остаётся прежним"
    },
    "deleted_by": {
      "type": [
        "integer",
        "null"
      ],
      "format": "int64"
    },
    "deleted_reason": {
      "type": "string",
      "enum": [
        "",
        "trashed",
        "draft_removed"
      ],
      "description": "Возвращают из корзины только trashed: у draft_removed документа у оператора больше нет"
    },
    "recognized": {
      "$ref": "#/$defs/DocflowRecognized"
    },
    "payment": {
      "oneOf": [
        {
          "$ref": "#/$defs/DocflowMessagePayment"
        },
        {
          "type": "null"
        }
      ],
      "description": "Что стало с оплатой этого счёта. Приходит И В СПИСКЕ, в отличие от состава пакета: состояние оплаты — ровно то, что человек читает глазами в каждой строке. Считает его модуль finance (счета, выписки и расчёты) одним запросом на всю страницу. null означает «этот счёт никто не оплачивает»: ни заведённой заявки, ни платежа, — именно там и остаётся кнопка «Отправить в оплату»."
    },
    "viewed": {
      "type": "boolean",
      "description": "Открывал ли карточку пакета текущий сотрудник — личная отметка, а не состояние у оператора. Считается в ленте одним запросом на страницу; карточка отдаёт false, потому что её открытие само ставит отметку дверью viewed."
    },
    "state_category": {
      "$ref": "#/$defs/DocflowStateCategory"
    },
    "operator_link": {
      "type": "string",
      "description": "Карточка документа в кабинете нашей организации у оператора («СсылкаДляНашаОрганизация»); пусто, пока карточку не перечитали"
    },
    "print_form": {
      "oneOf": [
        {
          "$ref": "#/$defs/DocflowMessagePrintForm"
        },
        {
          "type": "null"
        }
      ],
      "description": "Печатный вид пакета (GET .../print); null — показать нечего"
    }
  },
  "$defs": {
    "DocflowAttachment": {
      "type": "object",
      "additionalProperties": false,
      "description": "Файл внутри пакета. Внутреннего пути в хранилище здесь нет: снаружи файл получают отдельной операцией, а путь не часть контракта и не подсказка для перебора.",
      "required": [
        "id",
        "message",
        "external_id",
        "name",
        "kind",
        "content_type",
        "size_bytes",
        "sha256",
        "stored",
        "created_at"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/UUID"
        },
        "message": {
          "$ref": "#/$defs/UUID"
        },
        "external_id": {
          "type": "string",
          "description": "Идентификатор вложения у оператора"
        },
        "name": {
          "type": "string",
          "description": "Имя файла словами оператора"
        },
        "kind": {
          "type": "string",
          "enum": [
            "",
            "document",
            "title",
            "notice"
          ],
          "description": "Наш словарь, а не оператора: документ, ответный титул, служебное извещение. Пусто означает, что вид неизвестен, и это законно"
        },
        "content_type": {
          "type": "string"
        },
        "size_bytes": {
          "type": "integer",
          "format": "int64"
        },
        "sha256": {
          "type": "string"
        },
        "stored": {
          "type": "boolean",
          "description": "Байты скачаны и лежат у НАС. Ссылка оператора хранилищем не считается: она живёт около месяца, а накладную спрашивают через три года"
        },
        "downloaded_at": {
          "type": "string",
          "format": "date-time"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        }
      }
    },
    "DocflowCancellation": {
      "type": "object",
      "additionalProperties": false,
      "description": "Соглашение сторон об аннулировании документа. Запускает его любая сторона, а решает вторая: согласие даёт состояние 22 «Документ аннулирован», отказ — состояние 40 «Аннулирование отклонено», при котором состояние самого документа НЕ меняется. Шаг цепочки выводится из ленты СОБЫТИЙ пакета, а не из кода состояния: состояние 27 «Ожидает аннулирования» оператор отдаёт только отдельным методом выборки по событиям.",
      "required": [
        "state",
        "state_name",
        "initiator",
        "reason",
        "requested_at",
        "decided_at",
        "available",
        "can_request",
        "can_approve",
        "can_reject"
      ],
      "properties": {
        "state": {
          "type": "string",
          "enum": [
            "none",
            "requested",
            "agreed",
            "refused"
          ],
          "description": "Шаг цепочки: none — её нет; requested — ждём решения; agreed — аннулирован по соглашению; refused — в аннулировании отказано, и документ остался действующим"
        },
        "state_name": {
          "type": "string",
          "description": "Слова ОПЕРАТОРА о состоянии, когда оно относится к аннулированию. Своего перевода состояний у нас нет и быть не должно"
        },
        "initiator": {
          "type": "string",
          "enum": [
            "",
            "us",
            "counterparty"
          ],
          "description": "Кто запустил цепочку. Пусто означает «неизвестно», а не «мы»"
        },
        "reason": {
          "type": "string",
          "description": "Причина словами того, кто её написал. Не переводится"
        },
        "requested_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "decided_at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "available": {
          "type": "boolean",
          "description": "Вид документа вообще допускает аннулирование. У электронной транспортной накладной его нет: там отказ 409 с кодом docflow.edo.cancellation_unavailable"
        },
        "can_request": {
          "type": "boolean",
          "description": "Ход за нами и цепочку можно начать"
        },
        "can_approve": {
          "type": "boolean",
          "description": "Соглашение прислали нам и на него можно согласиться"
        },
        "can_reject": {
          "type": "boolean",
          "description": "Соглашение прислали нам и в нём можно отказать"
        }
      }
    },
    "DocflowCertificate": {
      "type": "object",
      "additionalProperties": false,
      "description": "Сертификат, которым подпись доказывают спустя годы: имя подписанта меняется, отпечаток нет.",
      "required": [
        "thumbprint",
        "subject"
      ],
      "properties": {
        "thumbprint": {
          "type": "string"
        },
        "subject": {
          "type": "string"
        },
        "valid_from": {
          "type": "string",
          "format": "date-time"
        },
        "valid_to": {
          "type": "string",
          "format": "date-time"
        }
      }
    },
    "DocflowCounterparty": {
      "type": "object",
      "additionalProperties": false,
      "description": "Вторая сторона обмена. Реквизиты хранятся текстом всегда, даже когда сопоставление с нашим контрагентом состоялось: карточку могут удалить или переименовать, а пакет обязан остаться читаемым спустя годы.",
      "required": [
        "name",
        "inn",
        "kpp",
        "external_id",
        "contact_name"
      ],
      "properties": {
        "name": {
          "type": "string"
        },
        "inn": {
          "type": "string"
        },
        "kpp": {
          "type": "string"
        },
        "external_id": {
          "type": "string",
          "description": "Идентификатор участника обмена у оператора: надёжнее ИНН, потому что у одного ИНН бывает несколько ящиков"
        },
        "contact": {
          "$ref": "#/$defs/UUID"
        },
        "contact_name": {
          "type": "string",
          "description": "Наш контрагент, если сопоставление состоялось. Это наша догадка по ИНН либо выбор человека, а не факт от оператора"
        }
      }
    },
    "DocflowEvent": {
      "type": "object",
      "additionalProperties": false,
      "description": "Событие ленты пакета. Лента — то, по чему человек восстанавливает ход спора с контрагентом, поэтому название и комментарий хранятся словами оператора и не переводятся.",
      "required": [
        "id",
        "message",
        "external_id",
        "name",
        "comment",
        "created_at"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/UUID"
        },
        "message": {
          "$ref": "#/$defs/UUID"
        },
        "external_id": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "comment": {
          "type": "string"
        },
        "occurred_at": {
          "type": "string",
          "format": "date-time"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        }
      }
    },
    "DocflowFlowKind": {
      "type": "string",
      "description": "Вид документа внутреннего контура. Вид называет бумагу, а не учётную операцию: продажу и закупку из бумаги делают отдельные команды. Внутренние виды memo (служебная записка), decree (приказ), directive (распоряжение) и minutes (протокол) всегда имеют направление internal и живут без контрагента.",
      "enum": [
        "contract",
        "specification",
        "amendment",
        "invoice",
        "act",
        "upd",
        "goods_waybill",
        "transport_waybill",
        "consignment_note",
        "transport_order",
        "tax_invoice",
        "correction",
        "return",
        "discrepancy_act",
        "reconciliation_act",
        "power_of_attorney",
        "letter",
        "memo",
        "decree",
        "directive",
        "minutes",
        "other"
      ]
    },
    "DocflowMessageFlowLink": {
      "type": "object",
      "additionalProperties": false,
      "description": "Карточка документооборота в пакете — обратная сторона связи edo_links карточки. Пакет доказывает отправку и подпись, а содержание живёт в карточке; здесь видно, чьё содержание он вёз и чем карточка ему приходится.",
      "required": [
        "id",
        "document",
        "role",
        "version",
        "kind",
        "status",
        "title",
        "number",
        "date",
        "created_at"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/UUID"
        },
        "document": {
          "$ref": "#/$defs/UUID"
        },
        "role": {
          "type": "string",
          "enum": [
            "primary",
            "attachment",
            "basis"
          ],
          "description": "Чем карточка приходится конверту: основной документ, приложение или основание"
        },
        "version": {
          "type": "integer",
          "minimum": 1,
          "description": "Текущая редакция карточки: открывать человеку следует её"
        },
        "kind": {
          "$ref": "#/$defs/DocflowFlowKind"
        },
        "status": {
          "type": "string",
          "enum": [
            "draft",
            "registered",
            "archived"
          ]
        },
        "title": {
          "type": "string"
        },
        "number": {
          "type": "string"
        },
        "date": {
          "type": "string",
          "format": "date"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "external_attachment_id": {
          "type": "string",
          "description": "Файл пакета, по которому заведена карточка (ERP-2063): идентификатор вложения у оператора (external_id), а без него — «id:» и id вложения. У пакета «ДС + счёт» своя карточка у каждого файла. Нет у карточки на весь пакет — так заводила приёмка до разбора по файлам"
        }
      }
    },
    "DocflowMessagePayment": {
      "type": "object",
      "additionalProperties": false,
      "description": "Состояние оплаты входящего счёта. Два состояния, а не шесть: путь заявки внутри финансов подробнее (план, отправлена, ждёт подписи, исполнена, отклонена, отменена), но ленте нужен ответ на один вопрос — деньги уже ушли или ещё нет. Оплаченным платёж делает ВЫПИСКА, а не наша кнопка и не слово банка: «отправлено в банк» означает лишь, что платёжка легла в интернет-банк на подпись.",
      "required": [
        "state",
        "request"
      ],
      "properties": {
        "state": {
          "type": "string",
          "enum": [
            "requested",
            "paid"
          ],
          "description": "requested — заявка заведена, денег ещё нет; paid — платёж подтверждён выпиской"
        },
        "request": {
          "$ref": "#/$defs/UUID"
        },
        "number": {
          "type": "string",
          "description": "Номер заявки на оплату словами для человека"
        },
        "paid_on": {
          "type": "string",
          "description": "Дата оплаты из выписки в форме ГГГГ-ММ-ДД. Заполнена только у state=paid"
        },
        "step": {
          "type": "string",
          "enum": [
            "draft",
            "on_approval",
            "rework",
            "approved",
            "scheduled",
            "sent",
            "exported",
            "partially_paid",
            "paid",
            "payment_cancelled"
          ],
          "description": "Шаг заявки словарём хода заявки «Документов»: до согласования — состояние документа заявки, после — строка очереди финансов; exported — выгружена в файл"
        },
        "docflow_request": {
          "allOf": [
            {
              "$ref": "#/$defs/UUID"
            }
          ],
          "description": "Заявка «Документов» по этому счёту, если она есть"
        },
        "order": {
          "allOf": [
            {
              "$ref": "#/$defs/UUID"
            }
          ],
          "description": "Счёт оплачен своей закупкой: заявки нет (request нулевой), оплата закупки покрывает сумму счёта"
        }
      }
    },
    "DocflowMessagePrintForm": {
      "type": "object",
      "additionalProperties": false,
      "description": "Печатный вид пакета. operator — PDF оператора с впечатанными подписями, лежащий у нас; ours — наша форма счёта или УПД по формализованному XML, когда оператор своего вида не отдал (штампа подписи оператора на ней нет).",
      "required": [
        "source",
        "size",
        "revision",
        "fetched_at"
      ],
      "properties": {
        "source": {
          "type": "string",
          "enum": [
            "operator",
            "ours"
          ]
        },
        "size": {
          "type": "integer",
          "format": "int64"
        },
        "revision": {
          "type": "string",
          "description": "Редакция пакета, с которой снят PDF оператора"
        },
        "fetched_at": {
          "type": "string",
          "format": "date-time"
        }
      }
    },
    "DocflowRecognized": {
      "type": "object",
      "additionalProperties": false,
      "description": "Сумма и реквизиты, прочитанные ИЗ ФАЙЛА пакета, а не присланные оператором. Оператор присылает сумму отдельным реквизитом только у формализованных документов — УПД и счёта-фактуры; у счёта на оплату и договора она живёт внутри PDF. Поле стоит РЯДОМ с amount, а не вместо него: amount — слова оператора, по ним сверяют переписку спустя годы, и подменять их нашим чтением чужой бумаги нельзя. Разбор локальный и детерминированный: текстовый слой PDF, у скана — распознавание изображения; ни одной нейросети и ни одного обращения к платному справочнику. Строк товарной таблицы здесь нет: со скана они не восстанавливаются и фактом не выдаются.",
      "required": [
        "source",
        "document",
        "amount",
        "currency",
        "number",
        "date"
      ],
      "properties": {
        "at": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time",
          "description": "Когда разбирали. Пусто — попытки ещё не было; это не то же самое, что source=none («читали и брать оказалось нечего»)"
        },
        "source": {
          "type": "string",
          "enum": [
            "",
            "title",
            "text",
            "none"
          ],
          "description": "Чем прочитано, и заодно насколько верить. title — подписанный файл обмена ФНС, проверять нечего; text — вытащено якорными правилами из чужой раскладки, и рядом со значением интерфейс ставит «проверьте»; none — читали и брать было нечего; пустая строка — разбора не было"
        },
        "document": {
          "type": "string",
          "description": "Имя вложения СЛОВАМИ ОПЕРАТОРА: по нему человек откроет ту же бумагу и сверит показанную цифру"
        },
        "amount": {
          "type": "string",
          "description": "Итог к оплате строкой, как и amount: через число с плавающей точкой здесь теряются копейки. Пустая строка — итог в бумаге не нашёлся"
        },
        "currency": {
          "type": "string",
          "description": "Валюта счёта, если бумага её назвала. Пусто означает «не сказано»: подставлять рубль молча нельзя"
        },
        "number": {
          "type": "string"
        },
        "date": {
          "type": "string",
          "description": "Дата документа в форме ГГГГ-ММ-ДД; пустая строка означает, что даты нет"
        }
      }
    },
    "DocflowSignature": {
      "type": "object",
      "additionalProperties": false,
      "description": "Подпись под вложением или под пакетом целиком. Подписей под одним файлом несколько — наша и контрагента, — и каждая приходит своим файлом со своим сертификатом.",
      "required": [
        "id",
        "message",
        "side",
        "signer_name",
        "signer_position",
        "certificate",
        "poa_number",
        "stored",
        "created_at"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/UUID"
        },
        "message": {
          "$ref": "#/$defs/UUID"
        },
        "attachment": {
          "$ref": "#/$defs/UUID"
        },
        "side": {
          "type": "string",
          "enum": [
            "ours",
            "counterparty"
          ]
        },
        "signer_name": {
          "type": "string"
        },
        "signer_position": {
          "type": "string"
        },
        "certificate": {
          "$ref": "#/$defs/DocflowCertificate"
        },
        "poa_number": {
          "type": "string",
          "description": "Номер машиночитаемой доверенности. С 2023 года подпись сотрудника без неё недействительна"
        },
        "signed_at": {
          "type": "string",
          "format": "date-time"
        },
        "stored": {
          "type": "boolean",
          "description": "Контейнер подписи скачан к нам и открывается отдельной операцией"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        }
      }
    },
    "DocflowStage": {
      "type": "object",
      "additionalProperties": false,
      "description": "Этап документооборота: что с пакетом можно сделать сейчас. Список действий приходит от ОПЕРАТОРА и не выводится из нашего состояния.",
      "required": [
        "id",
        "message",
        "external_id",
        "name",
        "actions",
        "requires_signature",
        "closed",
        "service",
        "started_at",
        "created_at",
        "updated_at"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/UUID"
        },
        "message": {
          "$ref": "#/$defs/UUID"
        },
        "external_id": {
          "type": "string",
          "description": "Идентификатор этапа у оператора; он же адресует действие"
        },
        "name": {
          "type": "string"
        },
        "actions": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/DocflowStageAction"
          }
        },
        "requires_signature": {
          "type": "boolean",
          "description": "Этап закрывается подписью. Признак оператора, а не наш вывод из названия"
        },
        "closed": {
          "type": "boolean",
          "description": "Ход не за нами. Закрытые этапы не показываются и не считаются"
        },
        "service": {
          "type": "boolean",
          "description": "Служебный этап оператора — извещение о получении, подтверждение, квитанция. Технология обмена, а не решение по документу: клиент обрабатывает все служебные этапы пакета одним действием, а не по кнопке на каждый"
        },
        "started_at": {
          "type": "string",
          "format": "date-time",
          "description": "С какого момента этап ждёт человека: дата этапа у оператора, без неё — когда зеркало увидело его открытым; открытый снова этап считается заново"
        },
        "created_at": {
          "type": "string",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time"
        }
      }
    },
    "DocflowStageAction": {
      "type": "object",
      "additionalProperties": false,
      "description": "Действие, которое оператор разрешает на этапе. Код отправляют оператору, надпись показывают человеку.",
      "required": [
        "code",
        "name"
      ],
      "properties": {
        "code": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "requires_signature": {
          "type": "boolean",
          "description": "Действие закрывается подписью («ТребуетПодписания» оператора). Точнее признака этапа: на этапе «Утверждение» подписи требует «Утвердить», а «Переназначить» — нет. У этапов, записанных до появления признака, false у всех действий — тогда судят по requires_signature этапа"
        }
      }
    },
    "DocflowStateCategory": {
      "type": "string",
      "enum": [
        "in_work",
        "awaiting_signature",
        "cancellation_requested",
        "cancellation_refused",
        "draft",
        "error",
        "signer_invalid",
        "approved",
        "rejected",
        "cancelled",
        "interrupted"
      ],
      "description": "Состояние пакета нашими словами поверх кода оператора (справочник «Код состояния документа»): в работе, ждёт подписи, запрос на аннулирование, отказ в аннулировании, черновик, с ошибкой, подписант не прошёл проверку, утверждён, отклонён, аннулирован, прервано. Слово оператора остаётся в state_name."
    },
    "UUID": {
      "type": "string",
      "format": "uuid"
    }
  }
}