Перейти к содержимому
Разделы

Коммуникации с гостями

Передать подписанное событие доставки провайдера

POST/guest-communication-providers/{providerId}/events/delivery

Проверяет существующую HMAC-подпись провайдера и сохраняет постоянную защиту от повторной обработки события. Для доставок под управлением Core минимальный факт надёжно сохраняется до подтверждения приёма; общий обработчик проверяет зафиксированное начало попытки перед обновлением результата. Необязательный исходный messageId позволяет сопоставить событие при потере ответа провайдера. Исторические сообщения, не переданные Core, сохраняют исходного доменного владельца доставки. Профиль Hallify HMAC guest-provider использует HMAC-SHA256. Канонические входные данные: временная метка RFC3339 + "." + JSON.stringify разобранного DTO. Передавайте x-hallify-timestamp в формате rfc3339; метки за пределами ±300 секунд считаются устаревшими. Передавайте x-hallify-signature в формате base64url; сравнение не зависит от совпадающего префикса. Обработка секрета: используйте выданный секрет как текст UTF-8. Допустимый Content-Type: application/json. Некорректные данные: неверная подпись возвращает 401 GUEST_PROVIDER_WEBHOOK_UNAUTHORIZED. Устаревшие данные: временная метка за пределами окна в 300 секунд возвращает 401 GUEST_PROVIDER_WEBHOOK_UNAUTHORIZED. Повторная доставка: подпись не отклоняется только из-за повторения; доменная дедупликация использует идентификаторы сообщения и события провайдера.

Авторизация

x-hallify-signature: <HALLIFY_SIGNATURE>

Подпись HMAC-SHA256. Точный протокол каждой операции указан в метаданных x-hallify-hmac и её описании.

Руководство по подключению

Параметры

providerIdПуть · Обязательно

UUID Hallify. До чтения или изменения ресурса проверяется его принадлежность всем родительским арендаторам и агрегатам маршрута.

string · uuid
Полное определение
{
  "type": "string",
  "format": "uuid",
  "example": "9b6163a8-afea-4877-818b-8e2ae28a2845"
}
x-hallify-timestampЗаголовок · Обязательно

Время в формате RFC3339; допустимое расхождение часов — ±300 секунд.

string
Полное определение
{
  "type": "string",
  "example": "example"
}

Тело запроса

Обязательно

Идентификаторы события и сообщения провайдера, статус доставки, время события и необязательные метаданные провайдера: подписанное обновление доставки.

application/json

GuestProviderDeliveryEventDto
Полное определение
{
  "$ref": "#/components/schemas/GuestProviderDeliveryEventDto"
}

Ответы

200Подтверждает надёжное сохранение подписанного события и сообщает, было ли оно повторным; результаты доставок под управлением Core обновляются асинхронно.
GuestProviderWebhooksDeliveryResultDto
Полное определение
{
  "$ref": "#/components/schemas/GuestProviderWebhooksDeliveryResultDto"
}
Пример ответа · 200 · application/json
{
  "accepted": true,
  "duplicate": true
}
400Некорректный идентификатор провайдера или тело события доставки.
TranslatedErrorDto
Полное определение
{
  "$ref": "#/components/schemas/TranslatedErrorDto"
}
Пример ответа · 400 · application/json
{
  "statusCode": 400,
  "error": "errors:http.badRequest",
  "code": "HTTP_BAD_REQUEST",
  "message": "errors:http.badRequest",
  "translationKey": "errors:http.badRequest"
}
401Провайдер недоступен либо его HMAC-подпись недействительна или просрочена.
TranslatedErrorDto
Полное определение
{
  "$ref": "#/components/schemas/TranslatedErrorDto"
}
Пример ответа · 401 · application/json
{
  "statusCode": 401,
  "error": "errors:http.unauthorized",
  "code": "HTTP_UNAUTHORIZED",
  "message": "errors:http.unauthorized",
  "translationKey": "errors:http.unauthorized"
}
404Указанное сообщение гостя не найдено.
TranslatedErrorDto
Полное определение
{
  "$ref": "#/components/schemas/TranslatedErrorDto"
}
Пример ответа · 404 · application/json
{
  "statusCode": 404,
  "error": "errors:http.notFound",
  "code": "HTTP_NOT_FOUND",
  "message": "errors:http.notFound",
  "translationKey": "errors:http.notFound"
}
503Не удалось расшифровать секрет подписи провайдера.
TranslatedErrorDto
Полное определение
{
  "$ref": "#/components/schemas/TranslatedErrorDto"
}
Пример ответа · 503 · application/json
{
  "statusCode": 503,
  "error": "errors:http.serviceUnavailable",
  "code": "HTTP_SERVICE_UNAVAILABLE",
  "message": "errors:http.serviceUnavailable",
  "translationKey": "errors:http.serviceUnavailable"
}

Схемы

GuestProviderDeliveryEventDto

Проверяет событие провайдера, устраняет повторы и обновляет состояние доставки указанного исходящего сообщения без перезаписи прежних попыток.

externalEventIdОбязательно

Непрозрачный идентификатор externalEventId; клиент не должен предполагать формат UUID. Ограничения: максимальная длина 191.

string
Полное определение
{
  "type": "string",
  "maxLength": 191,
  "description": "Непрозрачный идентификатор `externalEventId`; клиент не должен предполагать формат UUID. Ограничения: максимальная длина 191.",
  "example": "example-id"
}
externalMessageIdОбязательно

Непрозрачный идентификатор externalMessageId; клиент не должен предполагать формат UUID. Ограничения: максимальная длина 191.

string
Полное определение
{
  "type": "string",
  "maxLength": 191,
  "description": "Непрозрачный идентификатор `externalMessageId`; клиент не должен предполагать формат UUID. Ограничения: максимальная длина 191.",
  "example": "Synthetic example"
}
statusОбязательно

Статус сообщения по данным провайдера. Приём событий доставки допускает SENT, DELIVERED и FAILED; остальные внутренние состояния сообщения отклоняются политикой доставки.

string
Полное определение
{
  "type": "string",
  "enum": [
    "QUEUED",
    "SENDING",
    "CORE_PENDING",
    "CORE_UNKNOWN",
    "CORE_FAILED",
    "SENT",
    "DELIVERED",
    "FAILED",
    "RECEIVED"
  ],
  "example": "DELIVERED",
  "description": "Статус сообщения по данным провайдера. Приём событий доставки допускает SENT, DELIVERED и FAILED; остальные внутренние состояния сообщения отклоняются политикой доставки."
}
occurredAtОбязательно

Время occurredAt в формате RFC3339; разные часовые смещения могут обозначать один абсолютный момент.

string · date-time
Полное определение
{
  "type": "string",
  "format": "date-time",
  "description": "Время `occurredAt` в формате RFC3339; разные часовые смещения могут обозначать один абсолютный момент.",
  "example": "2026-01-15T12:00:00.000Z"
}
payloadНеобязательно

Структурированное тело события или провайдера для обновления доставки гостевого сообщения.

object
Полное определение
{
  "type": "object",
  "additionalProperties": {
    "$ref": "#/components/schemas/JsonValue"
  },
  "description": "Структурированное тело события или провайдера для обновления доставки гостевого сообщения.",
  "example": {
    "exampleKey": "example"
  }
}
messageIdНеобязательно

Исходный Hallify messageId из исходящего запроса, включая /send/{generation} для повторной отправки кода бронирования или префикс portal-reentry/ для новых операций повторного входа по телефону. Позволяет сопоставить событие при потере ответа провайдера; не предоставляет гостевой доступ.

string · null
Полное определение
{
  "type": "string",
  "nullable": true,
  "minLength": 1,
  "maxLength": 128,
  "example": "portal-reentry/8d7f4a91-86d9-4ef9-ae07-77b99d10a823",
  "description": "Исходный Hallify messageId из исходящего запроса, включая /send/{generation} для повторной отправки кода бронирования или префикс portal-reentry/ для новых операций повторного входа по телефону. Позволяет сопоставить событие при потере ответа провайдера; не предоставляет гостевой доступ."
}
Полное определение
{
  "type": "object",
  "properties": {
    "externalEventId": {
      "type": "string",
      "maxLength": 191,
      "description": "Непрозрачный идентификатор `externalEventId`; клиент не должен предполагать формат UUID. Ограничения: максимальная длина 191.",
      "example": "example-id"
    },
    "externalMessageId": {
      "type": "string",
      "maxLength": 191,
      "description": "Непрозрачный идентификатор `externalMessageId`; клиент не должен предполагать формат UUID. Ограничения: максимальная длина 191.",
      "example": "Synthetic example"
    },
    "status": {
      "type": "string",
      "enum": [
        "QUEUED",
        "SENDING",
        "CORE_PENDING",
        "CORE_UNKNOWN",
        "CORE_FAILED",
        "SENT",
        "DELIVERED",
        "FAILED",
        "RECEIVED"
      ],
      "example": "DELIVERED",
      "description": "Статус сообщения по данным провайдера. Приём событий доставки допускает SENT, DELIVERED и FAILED; остальные внутренние состояния сообщения отклоняются политикой доставки."
    },
    "occurredAt": {
      "type": "string",
      "format": "date-time",
      "description": "Время `occurredAt` в формате RFC3339; разные часовые смещения могут обозначать один абсолютный момент.",
      "example": "2026-01-15T12:00:00.000Z"
    },
    "payload": {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/components/schemas/JsonValue"
      },
      "description": "Структурированное тело события или провайдера для обновления доставки гостевого сообщения.",
      "example": {
        "exampleKey": "example"
      }
    },
    "messageId": {
      "type": "string",
      "nullable": true,
      "minLength": 1,
      "maxLength": 128,
      "example": "portal-reentry/8d7f4a91-86d9-4ef9-ae07-77b99d10a823",
      "description": "Исходный Hallify messageId из исходящего запроса, включая /send/{generation} для повторной отправки кода бронирования или префикс portal-reentry/ для новых операций повторного входа по телефону. Позволяет сопоставить событие при потере ответа провайдера; не предоставляет гостевой доступ."
    }
  },
  "required": [
    "externalEventId",
    "externalMessageId",
    "status",
    "occurredAt"
  ],
  "description": "Проверяет событие провайдера, устраняет повторы и обновляет состояние доставки указанного исходящего сообщения без перезаписи прежних попыток.",
  "example": {
    "externalEventId": "example-id",
    "externalMessageId": "Synthetic example",
    "status": "DELIVERED",
    "occurredAt": "2026-01-15T12:00:00.000Z"
  }
}
JsonValue

Рекурсивно допустимое JSON-значение. Используется только там, где контракт явно разрешает произвольные структурированные данные.

Полное определение
{
  "oneOf": [
    {
      "type": "string",
      "nullable": true,
      "example": "example"
    },
    {
      "type": "number",
      "example": 0
    },
    {
      "type": "boolean",
      "example": true
    },
    {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/JsonValue"
      },
      "example": [
        "example"
      ]
    },
    {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/components/schemas/JsonValue"
      },
      "example": {
        "exampleKey": "example"
      }
    }
  ],
  "description": "Рекурсивно допустимое JSON-значение. Используется только там, где контракт явно разрешает произвольные структурированные данные.",
  "example": "example"
}
GuestProviderWebhooksDeliveryResultDto

Возвращает обновлённое состояние доставки сообщения и признак нового применения или повтора события.

acceptedОбязательно

Допустимые значения accepted: true.

boolean
Полное определение
{
  "type": "boolean",
  "enum": [
    true
  ],
  "description": "Допустимые значения `accepted`: true.",
  "example": true
}
duplicateОбязательно

Было ли переданное событие уже принято и обработано как повтор.

boolean
Полное определение
{
  "type": "boolean",
  "description": "Было ли переданное событие уже принято и обработано как повтор.",
  "example": true
}
Полное определение
{
  "type": "object",
  "required": [
    "accepted",
    "duplicate"
  ],
  "properties": {
    "accepted": {
      "type": "boolean",
      "enum": [
        true
      ],
      "description": "Допустимые значения `accepted`: true.",
      "example": true
    },
    "duplicate": {
      "type": "boolean",
      "description": "Было ли переданное событие уже принято и обработано как повтор.",
      "example": true
    }
  },
  "description": "Возвращает обновлённое состояние доставки сообщения и признак нового применения или повтора события.",
  "example": {
    "accepted": true,
    "duplicate": true
  }
}
TranslatedErrorDto

Стабильная оболочка ошибки общего обработчика HTTP-исключений. Дополнительные машинные данные домена вложены в details.

statusCodeОбязательно

HTTP-статус, повторённый из ответа.

integer
Полное определение
{
  "type": "integer",
  "description": "HTTP-статус, повторённый из ответа.",
  "example": 400
}
errorОбязательно

Ключ перевода HTTP-категории, например errors:http.conflict. Конкретную причину определяют code и translationKey.

string
Полное определение
{
  "type": "string",
  "description": "Ключ перевода HTTP-категории, например errors:http.conflict. Конкретную причину определяют code и translationKey.",
  "example": "errors.request.invalid"
}
codeОбязательно

Стабильный машинный код домена либо стандартный HTTP_*, если доменный код не задан. Используйте это поле и HTTP-статус для программной логики; локализованная формулировка не управляет повторами или бизнес-решениями.

string
Полное определение
{
  "type": "string",
  "example": "HTTP_BAD_REQUEST",
  "description": "Стабильный машинный код домена либо стандартный HTTP_*, если доменный код не задан. Используйте это поле и HTTP-статус для программной логики; локализованная формулировка не управляет повторами или бизнес-решениями."
}
messageОбязательно

Ключ перевода, идентичный translationKey. API не возвращает локализованный текст интерфейса. Найдите перевод ключа и подставьте translationValues в приложении-потребителе.

string
Полное определение
{
  "type": "string",
  "example": "errors:http.badRequest",
  "description": "Ключ перевода, идентичный translationKey. API не возвращает локализованный текст интерфейса. Найдите перевод ключа и подставьте translationValues в приложении-потребителе."
}
translationKeyОбязательно

Канонический ключ перевода, идентичный message. Ключи errors:http.* соответствующего статуса описывают неуточнённые ошибки. Публичные ключи и пояснения EN/RU перечислены в Developers; неизвестный ключ требует локализованного запасного сообщения в клиенте.

string
Полное определение
{
  "type": "string",
  "example": "errors:http.badRequest",
  "description": "Канонический ключ перевода, идентичный message. Ключи errors:http.* соответствующего статуса описывают неуточнённые ошибки. Публичные ключи и пояснения EN/RU перечислены в Developers; неизвестный ключ требует локализованного запасного сообщения в клиенте."
}
translationValuesНеобязательно

Необязательные скалярные значения параметров шаблона перевода. Обрабатывайте их как данные, экранируйте при отображении и никогда не используйте как настройки переводчика.

object
Полное определение
{
  "type": "object",
  "additionalProperties": {
    "oneOf": [
      {
        "type": "string",
        "example": "example"
      },
      {
        "type": "number",
        "example": 0
      },
      {
        "type": "boolean",
        "example": true
      }
    ],
    "example": "example"
  },
  "description": "Необязательные скалярные значения параметров шаблона перевода. Обрабатывайте их как данные, экранируйте при отображении и никогда не используйте как настройки переводчика.",
  "example": {
    "exampleKey": "example"
  }
}
validationErrorsНеобязательно

Ошибки проверки полей с ключами переводов и стабильными кодами валидаторов. Введённые значения и исходные тексты валидаторов не включаются.

array
Полное определение
{
  "description": "Ошибки проверки полей с ключами переводов и стабильными кодами валидаторов. Введённые значения и исходные тексты валидаторов не включаются.",
  "type": "array",
  "items": {
    "$ref": "#/components/schemas/ValidationErrorDto"
  },
  "example": [
    {
      "field": "email",
      "translationKey": "validation:isEmail",
      "code": "isEmail",
      "message": "validation:isEmail"
    }
  ]
}
detailsНеобязательно

Необязательные сведения о доменных препятствиях или ошибках валидации.

oneOf
Полное определение
{
  "description": "Необязательные сведения о доменных препятствиях или ошибках валидации.",
  "oneOf": [
    {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/JsonValue"
      },
      "example": [
        "example"
      ]
    },
    {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/components/schemas/JsonValue"
      },
      "example": {
        "exampleKey": "example"
      }
    }
  ],
  "example": [
    "example"
  ]
}
Полное определение
{
  "type": "object",
  "properties": {
    "statusCode": {
      "type": "integer",
      "description": "HTTP-статус, повторённый из ответа.",
      "example": 400
    },
    "error": {
      "type": "string",
      "description": "Ключ перевода HTTP-категории, например errors:http.conflict. Конкретную причину определяют code и translationKey.",
      "example": "errors.request.invalid"
    },
    "code": {
      "type": "string",
      "example": "HTTP_BAD_REQUEST",
      "description": "Стабильный машинный код домена либо стандартный HTTP_*, если доменный код не задан. Используйте это поле и HTTP-статус для программной логики; локализованная формулировка не управляет повторами или бизнес-решениями."
    },
    "message": {
      "type": "string",
      "example": "errors:http.badRequest",
      "description": "Ключ перевода, идентичный translationKey. API не возвращает локализованный текст интерфейса. Найдите перевод ключа и подставьте translationValues в приложении-потребителе."
    },
    "translationKey": {
      "type": "string",
      "example": "errors:http.badRequest",
      "description": "Канонический ключ перевода, идентичный message. Ключи errors:http.* соответствующего статуса описывают неуточнённые ошибки. Публичные ключи и пояснения EN/RU перечислены в Developers; неизвестный ключ требует локализованного запасного сообщения в клиенте."
    },
    "translationValues": {
      "type": "object",
      "additionalProperties": {
        "oneOf": [
          {
            "type": "string",
            "example": "example"
          },
          {
            "type": "number",
            "example": 0
          },
          {
            "type": "boolean",
            "example": true
          }
        ],
        "example": "example"
      },
      "description": "Необязательные скалярные значения параметров шаблона перевода. Обрабатывайте их как данные, экранируйте при отображении и никогда не используйте как настройки переводчика.",
      "example": {
        "exampleKey": "example"
      }
    },
    "validationErrors": {
      "description": "Ошибки проверки полей с ключами переводов и стабильными кодами валидаторов. Введённые значения и исходные тексты валидаторов не включаются.",
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/ValidationErrorDto"
      },
      "example": [
        {
          "field": "email",
          "translationKey": "validation:isEmail",
          "code": "isEmail",
          "message": "validation:isEmail"
        }
      ]
    },
    "details": {
      "description": "Необязательные сведения о доменных препятствиях или ошибках валидации.",
      "oneOf": [
        {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/JsonValue"
          },
          "example": [
            "example"
          ]
        },
        {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/components/schemas/JsonValue"
          },
          "example": {
            "exampleKey": "example"
          }
        }
      ],
      "example": [
        "example"
      ]
    }
  },
  "required": [
    "statusCode",
    "error",
    "code",
    "message",
    "translationKey"
  ],
  "description": "Стабильная оболочка ошибки общего обработчика HTTP-исключений. Дополнительные машинные данные домена вложены в details.",
  "example": {
    "statusCode": 400,
    "error": "errors:http.badRequest",
    "code": "HTTP_BAD_REQUEST",
    "message": "errors:http.badRequest",
    "translationKey": "errors:http.badRequest"
  }
}
ValidationErrorDto

Ошибка проверки поля с путём поля, стабильным кодом валидатора и ключом перевода. Человекочитаемый текст принадлежит приложению-потребителю.

fieldОбязательно

Публичный путь поля. Вложенные свойства и индексы массива разделены точками.

string
Полное определение
{
  "type": "string",
  "example": "email",
  "description": "Публичный путь поля. Вложенные свойства и индексы массива разделены точками."
}
translationKeyОбязательно

Ключ перевода этого валидатора, идентичный message. Найдите его в клиентском словаре; см. публичный каталог ошибок Developers.

string
Полное определение
{
  "type": "string",
  "example": "validation:isEmail",
  "description": "Ключ перевода этого валидатора, идентичный message. Найдите его в клиентском словаре; см. публичный каталог ошибок Developers."
}
codeОбязательно

Стабильный идентификатор валидатора для ошибки поля. Пользовательские валидаторы могут определять дополнительные идентификаторы.

string
Полное определение
{
  "type": "string",
  "example": "isEmail",
  "description": "Стабильный идентификатор валидатора для ошибки поля. Пользовательские валидаторы могут определять дополнительные идентификаторы."
}
messageОбязательно

Ключ перевода, описывающий ошибку проверки поля, идентичный translationKey. Введённые значения и тексты валидаторов не включаются.

string
Полное определение
{
  "type": "string",
  "example": "validation:isEmail",
  "description": "Ключ перевода, описывающий ошибку проверки поля, идентичный translationKey. Введённые значения и тексты валидаторов не включаются."
}
translationValuesНеобязательно

Необязательные скалярные значения параметров шаблона перевода. Обрабатывайте их как данные, экранируйте при отображении и никогда не используйте как настройки переводчика.

object
Полное определение
{
  "type": "object",
  "additionalProperties": {
    "oneOf": [
      {
        "type": "string",
        "example": "example"
      },
      {
        "type": "number",
        "example": 0
      },
      {
        "type": "boolean",
        "example": true
      }
    ],
    "example": "example"
  },
  "description": "Необязательные скалярные значения параметров шаблона перевода. Обрабатывайте их как данные, экранируйте при отображении и никогда не используйте как настройки переводчика.",
  "example": {
    "exampleKey": "example"
  }
}
Полное определение
{
  "type": "object",
  "properties": {
    "field": {
      "type": "string",
      "example": "email",
      "description": "Публичный путь поля. Вложенные свойства и индексы массива разделены точками."
    },
    "translationKey": {
      "type": "string",
      "example": "validation:isEmail",
      "description": "Ключ перевода этого валидатора, идентичный message. Найдите его в клиентском словаре; см. публичный каталог ошибок Developers."
    },
    "code": {
      "type": "string",
      "example": "isEmail",
      "description": "Стабильный идентификатор валидатора для ошибки поля. Пользовательские валидаторы могут определять дополнительные идентификаторы."
    },
    "message": {
      "type": "string",
      "example": "validation:isEmail",
      "description": "Ключ перевода, описывающий ошибку проверки поля, идентичный translationKey. Введённые значения и тексты валидаторов не включаются."
    },
    "translationValues": {
      "type": "object",
      "additionalProperties": {
        "oneOf": [
          {
            "type": "string",
            "example": "example"
          },
          {
            "type": "number",
            "example": 0
          },
          {
            "type": "boolean",
            "example": true
          }
        ],
        "example": "example"
      },
      "description": "Необязательные скалярные значения параметров шаблона перевода. Обрабатывайте их как данные, экранируйте при отображении и никогда не используйте как настройки переводчика.",
      "example": {
        "exampleKey": "example"
      }
    }
  },
  "required": [
    "field",
    "translationKey",
    "code",
    "message"
  ],
  "description": "Ошибка проверки поля с путём поля, стабильным кодом валидатора и ключом перевода. Человекочитаемый текст принадлежит приложению-потребителю.",
  "example": {
    "field": "email",
    "translationKey": "validation:isEmail",
    "code": "isEmail",
    "message": "validation:isEmail"
  }
}

Hallify использует обязательные cookies и опциональную аналитику.

Обязательные cookies поддерживают вход, язык и тему. Аналитика выключена, пока вы явно ее не разрешите.