> ## 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.

# Configure webhooks

> Receive YCloud events at your HTTPS endpoint.

## What it is

Webhooks are HTTPS requests that YCloud sends to your application when message
delivery, inbound messages, contacts, templates, calls, and other resources
change.

## Before you begin

* Store your YCloud API key in `YCLOUD_API_KEY`.
* Deploy a publicly reachable HTTPS endpoint.
* Preserve the raw request body for signature verification.
* Decide which event types your application needs.

## How it works

1. Create a Webhook endpoint and subscribe it to event types.
2. Store the returned endpoint `secret`.
3. YCloud sends an event request to your endpoint.
4. Verify `YCloud-Signature` before trusting the request.
5. Return a `2xx` response promptly.
6. Process the event idempotently, because delivery may be repeated.

## Request

Create an endpoint with `POST /webhookEndpoints`.

### Request fields

| Field | Required | Description |
| - | - | - |
| `url` | Yes | Public HTTPS URL that receives event requests. Maximum 500 characters. |
| `enabledEvents` | Yes | Event types delivered to this endpoint. |
| `eventProperties` | Conditional | Properties included for selected event types. Required for `contact.attributes_changed`. |
| `description` | No | Description of the endpoint. Maximum 400 characters. |
| `status` | No | Initial endpoint status. |

### Example request

```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"
}'
```

### Subscribe to echo and handover events

For Agents onboarded through the Public REST API, create an endpoint with the
following subscriptions. Console-created Agents do not emit these three events.
To change an existing endpoint, preserve any event subscriptions you still need.

```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"
  }'
```

The two echo event types carry a standard message-shaped `whatsappMessage` payload.
The handover event carries `whatsappMetaBusinessAgent` and retains its Agent/control information.
They do not use the WhatsApp Business App `whatsapp.smb.message.echoes` contract.
See [echo and handover event details](/en/api-reference/guides/examples/webhook-examples/overview#echo-and-agent-handover-events)
for field definitions, examples, ordering, and handover correlation limits.

## Response

The response returns the created endpoint and its signing `secret`. Store the
secret securely. YCloud uses it to generate Webhook signatures.

### Example response

```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"
}
```

### Response fields

| Field | Description |
| - | - |
| `id` | Webhook endpoint ID used to retrieve, update, delete, or rotate the endpoint secret. |
| `url` | Destination URL for event delivery. |
| `enabledEvents` | Event types currently enabled. |
| `status` | Current endpoint state. |
| `secret` | Secret used to verify `YCloud-Signature`. Store it securely. |
| `createTime`, `updateTime` | Endpoint timestamps in RFC 3339 format. |

## Receive events

### Event request

YCloud sends a JSON event object to the configured `url`. The event includes
common fields such as `id`, `type`, `apiVersion`, and `createTime`, plus a
type-specific payload.

Your handler should:

1. Read the raw request body.
2. Validate the `YCloud-Signature` header with the endpoint secret before trusting the payload.
3. Return a successful `2xx` response promptly.
4. Move slow processing to a queue.
5. Make event processing idempotent so repeated delivery does not repeat business actions.

<Warning>
  Do not parse or modify the request body before signature validation. Use the exact raw bytes received by your server.
</Warning>

### Receiver response

Return a successful `2xx` HTTP response as soon as the signature and request are
accepted. The response body can be empty.

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

Move slow business processing to a queue. A timeout or non-`2xx` response can
cause YCloud to retry the event, so deduplicate by event `id`.

## Common payload examples

Expand an event to inspect its complete example payload. These examples come from the OpenAPI webhook specification. See [all webhook payload examples](/en/api-reference/guides/examples/webhook-examples/webhook-payload-examples) for every supported event type.

<AccordionGroup>
  <Accordion title="Contact attributes changed event">
    Example payload when contact attributes are changed

    ```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="Contact created event">
    Example payload when a new contact is created

    ```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="Contact deleted event">
    Example payload when a contact is deleted

    ```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="Customer cancels subscription event">
    Example payload when a customer cancels subscription

    ```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="Customer resumes subscription">
    Example payload when a customer resumes subscription

    ```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 template archived event">
    Example payload when a WhatsApp template is archived

    ```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 template unarchived event">
    Example payload when a WhatsApp template is unarchived. The template status is the current status returned by Meta and does not represent a new approval review.

    ```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 call connect event">
    Example payload when a WhatsApp call is connected

    ```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 call terminate event">
    Example payload when a WhatsApp call is terminated

    ```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 call status updated event">
    Example payload when a WhatsApp call status is updated

    ```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>

See [Webhook event payloads](/en/api-reference/webhooks/test-webhooks) for the complete `Event` schema and interactive payload reference.

## Rotate the endpoint secret

Rotate a secret if it is exposed or as part of your security policy:

```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"
```

Deploy the new secret to your receiver immediately after rotation.

<Note>
  An endpoint that repeatedly fails to receive notifications can move to `pending` status and stop receiving events. Monitor webhook failures and endpoint status.
</Note>

For signature verification code, retry intervals, and receiver implementation, see
[Implement a webhook receiver](/en/api-reference/guides/api-fundamentals/implement-a-webhook-receiver).


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