Перейти к содержимому
СервисАпп API
На этой странице

Договоры обслуживания

Все операции. Авторизация. Запросы и повторы.

Все пути в этом файле дополняют /api/v1 на домене организации.

Описание и ограничения

Назначение

Ведение договора клиента/объекта, состава оборудования, SLA, абонплаты, скидок и срока действия.

Доступные возможности и ограничения

Открыты список, карточка, создание, частичное изменение, чтение и полная замена состава оборудования, переход состояния. Доступ к API — «Энтерпрайз», «Энтерпрайз Про» или действующий пробный период; «Энтерпрайз Лайт» не включает API.

Требуются service_contracts:read, «Клиенты и поставщики → Просмотр», доступный модуль договоров и пересечение разрешённых мастерских. fee, discount_operations, discount_products и next_invoice_date включаются только с текущим «Деньги → Просмотр»; владелец получает их автоматически. Финансовые изменения дополнительно требуют «Деньги → Изменение» в мастерской договора. Вложенный GET состава требует equipment:read и «ТОиР — Оборудование → Просмотр»; сами ID в карточке договора не дают доступа к карточкам оборудования. GET не запускает биллинг или генерацию ТО.

data.version — строка Unix-секунд из updated_at. Два изменения в одну секунду могут иметь одинаковую версию. Для проверки изменений используйте правила синхронизации. Карточка также возвращает отдельный ETag своего представления. Изменение состава оборудования обновляет версию договора; запрос с прежним составом не создаёт событие.

Поля и назначение

Публичное поле Формат и смысл Доступ
id, number, title идентичность и наименование только чтение / чтение и запись
customer_id, customer_site_id, workshop_id клиент, объект и мастерская чтение и запись
status, billing_period перечисление состояния и периодичности отдельная команда / чтение и запись
fee денежная абонплата чтение и запись
reaction_hours, resolution_hours целые часы SLA/null чтение и запись
discount_operations, discount_products десятичные проценты чтение и запись
start_date, end_date календарные даты чтение и запись
equipment_ids список доступных единиц отдельная команда
next_invoice_date, next_maintenance_date вычисляемые календарные сроки только чтение
maintenance_interval_days положительное целое число/null; интервал автоматического обслуживания парка чтение и запись
note заметка/null с проверкой доступа чтение и запись

Обязательность и null указаны в схемах каждой операции ниже.

Доступ и выборка

service_contracts:read/write и «Клиенты и поставщики → Просмотр, Изменение»; финансовые поля требуют соответствующих полномочий; ТО дополнительно проверяет тариф.

Фильтры: customer_id, customer_site_id, workshop_id, status, start_from/to, end_from/to.

Запросы команд

Для создания требуются customer_id, workshop_id, title, billing_period и fee. Значения по умолчанию: status=draft, equipment_ids=[], customer_site_id=null, start_date/end_date=null, reaction_hours/resolution_hours=null, discount_operations/discount_products="0", maintenance_interval_days=null. billing_period: monthly/quarterly/yearly. fee неотрицательна в валюте организации, проценты — десятичные строки 0–100, SLA — положительные целые часы. Номер задаётся по штатной нумерации, если number не передан; явный number — непустая строка до 255 с проверкой конфликта. Автоматический график ТО появляется только при ненулевом maintenance_interval_days и активном договоре, а не из одного наличия next_maintenance_date в ответе.

fee допускает не более двух знаков после десятичной точки и сумму менее 10 000 000 000 по модулю. Избыточная точность не округляется: например, 1.001 в валюте с тремя дробными разрядами возвращает 422 до принятия операции.

POST equipment принимает { "equipment_ids": [1, 2] }, If-Resource-Version договора; это полная атомарная замена состава, [] очищает только при отсутствии блокирующих зависимостей, максимум 100. Status-команда принимает { "status": "active" }, If-Resource-Version договора: draft→active/ended, active→suspended/ended, suspended→active/ended. Ended не открывается повторно; тот же статус — changed=false. Активация проверяет даты, обязательный состав для автоматического ТО и связанные ограничения. Команды возвращают 200 с карточкой и affected_resources; create — 201. Недопустимый переход/состав — 409 CONTRACT_STATE_CONFLICT.

Правила и связи

  • Состав принадлежит одному клиенту и при заданном объекте — этому объекту.
  • Договорное ТО не создаёт построчные платные работы поверх включённой абонплаты.
  • Не отдавать/принимать произвольную HTML-разметку body вместо отдельного проверенного контракта документа.
  • Активизация запускает штатные сроки биллинга/ТО и не дублирует начисления при повторе.

Операции

Метод Путь Назначение
GET /service-contracts Список с фильтрами и пагинацией
POST /service-contracts Создание
GET /service-contracts/{id} Карточка
POST /service-contracts/{id}/update Изменение разрешённых полей
POST /service-contracts/{id}/equipment Установка согласованного состава оборудования
GET /service-contracts/{id}/equipment Состав обслуживаемых единиц
POST /service-contracts/{id}/status Изменение состояния договора

GET /service-contracts

Список с фильтрами и пагинацией.

Доступ. Разрешения подключения: service_contracts:read. Права сотрудника: «Клиенты и поставщики → Просмотр». Дополнительно действуют доступ к записям, мастерским, модулям и условия полей из описания ресурса выше.

Параметры

Имя Где Тип Обязательно null Ограничения
Authorization заголовок строка да нет Bearer <SERVICEAPP_TOKEN>
sort параметр запроса строка нет нет Допустимо: "id", "-id"
page[size] параметр запроса целое число нет нет ≥ 1; ≤ 100
page[cursor] параметр запроса строка нет нет не более 8192 символов
filter[customer_id] параметр запроса целое число нет нет ≥ 1
filter[customer_site_id] параметр запроса целое число нет нет ≥ 1
filter[workshop_id] параметр запроса целое число нет нет ≥ 1
filter[status] параметр запроса строка нет нет Допустимо: "draft", "active", "suspended", "ended"
filter[start_from] параметр запроса строка (дата) нет нет —
filter[start_to] параметр запроса строка (дата) нет нет —
filter[end_from] параметр запроса строка (дата) нет нет —
filter[end_to] параметр запроса строка (дата) нет нет —

Ответы

HTTP Назначение и схема
200 Успех. Полная схема и пример
401 Требуется действующий Bearer. Коды и формат ошибки
403 Недостаточно допуска. Коды и формат ошибки
409 Конфликт состояния или повтора. Коды и формат ошибки
422 Ошибка входных данных. Коды и формат ошибки
429 Лимит запросов, Retry-After. Коды и формат ошибки
503 Временно недоступно. Коды и формат ошибки

Каждый ответ содержит новый X-Request-Id в заголовке. Общие транспортные отказы и правила повтора действуют также при отказе до контроллера; см. ошибки.

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

Запускается из каталога комплекта после настройки переменных в быстром старте. Замените демонстрационные идентификаторы 101 и UUID идентификаторами доступных записей. $RESOURCE_VERSION берётся из GET владельца версии, описанного выше. Для нового действия сохраните новый ключ; для повтора используйте прежний.

curl --silent --show-error --globoff \
  "$API/service-contracts" \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  --header "Accept: application/json"

POST /service-contracts

Создание.

Доступ. Разрешения подключения: service_contracts:write. Права сотрудника: «Клиенты и поставщики → Изменение», «Клиенты и поставщики → Просмотр». Дополнительно действуют доступ к записям, мастерским, модулям и условия полей из описания ресурса выше.

Параметры

Имя Где Тип Обязательно null Ограничения
Authorization заголовок строка да нет Bearer <SERVICEAPP_TOKEN>
Idempotency-Key заголовок строка да нет не менее 1 символов; не более 128 символов; Шаблон: ^[A-Za-z0-9._:-]+$

Тело запроса

Content-Type: application/json. Тело обязательно.

Поле Тип Обязательно null Ограничения и смысл
customer_id целое число да нет ≥ 1
workshop_id целое число да нет ≥ 1
title строка да нет не менее 1 символов; не более 255 символов
number строка нет нет не менее 1 символов; не более 255 символов
customer_site_id целое число / null нет да ≥ 1
billing_period строка да нет Допустимо: "monthly", "quarterly", "yearly"
fee объект да нет Только перечисленные ключи
fee.amount строка да нет Шаблон: ^(?:0|[1-9][0-9]{0,9})(?:\.[0-9]{1,4})?$; Условие: required_with:fee
fee.currency строка да нет не менее 3 символов; не более 3 символов; Условие: required_with:fee
reaction_hours целое число / null нет да ≥ 1; ≤ 4294967295
resolution_hours целое число / null нет да ≥ 1; ≤ 4294967295
discount_operations число нет нет ≥ 0.0; ≤ 100.0; не менее 0 символов; не более 100 символов; Шаблон: ^(?:0|[1-9][0-9]*)(?:\.[0-9]{1,2})?$
discount_products число нет нет ≥ 0.0; ≤ 100.0; не менее 0 символов; не более 100 символов; Шаблон: ^(?:0|[1-9][0-9]*)(?:\.[0-9]{1,2})?$
start_date строка / null (дата) нет да —
end_date строка / null (дата) нет да —
maintenance_interval_days целое число / null нет да ≥ 1; ≤ 4294967295
note строка / null нет да не более 10000 символов

Ответы

HTTP Назначение и схема
201 Создано. Полная схема и пример
401 Требуется действующий Bearer. Коды и формат ошибки
403 Недостаточно допуска. Коды и формат ошибки
404 Не найдено или недоступно. Коды и формат ошибки
409 Конфликт состояния или повтора. Коды и формат ошибки
422 Ошибка входных данных. Коды и формат ошибки
429 Лимит запросов, Retry-After. Коды и формат ошибки
503 Временно недоступно. Коды и формат ошибки
HTTP Заголовок ответа Тип Описание
201 Location строка
201 Idempotency-Replayed строка

Каждый ответ содержит новый X-Request-Id в заголовке. Общие транспортные отказы и правила повтора действуют также при отказе до контроллера; см. ошибки.

У принятого POST Location и meta.operation_id указывают на журнал операции; ETag отсутствует. При повторе запроса сохраняются исходные data/meta, добавляется Idempotency-Replayed: true. Версии передавайте по назначению, указанному в описании ресурса.

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

Запускается из каталога комплекта после настройки переменных в быстром старте. Замените демонстрационные идентификаторы 101 и UUID идентификаторами доступных записей. $RESOURCE_VERSION берётся из GET владельца версии, описанного выше. Для нового действия сохраните новый ключ; для повтора используйте прежний.

curl --silent --show-error --globoff --request POST \
  "$API/service-contracts" \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  --header "Accept: application/json" \
  --header "Idempotency-Key: example:v1-service-contracts-store:001" \
  --header "Content-Type: application/json" \
  --data-binary '@examples/requests/v1.service-contracts.store.json'

GET /service-contracts/{id}

Карточка.

Доступ. Разрешения подключения: service_contracts:read. Права сотрудника: «Клиенты и поставщики → Просмотр». Дополнительно действуют доступ к записям, мастерским, модулям и условия полей из описания ресурса выше.

Параметры

Имя Где Тип Обязательно null Ограничения
Authorization заголовок строка да нет Bearer <SERVICEAPP_TOKEN>
id путь строка да нет Шаблон: ^(?:[0-9]+)$
If-None-Match заголовок строка нет нет —

Ответы

HTTP Назначение и схема
200 Успех. Полная схема и пример
304 Представление не изменилось, без тела. Условный GET
401 Требуется действующий Bearer. Коды и формат ошибки
403 Недостаточно допуска. Коды и формат ошибки
404 Не найдено или недоступно. Коды и формат ошибки
422 Ошибка входных данных. Коды и формат ошибки
429 Лимит запросов, Retry-After. Коды и формат ошибки
503 Временно недоступно. Коды и формат ошибки
HTTP Заголовок ответа Тип Описание
200 ETag строка
304 ETag строка

Каждый ответ содержит новый X-Request-Id в заголовке. Общие транспортные отказы и правила повтора действуют также при отказе до контроллера; см. ошибки.

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

Запускается из каталога комплекта после настройки переменных в быстром старте. Замените демонстрационные идентификаторы 101 и UUID идентификаторами доступных записей. $RESOURCE_VERSION берётся из GET владельца версии, описанного выше. Для нового действия сохраните новый ключ; для повтора используйте прежний.

curl --silent --show-error --globoff \
  "$API/service-contracts/101" \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  --header "Accept: application/json"

POST /service-contracts/{id}/update

Изменение разрешённых полей.

Доступ. Разрешения подключения: service_contracts:write. Права сотрудника: «Клиенты и поставщики → Изменение», «Клиенты и поставщики → Просмотр». Дополнительно действуют доступ к записям, мастерским, модулям и условия полей из описания ресурса выше.

Параметры

Имя Где Тип Обязательно null Ограничения
Authorization заголовок строка да нет Bearer <SERVICEAPP_TOKEN>
id путь строка да нет Шаблон: ^(?:[0-9]+)$
Idempotency-Key заголовок строка да нет не менее 1 символов; не более 128 символов; Шаблон: ^[A-Za-z0-9._:-]+$
If-Resource-Version заголовок строка да нет не менее 1 символов; не более 128 символов; Шаблон: ^[A-Za-z0-9._~-]+$

Тело запроса

Content-Type: application/json. Тело обязательно.

Поле Тип Обязательно null Ограничения и смысл
customer_id целое число нет нет ≥ 1
workshop_id целое число нет нет ≥ 1
title строка нет нет не менее 1 символов; не более 255 символов
number строка нет нет не менее 1 символов; не более 255 символов
customer_site_id целое число / null нет да ≥ 1
billing_period строка нет нет Допустимо: "monthly", "quarterly", "yearly"
fee объект нет нет Только перечисленные ключи
fee.amount строка да нет Шаблон: ^(?:0|[1-9][0-9]{0,9})(?:\.[0-9]{1,4})?$; Условие: required_with:fee
fee.currency строка да нет не менее 3 символов; не более 3 символов; Условие: required_with:fee
reaction_hours целое число / null нет да ≥ 1; ≤ 4294967295
resolution_hours целое число / null нет да ≥ 1; ≤ 4294967295
discount_operations число нет нет ≥ 0.0; ≤ 100.0; не менее 0 символов; не более 100 символов; Шаблон: ^(?:0|[1-9][0-9]*)(?:\.[0-9]{1,2})?$
discount_products число нет нет ≥ 0.0; ≤ 100.0; не менее 0 символов; не более 100 символов; Шаблон: ^(?:0|[1-9][0-9]*)(?:\.[0-9]{1,2})?$
start_date строка / null (дата) нет да —
end_date строка / null (дата) нет да —
maintenance_interval_days целое число / null нет да ≥ 1; ≤ 4294967295
note строка / null нет да не более 10000 символов

Ответы

HTTP Назначение и схема
200 Успех. Полная схема и пример
401 Требуется действующий Bearer. Коды и формат ошибки
403 Недостаточно допуска. Коды и формат ошибки
404 Не найдено или недоступно. Коды и формат ошибки
409 Конфликт состояния или повтора. Коды и формат ошибки
412 Версия устарела. Коды и формат ошибки
422 Ошибка входных данных. Коды и формат ошибки
428 Нужно предусловие версии. Коды и формат ошибки
429 Лимит запросов, Retry-After. Коды и формат ошибки
503 Временно недоступно. Коды и формат ошибки
HTTP Заголовок ответа Тип Описание
200 Location строка
200 Idempotency-Replayed строка

Каждый ответ содержит новый X-Request-Id в заголовке. Общие транспортные отказы и правила повтора действуют также при отказе до контроллера; см. ошибки.

У принятого POST Location и meta.operation_id указывают на журнал операции; ETag отсутствует. При повторе запроса сохраняются исходные data/meta, добавляется Idempotency-Replayed: true. Версии передавайте по назначению, указанному в описании ресурса.

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

Запускается из каталога комплекта после настройки переменных в быстром старте. Замените демонстрационные идентификаторы 101 и UUID идентификаторами доступных записей. $RESOURCE_VERSION берётся из GET владельца версии, описанного выше. Для нового действия сохраните новый ключ; для повтора используйте прежний.

curl --silent --show-error --globoff --request POST \
  "$API/service-contracts/101/update" \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  --header "Accept: application/json" \
  --header "Idempotency-Key: example:v1-service-contracts-update:001" \
  --header "If-Resource-Version: $RESOURCE_VERSION" \
  --header "Content-Type: application/json" \
  --data-binary '@examples/requests/v1.service-contracts.update.json'

POST /service-contracts/{id}/equipment

Установка согласованного состава оборудования.

Доступ. Разрешения подключения: service_contracts:write. Права сотрудника: «Клиенты и поставщики → Изменение», «Клиенты и поставщики → Просмотр». Дополнительно действуют доступ к записям, мастерским, модулям и условия полей из описания ресурса выше.

Параметры

Имя Где Тип Обязательно null Ограничения
Authorization заголовок строка да нет Bearer <SERVICEAPP_TOKEN>
id путь строка да нет Шаблон: ^(?:[0-9]+)$
Idempotency-Key заголовок строка да нет не менее 1 символов; не более 128 символов; Шаблон: ^[A-Za-z0-9._:-]+$
If-Resource-Version заголовок строка да нет не менее 1 символов; не более 128 символов; Шаблон: ^[A-Za-z0-9._~-]+$

Тело запроса

Content-Type: application/json. Тело обязательно.

Поле Тип Обязательно null Ограничения и смысл
equipment_ids массив да нет не менее 1 элементов; не более 100 элементов; Без повторов
equipment_ids[] целое число да нет ≥ 1

Ответы

HTTP Назначение и схема
200 Успех. Полная схема и пример
401 Требуется действующий Bearer. Коды и формат ошибки
403 Недостаточно допуска. Коды и формат ошибки
404 Не найдено или недоступно. Коды и формат ошибки
409 Конфликт состояния или повтора. Коды и формат ошибки
412 Версия устарела. Коды и формат ошибки
422 Ошибка входных данных. Коды и формат ошибки
428 Нужно предусловие версии. Коды и формат ошибки
429 Лимит запросов, Retry-After. Коды и формат ошибки
503 Временно недоступно. Коды и формат ошибки
HTTP Заголовок ответа Тип Описание
200 Location строка
200 Idempotency-Replayed строка

Каждый ответ содержит новый X-Request-Id в заголовке. Общие транспортные отказы и правила повтора действуют также при отказе до контроллера; см. ошибки.

У принятого POST Location и meta.operation_id указывают на журнал операции; ETag отсутствует. При повторе запроса сохраняются исходные data/meta, добавляется Idempotency-Replayed: true. Версии передавайте по назначению, указанному в описании ресурса.

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

Запускается из каталога комплекта после настройки переменных в быстром старте. Замените демонстрационные идентификаторы 101 и UUID идентификаторами доступных записей. $RESOURCE_VERSION берётся из GET владельца версии, описанного выше. Для нового действия сохраните новый ключ; для повтора используйте прежний.

curl --silent --show-error --globoff --request POST \
  "$API/service-contracts/101/equipment" \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  --header "Accept: application/json" \
  --header "Idempotency-Key: example:v1-service-contracts-equipment-set:001" \
  --header "If-Resource-Version: $RESOURCE_VERSION" \
  --header "Content-Type: application/json" \
  --data-binary '@examples/requests/v1.service-contracts.equipment.set.json'

GET /service-contracts/{id}/equipment

Состав обслуживаемых единиц.

Доступ. Разрешения подключения: service_contracts:read. Права сотрудника: «Клиенты и поставщики → Просмотр». Дополнительно действуют доступ к записям, мастерским, модулям и условия полей из описания ресурса выше.

Параметры

Имя Где Тип Обязательно null Ограничения
Authorization заголовок строка да нет Bearer <SERVICEAPP_TOKEN>
id путь строка да нет Шаблон: ^(?:[0-9]+)$
sort параметр запроса строка нет нет Допустимо: "id", "-id"
page[size] параметр запроса целое число нет нет ≥ 1; ≤ 100
page[cursor] параметр запроса строка нет нет не более 8192 символов

Ответы

HTTP Назначение и схема
200 Успех. Полная схема и пример
401 Требуется действующий Bearer. Коды и формат ошибки
403 Недостаточно допуска. Коды и формат ошибки
404 Не найдено или недоступно. Коды и формат ошибки
409 Конфликт состояния или повтора. Коды и формат ошибки
422 Ошибка входных данных. Коды и формат ошибки
429 Лимит запросов, Retry-After. Коды и формат ошибки
503 Временно недоступно. Коды и формат ошибки

Каждый ответ содержит новый X-Request-Id в заголовке. Общие транспортные отказы и правила повтора действуют также при отказе до контроллера; см. ошибки.

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

Запускается из каталога комплекта после настройки переменных в быстром старте. Замените демонстрационные идентификаторы 101 и UUID идентификаторами доступных записей. $RESOURCE_VERSION берётся из GET владельца версии, описанного выше. Для нового действия сохраните новый ключ; для повтора используйте прежний.

curl --silent --show-error --globoff \
  "$API/service-contracts/101/equipment" \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  --header "Accept: application/json"

POST /service-contracts/{id}/status

Изменение состояния договора.

Доступ. Разрешения подключения: service_contracts:write. Права сотрудника: «Клиенты и поставщики → Изменение», «Клиенты и поставщики → Просмотр». Дополнительно действуют доступ к записям, мастерским, модулям и условия полей из описания ресурса выше.

Параметры

Имя Где Тип Обязательно null Ограничения
Authorization заголовок строка да нет Bearer <SERVICEAPP_TOKEN>
id путь строка да нет Шаблон: ^(?:[0-9]+)$
Idempotency-Key заголовок строка да нет не менее 1 символов; не более 128 символов; Шаблон: ^[A-Za-z0-9._:-]+$
If-Resource-Version заголовок строка да нет не менее 1 символов; не более 128 символов; Шаблон: ^[A-Za-z0-9._~-]+$

Тело запроса

Content-Type: application/json. Тело обязательно.

Поле Тип Обязательно null Ограничения и смысл
status строка да нет Допустимо: "draft", "active", "suspended", "ended"

Ответы

HTTP Назначение и схема
200 Успех. Полная схема и пример
401 Требуется действующий Bearer. Коды и формат ошибки
403 Недостаточно допуска. Коды и формат ошибки
404 Не найдено или недоступно. Коды и формат ошибки
409 Конфликт состояния или повтора. Коды и формат ошибки
412 Версия устарела. Коды и формат ошибки
422 Ошибка входных данных. Коды и формат ошибки
428 Нужно предусловие версии. Коды и формат ошибки
429 Лимит запросов, Retry-After. Коды и формат ошибки
503 Временно недоступно. Коды и формат ошибки
HTTP Заголовок ответа Тип Описание
200 Location строка
200 Idempotency-Replayed строка

Каждый ответ содержит новый X-Request-Id в заголовке. Общие транспортные отказы и правила повтора действуют также при отказе до контроллера; см. ошибки.

У принятого POST Location и meta.operation_id указывают на журнал операции; ETag отсутствует. При повторе запроса сохраняются исходные data/meta, добавляется Idempotency-Replayed: true. Версии передавайте по назначению, указанному в описании ресурса.

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

Запускается из каталога комплекта после настройки переменных в быстром старте. Замените демонстрационные идентификаторы 101 и UUID идентификаторами доступных записей. $RESOURCE_VERSION берётся из GET владельца версии, описанного выше. Для нового действия сохраните новый ключ; для повтора используйте прежний.

curl --silent --show-error --globoff --request POST \
  "$API/service-contracts/101/status" \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  --header "Accept: application/json" \
  --header "Idempotency-Key: example:v1-service-contracts-status:001" \
  --header "If-Resource-Version: $RESOURCE_VERSION" \
  --header "Content-Type: application/json" \
  --data-binary '@examples/requests/v1.service-contracts.status.json'