{
  "openapi": "3.1.0",
  "info": {
    "title": "Dialogi API",
    "description": "Публичный API Dialogi. Каждый запрос подписывается секретным ключом компании `dk_live_…` в заголовке `Authorization: Bearer`, см. [Ключи и права](/developers/authentication). Ответы и ошибки - JSON, время - ISO 8601 в UTC, телефоны - E.164, см. [Формат данных](/developers/conventions).",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://api.ru.dialogi.io/v1",
      "description": "Россия"
    }
  ],
  "tags": [
    {
      "name": "Contacts",
      "description": "Контакты - карточки клиентов в CRM. Через API контакты можно искать по email и телефону, создавать и менять. Контакт принадлежит проекту: ключ видит контакты только своих проектов."
    },
    {
      "name": "Conversations",
      "description": "Диалоги с клиентами из чата на сайте, мессенджеров и почты - те же, что в инбоксе личного кабинета. Через API можно читать диалоги и сообщения, отвечать клиенту и закрывать диалог. Диалог принадлежит проекту: ключ видит диалоги только своих проектов."
    },
    {
      "name": "Messages",
      "description": "Сообщения диалога: чтение переписки и ответ клиенту."
    },
    {
      "name": "Leads",
      "description": "Заявки на обратный звонок - как с виджета Перезвони на сайте. Через API можно заказать звонок клиенту и следить, чем он закончился. Заявка принадлежит проекту: ключ видит заявки только своих проектов."
    },
    {
      "name": "Appointments",
      "description": "Записи клиентов на услуги - те же, что в разделе «Запись» личного кабинета. Через API можно найти свободное время, записать клиента, перенести и отменить запись. Услуги, исполнители и филиалы для записи - в справочнике ниже. Запись принадлежит проекту: ключ видит записи только своих проектов."
    },
    {
      "name": "Slots",
      "description": "Свободное время для записи."
    },
    {
      "name": "Services",
      "description": "Справочник для записи: активные услуги."
    },
    {
      "name": "Resources",
      "description": "Справочник для записи: исполнители и ресурсы филиалов."
    },
    {
      "name": "Branches",
      "description": "Справочник для записи: филиалы."
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/contacts": {
      "get": {
        "operationId": "contacts.list",
        "description": "Контакты проектов ключа, от новых к старым, по страницам. Фильтры можно сочетать: `email` и `phone` находят контакт по основному email и телефону.",
        "summary": "Список контактов",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Сколько контактов на странице, от 1 до 100.",
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "default": 20,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "starting_after",
            "in": "query",
            "description": "id последнего контакта предыдущей страницы: страница начнётся после него. См. [Пагинация](/developers/pagination).",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Только контакты этого проекта. Проекта нет в ключе - ошибка `403`.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "email",
            "in": "query",
            "description": "Контакты с таким основным email, точное совпадение.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 255
            },
            "example": "anna@example.com"
          },
          {
            "name": "phone",
            "in": "query",
            "description": "Контакты с таким основным телефоном. Номер в другой записи API приведёт к E.164.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 32
            },
            "example": "+79101234567"
          },
          {
            "name": "lifecycle",
            "in": "query",
            "description": "Контакты на этом этапе.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "enum": [
                "lead",
                "mql",
                "sql",
                "customer",
                "churned",
                null
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Страница списка контактов.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactList"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "contacts:read"
        ]
      },
      "post": {
        "operationId": "contacts.create",
        "description": "Создаёт контакт в проекте. Ключ с одним проектом подставит его сам, с несколькими - передайте `project_id`.\n\nОтветственного назначат правила распределения CRM, как у контакта из других источников. Если ни одно правило не сработало, контакт остаётся без ответственного. Правило может поменять и этап, если `lifecycle` не передан или равен `lead`: в ответе - этап, который сохранился.\n\nКаждый запрос создаёт новый контакт, даже с тем же телефоном или email. Чтобы не завести дубль, сначала поищите контакт в списке по `phone` или `email`.",
        "summary": "Создать контакт",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Ключ идемпотентности, обязателен. Повтор с тем же ключом и тем же телом вернёт ответ первого запроса и не выполнит действие второй раз. Вместо него можно передать `X-Idempotency-Key`. См. [Идемпотентность](/developers/idempotency).",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "pattern": "^[A-Za-z0-9_\\-:.]{1,64}$"
            },
            "example": "order-20195208"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "project_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uuid",
                    "description": "Проект контакта. Обязателен, если в ключе несколько проектов."
                  },
                  "type": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "`person` - человек, `b2b_company` - компания.",
                    "enum": [
                      "person",
                      "b2b_company",
                      null
                    ],
                    "default": "person"
                  },
                  "name": {
                    "type": "string",
                    "description": "Имя, как его показывать в личном кабинете.",
                    "examples": [
                      "Анна Смирнова"
                    ],
                    "maxLength": 255
                  },
                  "first_name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Имя.",
                    "maxLength": 128
                  },
                  "last_name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Фамилия.",
                    "maxLength": 128
                  },
                  "email": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "email",
                    "description": "Основной email.",
                    "maxLength": 255
                  },
                  "phone": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Основной телефон, лучше в E.164. Номер в другой записи API приведёт к E.164.",
                    "examples": [
                      "+79101234567"
                    ],
                    "maxLength": 32
                  },
                  "position": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Должность.",
                    "maxLength": 128
                  },
                  "lifecycle": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Этап клиента. Если этап не передан или равен `lead`, его может поменять правило распределения CRM.",
                    "enum": [
                      "lead",
                      "mql",
                      "sql",
                      "customer",
                      "churned",
                      null
                    ],
                    "default": "lead"
                  },
                  "metadata": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "description": "Ваши данные: плоский объект до 50 ключей, ключ - до 40 символов и не число (`10042` или `-5` не подойдут), значение - строка до 500 символов, число, `true`/`false` или `null`. Пробелы по краям строки API убирает, пустая строка сохраняется как `null`. См. [Формат данных](/developers/conventions#metadata).",
                    "additionalProperties": {
                      "type": [
                        "string",
                        "number",
                        "boolean",
                        "null"
                      ]
                    }
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Созданный контакт.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              },
              "Idempotent-Replayed": {
                "description": "`true`, если это повтор запроса с тем же `Idempotency-Key`: ответ первого запроса, действие не выполнено второй раз.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/IdempotencyKeyRequired"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "contacts:write"
        ],
        "x-idempotency": "required"
      }
    },
    "/contacts/{contact}": {
      "get": {
        "operationId": "contacts.get",
        "description": "Контакт по id. Контакт из проекта, которого нет в ключе, для ключа не существует - ответ `404`.",
        "summary": "Получить контакт",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "contact",
            "in": "path",
            "required": true,
            "description": "id контакта.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Контакт.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "contacts:read"
        ]
      },
      "patch": {
        "operationId": "contacts.update",
        "description": "Меняет только переданные поля. `null` очищает необязательное поле.",
        "summary": "Изменить контакт",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "contact",
            "in": "path",
            "required": true,
            "description": "id контакта.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Имя, как его показывать в личном кабинете.",
                    "maxLength": 255
                  },
                  "first_name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Имя.",
                    "maxLength": 128
                  },
                  "last_name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Фамилия.",
                    "maxLength": 128
                  },
                  "email": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "email",
                    "description": "Основной email.",
                    "maxLength": 255
                  },
                  "phone": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Основной телефон, лучше в E.164. Номер в другой записи API приведёт к E.164.",
                    "maxLength": 32
                  },
                  "position": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Должность.",
                    "maxLength": 128
                  },
                  "lifecycle": {
                    "type": "string",
                    "description": "Этап клиента.",
                    "enum": [
                      "lead",
                      "mql",
                      "sql",
                      "customer",
                      "churned"
                    ]
                  },
                  "status": {
                    "type": "string",
                    "description": "`active` - рабочий контакт, `archived` - в архиве.",
                    "enum": [
                      "active",
                      "archived"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Контакт после изменения.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "contacts:write"
        ]
      }
    },
    "/conversations": {
      "get": {
        "operationId": "conversations.list",
        "description": "Диалоги проектов ключа, от новых к старым, по страницам. Фильтры можно сочетать.",
        "summary": "Список диалогов",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Сколько объектов на странице, от 1 до 100.",
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "default": 20,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "starting_after",
            "in": "query",
            "description": "id последнего объекта предыдущей страницы: страница начнётся после него. См. [Пагинация](/developers/pagination).",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Только объекты этого проекта. Проекта нет в ключе - ошибка `403`.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Только диалоги в этих статусах, через запятую. Значения - как у поля `status` диалога.",
            "schema": {
              "type": [
                "string",
                "null"
              ]
            },
            "example": "open,snoozed"
          },
          {
            "name": "channel",
            "in": "query",
            "description": "Только диалоги этих каналов, через запятую. Значения - как у поля `channel` диалога.",
            "schema": {
              "type": [
                "string",
                "null"
              ]
            },
            "example": "telegram,vk"
          },
          {
            "name": "created[gte]",
            "in": "query",
            "description": "Диалоги, созданные не раньше этого времени. Время с часовым поясом (RFC 3339).",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            },
            "example": "2026-09-01T00:00:00+03:00"
          },
          {
            "name": "created[lte]",
            "in": "query",
            "description": "Диалоги, созданные не позже этого времени. Время с часовым поясом (RFC 3339).",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Страница списка диалогов.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationList"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "conversations:read"
        ]
      }
    },
    "/conversations/{conversation}": {
      "get": {
        "operationId": "conversations.get",
        "description": "Диалог по id. Диалог из проекта, которого нет в ключе, для ключа не существует - ответ `404`.",
        "summary": "Получить диалог",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "conversation",
            "in": "path",
            "required": true,
            "description": "id диалога.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Диалог.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "conversations:read"
        ]
      }
    },
    "/conversations/{conversation}/close": {
      "post": {
        "operationId": "conversations.close",
        "description": "Закрывает диалог так же, как кнопка «Закрыть» у сотрудника в инбоксе личного кабинета. Повторное закрытие уже закрытого диалога - не ошибка: ответ `200` с тем же диалогом, причина не меняется.",
        "summary": "Закрыть диалог",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "conversation",
            "in": "path",
            "required": true,
            "description": "id диалога.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Ключ идемпотентности, по желанию. Повтор с тем же ключом и тем же телом вернёт ответ первого запроса и не выполнит действие второй раз. Вместо него можно передать `X-Idempotency-Key`. См. [Идемпотентность](/developers/idempotency).",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "pattern": "^[A-Za-z0-9_\\-:.]{1,64}$"
            },
            "example": "order-20195208"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Причина закрытия - как у поля `closed_reason` диалога.",
                    "enum": [
                      "resolved",
                      "abandoned",
                      "duplicate",
                      "spam",
                      "wrong_channel",
                      null
                    ],
                    "default": "resolved"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Закрытый диалог.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              },
              "Idempotent-Replayed": {
                "description": "`true`, если это повтор запроса с тем же `Idempotency-Key`: ответ первого запроса, действие не выполнено второй раз.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/IdempotencyKeyInvalid"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "conversations:write"
        ],
        "x-idempotency": "optional"
      }
    },
    "/conversations/{conversation}/messages": {
      "get": {
        "operationId": "messages.list",
        "description": "Сообщения диалога от новых к старым, по страницам. Только переписка с клиентом, без внутренних заметок команды.",
        "summary": "Список сообщений",
        "tags": [
          "Messages"
        ],
        "parameters": [
          {
            "name": "conversation",
            "in": "path",
            "required": true,
            "description": "id диалога.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Сколько объектов на странице, от 1 до 100.",
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "default": 20,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "starting_after",
            "in": "query",
            "description": "id последнего объекта предыдущей страницы: страница начнётся после него. См. [Пагинация](/developers/pagination).",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Не влияет на список: сообщения берутся из диалога, id которого в пути.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Страница сообщений диалога.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageList"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "conversations:read"
        ]
      },
      "post": {
        "operationId": "messages.create",
        "description": "Отправляет клиенту текст в канал диалога. Сообщение уходит как ответ сотрудника: в чате на сайте клиент увидит название ключа API как имя оператора, а ИИ-ассистент после такого ответа на время перестаёт отвечать в диалоге - так же, как после ответа сотрудника.\n\nТолько текст: вложения через API не отправляются, запрос с непустым полем `attachments` - ошибка `422`. Длина - по каналу: Telegram и VK - до 4096 символов, MAX - до 4000, чат на сайте и почта - до 8000. Закрытый диалог API заново не открывает, а в канал `image` писать нельзя - в обоих случаях ошибка `409`.\n\nЕсли канал не принял сообщение, ответ всё равно `201`: сообщение сохранено со статусом `failed`, причина - в `failure.code`. Повтор с тем же `Idempotency-Key` вернёт это же сообщение со статусом `failed` - чтобы отправить его ещё раз, передайте новый ключ.\n\n`Idempotency-Key` обязателен: повтор запроса без него отправил бы клиенту сообщение второй раз. Повтор в тот же диалог с тем же ключом и тем же телом вернёт то же сообщение и не отправит его снова - и спустя сутки тоже. Ключ закреплён за диалогом: тот же ключ в запросе к другому диалогу в первые 24 часа - ошибка `409`, а позже отправит новое сообщение. Для каждого сообщения берите свой ключ.",
        "summary": "Отправить сообщение",
        "tags": [
          "Messages"
        ],
        "parameters": [
          {
            "name": "conversation",
            "in": "path",
            "required": true,
            "description": "id диалога.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Ключ идемпотентности, обязателен. Повтор с тем же ключом и тем же телом вернёт ответ первого запроса и не выполнит действие второй раз. Вместо него можно передать `X-Idempotency-Key`. См. [Идемпотентность](/developers/idempotency).",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "pattern": "^[A-Za-z0-9_\\-:.]{1,64}$"
            },
            "example": "order-20195208"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "type": "string",
                    "description": "Текст сообщения. Длина - по каналу диалога: Telegram и VK - до 4096 символов, MAX - до 4000, чат на сайте и почта - до 8000.",
                    "examples": [
                      "Здравствуйте! Заказ 20195208 передан в доставку."
                    ]
                  }
                },
                "required": [
                  "text"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Сообщение сохранено и отправлено в канал - или не доставлено, тогда status = failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              },
              "Idempotent-Replayed": {
                "description": "`true`, если это повтор запроса с тем же `Idempotency-Key`: ответ первого запроса, действие не выполнено второй раз.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/IdempotencyKeyRequired"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Idempotency-Key уже использован с другим запросом (idempotency-conflict) или первый запрос с ним ещё выполняется (idempotency-in-progress). Диалог закрыт (conversation-closed), диалог в чате на сайте завершён (conversation-archived), в этот канал API не пишет (channel-not-supported) или канал отключён в личном кабинете (channel-disconnected).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "conversations:write"
        ],
        "x-idempotency": "required"
      }
    },
    "/leads": {
      "get": {
        "operationId": "leads.list",
        "description": "Заявки проектов ключа - с виджета и через API, от новых к старым, по страницам. Фильтры можно сочетать.",
        "summary": "Список заявок",
        "tags": [
          "Leads"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Сколько заявок на странице, от 1 до 100.",
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "default": 20,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "starting_after",
            "in": "query",
            "description": "id последней заявки предыдущей страницы: страница начнётся после неё. См. [Пагинация](/developers/pagination).",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Только заявки этого проекта. Проекта нет в ключе - ошибка `403`.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Только заявки в этих статусах, через запятую. Значения - как у поля `status` заявки.",
            "schema": {
              "type": [
                "string",
                "null"
              ]
            },
            "example": "missed,completed"
          },
          {
            "name": "phone",
            "in": "query",
            "description": "Заявки с этим телефоном клиента. Номер в другой записи API приведёт к E.164.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 32
            },
            "example": "+79991234567"
          },
          {
            "name": "source",
            "in": "query",
            "description": "`widget` - заявки с виджета, `api` - через API.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "enum": [
                "widget",
                "api",
                null
              ]
            }
          },
          {
            "name": "created[gte]",
            "in": "query",
            "description": "Заявки, созданные не раньше этого времени. Время с часовым поясом (RFC 3339).",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            },
            "example": "2026-09-01T00:00:00+03:00"
          },
          {
            "name": "created[lte]",
            "in": "query",
            "description": "Заявки, созданные не позже этого времени. Время с часовым поясом (RFC 3339).",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Страница списка заявок.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeadList"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "leads:read"
        ]
      },
      "post": {
        "operationId": "leads.create",
        "description": "Заявка через API - такой же звонок клиенту, как заявка с виджета на сайте: звонят сотрудники отдела или ИИ-ассистент - как настроен Перезвони в проекте. Тарифицируется заявка так же, как с виджета.\n\nПроверка строже, чем у виджета: отдел не из проекта, причина звонка не из списка отдела, время звонка в прошлом - ошибка `422`, а не тихая замена.\n\nЕсли по этому номеру уже есть заявка в работе, созданная в последнюю минуту, второй звонок не заказывается: ответ `200` с этой заявкой. Вне рабочего времени отдела звонок может быть перенесён на ближайшее рабочее время - тогда у заявки статус `scheduled` и время в `scheduled_at`.\n\n`Idempotency-Key` обязателен: повтор запроса без него заказал бы клиенту второй звонок.",
        "summary": "Создать заявку на звонок",
        "tags": [
          "Leads"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Ключ идемпотентности, обязателен. Повтор с тем же ключом и тем же телом вернёт ответ первого запроса и не выполнит действие второй раз. Вместо него можно передать `X-Idempotency-Key`. См. [Идемпотентность](/developers/idempotency).",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "pattern": "^[A-Za-z0-9_\\-:.]{1,64}$"
            },
            "example": "order-20195208"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "project_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uuid",
                    "description": "Проект заявки. Обязателен, если в ключе несколько проектов."
                  },
                  "phone": {
                    "type": "string",
                    "description": "Телефон клиента, на него позвоним. Лучше в E.164; номер в другой записи API приведёт к E.164.",
                    "examples": [
                      "+79991234567"
                    ],
                    "maxLength": 32
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Имя клиента.",
                    "examples": [
                      "Иван"
                    ],
                    "maxLength": 255
                  },
                  "department_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uuid",
                    "description": "Отдел, сотрудникам которого звонить. Должен быть отделом с настройками Перезвони в этом проекте. Без него - отдел, настроенный первым."
                  },
                  "scheduled_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "Позвонить в это время, а не сразу. Время с часовым поясом (RFC 3339), в будущем и не дальше 14 дней."
                  },
                  "qualifier": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Причина звонка - одна из причин, настроенных у отдела.",
                    "maxLength": 255
                  },
                  "source_url": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uri",
                    "description": "Страница, с которой пришёл клиент, `http` или `https`.",
                    "maxLength": 1024
                  },
                  "utm": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "description": "UTM-метки: `utm_source`, `utm_medium`, `utm_campaign`, `utm_term`, `utm_content`, строки до 255 символов. Другие ключи пропускаем без ошибки, они не сохраняются.",
                    "properties": {
                      "utm_source": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "maxLength": 255
                      },
                      "utm_medium": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "maxLength": 255
                      },
                      "utm_campaign": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "maxLength": 255
                      },
                      "utm_term": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "maxLength": 255
                      },
                      "utm_content": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "maxLength": 255
                      }
                    }
                  },
                  "metadata": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "description": "Ваши данные: плоский объект до 50 ключей, ключ - до 40 символов и не число (`10042` или `-5` не подойдут), значение - строка до 500 символов, число, `true`/`false` или `null`. Пробелы по краям строки API убирает, пустая строка сохраняется как `null`. См. [Формат данных](/developers/conventions#metadata).",
                    "additionalProperties": {
                      "type": [
                        "string",
                        "number",
                        "boolean",
                        "null"
                      ]
                    }
                  }
                },
                "required": [
                  "phone"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "По этому номеру уже есть заявка в работе: вернули её, второй звонок не заказан.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Lead"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              },
              "Idempotent-Replayed": {
                "description": "`true`, если это повтор запроса с тем же `Idempotency-Key`: ответ первого запроса, действие не выполнено второй раз.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Заявка принята, звонок заказан.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Lead"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              },
              "Idempotent-Replayed": {
                "description": "`true`, если это повтор запроса с тем же `Idempotency-Key`: ответ первого запроса, действие не выполнено второй раз.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/IdempotencyKeyRequired"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "Idempotency-Key уже использован с другим запросом (idempotency-conflict) или первый запрос с ним ещё выполняется (idempotency-in-progress). В проекте не настроен Перезвони (perezvoni-not-configured).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "description": "Превышен лимит запросов (rate-limited). Повторите через столько секунд, сколько указано в Retry-After. У создания заявок свои лимиты: новых заявок на ключ в минуту и заявок на один номер.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Через сколько секунд можно повторить запрос.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "leads:write"
        ],
        "x-idempotency": "required"
      }
    },
    "/leads/{lead}": {
      "get": {
        "operationId": "leads.get",
        "description": "Заявка по id - со статусом звонка и его итогом. Заявка из проекта, которого нет в ключе, для ключа не существует - ответ `404`.",
        "summary": "Получить заявку",
        "tags": [
          "Leads"
        ],
        "parameters": [
          {
            "name": "lead",
            "in": "path",
            "required": true,
            "description": "id заявки.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Заявка.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Lead"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "leads:read"
        ]
      }
    },
    "/appointments": {
      "get": {
        "operationId": "appointments.list",
        "description": "Записи проектов ключа, от новых к старым, по страницам. Фильтры можно сочетать: например, записи мастера на день - `resource_id` и `starts_at[gte]`, `starts_at[lt]`.",
        "summary": "Список записей",
        "tags": [
          "Appointments"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Сколько объектов на странице, от 1 до 100.",
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "default": 20,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "starting_after",
            "in": "query",
            "description": "id последнего объекта предыдущей страницы: страница начнётся после него. См. [Пагинация](/developers/pagination).",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Только объекты этого проекта. Проекта нет в ключе - ошибка `403`.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Только записи в этом статусе.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "enum": [
                "pending",
                "confirmed",
                "arrived",
                "completed",
                "cancelled",
                "no_show",
                null
              ]
            }
          },
          {
            "name": "branch_id",
            "in": "query",
            "description": "Только записи этого филиала.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "service_id",
            "in": "query",
            "description": "Только записи на эту услугу.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "resource_id",
            "in": "query",
            "description": "Только записи, где занят этот ресурс: мастер, место или оборудование.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "contact_id",
            "in": "query",
            "description": "Только записи этого клиента - id контакта в CRM.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "customer_phone",
            "in": "query",
            "description": "Только записи с этим телефоном клиента. Номер в другой записи API приведёт к E.164.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 32
            },
            "example": "+79991234567"
          },
          {
            "name": "starts_at[gte]",
            "in": "query",
            "description": "Визиты, которые начинаются не раньше этого времени. Время с часовым поясом (RFC 3339).",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            },
            "example": "2026-10-01T00:00:00+03:00"
          },
          {
            "name": "starts_at[lt]",
            "in": "query",
            "description": "Визиты, которые начинаются раньше этого времени. Время с часовым поясом (RFC 3339).",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Страница списка записей.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppointmentList"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "appointments:read"
        ]
      },
      "post": {
        "operationId": "appointments.create",
        "description": "Записывает клиента на услугу. Время проверяется так же, как при записи через виджет: по графику, буферам и занятости. Какое время свободно, покажет [Свободное время](/developers/api/appointments#slots-list).\n\nПроект записи - проект услуги. Филиал - `branch_id`, филиал выбранного `resource_id` или единственный филиал проекта. Без `resource_id` исполнителя подберут сами.\n\nКлиент - `contact_id` из CRM или `customer_phone` (с ним имя и email). Письма клиенту о записи уходят как при записи через виджет; `notify_customer` = `false` их выключает.\n\nЗапись создаётся подтверждённой, по цене из услуги. В прошлое записать нельзя.",
        "summary": "Создать запись",
        "tags": [
          "Appointments"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Ключ идемпотентности, обязателен. Повтор с тем же ключом и тем же телом вернёт ответ первого запроса и не выполнит действие второй раз. Вместо него можно передать `X-Idempotency-Key`. См. [Идемпотентность](/developers/idempotency).",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "pattern": "^[A-Za-z0-9_\\-:.]{1,64}$"
            },
            "example": "order-20195208"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "service_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "id услуги из справочника услуг."
                  },
                  "starts_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Начало визита, время с часовым поясом (RFC 3339).",
                    "examples": [
                      "2026-10-01T12:00:00+03:00"
                    ]
                  },
                  "branch_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uuid",
                    "description": "Филиал. Обязателен, если у проекта несколько филиалов и не передан `resource_id`."
                  },
                  "resource_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uuid",
                    "description": "Исполнитель - мастер, место или оборудование. Без него подберут свободного."
                  },
                  "duration_min": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "Длительность в минутах - только для аренды (`booking_mode` = `interval`), в границах и с шагом услуги.",
                    "minimum": 1,
                    "maximum": 1440
                  },
                  "guests_count": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "Сколько гостей. У аренды - не больше `max_guests` услуги, у остальных услуг - не больше свободных мест ресурса (`capacity`).",
                    "default": 1,
                    "minimum": 1,
                    "maximum": 1000
                  },
                  "contact_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uuid",
                    "description": "Клиент - id контакта в CRM проекта услуги. Без него нужен `customer_phone`."
                  },
                  "customer_name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Имя клиента. С `contact_id` - вместо имени из CRM.",
                    "examples": [
                      "Иван"
                    ],
                    "maxLength": 255
                  },
                  "customer_phone": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Телефон клиента. Обязателен без `contact_id`. Номер в другой записи API приведёт к E.164.",
                    "examples": [
                      "+79991234567"
                    ],
                    "maxLength": 32
                  },
                  "customer_email": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "email",
                    "description": "Email клиента. С `contact_id` - вместо email из CRM.",
                    "maxLength": 255
                  },
                  "comment": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Комментарий к записи.",
                    "maxLength": 2000
                  },
                  "notify_customer": {
                    "type": [
                      "boolean",
                      "null"
                    ],
                    "description": "`false` - не отправлять клиенту письма об этой записи.",
                    "default": true
                  },
                  "metadata": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "description": "Ваши данные: плоский объект до 50 ключей, ключ - до 40 символов и не число (`10042` или `-5` не подойдут), значение - строка до 500 символов, число, `true`/`false` или `null`. Пробелы по краям строки API убирает, пустая строка сохраняется как `null`. См. [Формат данных](/developers/conventions#metadata).",
                    "additionalProperties": {
                      "type": [
                        "string",
                        "number",
                        "boolean",
                        "null"
                      ]
                    }
                  }
                },
                "required": [
                  "service_id",
                  "starts_at"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Созданная запись.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Appointment"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              },
              "Idempotent-Replayed": {
                "description": "`true`, если это повтор запроса с тем же `Idempotency-Key`: ответ первого запроса, действие не выполнено второй раз.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/IdempotencyKeyRequired"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "Idempotency-Key уже использован с другим запросом (idempotency-conflict) или первый запрос с ним ещё выполняется (idempotency-in-progress). Время уже занято или на нём не хватает мест для гостей (slot-unavailable), вне графика работы (outside-working-hours) или в филиале нет исполнителя для услуги (no-resources).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "422": {
            "description": "Данные запроса не прошли проверку (validation). Какие поля и почему - в errors. Нельзя записать в прошлое (starts-at-in-past), услуга или филиал не найдены (service-not-found, branch-not-found), у проекта несколько филиалов, а branch_id не передан (branch-id-required), исполнитель не подходит (resource-not-eligible), клиент не найден (contact-not-found), длительность или число гостей вне правил аренды (invalid-duration, too-many-guests).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "appointments:write"
        ],
        "x-idempotency": "required"
      }
    },
    "/appointments/{appointment}": {
      "get": {
        "operationId": "appointments.get",
        "description": "Запись по id. Запись из проекта, которого нет в ключе, для ключа не существует - ответ `404`.",
        "summary": "Получить запись",
        "tags": [
          "Appointments"
        ],
        "parameters": [
          {
            "name": "appointment",
            "in": "path",
            "required": true,
            "description": "id записи.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Запись.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Appointment"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "appointments:read"
        ]
      }
    },
    "/appointments/{appointment}/reschedule": {
      "post": {
        "operationId": "appointments.reschedule",
        "description": "Переносит запись на другое время, по желанию - к другому исполнителю. Время проверяется так же, как при создании. Перенести можно только запись, которая ещё не состоялась: `pending` или `confirmed`.\n\nБез `resource_id` запись остаётся у прежнего исполнителя, и новое время должно быть свободно у него. Его свободное время покажет [Свободное время](/developers/api/appointments#slots-list) с `resource_id` записи. Если берёте слот из общего списка, передайте и `resource_id` этого слота.",
        "summary": "Перенести запись",
        "tags": [
          "Appointments"
        ],
        "parameters": [
          {
            "name": "appointment",
            "in": "path",
            "required": true,
            "description": "id записи.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Ключ идемпотентности, по желанию. Повтор с тем же ключом и тем же телом вернёт ответ первого запроса и не выполнит действие второй раз. Вместо него можно передать `X-Idempotency-Key`. См. [Идемпотентность](/developers/idempotency).",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "pattern": "^[A-Za-z0-9_\\-:.]{1,64}$"
            },
            "example": "order-20195208"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "starts_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Новое начало визита, время с часовым поясом (RFC 3339).",
                    "examples": [
                      "2026-10-02T15:00:00+03:00"
                    ]
                  },
                  "resource_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uuid",
                    "description": "Другой исполнитель того же филиала, например `resource_id` из слота. Без него запись остаётся у прежнего исполнителя."
                  },
                  "notify_customer": {
                    "type": [
                      "boolean",
                      "null"
                    ],
                    "description": "`false` - не отправлять клиенту письмо о переносе.",
                    "default": true
                  }
                },
                "required": [
                  "starts_at"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Запись после переноса.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Appointment"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              },
              "Idempotent-Replayed": {
                "description": "`true`, если это повтор запроса с тем же `Idempotency-Key`: ответ первого запроса, действие не выполнено второй раз.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/IdempotencyKeyInvalid"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Idempotency-Key уже использован с другим запросом (idempotency-conflict) или первый запрос с ним ещё выполняется (idempotency-in-progress). Запись в этом статусе нельзя перенести (appointment-not-reschedulable), услугу записи выключили (service-inactive). Время уже занято (slot-unavailable), вне графика работы (outside-working-hours) или в филиале нет исполнителя для услуги (no-resources).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "422": {
            "description": "Данные запроса не прошли проверку (validation). Какие поля и почему - в errors. Нельзя перенести в прошлое (starts-at-in-past) или исполнитель не подходит (resource-not-eligible).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "appointments:write"
        ],
        "x-idempotency": "optional"
      }
    },
    "/appointments/{appointment}/cancel": {
      "post": {
        "operationId": "appointments.cancel",
        "description": "Отменяет запись и освобождает время. Повторная отмена уже отменённой записи - не ошибка: ответ `200` с той же записью. Состоявшийся визит отменить нельзя.",
        "summary": "Отменить запись",
        "tags": [
          "Appointments"
        ],
        "parameters": [
          {
            "name": "appointment",
            "in": "path",
            "required": true,
            "description": "id записи.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Ключ идемпотентности, по желанию. Повтор с тем же ключом и тем же телом вернёт ответ первого запроса и не выполнит действие второй раз. Вместо него можно передать `X-Idempotency-Key`. См. [Идемпотентность](/developers/idempotency).",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "pattern": "^[A-Za-z0-9_\\-:.]{1,64}$"
            },
            "example": "order-20195208"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Причина отмены.",
                    "examples": [
                      "Клиент перенёс поездку"
                    ],
                    "maxLength": 512
                  },
                  "notify_customer": {
                    "type": [
                      "boolean",
                      "null"
                    ],
                    "description": "`false` - не отправлять клиенту письмо об отмене.",
                    "default": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Отменённая запись.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Appointment"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              },
              "Idempotent-Replayed": {
                "description": "`true`, если это повтор запроса с тем же `Idempotency-Key`: ответ первого запроса, действие не выполнено второй раз.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/IdempotencyKeyInvalid"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Idempotency-Key уже использован с другим запросом (idempotency-conflict) или первый запрос с ним ещё выполняется (idempotency-in-progress). Запись в этом статусе нельзя отменить (appointment-not-cancellable).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "appointments:write"
        ],
        "x-idempotency": "optional"
      }
    },
    "/slots": {
      "get": {
        "operationId": "slots.list",
        "description": "Свободное время услуги в филиале в окне `from` - `to` не шире 31 дня. Учитывает график, буферы и занятость - то же время, что видит виджет записи. Прошедшее время в ответ не попадает.",
        "summary": "Свободное время",
        "tags": [
          "Slots"
        ],
        "parameters": [
          {
            "name": "service_id",
            "in": "query",
            "required": true,
            "description": "id услуги.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": true,
            "description": "Начало окна поиска, время с часовым поясом (RFC 3339).",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-10-01T00:00:00+03:00"
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "description": "Конец окна поиска, время с часовым поясом (RFC 3339). Позже `from`, не дальше 31 дня от него.",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-10-08T00:00:00+03:00"
          },
          {
            "name": "branch_id",
            "in": "query",
            "description": "Филиал. Обязателен, если у проекта несколько филиалов и не передан `resource_id`.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "resource_id",
            "in": "query",
            "description": "Только время этого исполнителя.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "guests",
            "in": "query",
            "description": "Сколько гостей - для услуг и мест на несколько человек.",
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "default": 1,
              "minimum": 1,
              "maximum": 1000
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Сколько слотов или окон вернуть, от 1 до 200.",
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "default": 100,
              "minimum": 1,
              "maximum": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Свободное время.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Availability"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "description": "Данные запроса не прошли проверку (validation). Какие поля и почему - в errors. Услуга или филиал не найдены (service-not-found, branch-not-found), у проекта несколько филиалов, а branch_id не передан (branch-id-required), исполнитель не подходит (resource-not-eligible).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "appointments:read"
        ]
      }
    },
    "/services": {
      "get": {
        "operationId": "services.list",
        "description": "Активные услуги проектов ключа - на них можно записать. Отсюда берут `service_id` для записи и свободного времени.",
        "summary": "Список услуг",
        "tags": [
          "Services"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Сколько объектов на странице, от 1 до 100.",
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "default": 20,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "starting_after",
            "in": "query",
            "description": "id последнего объекта предыдущей страницы: страница начнётся после него. См. [Пагинация](/developers/pagination).",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Только объекты этого проекта. Проекта нет в ключе - ошибка `403`.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Страница списка услуг.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceList"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "appointments:read"
        ]
      }
    },
    "/resources": {
      "get": {
        "operationId": "resources.list",
        "description": "Активные исполнители и ресурсы: мастера, места и оборудование. С `service_id` - только те, к кому можно записать на эту услугу.",
        "summary": "Список исполнителей",
        "tags": [
          "Resources"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Сколько объектов на странице, от 1 до 100.",
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "default": 20,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "starting_after",
            "in": "query",
            "description": "id последнего объекта предыдущей страницы: страница начнётся после него. См. [Пагинация](/developers/pagination).",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Только объекты этого проекта. Проекта нет в ключе - ошибка `403`.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "branch_id",
            "in": "query",
            "description": "Только ресурсы этого филиала.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "description": "`person` - мастера, `place` - места, `item` - оборудование.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "enum": [
                "person",
                "place",
                "item",
                null
              ]
            }
          },
          {
            "name": "service_id",
            "in": "query",
            "description": "Только те, к кому можно записать на эту услугу.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Страница списка исполнителей и ресурсов.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResourceList"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "description": "Данные запроса не прошли проверку (validation). Какие поля и почему - в errors. Услуга не найдена (service-not-found).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "appointments:read"
        ]
      }
    },
    "/branches": {
      "get": {
        "operationId": "branches.list",
        "description": "Активные филиалы проектов ключа. Отсюда берут `branch_id`, если у проекта несколько филиалов.",
        "summary": "Список филиалов",
        "tags": [
          "Branches"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Сколько объектов на странице, от 1 до 100.",
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "default": 20,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "starting_after",
            "in": "query",
            "description": "id последнего объекта предыдущей страницы: страница начнётся после него. См. [Пагинация](/developers/pagination).",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Только объекты этого проекта. Проекта нет в ключе - ошибка `403`.",
            "schema": {
              "type": [
                "string",
                "null"
              ],
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Страница списка филиалов.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BranchList"
                }
              }
            },
            "headers": {
              "Request-Id": {
                "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Limit": {
                "description": "Сколько запросов разрешено за минуту.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Сколько запросов осталось в текущей минуте.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Через сколько секунд счётчик обнулится.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "$ref": "#/components/responses/ApiAddonRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        },
        "x-scopes": [
          "appointments:read"
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "description": "Секретный ключ компании `dk_live_…` в заголовке `Authorization: Bearer`. См. [Ключи и права](/developers/authentication).",
        "scheme": "bearer"
      }
    },
    "schemas": {
      "Appointment": {
        "type": "object",
        "description": "Запись клиента на услугу.",
        "required": [
          "object",
          "id",
          "project_id",
          "branch_id",
          "service_id",
          "service_name",
          "resource_id",
          "resource_ids",
          "status",
          "source",
          "starts_at",
          "ends_at",
          "timezone",
          "guests_count",
          "contact_id",
          "customer_name",
          "customer_phone",
          "customer_email",
          "conversation_id",
          "price_amount",
          "price_currency",
          "comment",
          "cancel_reason",
          "cancelled_by",
          "metadata",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "appointment",
            "description": "Тип объекта, всегда `appointment`."
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "id записи."
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "id проекта записи."
          },
          "branch_id": {
            "type": "string",
            "format": "uuid",
            "description": "id филиала."
          },
          "service_id": {
            "type": "string",
            "format": "uuid",
            "description": "id услуги."
          },
          "service_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Название услуги."
          },
          "resource_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "id главного исполнителя записи: мастера, места или оборудования."
          },
          "resource_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "id всех ресурсов, занятых записью, например мастер и кабинет. У отменённой записи пусто: время освобождено."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "confirmed",
              "arrived",
              "completed",
              "cancelled",
              "no_show"
            ],
            "description": "`pending` - ждёт подтверждения, `confirmed` - подтверждена, `arrived` - клиент пришёл, `completed` - визит состоялся, `cancelled` - отменена, `no_show` - клиент не пришёл."
          },
          "source": {
            "type": "string",
            "description": "Откуда запись: `api` - через API, `widget` - виджет записи на сайте, `page` - страница записи, `lk` - сотрудник в личном кабинете, `neuro_chat`, `neuro_voice`, `neuro_image` - ИИ-ассистент в чате, в звонке, в ответах на комментарии, `waitlist` - из листа ожидания. Список значений может пополняться."
          },
          "starts_at": {
            "type": "string",
            "format": "date-time",
            "description": "Начало визита, UTC."
          },
          "ends_at": {
            "type": "string",
            "format": "date-time",
            "description": "Конец визита, UTC."
          },
          "timezone": {
            "type": "string",
            "description": "Часовой пояс филиала, например `Europe/Moscow`. Время клиенту показывайте в нём."
          },
          "guests_count": {
            "type": "integer",
            "description": "Сколько гостей в записи."
          },
          "contact_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "id контакта клиента в CRM."
          },
          "customer_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Имя клиента."
          },
          "customer_phone": {
            "type": [
              "string",
              "null"
            ],
            "description": "Телефон клиента в E.164."
          },
          "customer_email": {
            "type": [
              "string",
              "null"
            ],
            "description": "Email клиента."
          },
          "conversation_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "id диалога в чате, в котором сделали запись, - тот же id, что в `GET /v1/conversations/{conversation}`. У записей не из чата - `null`."
          },
          "price_amount": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Цена в копейках, как её посчитали при записи."
          },
          "price_currency": {
            "type": [
              "string",
              "null"
            ],
            "description": "Валюта цены, ISO 4217: `RUB`."
          },
          "comment": {
            "type": [
              "string",
              "null"
            ],
            "description": "Комментарий к записи."
          },
          "cancel_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Причина отмены."
          },
          "cancelled_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Кто отменил: `api` - через API, `staff` - сотрудник, `client` - клиент, `neuro` - ИИ-ассистент, `system` - автоматически. Список значений может пополняться. Не отменена - `null`."
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "description": "Ваши данные, переданные при создании через API. У записей из других источников - `null`. См. [Формат данных](/developers/conventions#metadata).",
            "additionalProperties": {
              "type": [
                "string",
                "number",
                "boolean",
                "null"
              ]
            }
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Когда запись создана, UTC."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Когда запись последний раз менялась, UTC."
          }
        },
        "examples": [
          {
            "object": "appointment",
            "id": "01a0d7f0-d3e1-7a2b-8c4d-5e6f7a8b9c0d",
            "project_id": "01a0c4e2-3f10-7b4d-9c2e-5d8a1f6b3e20",
            "branch_id": "01a0c4e2-6a2c-7d11-b3f4-7e8a9b0c1d2e",
            "service_id": "01a0c4e2-7b3d-7e22-a4c5-8f9a0b1c2d3e",
            "service_name": "Стрижка",
            "resource_id": "01a0c4e2-8c4e-7f33-95d6-9a0b1c2d3e4f",
            "resource_ids": [
              "01a0c4e2-8c4e-7f33-95d6-9a0b1c2d3e4f"
            ],
            "status": "confirmed",
            "source": "api",
            "starts_at": "2026-10-01T09:00:00Z",
            "ends_at": "2026-10-01T10:00:00Z",
            "timezone": "Europe/Moscow",
            "guests_count": 1,
            "contact_id": "01a0d7f0-b6c0-7a1a-82e4-2cab98a901c7",
            "customer_name": "Иван",
            "customer_phone": "+79991234567",
            "customer_email": null,
            "conversation_id": null,
            "price_amount": 150000,
            "price_currency": "RUB",
            "comment": null,
            "cancel_reason": null,
            "cancelled_by": null,
            "metadata": {
              "visit_id": "V-2031"
            },
            "created_at": "2026-09-25T09:41:12Z",
            "updated_at": "2026-09-25T09:41:12Z"
          }
        ],
        "title": "Appointment"
      },
      "AppointmentList": {
        "type": "object",
        "description": "Страница списка записей.",
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "Тип объекта, всегда `list`."
          },
          "data": {
            "type": "array",
            "description": "Объекты страницы, от новых к старым.",
            "items": {
              "$ref": "#/components/schemas/Appointment"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "`true`, если дальше есть ещё объекты: запросите следующую страницу, передав в `starting_after` id последнего объекта из `data`. См. [Пагинация](/developers/pagination)."
          }
        },
        "title": "AppointmentList"
      },
      "Availability": {
        "type": "object",
        "description": "Свободное время услуги в филиале. У услуги с фиксированной длительностью (`mode` = `fixed`) - слоты в `slots`, у аренды (`interval`) - свободные окна в `windows`: в окне можно выбрать начало и длительность в границах услуги.",
        "required": [
          "object",
          "service_id",
          "project_id",
          "branch_id",
          "mode",
          "timezone",
          "duration_min",
          "min_duration_min",
          "max_duration_min",
          "duration_step_min",
          "slots",
          "windows",
          "has_more"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "availability",
            "description": "Тип объекта, всегда `availability`."
          },
          "service_id": {
            "type": "string",
            "format": "uuid",
            "description": "id услуги."
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "id проекта услуги."
          },
          "branch_id": {
            "type": "string",
            "format": "uuid",
            "description": "id филиала."
          },
          "mode": {
            "type": "string",
            "enum": [
              "fixed",
              "interval"
            ],
            "description": "`fixed` - запись на время из слотов, `interval` - аренда: клиент выбирает начало и длительность."
          },
          "timezone": {
            "type": "string",
            "description": "Часовой пояс филиала, например `Europe/Moscow`. Время клиенту показывайте в нём."
          },
          "duration_min": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Длительность записи в минутах. У аренды - `null`."
          },
          "min_duration_min": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Аренда: наименьшая длительность в минутах. У услуги с фиксированной длительностью - `null`."
          },
          "max_duration_min": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Аренда: наибольшая длительность в минутах, `null` - без ограничения. У услуги с фиксированной длительностью - `null`."
          },
          "duration_step_min": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Аренда: шаг длительности в минутах. У услуги с фиксированной длительностью - `null`."
          },
          "slots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Slot"
            },
            "description": "Свободные слоты по времени начала. У аренды - пусто."
          },
          "windows": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Slot"
            },
            "description": "Аренда: свободные окна. У услуги с фиксированной длительностью - пусто."
          },
          "has_more": {
            "type": "boolean",
            "description": "`true`, если в окне поиска есть ещё время сверх `limit`. В ответе - самое раннее время по всем исполнителям и объектам. Чтобы получить остальное, увеличьте `limit` (до 200) или запросите окно короче, например по дням."
          }
        },
        "examples": [
          {
            "object": "availability",
            "service_id": "01a0c4e2-7b3d-7e22-a4c5-8f9a0b1c2d3e",
            "project_id": "01a0c4e2-3f10-7b4d-9c2e-5d8a1f6b3e20",
            "branch_id": "01a0c4e2-6a2c-7d11-b3f4-7e8a9b0c1d2e",
            "mode": "fixed",
            "timezone": "Europe/Moscow",
            "duration_min": 60,
            "min_duration_min": null,
            "max_duration_min": null,
            "duration_step_min": null,
            "slots": [
              {
                "starts_at": "2026-10-01T09:00:00Z",
                "ends_at": "2026-10-01T10:00:00Z",
                "resource_id": "01a0c4e2-8c4e-7f33-95d6-9a0b1c2d3e4f"
              },
              {
                "starts_at": "2026-10-01T10:00:00Z",
                "ends_at": "2026-10-01T11:00:00Z",
                "resource_id": "01a0c4e2-8c4e-7f33-95d6-9a0b1c2d3e4f"
              }
            ],
            "windows": [],
            "has_more": false
          }
        ],
        "title": "Availability"
      },
      "Branch": {
        "type": "object",
        "description": "Филиал - точка, где проходят визиты. Только активные.",
        "required": [
          "object",
          "id",
          "project_id",
          "name",
          "address",
          "phone",
          "timezone",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "branch",
            "description": "Тип объекта, всегда `branch`."
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "id филиала - его передают в `branch_id` записи и свободного времени."
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "id проекта."
          },
          "name": {
            "type": "string",
            "description": "Название."
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "description": "Адрес."
          },
          "phone": {
            "type": [
              "string",
              "null"
            ],
            "description": "Телефон филиала."
          },
          "timezone": {
            "type": "string",
            "description": "Часовой пояс филиала, например `Europe/Moscow`."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Когда филиал создан, UTC."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Когда филиал последний раз менялся, UTC."
          }
        },
        "examples": [
          {
            "object": "branch",
            "id": "01a0c4e2-6a2c-7d11-b3f4-7e8a9b0c1d2e",
            "project_id": "01a0c4e2-3f10-7b4d-9c2e-5d8a1f6b3e20",
            "name": "Центр",
            "address": "Москва, Тверская, 1",
            "phone": "+74950000000",
            "timezone": "Europe/Moscow",
            "created_at": "2026-08-20T07:00:00Z",
            "updated_at": "2026-08-20T07:00:00Z"
          }
        ],
        "title": "Branch"
      },
      "BranchList": {
        "type": "object",
        "description": "Страница списка филиалов.",
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "Тип объекта, всегда `list`."
          },
          "data": {
            "type": "array",
            "description": "Объекты страницы, от новых к старым.",
            "items": {
              "$ref": "#/components/schemas/Branch"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "`true`, если дальше есть ещё объекты: запросите следующую страницу, передав в `starting_after` id последнего объекта из `data`. См. [Пагинация](/developers/pagination)."
          }
        },
        "title": "BranchList"
      },
      "Contact": {
        "type": "object",
        "description": "Контакт - карточка клиента в CRM проекта.",
        "required": [
          "object",
          "id",
          "project_id",
          "type",
          "name",
          "first_name",
          "last_name",
          "email",
          "phone",
          "position",
          "lifecycle",
          "status",
          "source",
          "metadata",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "contact",
            "description": "Тип объекта, всегда `contact`."
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "id контакта."
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "id проекта, в котором контакт."
          },
          "type": {
            "type": "string",
            "enum": [
              "person",
              "b2b_company"
            ],
            "description": "`person` - человек, `b2b_company` - компания."
          },
          "name": {
            "type": "string",
            "description": "Имя, как его показывает личный кабинет."
          },
          "first_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Имя."
          },
          "last_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Фамилия."
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "description": "Основной email."
          },
          "phone": {
            "type": [
              "string",
              "null"
            ],
            "description": "Основной телефон, обычно в E.164: `+79101234567`. Строка, которую не удалось разобрать как номер, хранится как есть."
          },
          "position": {
            "type": [
              "string",
              "null"
            ],
            "description": "Должность."
          },
          "lifecycle": {
            "type": "string",
            "description": "Этап клиента: `lead` - лид, `mql` и `sql` - квалифицированный лид маркетингом и продажами, `customer` - клиент, `churned` - ушёл. Этап может быть и другой строкой, если его загрузили из файла в личном кабинете."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "archived",
              "blocked"
            ],
            "description": "`active` - рабочий контакт, `archived` - в архиве, `blocked` - заблокирован в личном кабинете."
          },
          "source": {
            "type": "string",
            "description": "Откуда пришёл контакт, например `api` - создан через API, `manual` - вручную в личном кабинете. Список значений может пополняться."
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "description": "Ваши данные, переданные при создании через API. У контактов из других источников - `null`. См. [Формат данных](/developers/conventions#metadata).",
            "additionalProperties": {
              "type": [
                "string",
                "number",
                "boolean",
                "null"
              ]
            }
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Когда контакт создан, UTC."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Когда контакт последний раз менялся, UTC."
          }
        },
        "examples": [
          {
            "object": "contact",
            "id": "01a0d7f0-b6c0-7a1a-82e4-2cab98a901c7",
            "project_id": "01a0c4e2-3f10-7b4d-9c2e-5d8a1f6b3e20",
            "type": "person",
            "name": "Анна Смирнова",
            "first_name": "Анна",
            "last_name": "Смирнова",
            "email": "anna@example.com",
            "phone": "+79101234567",
            "position": null,
            "lifecycle": "lead",
            "status": "active",
            "source": "api",
            "metadata": {
              "crm_id": "A-10042"
            },
            "created_at": "2026-09-25T09:41:12Z",
            "updated_at": "2026-09-25T09:41:12Z"
          }
        ],
        "title": "Contact"
      },
      "ContactList": {
        "type": "object",
        "description": "Страница списка контактов.",
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "Тип объекта, всегда `list`."
          },
          "data": {
            "type": "array",
            "description": "Объекты страницы, от новых к старым.",
            "items": {
              "$ref": "#/components/schemas/Contact"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "`true`, если дальше есть ещё объекты: запросите следующую страницу, передав в `starting_after` id последнего объекта из `data`. См. [Пагинация](/developers/pagination)."
          }
        },
        "title": "ContactList"
      },
      "Conversation": {
        "type": "object",
        "description": "Диалог с клиентом в одном канале: чат на сайте, мессенджер или почта.",
        "required": [
          "object",
          "id",
          "project_id",
          "channel",
          "status",
          "closed_reason",
          "closed_at",
          "customer_name",
          "message_count",
          "first_message_at",
          "last_message_at",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "conversation",
            "description": "Тип объекта, всегда `conversation`."
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "id диалога."
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "id проекта диалога."
          },
          "channel": {
            "type": "string",
            "description": "Канал: `web` - чат на сайте, `telegram`, `vk`, `max`, `email`, `image` - комментарии в соцсетях: читать и закрывать можно, отвечать через API нельзя. Список значений может пополняться."
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "snoozed",
              "closed",
              "spam"
            ],
            "description": "`open` - открыт, `snoozed` - отложен, `closed` - закрыт, `spam` - помечен как спам."
          },
          "closed_reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "resolved",
              "abandoned",
              "duplicate",
              "spam",
              "wrong_channel",
              null
            ],
            "description": "Почему закрыт: `resolved` - закрыт как решённый, `abandoned` - клиент пропал, `duplicate` - дубль, `spam` - спам, `wrong_channel` - не по адресу. У незакрытого или без причины - `null`. `resolved` не значит, что клиент подтвердил решение: так закрывается и диалог, который ИИ-ассистент закрыл прощанием, когда клиент не ответил на его вопрос, и диалог в чате на сайте, когда посетитель сам начал новый, а при закрытии сотрудником или через API это причина по умолчанию."
          },
          "closed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Когда диалог закрыли, UTC. У незакрытого - `null`."
          },
          "customer_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Как клиент подписан в канале: имя в мессенджере, email или телефон."
          },
          "message_count": {
            "type": "integer",
            "description": "Сколько сообщений в диалоге."
          },
          "first_message_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Время первого сообщения, UTC."
          },
          "last_message_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Время последнего сообщения, UTC."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Когда диалог создан, UTC."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Когда диалог последний раз менялся, UTC."
          }
        },
        "examples": [
          {
            "object": "conversation",
            "id": "01a0d7f0-e4f2-7b3c-9d5e-6f7a8b9c0d1e",
            "project_id": "01a0c4e2-3f10-7b4d-9c2e-5d8a1f6b3e20",
            "channel": "telegram",
            "status": "open",
            "closed_reason": null,
            "closed_at": null,
            "customer_name": "Анна",
            "message_count": 4,
            "first_message_at": "2026-09-25T09:30:02Z",
            "last_message_at": "2026-09-25T09:41:12Z",
            "created_at": "2026-09-25T09:30:02Z",
            "updated_at": "2026-09-25T09:41:12Z"
          }
        ],
        "title": "Conversation"
      },
      "ConversationList": {
        "type": "object",
        "description": "Страница списка диалогов.",
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "Тип объекта, всегда `list`."
          },
          "data": {
            "type": "array",
            "description": "Объекты страницы, от новых к старым.",
            "items": {
              "$ref": "#/components/schemas/Conversation"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "`true`, если дальше есть ещё объекты: запросите следующую страницу, передав в `starting_after` id последнего объекта из `data`. См. [Пагинация](/developers/pagination)."
          }
        },
        "title": "ConversationList"
      },
      "Lead": {
        "type": "object",
        "description": "Заявка на обратный звонок: с виджета на сайте или через API.",
        "required": [
          "object",
          "id",
          "project_id",
          "department_id",
          "phone",
          "name",
          "status",
          "status_reason",
          "source",
          "source_url",
          "utm",
          "qualifier",
          "scheduled_at",
          "call",
          "rating",
          "handled_at",
          "metadata",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "lead",
            "description": "Тип объекта, всегда `lead`."
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "id заявки."
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "id проекта заявки."
          },
          "department_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "id отдела, сотрудникам которого звоним."
          },
          "phone": {
            "type": "string",
            "description": "Телефон клиента, обычно в E.164: `+79991234567`."
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Имя клиента."
          },
          "status": {
            "type": "string",
            "enum": [
              "scheduled",
              "queued",
              "in_progress",
              "completed",
              "missed",
              "cancelled",
              "not_called"
            ],
            "description": "Где заявка сейчас: `scheduled` - звонок назначен на время (или ждёт повтора), `queued` - в очереди на звонок, `in_progress` - идёт звонок, `completed` - разговор состоялся: с сотрудником или с ИИ-ассистентом (см. `call.handled_by`), `missed` - дозвониться не удалось (почему - в `status_reason`), `cancelled` - заявку отменили, `not_called` - звонок не заказывали (почему - в `status_reason`)."
          },
          "status_reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "team_no_answer",
              "customer_no_answer",
              "error",
              "insufficient_funds",
              null
            ],
            "description": "Почему `missed` или `not_called`: `team_no_answer` - не ответили сотрудники, `customer_no_answer` - не ответил клиент, `error` - сбой связи, `insufficient_funds` - на балансе не хватило денег на звонок. У остальных статусов - `null`."
          },
          "source": {
            "type": "string",
            "enum": [
              "widget",
              "api"
            ],
            "description": "`widget` - заявка с виджета на сайте, `api` - через API."
          },
          "source_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Страница, с которой оставили заявку."
          },
          "utm": {
            "type": [
              "object",
              "null"
            ],
            "description": "UTM-метки заявки: только непустые из пяти стандартных. Нет ни одной - `null`.",
            "properties": {
              "utm_source": {
                "type": "string",
                "description": "utm_source."
              },
              "utm_medium": {
                "type": "string",
                "description": "utm_medium."
              },
              "utm_campaign": {
                "type": "string",
                "description": "utm_campaign."
              },
              "utm_term": {
                "type": "string",
                "description": "utm_term."
              },
              "utm_content": {
                "type": "string",
                "description": "utm_content."
              }
            }
          },
          "qualifier": {
            "type": [
              "string",
              "null"
            ],
            "description": "Причина звонка из списка отдела."
          },
          "scheduled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "На какое время назначен звонок, UTC. Если ждёт повтора после недозвона - время повтора. Звонок сразу - `null`."
          },
          "call": {
            "type": [
              "object",
              "null"
            ],
            "description": "Звонок по заявке. Звонили несколько раз - последняя попытка. Пока звонка не было - `null`.",
            "required": [
              "started_at",
              "answered_at",
              "connected_at",
              "ended_at",
              "duration_sec",
              "handled_by",
              "ai_outcome"
            ],
            "properties": {
              "started_at": {
                "type": "string",
                "format": "date-time",
                "description": "Когда начали звонить, UTC."
              },
              "answered_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "Когда ответил сотрудник, UTC. Звонил ИИ-ассистент - `null`."
              },
              "connected_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "Когда начался разговор клиента с сотрудником или с ИИ-ассистентом, UTC."
              },
              "ended_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "Когда звонок закончился, UTC."
              },
              "duration_sec": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Сколько секунд длился разговор."
              },
              "handled_by": {
                "type": "string",
                "enum": [
                  "team",
                  "ai"
                ],
                "description": "`team` - звонили сотрудники, `ai` - звонил ИИ-ассистент."
              },
              "ai_outcome": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "transferred",
                  "lead",
                  "ended",
                  "limit",
                  "failed",
                  "hangup",
                  null
                ],
                "description": "Чем закончился разговор с ИИ-ассистентом: `transferred` - перевёл на сотрудника, `lead` - записал заявку, `ended` - разговор завершён, `limit` - кончилось время разговора, `failed` - сбой, `hangup` - клиент положил трубку. Звонили сотрудники или итога ещё нет - `null`."
              }
            }
          },
          "rating": {
            "type": [
              "object",
              "null"
            ],
            "description": "Оценка звонка клиентом. Не оценил - `null`.",
            "required": [
              "score",
              "reasons",
              "rated_at"
            ],
            "properties": {
              "score": {
                "type": "integer",
                "minimum": 1,
                "maximum": 5,
                "description": "Оценка от 1 до 5."
              },
              "reasons": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Что клиент отметил в оценке."
              },
              "rated_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "Когда клиент оценил звонок, UTC."
              }
            }
          },
          "handled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Когда сотрудник отметил заявку обработанной в личном кабинете, UTC. Не отмечена - `null`."
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "description": "Ваши данные, переданные при создании через API. У заявок с виджета - `null`. См. [Формат данных](/developers/conventions#metadata).",
            "additionalProperties": {
              "type": [
                "string",
                "number",
                "boolean",
                "null"
              ]
            }
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Когда заявка создана, UTC."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Когда заявка последний раз менялась, UTC."
          }
        },
        "examples": [
          {
            "object": "lead",
            "id": "01a0d7f0-c2b4-7e61-9a3f-6b1d2e8c4a57",
            "project_id": "01a0c4e2-3f10-7b4d-9c2e-5d8a1f6b3e20",
            "department_id": "01a0c4e2-51a8-7c30-8e4b-0f9d3a6c2b18",
            "phone": "+79991234567",
            "name": "Иван",
            "status": "completed",
            "status_reason": null,
            "source": "api",
            "source_url": "https://shop.example.com/cart",
            "utm": {
              "utm_source": "crm",
              "utm_campaign": "autumn"
            },
            "qualifier": "Сервис",
            "scheduled_at": null,
            "call": {
              "started_at": "2026-09-25T09:41:15Z",
              "answered_at": "2026-09-25T09:41:22Z",
              "connected_at": "2026-09-25T09:41:30Z",
              "ended_at": "2026-09-25T09:44:02Z",
              "duration_sec": 152,
              "handled_by": "team",
              "ai_outcome": null
            },
            "rating": null,
            "handled_at": null,
            "metadata": {
              "order_id": "20195208"
            },
            "created_at": "2026-09-25T09:41:12Z",
            "updated_at": "2026-09-25T09:44:02Z"
          }
        ],
        "title": "Lead"
      },
      "LeadList": {
        "type": "object",
        "description": "Страница списка заявок.",
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "Тип объекта, всегда `list`."
          },
          "data": {
            "type": "array",
            "description": "Объекты страницы, от новых к старым.",
            "items": {
              "$ref": "#/components/schemas/Lead"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "`true`, если дальше есть ещё объекты: запросите следующую страницу, передав в `starting_after` id последнего объекта из `data`. См. [Пагинация](/developers/pagination)."
          }
        },
        "title": "LeadList"
      },
      "Message": {
        "type": "object",
        "description": "Сообщение диалога: от клиента или клиенту. Внутренние заметки команды в API не попадают.",
        "required": [
          "object",
          "id",
          "conversation_id",
          "direction",
          "author_type",
          "source",
          "text",
          "attachments",
          "status",
          "failure",
          "created_at"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "message",
            "description": "Тип объекта, всегда `message`."
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "id сообщения."
          },
          "conversation_id": {
            "type": "string",
            "format": "uuid",
            "description": "id диалога."
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ],
            "description": "`inbound` - от клиента, `outbound` - клиенту."
          },
          "author_type": {
            "type": "string",
            "enum": [
              "customer",
              "operator",
              "ai",
              "system"
            ],
            "description": "`customer` - клиент, `operator` - сотрудник или ваша интеграция через API, `ai` - ИИ-ассистент, `system` - служебное сообщение."
          },
          "source": {
            "type": [
              "string",
              "null"
            ],
            "description": "`api` - сообщение отправлено через API. У остальных сообщений - `null`."
          },
          "text": {
            "type": "string",
            "description": "Текст сообщения. У сообщения только с файлами - пустая строка."
          },
          "attachments": {
            "type": "array",
            "description": "Вложения. Отправить файл через API нельзя, прочитать - можно.",
            "items": {
              "type": "object",
              "required": [
                "name",
                "mime_type",
                "size",
                "kind",
                "url"
              ],
              "properties": {
                "name": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Имя файла."
                },
                "mime_type": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "MIME-тип, например `image/jpeg`."
                },
                "size": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "Размер в байтах."
                },
                "kind": {
                  "type": "string",
                  "enum": [
                    "image",
                    "document",
                    "video",
                    "audio",
                    "other"
                  ],
                  "description": "`image` - картинка, `document` - документ, `video` - видео, `audio` - аудио, `other` - другое."
                },
                "url": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "uri",
                  "description": "Временная ссылка на файл, действует несколько минут: за свежей ссылкой запросите список сообщений заново. `null` - ссылки сейчас нет: файл ещё не получен из канала, получить его не удалось (например, он слишком большой) или хранилище временно недоступно."
                }
              }
            }
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "pending",
              "sent",
              "delivered",
              "read",
              "failed",
              null
            ],
            "description": "Доставка сообщения клиенту: `pending` - отправляется, `delivered` - канал принял сообщение (это не значит, что клиент его уже увидел), `read` - клиент прочитал (только в чате на сайте), `failed` - не доставлено (почему - в `failure`). `sent` - зарезервированное значение, API его не возвращает. У сообщений от клиента - `null`."
          },
          "failure": {
            "type": [
              "object",
              "null"
            ],
            "description": "Почему сообщение не доставлено. У остальных - `null`.",
            "required": [
              "code"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "`channel_not_configured` - канал настроен не до конца: нет токена бота, ключ доступа устарел или у него нет нужных прав, исправляется в личном кабинете; `recipient_unavailable` - площадка не доставляет сообщения этому человеку, например клиент заблокировал бота; `provider_error` - прочий сбой сети или площадки. Список значений может пополняться. Чтобы отправить сообщение ещё раз, передайте новый `Idempotency-Key`: повтор с тем же ключом вернёт это же сообщение со статусом `failed`."
              }
            }
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Когда сообщение создано, UTC."
          }
        },
        "examples": [
          {
            "object": "message",
            "id": "01a0d7f0-f5a3-7c4d-8e6f-7a8b9c0d1e2f",
            "conversation_id": "01a0d7f0-e4f2-7b3c-9d5e-6f7a8b9c0d1e",
            "direction": "outbound",
            "author_type": "operator",
            "source": "api",
            "text": "Здравствуйте! Заказ 20195208 передан в доставку.",
            "attachments": [],
            "status": "delivered",
            "failure": null,
            "created_at": "2026-09-25T09:41:12Z"
          }
        ],
        "title": "Message"
      },
      "MessageList": {
        "type": "object",
        "description": "Страница сообщений диалога.",
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "Тип объекта, всегда `list`."
          },
          "data": {
            "type": "array",
            "description": "Объекты страницы, от новых к старым.",
            "items": {
              "$ref": "#/components/schemas/Message"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "`true`, если дальше есть ещё объекты: запросите следующую страницу, передав в `starting_after` id последнего объекта из `data`. См. [Пагинация](/developers/pagination)."
          }
        },
        "title": "MessageList"
      },
      "Problem": {
        "type": "object",
        "description": "Ошибка в формате RFC 7807. Разбирайте её по коду в конце `type`, а не по тексту. См. [Ошибки](/developers/errors).",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "Адрес описания ошибки. Последняя часть адреса - код ошибки, например `unauthenticated`."
          },
          "title": {
            "type": "string",
            "description": "Короткое название на английском."
          },
          "status": {
            "type": "integer",
            "description": "Код HTTP, тот же, что у ответа."
          },
          "detail": {
            "type": "string",
            "description": "Пояснение для человека на английском. Текст может меняться - не разбирайте его в программе."
          },
          "request_id": {
            "type": "string",
            "description": "id запроса, тот же, что в заголовке `Request-Id`. Если поля нет, возьмите id из заголовка."
          },
          "code": {
            "type": "string",
            "description": "Есть не у всех ошибок: тот же код, что в конце `type`, через подчёркивание, например `slot_unavailable`."
          },
          "errors": {
            "type": "object",
            "description": "Только у ошибки `422`: поля, которые не прошли проверку, и почему.",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "type": "https://dialogi.io/errors/forbidden",
            "title": "Forbidden",
            "status": 403,
            "detail": "The API key lacks the contacts:write permission.",
            "request_id": "req_4WHRB5tCR3dmQk9nOr3ibwfx"
          }
        ],
        "title": "Problem"
      },
      "Resource": {
        "type": "object",
        "description": "Исполнитель или ресурс филиала: мастер, место (баня, корт, зал) или оборудование. Только активные.",
        "required": [
          "object",
          "id",
          "project_id",
          "branch_id",
          "kind",
          "name",
          "position_title",
          "capacity",
          "timezone",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "resource",
            "description": "Тип объекта, всегда `resource`."
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "id ресурса - его передают в `resource_id` записи и свободного времени."
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "id проекта."
          },
          "branch_id": {
            "type": "string",
            "format": "uuid",
            "description": "id филиала ресурса."
          },
          "kind": {
            "type": "string",
            "enum": [
              "person",
              "place",
              "item"
            ],
            "description": "`person` - мастер, `place` - место: баня, корт, зал, `item` - оборудование."
          },
          "name": {
            "type": "string",
            "description": "Название или имя."
          },
          "position_title": {
            "type": [
              "string",
              "null"
            ],
            "description": "Должность мастера."
          },
          "capacity": {
            "type": "integer",
            "description": "Сколько гостей ресурс принимает одновременно."
          },
          "timezone": {
            "type": "string",
            "description": "Часовой пояс графика ресурса, например `Europe/Moscow`."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Когда ресурс создан, UTC."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Когда ресурс последний раз менялся, UTC."
          }
        },
        "examples": [
          {
            "object": "resource",
            "id": "01a0c4e2-8c4e-7f33-95d6-9a0b1c2d3e4f",
            "project_id": "01a0c4e2-3f10-7b4d-9c2e-5d8a1f6b3e20",
            "branch_id": "01a0c4e2-6a2c-7d11-b3f4-7e8a9b0c1d2e",
            "kind": "person",
            "name": "Марина",
            "position_title": "Стилист",
            "capacity": 1,
            "timezone": "Europe/Moscow",
            "created_at": "2026-08-20T07:00:00Z",
            "updated_at": "2026-08-20T07:00:00Z"
          }
        ],
        "title": "Resource"
      },
      "ResourceList": {
        "type": "object",
        "description": "Страница списка исполнителей и ресурсов.",
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "Тип объекта, всегда `list`."
          },
          "data": {
            "type": "array",
            "description": "Объекты страницы, от новых к старым.",
            "items": {
              "$ref": "#/components/schemas/Resource"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "`true`, если дальше есть ещё объекты: запросите следующую страницу, передав в `starting_after` id последнего объекта из `data`. См. [Пагинация](/developers/pagination)."
          }
        },
        "title": "ResourceList"
      },
      "Service": {
        "type": "object",
        "description": "Услуга, на которую можно записать. Только активные услуги.",
        "required": [
          "object",
          "id",
          "project_id",
          "name",
          "description",
          "booking_mode",
          "duration_min",
          "min_duration_min",
          "max_duration_min",
          "duration_step_min",
          "max_guests",
          "price_amount",
          "price_currency",
          "price_unit",
          "online_bookable",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "service",
            "description": "Тип объекта, всегда `service`."
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "id услуги - его передают в `service_id` записи и свободного времени."
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "id проекта услуги."
          },
          "name": {
            "type": "string",
            "description": "Название."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Описание."
          },
          "booking_mode": {
            "type": "string",
            "enum": [
              "fixed",
              "interval"
            ],
            "description": "`fixed` - запись на время из слотов с длительностью услуги, `interval` - аренда: клиент выбирает начало и длительность."
          },
          "duration_min": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Длительность в минутах. У аренды - `null`."
          },
          "min_duration_min": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Аренда: наименьшая длительность в минутах. У `fixed` - `null`."
          },
          "max_duration_min": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Аренда: наибольшая длительность в минутах, `null` - без ограничения. У `fixed` - `null`."
          },
          "duration_step_min": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Аренда: шаг длительности в минутах. У `fixed` - `null`."
          },
          "max_guests": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Аренда: сколько гостей можно записать за раз, `null` - без ограничения. У `fixed` не применяется: гостей ограничивает `capacity` ресурса, и запись, которой не хватает мест, получит ошибку [slot-unavailable](/developers/errors#slot-unavailable)."
          },
          "price_amount": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Цена в копейках. У аренды с `price_unit` = `hour` - за час, итог считается при записи."
          },
          "price_currency": {
            "type": [
              "string",
              "null"
            ],
            "description": "Валюта цены, ISO 4217: `RUB`."
          },
          "price_unit": {
            "type": "string",
            "enum": [
              "service",
              "hour"
            ],
            "description": "`service` - цена за услугу, `hour` - за час аренды."
          },
          "online_bookable": {
            "type": "boolean",
            "description": "Показывается ли услуга в онлайн-записи на сайте. Через API записать можно и на услугу, которой там нет."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Когда услуга создана, UTC."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Когда услуга последний раз менялась, UTC."
          }
        },
        "examples": [
          {
            "object": "service",
            "id": "01a0c4e2-7b3d-7e22-a4c5-8f9a0b1c2d3e",
            "project_id": "01a0c4e2-3f10-7b4d-9c2e-5d8a1f6b3e20",
            "name": "Стрижка",
            "description": null,
            "booking_mode": "fixed",
            "duration_min": 60,
            "min_duration_min": null,
            "max_duration_min": null,
            "duration_step_min": null,
            "max_guests": null,
            "price_amount": 150000,
            "price_currency": "RUB",
            "price_unit": "service",
            "online_bookable": true,
            "created_at": "2026-08-20T07:00:00Z",
            "updated_at": "2026-09-01T12:30:00Z"
          }
        ],
        "title": "Service"
      },
      "ServiceList": {
        "type": "object",
        "description": "Страница списка услуг.",
        "required": [
          "object",
          "data",
          "has_more"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "description": "Тип объекта, всегда `list`."
          },
          "data": {
            "type": "array",
            "description": "Объекты страницы, от новых к старым.",
            "items": {
              "$ref": "#/components/schemas/Service"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "`true`, если дальше есть ещё объекты: запросите следующую страницу, передав в `starting_after` id последнего объекта из `data`. См. [Пагинация](/developers/pagination)."
          }
        },
        "title": "ServiceList"
      },
      "Slot": {
        "type": "object",
        "description": "Свободное время: слот записи или окно аренды.",
        "required": [
          "starts_at",
          "ends_at",
          "resource_id"
        ],
        "properties": {
          "starts_at": {
            "type": "string",
            "format": "date-time",
            "description": "Начало, UTC."
          },
          "ends_at": {
            "type": "string",
            "format": "date-time",
            "description": "Конец, UTC."
          },
          "resource_id": {
            "type": "string",
            "format": "uuid",
            "description": "id исполнителя, который свободен в это время. Передайте его в `resource_id` записи, чтобы записать именно к нему."
          }
        },
        "title": "Slot"
      }
    },
    "responses": {
      "ApiAddonRequired": {
        "description": "У компании не подключено дополнение «Публичный API» (api-addon-required).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "headers": {
          "Request-Id": {
            "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "Forbidden": {
        "description": "У ключа нет нужного права или доступа к проекту (forbidden).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "headers": {
          "Request-Id": {
            "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "IdempotencyConflict": {
        "description": "Idempotency-Key уже использован с другим запросом (idempotency-conflict) или первый запрос с ним ещё выполняется (idempotency-in-progress).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "headers": {
          "Request-Id": {
            "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "IdempotencyKeyInvalid": {
        "description": "Idempotency-Key в неверном формате (idempotency-key-invalid).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "headers": {
          "Request-Id": {
            "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "IdempotencyKeyRequired": {
        "description": "Нет заголовка Idempotency-Key (idempotency-key-required) или ключ в неверном формате (idempotency-key-invalid).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "headers": {
          "Request-Id": {
            "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "NotFound": {
        "description": "Объекта с таким id нет или он в проекте, которого нет в ключе (not-found).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "headers": {
          "Request-Id": {
            "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Превышен лимит запросов (rate-limited). Повторите через столько секунд, сколько указано в Retry-After.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "headers": {
          "Request-Id": {
            "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
            "schema": {
              "type": "string"
            }
          },
          "Retry-After": {
            "description": "Через сколько секунд можно повторить запрос.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Limit": {
            "description": "Сколько запросов разрешено за минуту.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Remaining": {
            "description": "Сколько запросов осталось в текущей минуте.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Reset": {
            "description": "Через сколько секунд счётчик обнулится.",
            "schema": {
              "type": "integer"
            }
          }
        }
      },
      "Unauthenticated": {
        "description": "Нет ключа, ключ неверный, истёк или отозван (unauthenticated).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "headers": {
          "Request-Id": {
            "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "Unavailable": {
        "description": "Сервис временно недоступен (unavailable). Повторите позже.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "headers": {
          "Request-Id": {
            "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "ValidationError": {
        "description": "Данные запроса не прошли проверку (validation). Какие поля и почему - в errors.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "headers": {
          "Request-Id": {
            "description": "id запроса. Укажите его, если пишете в поддержку о конкретном запросе.",
            "schema": {
              "type": "string"
            }
          }
        }
      }
    }
  }
}
