Billing API
Документация по методам интеграции с биллингом, доступным снаружи как:
POST /frontend/billing/addressesPOST /frontend/billing/subscriptions
Внутренние PHP-обработчики лежат в:
server/api/billing/addresses.phpserver/api/billing/subscriptions.php
Общее
- Все методы требуют
Authorization: Bearer <TOKEN>. - Формат тела запроса:
Content-Type: application/json. - Успешный ответ приходит в стандартной обёртке frontend API:
{"addresses": {...}}для/frontend/billing/addresses{"subscriptions": {...}}для/frontend/billing/subscriptions- Ошибка приходит в виде
{"error":"..."}с HTTP-кодом frontend API.
Примеры ниже используют реальные адресные значения из https://rbt.sesameware.com по состоянию
на 2026-03-29:
- регион:
Тамбовская,regionUuid = a9a71961-9363-44ba-91b5-ddf0463aebc2 - город:
Тамбов,cityUuid = ea2a1270-1e19-4224-b1a0-4228b9de3c7a - улица:
Интернациональная,streetUuid = 47d50419-7bcc-486b-963f-962225731065 - дом:
69,houseUuid = b8ce5933-da5a-4ecd-b389-f081abd8e521 - существующие квартиры в этом доме:
1..8
Если запускать примеры импорта адресов на этой же базе, адресные сущности и часть квартир уже
существуют, поэтому в ответе нормально увидеть skipped, а не created.
В примерах subscriptions реальными взяты адресные UUID и номера квартир. Поля
subscriberID, agreement, login и password оставлены демонстрационными, потому что это уже
данные биллинга, а не адресного справочника RBT.
buildingUUID в методе subscriptions должен совпадать с UUID дома, который был загружен через
/frontend/billing/addresses в поле houseUuid.
POST /frontend/billing/addresses
Метод импортирует адресную иерархию из биллинга в RBT:
- регион;
- район;
- город;
- населённый пункт;
- улицу;
- дом;
- квартиры;
- список доступных услуг дома.
Если адресная сущность уже существует, она не создаётся повторно. Это относится к:
- региону
- району
- городу
- населённому пункту
- улице
- дому
Квартиры тоже не создаются повторно, но для них действует отдельная логика:
- квартира не участвует в сопоставлении по UUID или имени;
- она проверяется внутри конкретного дома по
flatNumber; - если квартира с таким номером в доме уже есть, она будет пропущена.
Поиск для этих сущностей идёт сначала по UUID, а если UUID не найден, то по имени. Для fallback по имени используются именно поля:
regionareacitysettlementstreethouse
Поля *WithType, *Type, *TypeFull и houseFull в fallback-сопоставлении не участвуют.
Если объект был найден по имени, а UUID отличается, импорт не падает, но в ответе увеличивается
uuidMismatches, а в errors добавляется запись вида *UuidMismatch.
Формат запроса
Тело запроса:
{
"addresses": [
{
"regionUuid": "a9a71961-9363-44ba-91b5-ddf0463aebc2",
"region": "Тамбовская",
"cityUuid": "ea2a1270-1e19-4224-b1a0-4228b9de3c7a",
"city": "Тамбов",
"streetUuid": "47d50419-7bcc-486b-963f-962225731065",
"street": "Интернациональная",
"houseUuid": "b8ce5933-da5a-4ecd-b389-f081abd8e521",
"house": "69"
}
]
}
Поля addresses[]
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
regionUuid |
string |
да | UUID региона |
region |
string |
да | Название региона |
areaUuid |
string |
нет | UUID района |
area |
string |
нет | Название района |
cityUuid |
string |
нет | UUID города |
city |
string |
нет | Название города |
settlementUuid |
string |
нет | UUID населённого пункта |
settlement |
string |
нет | Название населённого пункта |
streetUuid |
string |
нет | UUID улицы |
street |
string |
нет | Название улицы |
houseUuid |
string |
да | UUID дома |
house |
string |
да | Номер или имя дома |
services |
string[] |
нет | Список услуг дома |
flats |
object[] |
нет | Явный список квартир |
flatRanges |
object[] |
нет | Диапазоны квартир |
Дополнительные поля адреса
Можно передавать дополнительные атрибуты для нормального заполнения адресных сущностей:
regionIsoCoderegionWithType,regionType,regionTypeFullareaWithType,areaType,areaTypeFullcityWithType,cityType,cityTypeFullsettlementWithType,settlementType,settlementTypeFullstreetWithType,streetType,streetTypeFullhouseType,houseTypeFull,houseFulltimezonecompanyId- ID управляющей компании, обслуживающей дом
Если часть этих полей не передана, backend подставляет безопасные значения по умолчанию:
timezone->"-"как внутренний маркер "timezone не задан"; при сохранении в БД это превращается вnullhouseFull-> значениеhousecompanyId->0(дом без привязки к управляющей компании)*WithType-> обычное имя сущности
Поля *WithType, *Type, *TypeFull и houseFull нужны для сохранения и отображения полного
адреса в RBT. Для fallback-сопоставления они не используются.
Правила валидации
- Обязательны
regionUuid,region,houseUuid,house. - Должен быть указан хотя бы один из вариантов:
areaUuid + areacityUuid + city- Должен быть указан хотя бы один из вариантов:
settlementUuid + settlementstreetUuid + street- Если передана улица, то должен быть ещё и город или населённый пункт.
companyIdдолжен быть целым числом и означать ID управляющей компании в RBT.servicesдолжен быть массивом строк.- Разрешённые значения
services: internetiptvctvphonecctvdomophonegsm
Квартиры: flats
flats используется, когда биллинг передаёт явный список квартир.
Формат элемента:
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
flatNumber |
string |
да | Номер квартиры |
floor |
int |
нет | Этаж, по умолчанию 0 |
Особенности:
- если квартира уже существует в доме, она будет пропущена;
- если
floorневалиден, backend сохранит0.
Квартиры: flatRanges
flatRanges используется, когда в биллинге квартиры идут диапазонами.
Формат элемента:
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
fromFlat |
int|string |
да | Начало диапазона, только положительное целое |
toFlat |
int|string |
да | Конец диапазона, только положительное целое |
floor |
int |
нет | Этаж для всех квартир диапазона, по умолчанию 0 |
Особенности:
- диапазон разворачивается в последовательность квартир;
- если
fromFlat > toFlat, диапазон считается невалидным; - разрешены только положительные целые номера.
Что делает метод дополнительно
- Если передан
services, список услуг дома сохраняется в custom field домаservices. - Если передан
companyId, он используется как привязка дома к управляющей компании. - Если дом уже существует и в payload пришёл
companyId, текущий импорт обновитcompanyIdу найденного дома. - Если
companyIdв payload не пришёл, существующая привязка дома к управляющей компании не меняется. - Если в payload пришёл
timezone, текущий импорт обновитtimezoneу уже существующихregion,areaиcity. - Если
timezoneв payload не пришёл, существующие timezone у найденныхregion,areaиcityне меняются. - Перед сохранением услуги:
- приводятся к нижнему регистру;
- дедуплицируются;
- сортируются;
- сохраняются как строка через запятую.
Успешный ответ
{
"addresses": {
"processed": 1,
"invalid": 0,
"failed": 0,
"created": {
"regions": 0,
"areas": 0,
"cities": 1,
"settlements": 0,
"streets": 1,
"houses": 1,
"flats": 4
},
"skipped": {
"regions": 1,
"areas": 0,
"cities": 0,
"settlements": 0,
"streets": 0,
"houses": 0,
"flats": 0
},
"servicesUpdated": 1,
"uuidMismatches": 0,
"errors": []
}
}
Основные поля ответа
| Поле | Описание |
|---|---|
processed |
сколько элементов addresses[] обработано |
invalid |
сколько элементов отклонено из-за валидации |
failed |
сколько внутренних операций не удалось |
created.* |
сколько сущностей реально создано |
skipped.* |
сколько сущностей уже существовало |
servicesUpdated |
сколько домов получили обновление custom field services |
uuidMismatches |
сколько сущностей были найдены по имени, но с другим UUID |
errors[] |
список ошибок и предупреждений с деталями |
Пример 1. Минимальный импорт дома
API='https://<host>/frontend/billing/addresses'
TOKEN='<TOKEN>'
curl -sS "$API" \
-X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @- <<'JSON'
{
"addresses": [
{
"regionUuid": "a9a71961-9363-44ba-91b5-ddf0463aebc2",
"region": "Тамбовская",
"cityUuid": "ea2a1270-1e19-4224-b1a0-4228b9de3c7a",
"city": "Тамбов",
"streetUuid": "47d50419-7bcc-486b-963f-962225731065",
"street": "Интернациональная",
"houseUuid": "b8ce5933-da5a-4ecd-b389-f081abd8e521",
"house": "69",
"houseFull": "Россия, г Тамбов, ул Интернациональная, д 69",
"services": ["internet", "domophone"]
}
]
}
JSON
Пример 2. Импорт дома с *WithType, *Type, *TypeFull, houseFull
API='https://<host>/frontend/billing/addresses'
TOKEN='<TOKEN>'
curl -sS "$API" \
-X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @- <<'JSON'
{
"addresses": [
{
"regionUuid": "a9a71961-9363-44ba-91b5-ddf0463aebc2",
"region": "Тамбовская",
"regionWithType": "Тамбовская обл",
"regionType": "обл",
"regionTypeFull": "область",
"cityUuid": "ea2a1270-1e19-4224-b1a0-4228b9de3c7a",
"city": "Тамбов",
"cityWithType": "г Тамбов",
"cityType": "г",
"cityTypeFull": "город",
"streetUuid": "47d50419-7bcc-486b-963f-962225731065",
"street": "Интернациональная",
"streetWithType": "ул Интернациональная",
"streetType": "ул",
"streetTypeFull": "улица",
"houseUuid": "b8ce5933-da5a-4ecd-b389-f081abd8e521",
"house": "69",
"houseType": "д",
"houseTypeFull": "дом",
"houseFull": "Россия, г Тамбов, ул Интернациональная, д 69",
"timezone": "Europe/Moscow",
"services": ["internet", "iptv"],
"flats": [
{ "flatNumber": "1", "floor": 1 },
{ "flatNumber": "2", "floor": 1 },
{ "flatNumber": "3" },
{ "flatNumber": "4" }
]
}
]
}
JSON
Пример 3. Импорт дома с явным списком квартир
API='https://<host>/frontend/billing/addresses'
TOKEN='<TOKEN>'
curl -sS "$API" \
-X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @- <<'JSON'
{
"addresses": [
{
"regionUuid": "a9a71961-9363-44ba-91b5-ddf0463aebc2",
"region": "Тамбовская",
"cityUuid": "ea2a1270-1e19-4224-b1a0-4228b9de3c7a",
"city": "Тамбов",
"streetUuid": "47d50419-7bcc-486b-963f-962225731065",
"street": "Интернациональная",
"houseUuid": "b8ce5933-da5a-4ecd-b389-f081abd8e521",
"house": "69",
"services": ["internet", "iptv"],
"flats": [
{ "flatNumber": "1", "floor": 1 },
{ "flatNumber": "2", "floor": 1 },
{ "flatNumber": "3" },
{ "flatNumber": "4" }
]
}
]
}
JSON
Пример 4. Импорт дома с диапазонами квартир
API='https://<host>/frontend/billing/addresses'
TOKEN='<TOKEN>'
curl -sS "$API" \
-X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @- <<'JSON'
{
"addresses": [
{
"regionUuid": "a9a71961-9363-44ba-91b5-ddf0463aebc2",
"region": "Тамбовская",
"cityUuid": "ea2a1270-1e19-4224-b1a0-4228b9de3c7a",
"city": "Тамбов",
"streetUuid": "47d50419-7bcc-486b-963f-962225731065",
"street": "Интернациональная",
"houseUuid": "b8ce5933-da5a-4ecd-b389-f081abd8e521",
"house": "69",
"services": ["domophone", "gsm"],
"flatRanges": [
{ "fromFlat": 1, "toFlat": 4, "floor": 1 },
{ "fromFlat": 5, "toFlat": 8 }
]
}
]
}
JSON
POST /frontend/billing/subscriptions
Метод синхронизирует состояние абонентских договоров из биллинга с квартирами в RBT.
Что делает метод:
- выставляет
autoBlockквартиры по признаку активности договора; - при необходимости обновляет
flat.contract; - может обновить
flat.loginиflat.password; - может сохранить
agreementиaddressTextв custom fields квартиры; - может добавить телефоны абонента в квартиру RBT.
Важно для addressText:
- в текущей реализации это только справочное поле;
- оно просто сохраняется в custom field квартиры и может использоваться для отладки;
- заполнение адресных классификаторов выполняется через
/frontend/billing/addresses, а не через/frontend/billing/subscriptions.
Публичный frontend-метод всегда работает в режиме skipMissing:
- договоры, которых нет в текущем запросе, не блокируются и не разблокируются автоматически;
- параметр
defaultActionснаружи не передаётся.
Логика поиска квартиры
Каждый элемент subscribers[] должен содержать хотя бы один способ поиска:
subscriberID- или пару
buildingUUID + flatNumber
Порядок поиска:
- Если есть
buildingUUID + flatNumber, сначала ищется квартира по этой паре. - Если по паре квартира не найдена и есть
subscriberID, backend пытается найти квартиру поflat.contract = subscriberID. - Если по
subscriberIDнайдено несколько квартир, метод возвращает ошибкуmultipleFlatsByContractFallback.
Важно:
- если запрос был только по
subscriberID, fallback по договору считается штатным сценарием; - если в запросе были и
buildingUUID + flatNumber, иsubscriberID, но квартира нашлась только по fallback-договору, backend обновляетlogin/passwordиphones; autoBlockв этом fallback-сценарии обновляется только если в элементе был переданisActive;contract,agreementиaddressTextв этом fallback-сценарии не переписываются.
Как интерпретируется isActive
trueили1->autoBlock = 0falseили0->autoBlock = 1- если
isActiveне передан и элемент используется какphone-only-синхронизация,autoBlockне меняется
Формат запроса
{
"subscribers": [
{
"subscriberID": 1234,
"isActive": true,
"buildingUUID": "b8ce5933-da5a-4ecd-b389-f081abd8e521",
"flatNumber": "1"
}
]
}
Поля subscribers[]
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
isActive |
bool|int |
нет* | Состояние договора |
subscriberID |
int |
нет* | Идентификатор договора |
buildingUUID |
string |
нет* | UUID дома |
flatNumber |
string |
нет* | Номер квартиры |
agreement |
string |
нет | Номер договора для custom field квартиры |
addressText |
string |
нет | Справочный текстовый адрес; сохраняется только в custom field квартиры |
login |
string |
нет | Логин квартиры |
password |
string |
нет | Пароль квартиры |
phones |
object[] |
нет | Телефоны, которые нужно привязать к квартире |
* Обязательно хотя бы одно:
subscriberID- или пара
buildingUUID + flatNumber
* isActive обязателен, если элемент должен менять autoBlock. Его можно не передавать только
в режиме обновления телефонов, когда вместе с lookup-полями передаётся непустой phones[].
Поля phones[]
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
phone |
string|number |
да | Телефон абонента |
type |
string |
нет | owner или regular, по умолчанию regular |
Правила валидации и поведения
- Каждый элемент
subscribers[]должен быть объектом. isActiveобязателен для обычной синхронизации статуса договора.- Если
isActiveне передан, элемент должен содержать непустойphones[]; в этом режимеautoBlockне меняется. subscriberID, если передан, должен быть положительным целым.- Если передан
buildingUUID, то вместе с ним должен быть иflatNumber, и наоборот. agreementиaddressText, если переданы, должны быть непустыми строками.addressTextне участвует в поиске квартиры и не обновляет адресный справочник.loginиpassword, если переданы, должны быть строками.phonesдолжен быть массивом объектов.- Телефон нормализуется до цифр:
+79991234567->79991234567+442079460958->442079460958+380501234567->380501234567- Допустимая длина телефона после нормализации: от
10до15цифр. - Backend больше не делает автопреобразование локальных российских форматов.
- Телефон нужно передавать сразу с кодом страны. Для российских номеров используйте
+79...или79.... - Локальные форматы без кода страны не поддерживаются:
9991234567-> ошибка89123456781-> ошибка- Любой другой номер длиной от
10до15цифр после удаления нецифровых символов сохраняется как есть. - Один и тот же телефон нельзя передать дважды с разными
typeв рамках одного subscriber item.
Что обновляется в квартире
Если передан isActive:
autoBlock
При наличии subscriberID:
- если квартира найдена по
buildingUUID + flatNumber,contractобновляется значениемsubscriberID; - если запрос был только по
subscriberID, backend тоже передаётcontract = subscriberIDв patch квартиры, но обычно это то же самое значение, по которому квартира и была найдена.
При наличии login и/или password:
- если переданы оба поля, сохраняются оба;
- если передано только одно, второе дочитывается из текущей квартиры и сохраняется вместе с ним.
При наличии agreement и/или addressText:
- если квартира найдена:
- по
buildingUUID + flatNumber - или запрос был только по
subscriberID - создаются или нормализуются определения billing custom fields для
flat; - затем значения сохраняются в custom fields квартиры в режиме
patch.
Для addressText это означает только справочное сохранение:
- backend не использует его для поиска квартиры;
- backend не создаёт и не обновляет по нему регион/город/улицу/дом;
- адресный справочник нужно синхронизировать отдельно через
/frontend/billing/addresses.
Как работают phones
- Если телефон уже привязан к этой квартире, ничего не меняется.
- Если телефон ещё не привязан:
- вызывается добавление subscriber в RBT;
- телефон привязывается к текущей квартире.
- Если
type = owner, для новой связи с текущей квартирой выставляется роль owner. - Роли этого же subscriber в других квартирах не перетираются.
- Если элемент передан без
isActive, но с lookup-полями иphones[], метод работает какphone-only-синхронизация: телефоны обновляются, аautoBlockне меняется.
Успешный ответ
{
"subscriptions": {
"processed": 2,
"updated": 2,
"invalid": 0,
"notFound": 0,
"failed": 0,
"defaultAction": "skipMissing",
"missing": {
"updated": 0,
"unchanged": 0,
"failed": 0
},
"errors": []
}
}
Основные поля ответа
| Поле | Описание |
|---|---|
processed |
сколько элементов subscribers[] обработано |
updated |
сколько квартир успешно обновлено |
invalid |
сколько элементов отклонено по валидации |
notFound |
сколько элементов не удалось сопоставить с квартирой |
failed |
сколько внутренних операций завершились ошибкой |
defaultAction |
всегда skipMissing для frontend-метода |
missing.* |
служебный блок backend-режима для отсутствующих договоров |
errors[] |
список ошибок и предупреждений с деталями |
Пример 1. Обновление только телефонов без isActive
isActive можно не передавать, если элемент используется только для добавления телефонов к уже
найденной квартире.
API='https://<host>/frontend/billing/subscriptions'
TOKEN='<TOKEN>'
curl -sS "$API" \
-X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @- <<'JSON'
{
"subscribers": [
{
"buildingUUID": "b8ce5933-da5a-4ecd-b389-f081abd8e521",
"flatNumber": "1",
"phones": [
{
"phone": "+79990000011",
"type": "owner"
}
]
}
]
}
JSON
В этом примере:
- квартира ищется по
buildingUUID + flatNumber; - телефон будет добавлен к квартире, если его там ещё нет;
autoBlockне изменится, потому чтоisActiveне передан.
Пример 2. Минимальный запрос без agreement
agreement не является обязательным полем. Минимально достаточно передать способ поиска квартиры
и isActive.
API='https://<host>/frontend/billing/subscriptions'
TOKEN='<TOKEN>'
curl -sS "$API" \
-X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @- <<'JSON'
{
"subscribers": [
{
"subscriberID": 1234,
"isActive": true
}
]
}
JSON
В этом примере:
agreementне передаётся;addressText,login,password,phonesтоже не передаются;- backend просто найдёт квартиру по
subscriberIDи обновитautoBlock.
Пример 3. Основной сценарий: поиск по договору и по адресу
API='https://<host>/frontend/billing/subscriptions'
TOKEN='<TOKEN>'
curl -sS "$API" \
-X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @- <<'JSON'
{
"subscribers": [
{
"subscriberID": 1234,
"agreement": "1234",
"isActive": true,
"addressText": "Россия, г Тамбов, ул Интернациональная, д 69, кв 1",
"login": "demo-flat-1",
"password": "secret-1",
"buildingUUID": "b8ce5933-da5a-4ecd-b389-f081abd8e521",
"flatNumber": "1"
}
]
}
JSON
Что произойдёт:
- квартира ищется по
buildingUUID + flatNumber; autoBlockстанет0, потому чтоisActive=true;contractстанет1234;- обновятся
login/password; - в custom fields квартиры будут записаны
agreementиaddressText.
Пример 4. Поиск только по адресу квартиры
API='https://<host>/frontend/billing/subscriptions'
TOKEN='<TOKEN>'
curl -sS "$API" \
-X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @- <<'JSON'
{
"subscribers": [
{
"buildingUUID": "b8ce5933-da5a-4ecd-b389-f081abd8e521",
"flatNumber": "2",
"agreement": "A-0002",
"isActive": false
}
]
}
JSON
Что произойдёт:
- квартира ищется только по
buildingUUID + flatNumber; autoBlockстанет1, потому чтоisActive=false;agreementбудет записан в custom fields;contractне обновится, потому чтоsubscriberIDне передан.
Пример 5. Поиск только по subscriberID
API='https://<host>/frontend/billing/subscriptions'
TOKEN='<TOKEN>'
curl -sS "$API" \
-X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @- <<'JSON'
{
"subscribers": [
{
"subscriberID": 1234,
"agreement": "1234",
"isActive": true
}
]
}
JSON
Этот режим работает, только если по flat.contract = 1234 находится ровно одна квартира.
Пример 6. Синхронизация телефонов вместе со статусом договора
API='https://<host>/frontend/billing/subscriptions'
TOKEN='<TOKEN>'
curl -sS "$API" \
-X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @- <<'JSON'
{
"subscribers": [
{
"subscriberID": 1234,
"isActive": true,
"buildingUUID": "b8ce5933-da5a-4ecd-b389-f081abd8e521",
"flatNumber": "1",
"phones": [
{
"phone": "+79990000011",
"type": "owner"
},
{
"phone": "+79990000012",
"type": "regular"
}
]
}
]
}
JSON
Пример 7. Пакетная синхронизация нескольких квартир
API='https://<host>/frontend/billing/subscriptions'
TOKEN='<TOKEN>'
curl -sS "$API" \
-X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @- <<'JSON'
{
"subscribers": [
{
"subscriberID": 1234,
"agreement": "1234",
"isActive": true,
"addressText": "Россия, г Тамбов, ул Интернациональная, д 69, кв 1",
"buildingUUID": "b8ce5933-da5a-4ecd-b389-f081abd8e521",
"flatNumber": "1"
},
{
"subscriberID": 1235,
"agreement": "1235",
"isActive": true,
"addressText": "Россия, г Тамбов, ул Интернациональная, д 69, кв 2",
"buildingUUID": "b8ce5933-da5a-4ecd-b389-f081abd8e521",
"flatNumber": "2"
},
{
"buildingUUID": "b8ce5933-da5a-4ecd-b389-f081abd8e521",
"flatNumber": "3",
"isActive": false
}
]
}
JSON
Частые причины ошибок
Для /frontend/billing/addresses
invalidRequiredFields— нет обязательныхregionUuid/region/houseUuid/housemissingAreaOrCity— не переданы ни район, ни городmissingSettlementOrStreet— не переданы ни населённый пункт, ни улицаstreetRequiresCityOrSettlement— улица есть, но нет города и населённого пунктаinvalidServices/unknownService— проблемы со списком услугinvalidFlats/invalidFlatRanges/invalidFlatRange— проблемы с описанием квартир
Для /frontend/billing/subscriptions
invalidItem— элементsubscribers[]невалиденinvalidSubscriberID— некорректныйsubscriberIDbuildingUUIDAndFlatRequiredTogether— передана только одна часть парыinvalidBuildingUUIDFlat— пара передана, но значения пустые/некорректныеnoLookupParams— нет ниsubscriberID, ни парыbuildingUUID + flatNumberflatNotFound— квартира не найдена ни по паре, ни по договоруmultipleFlatsByContractFallback— поsubscriberIDнайдено больше одной квартирыphonesRequiredWithoutIsActive—isActiveне передан, ноphones[]отсутствуетinvalidPhone/invalidPhoneType/duplicatePhoneWithDifferentType— проблемы с телефонамиcantModifyFlat/cantModifyCustomFields/cantAddSubscriberPhone— внутренняя ошибка сохранения
Рекомендации по интеграции
- Сначала загрузите адресный справочник через
/frontend/billing/addresses. - После этого синхронизируйте договоры через
/frontend/billing/subscriptions. - Если используете режим поиска по адресу, следите, чтобы:
buildingUUIDбыл равенhouseUuid, который уже импортирован в RBT;flatNumberсовпадал с номером квартиры в RBT.- Если хотите обновлять billing custom fields
agreementиaddressText, достаточно просто начать передавать эти поля вsubscriptions: backend сам создаст нужные определения дляflat, если их ещё нет. addressTextвоспринимайте как справочное/отладочное поле квартиры. Для загрузки и обновления адресных классификаторов используйте/frontend/billing/addresses.