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

# Настройка Webhook

> Получайте события YCloud на вашей конечной точке HTTPS.

## Что это такое

Webhook — это HTTPS-запросы, которые YCloud отправляет вашему приложению при изменении статуса доставки сообщений, входящих сообщений, контактов, шаблонов, звонков и других ресурсов.

## Перед началом работы

* Сохраните свой API-ключ YCloud в `YCLOUD_API_KEY`.
* Разверните общедоступную конечную точку HTTPS.
* Сохраняйте необработанное тело запроса (raw request body) для проверки подписи.
* Определите, какие типы событий требуются вашему приложению.

## Как это работает

1. Создайте конечную точку Webhook и подпишите её на типы событий.
2. Сохраните возвращенный `secret` конечной точки.
3. YCloud отправляет запрос события на вашу конечную точку.
4. Проверьте `YCloud-Signature`, прежде чем доверять запросу.
5. Своевременно верните ответ `2xx`.
6. Обрабатывайте событие идемпотентно, так как доставка может повторяться.

## Запрос

Создайте конечную точку с помощью `POST /webhookEndpoints`.

### Поля запроса

| Поле | Обязательно | Описание |
| - | - | - |
| `url` | Да | Публичный URL HTTPS, принимающий запросы событий. Максимум 500 символов. |
| `enabledEvents` | Да | Типы событий, доставляемые на эту конечную точку. |
| `eventProperties` | Условно | Свойства, включаемые для выбранных типов событий. Обязательно для `contact.attributes_changed`. |
| `description` | Нет | Описание конечной точки. Максимум 400 символов. |
| `status` | Нет | Начальный статус конечной точки. |

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

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request POST https://api.ycloud.com/v2/webhookEndpoints \
  --header "X-API-Key: $YCLOUD_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "url": "https://example.com/webhooks/ycloud",
    "enabledEvents": [
      "whatsapp.inbound_message.received",
      "whatsapp.message.updated",
      "sms.message.updated"
    ],
    "description": "Production messaging events"
}'
```

### Подписка на события echo и handover

Для агентов, подключенных через общедоступный REST API, создайте конечную точку со следующими подписками. Агенты, созданные в консоли, не генерируют эти три события. Чтобы изменить существующую конечную точку, сохраните подписки на события, которые вам всё ещё нужны.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request POST https://api.ycloud.com/v2/webhookEndpoints \
  --header "X-API-Key: $YCLOUD_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "url": "https://example.com/webhooks/ycloud",
    "enabledEvents": [
      "whatsapp.echo_message.created",
      "whatsapp.echo_message.updated",
      "whatsapp.meta_business_agent.handover.updated",
      "whatsapp.inbound_message.received"
    ],
    "description": "API Agent echo and handover events"
  }'
```

Два типа событий echo содержат стандартную полезную нагрузку `whatsappMessage` в формате сообщения. Событие handover передает `whatsappMetaBusinessAgent` и сохраняет информацию об агенте/управлении. Они не используют формат `whatsapp.smb.message.echoes` приложения WhatsApp Business. См. [подробности о событиях echo и handover](/ru/api-reference/guides/examples/webhook-examples/overview#echo-and-agent-handover-events) для определений полей, примеров, порядка и ограничений корреляции handover.

## Ответ

В ответе возвращаются созданная конечная точка и её секрет подписи `secret`. Храните секрет в безопасности. YCloud использует его для создания подписей Webhook.

### Пример ответа

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "id": "WEBHOOK_ENDPOINT_ID",
  "url": "https://example.com/webhooks/ycloud",
  "enabledEvents": [
    "whatsapp.inbound_message.received",
    "whatsapp.message.updated",
    "sms.message.updated"
  ],
  "description": "Production messaging events",
  "status": "active",
  "secret": "whsec_REPLACE_WITH_RETURNED_SECRET",
  "createTime": "2026-07-16T12:00:00.000Z",
  "updateTime": "2026-07-16T12:00:00.000Z"
}
```

### Поля ответа

| Поле | Описание |
| - | - |
| `id` | Идентификатор конечной точки Webhook, используемый для получения, обновления, удаления или смены секрета конечной точки. |
| `url` | URL назначения для доставки событий. |
| `enabledEvents` | Включенные в настоящее время типы событий. |
| `status` | Текущее состояние конечной точки. |
| `secret` | Секрет, используемый для проверки `YCloud-Signature`. Храните его в безопасности. |
| `createTime`, `updateTime` | Временные метки конечной точки в формате RFC 3339. |

## Получение событий

### Запрос события

YCloud отправляет объект события JSON на настроенный `url`. Событие содержит общие поля, такие как `id`, `type`, `apiVersion` и `createTime`, а также полезную нагрузку, зависящую от типа события.

Ваш обработчик должен:

1. Считывать необработанное тело запроса.
2. Проверять заголовок `YCloud-Signature` с помощью секрета конечной точки перед обработкой полезной нагрузки.
3. Своевременно возвращать успешный ответ `2xx`.
4. Переносить длительную обработку в очередь.
5. Обеспечивать идемпотентность обработки событий, чтобы повторная доставка не дублировала бизнес-действия.

<Warning>
  Не парсить и не изменять тело запроса до валидации подписи. Используйте исходные необработанные байты, полученные вашим сервером.
</Warning>

### Ответ приемника

Возвращайте успешный HTTP-ответ `2xx`, как только подпись и запрос будут приняты. Тело ответа может быть пустым.

```http theme={"theme":{"light":"github-light","dark":"github-dark"}}
HTTP/1.1 204 No Content
```

Переносите длительную бизнес-логику в очередь. Таймаут или ответ, отличный от `2xx`, может привести к повторной отправке события со стороны YCloud, поэтому выполняйте дедупликацию по `id` события.

## Примеры распространенных полезных нагрузок

Разверните событие, чтобы просмотреть полный пример его полезной нагрузки. Эти примеры взяты из спецификации Webhook OpenAPI. См. [все примеры полезных нагрузок Webhook](/ru/api-reference/guides/examples/webhook-examples/webhook-payload-examples) для каждого поддерживаемого типа события.

<AccordionGroup>
  <Accordion title="Событие изменения атрибутов контакта">
    Пример полезной нагрузки при изменении атрибутов контакта

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_1234567890",
      "type": "contact.attributes_changed",
      "apiVersion": "v2",
      "createTime": "2024-01-01T12:00:00.000Z",
      "contactAttributesChanged": {
        "id": "1824266594102064128",
        "updateTime": "2024-01-01T12:00:00.000Z",
        "changedAttributes": {
          "nickName": {
            "oldValue": "John Doe",
            "newValue": "Johnny Doe"
          },
          "email": {
            "oldValue": "john.doe@example.com",
            "newValue": "johnny.doe@example.com"
          },
          "tags": {
            "oldValue": [
              "premium",
              "newsletter"
            ],
            "newValue": [
              "premium",
              "newsletter",
              "vip"
            ],
            "extra": [
              {
                "action": "ADDED",
                "id": "686dd294334be8606a5bf312",
                "value": "vip"
              }
            ]
          }
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="Событие создания контакта">
    Пример полезной нагрузки при создании нового контакта

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_2345678901",
      "type": "contact.created",
      "apiVersion": "v2",
      "createTime": "2024-01-01T12:00:00.000Z",
      "contactCreated": {
        "id": "1824266594102064128",
        "nickName": "John Doe",
        "realName": "John Smith",
        "phoneNumber": "+16315551111",
        "countryCode": "US",
        "countryName": "United States",
        "email": "john.doe@example.com",
        "sourceType": "api",
        "sourceId": "import_batch_123",
        "sourceUrl": "https://example.com/signup",
        "lastSeen": "2024-01-01T11:59:00.000Z",
        "lastConnectedNumber": "+16315552222",
        "ownerEmail": "owner@example.com",
        "tags": [
          "premium",
          "newsletter"
        ],
        "createTime": "2024-01-01T12:00:00.000Z",
        "updateTime": "2024-01-01T12:00:00.000Z",
        "blocked": false,
        "customAttributes": {
          "attr1": "value1",
          "attr2": "value2",
          "attr3": 123
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="Событие удаления контакта">
    Пример полезной нагрузки при удалении контакта

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_3456789012",
      "type": "contact.deleted",
      "apiVersion": "v2",
      "createTime": "2024-01-01T12:00:00.000Z",
      "contactDeleted": {
        "id": "1824266594102064128",
        "nickName": "John Doe",
        "phoneNumber": "+16315551111",
        "updateTime": "2024-01-01T12:00:00.000Z"
      }
    }
    ```
  </Accordion>

  <Accordion title="Событие отмены подписки клиентом">
    Пример полезной нагрузки при отмене подписки клиентом

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_3456789012",
      "type": "contact.unsubscribe.created",
      "apiVersion": "v2",
      "createTime": "2024-01-01T12:00:00.000Z",
      "unsubscriberChanged": {
        "phoneNumber": "+16315551111",
        "source": "Whatsapp",
        "updateTime": "2024-01-01T12:00:00.000Z"
      }
    }
    ```
  </Accordion>

  <Accordion title="Клиент возобновляет подписку">
    Пример полезной нагрузки при возобновлении клиентом подписки

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_3456789012",
      "type": "contact.unsubscribe.deleted",
      "apiVersion": "v2",
      "createTime": "2024-01-01T12:00:00.000Z",
      "unsubscriberChanged": {
        "phoneNumber": "+16315551111",
        "source": "Whatsapp",
        "updateTime": "2024-01-01T12:00:00.000Z"
      }
    }
    ```
  </Accordion>

  <Accordion title="Событие архивации шаблона WhatsApp">
    Пример полезной нагрузки при архивации шаблона WhatsApp

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_template_archived_123",
      "type": "whatsapp.template.reviewed",
      "apiVersion": "v2",
      "createTime": "2024-01-01T12:00:00.000Z",
      "whatsappTemplate": {
        "id": "template-id",
        "officialTemplateId": "official-template-id",
        "wabaId": "whatsapp-business-account-id",
        "name": "sample_whatsapp_template",
        "language": "en",
        "category": "MARKETING",
        "status": "ARCHIVED",
        "statusUpdateEvent": "ARCHIVED",
        "createTime": "2024-01-01T12:00:00.000Z",
        "updateTime": "2024-01-01T12:00:00.000Z"
      }
    }
    ```
  </Accordion>

  <Accordion title="Событие разархивации шаблона WhatsApp">
    Пример полезной нагрузки при разархивации шаблона WhatsApp. Статус шаблона отражает текущий статус, возвращенный Meta, и не указывает на повторную модерацию.

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_template_unarchived_123",
      "type": "whatsapp.template.reviewed",
      "apiVersion": "v2",
      "createTime": "2024-01-01T12:00:00.000Z",
      "whatsappTemplate": {
        "id": "template-id",
        "officialTemplateId": "official-template-id",
        "wabaId": "whatsapp-business-account-id",
        "name": "sample_whatsapp_template",
        "language": "en",
        "category": "MARKETING",
        "status": "APPROVED",
        "statusUpdateEvent": "UNARCHIVED",
        "createTime": "2024-01-01T12:00:00.000Z",
        "updateTime": "2024-01-01T12:00:00.000Z"
      }
    }
    ```
  </Accordion>

  <Accordion title="Событие соединения звонка WhatsApp">
    Пример полезной нагрузки при соединении звонка WhatsApp

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_call_connect_123",
      "type": "whatsapp.call.connect",
      "apiVersion": "v2",
      "createTime": "2024-01-01T12:00:00.000Z",
      "callingConnect": {
        "id": "6757b723960b25543b9ecc66",
        "wacid": "wacid.HBgNNjI4MTM2MTkwNTEzMxUCABIYIEF",
        "phoneId": "461269257068832",
        "from": "+6281361905133",
        "to": "+6283138205150",
        "direction": "USER_INITIATED",
        "dialTime": 1733826430000,
        "sdpType": "offer",
        "sdp": "v=0\r\no=- 1732169627243 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE audio\r\na=msid-semantic: WMS af3b01e3-eb42-4244-812e-db903c062ae7\r\na=ice-lite\r\nm=audio 3480 UDP/TLS/RTP/SAVPF 111 126\r\nc=IN IP4 31.13.87.130\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=candidate:785588535 1 udp 2122260223 31.13.87.130 3480 typ host generation 0 network-cost 50\r\na=candidate:1906600321 1 udp 2122262783 2a03:2880:f217:d0:face:b00c:0:699c 3480 typ host generation 0 network-cost 50\r\na=ice-ufrag:CvRXRnInnWhQzLIE\r\na=ice-pwd:HGXUGAFI8wK6seuVknBT2Q==\r\na=fingerprint:sha-256 FB:56:A1:C5:37:35:6C:5C:1B:05:23:B0:DD:BB:2E:C9:5F:E4:70:61:7B:D9:1D:09:84:76:46:23:12:38:B7:01\r\na=setup:actpass\r\na=mid:audio\r\na=sendrecv\r\na=msid:af3b01e3-eb42-4244-812e-db903c062ae7 WhatsAppTrack1\r\na=rtcp-mux\r\na=rtpmap:111 opus/48000/2\r\na=rtcp-fb:111 transport-cc\r\na=fmtp:111 maxaveragebitrate=20000;maxplaybackrate=16000;minptime=20;sprop-maxcapturerate=16000;useinbandfec=1\r\na=rtpmap:126 telephone-event/8000\r\na=maxptime:20\r\na=ptime:20\r\na=ssrc:659928310 cname:WhatsAppAudioStream1\r\n"
      }
    }
    ```
  </Accordion>

  <Accordion title="Событие завершения звонка WhatsApp">
    Пример полезной нагрузки при завершении звонка WhatsApp

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_6757b889a5a42d369ef48481",
      "type": "whatsapp.call.terminate",
      "apiVersion": "v2",
      "createTime": "2024-12-10T03:42:01.822Z",
      "callingTerminate": {
        "id": "6757b889960b25543b9ecc67",
        "wacid": "wacid.HBgNNjI4MTM2MTkwNTEzMxUCABIYIEFENjB",
        "phoneId": "461269257068832",
        "from": "+6281361905133",
        "to": "+6283138205150",
        "direction": "USER_INITIATED",
        "startTime": 1733734738000,
        "endTime": 1733734771000,
        "duration": 33,
        "status": "COMPLETED"
      }
    }
    ```
  </Accordion>

  <Accordion title="Событие обновления статуса звонка WhatsApp">
    Пример полезной нагрузки при обновлении статуса звонка WhatsApp

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "id": "evt_676e5ab57a9cb742d02d7646",
      "type": "whatsapp.call.status.updated",
      "apiVersion": "v2",
      "createTime": "2024-12-27T07:41:28.422Z",
      "callingStatusUpdated": {
        "wabaId": "188234691048809",
        "wacid": "wacid.HBgNNjI4MTM2MTkwNTEzMxUCABE",
        "status": "RINGING",
        "recipientPhone": "+6281361905133"
      }
    }
    ```
  </Accordion>
</AccordionGroup>

См. раздел [Полезные нагрузки событий Webhook](/ru/api-reference/webhooks/test-webhooks) для получения полной схемы `Event` и интерактивного справочника полезной нагрузки.

## Ротация секрета эндпоинта

Выполняйте ротацию секрета в случае его компрометации или в соответствии с вашей политикой безопасности:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request POST \
  https://api.ycloud.com/v2/webhookEndpoints/WEBHOOK_ENDPOINT_ID/rotateSecret \
  --header "X-API-Key: $YCLOUD_API_KEY"
```

Сразу после ротации разверните новый секрет на стороне вашего приемника.

<Note>
  Эндпоинт, который неоднократно не может принять уведомления, может перейти в статус `pending` и перестать получать события. Отслеживайте сбои webhook и статус эндпоинта.
</Note>

Информацию о коде проверки подписи, интервалах повторных попыток и реализации приемника см. в разделе
[Реализация приемника webhook](/ru/api-reference/guides/api-fundamentals/implement-a-webhook-receiver).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.