> ## Documentation Index
> Fetch the complete documentation index at: https://platform.doodocs.kz/llms.txt
> Use this file to discover all available pages before exploring further.

# Согласовать документ как участник

> Поймать событие, найти свой слот и согласовать, отклонить или вернуть на доработку

Интегратор не всегда создаёт документы — часто он действует на стороне
согласующего: система на вашей стороне решает, согласовать приказ или вернуть
его на доработку, и должна сделать это через API.

Всё ниже требует области `documents:write`, а чтение документа — `documents:read`.

<Warning>
  Документ, доступный вам только через участие в маршруте, **не появляется** в
  `GET /documents`: реестр перечисляет документы по инициатору и по правам. Поэтому
  единственный надёжный вход в этот сценарий — события. Подробнее в
  [Списке документов](/ru/guides/documents/list).
</Warning>

<Steps>
  <Step title="Подпишитесь на события согласования">
    ```bash theme={null}
    curl -X POST -H "X-API-Key: $DOODOCS_API_KEY" -H "Content-Type: application/json" \
      https://app.doodocs.kz/api/developer/v1/webhook_endpoints \
      -d '{
        "url": "https://ваш-сервер/hooks/doodocs",
        "event_types": ["document.approval_started", "document.change_requested", "document.completed"]
      }'
    ```

    Событие приносит `{"document_id": "…"}` — этого достаточно, чтобы прочитать
    документ своим ключом.
  </Step>

  <Step title="Прочитайте документ вместе с маршрутом">
    ```bash theme={null}
    curl -H "X-API-Key: $DOODOCS_API_KEY" \
      https://app.doodocs.kz/api/developer/v1/documents/8c2d5a91-…
    ```

    ```json theme={null}
    {
      "document": {
        "id": "8c2d5a91-…",
        "status": "DOCUMENT_STATUS_ON_APPROVAL",
        "route": {
          "is_active": true,
          "steps": [
            {
              "id": "st_1…",
              "index": 0,
              "step_type": "STEP_TYPE_APPROVAL",
              "rule": "STEP_RULE_ALL",
              "status": "STEP_STATUS_ACTIVE",
              "participants": [
                {
                  "id": "pt_9f…",
                  "employee_id": "3f2a9c7e-…",
                  "status": "PARTICIPANT_STATUS_ACTIVE"
                }
              ]
            }
          ]
        }
      }
    }
    ```
  </Step>

  <Step title="Найдите свой слот">
    Нужен участник, у которого `employee_id` совпадает с карточкой владельца
    ключа, а `status` равен `PARTICIPANT_STATUS_ACTIVE`. Именно его `id`
    передаётся в действие.

    ```python theme={null}
    def my_active_slot(document: dict, my_employee_id: str) -> str | None:
        for step in document["route"]["steps"]:
            if step["status"] != "STEP_STATUS_ACTIVE":
                continue
            for p in step["participants"]:
                if p["employee_id"] == my_employee_id and p["status"] == "PARTICIPANT_STATUS_ACTIVE":
                    return p["id"]
        return None
    ```

    <Note>
      Эндпоинта «кто я» в Developer API нет. Сохраните `employee_id` владельца
      ключа в конфигурации интеграции — он не меняется, пока владелец работает в
      той же организации.
    </Note>
  </Step>

  <Step title="Выполните действие">
    ```bash theme={null}
    curl -X POST -H "X-API-Key: $DOODOCS_API_KEY" -H "Content-Type: application/json" \
      https://app.doodocs.kz/api/developer/v1/documents/8c2d5a91-…/_approve \
      -d '{ "participant_id": "pt_9f…", "comment": "Согласовано" }'
    ```

    | Действие             | Эндпоинт           | Комментарий    | Результат                          |
    | -------------------- | ------------------ | -------------- | ---------------------------------- |
    | Согласовать          | `_approve`         | не обязателен  | шаг движется дальше                |
    | Отклонить            | `_reject`          | **обязателен** | `DOCUMENT_STATUS_REJECTED`         |
    | Вернуть на доработку | `_request_changes` | **обязателен** | `DOCUMENT_STATUS_CHANGE_REQUESTED` |
  </Step>
</Steps>

## Правила прохождения шага

`rule` определяет, когда шаг закрывается:

* `STEP_RULE_ALL` — нужны действия всех участников шага;
* `STEP_RULE_ANY_ONE` — достаточно одного, остальные слоты получат
  `PARTICIPANT_STATUS_SKIPPED`.

Поэтому не считайте, что ваше согласование завершит шаг: после ответа перечитайте
документ либо дождитесь `document.signing_started` или `document.completed`.

## Ошибки, которые стоит обработать

| Ситуация                              | Что вернётся                         |
| ------------------------------------- | ------------------------------------ |
| Слот уже отработал или шаг не активен | `400`, ошибка состояния документа    |
| Передан чужой `participant_id`        | `404` `DOCUMENT_NOT_FOUND`           |
| Документ недоступен ключу             | `404` `DOCUMENT_NOT_FOUND`           |
| Нет области `documents:write`         | `403` `DEVELOPER.SCOPE_INSUFFICIENT` |

Повторный `_approve` на отработавшем слоте безопасен: он не создаёт второго
согласования, а возвращает ошибку состояния.

## Дальше

<Columns cols={2}>
  <Card title="События документов" icon="bolt" href="/ru/guides/documents/events">
    Полный список событий и что делать по каждому.
  </Card>

  <Card title="Подписание" icon="pen" href="/ru/guides/documents/signing">
    Если ваш слот — подписывающий, а не согласующий.
  </Card>
</Columns>
