> ## Documentation Index
> Fetch the complete documentation index at: https://doc.convo.co.in/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks: Real-Time Event Notifications in Convo

> Convo webhooks push real-time event notifications to your server when messages are sent, delivered, read, or new contacts are created.

**Webhooks** are HTTP callbacks that Convo uses to push real-time event notifications to your server. Instead of polling the API to find out whether a message was delivered or a new contact was created, you register a publicly accessible endpoint and Convo sends an HTTP `POST` request to that URL the moment the event occurs. This makes webhooks the most efficient way to build reactive, event-driven integrations on top of the Convo platform.

<Note>
  Webhook subscriptions can be created and managed via the **Convo dashboard** (under **Integrations → Custom Apps**) or programmatically through the [Webhooks API endpoints](/api-reference/webhooks/list-webhooks).
</Note>

***

## Webhook Topics

A **topic** identifies the type of event that triggers a webhook delivery. When you register a webhook, you subscribe to one or more topics. Convo only sends notifications for the topics you have subscribed to.

| Topic               | Triggered When                                                                        |
| ------------------- | ------------------------------------------------------------------------------------- |
| `contact.created`   | A new Contact is created in your Project (via API, import, or first inbound message). |
| `message.sent`      | A message has been successfully submitted to WhatsApp from your Project.              |
| `message.delivered` | A message has been delivered to the recipient's device (double grey tick).            |
| `message.read`      | A message has been read by the recipient (double blue tick).                          |

Additional event topics may be available for your plan. Check the **Integrations** section of your dashboard for the full list of topics supported on your account.

***

## Webhook Object Fields

When you create a webhook, Convo stores a webhook subscription object with the following fields:

| Field           | Type              | Description                                                                        |
| --------------- | ----------------- | ---------------------------------------------------------------------------------- |
| `id`            | string            | Unique identifier for this webhook subscription.                                   |
| `app_id`        | string            | ID of the Custom App this webhook is associated with.                              |
| `project_id`    | string            | The Project that will trigger events for this webhook.                             |
| `topics`        | array of strings  | The list of event topics this webhook is subscribed to.                            |
| `webhook_url`   | string            | Your publicly accessible HTTPS endpoint that receives POST requests.               |
| `shared_secret` | string            | A secret token used to sign webhook payloads so you can verify their authenticity. |
| `created_at`    | ISO 8601 datetime | Timestamp when this webhook subscription was created.                              |

***

## Securing Webhooks

Because your webhook endpoint is publicly accessible, you need to verify that incoming requests genuinely originate from Convo and have not been tampered with in transit. Convo uses the `shared_secret` you configure to **sign every webhook payload**.

**How to verify the signature:**

<Steps>
  <Step title="Read the signature header">
    Convo includes a signature in the `x-convo-signature` HTTP header of every webhook request.
  </Step>

  <Step title="Compute the expected signature">
    Use your `shared_secret` and the raw request body to compute an HMAC digest (SHA-256) and compare it against the value in the header.
  </Step>

  <Step title="Reject mismatched requests">
    If the signatures do not match, discard the request — it was not sent by Convo or the payload was modified in transit. Return a `401 Unauthorized` response.
  </Step>

  <Step title="Respond with 200 OK">
    If the signature is valid, process the event and return `200 OK` promptly. Convo considers any non-2xx response a delivery failure and will retry.
  </Step>
</Steps>

Here is a minimal webhook handler in **Node.js / Express** that logs the incoming event:

```javascript theme={null}
const express = require('express');
const crypto = require('crypto');
const app = express();

app.use(express.json());

app.post('/webhook', (req, res) => {
  const signature = req.headers['x-convo-signature'];

  // Verify signature using your shared_secret
  const expectedSignature = crypto
    .createHmac('sha256', process.env.CONVO_SHARED_SECRET)
    .update(JSON.stringify(req.body))
    .digest('hex');

  if (signature !== expectedSignature) {
    console.warn('Webhook signature mismatch — request rejected.');
    return res.sendStatus(401);
  }

  // Signature verified — process the event
  const payload = req.body;
  console.log('Webhook event:', payload.topic, payload);

  // Always respond quickly so Convo does not retry
  res.sendStatus(200);
});

app.listen(3000, () => console.log('Webhook listener running on port 3000'));
```

<Warning>
  Always **store your `shared_secret` in an environment variable**, never hard-code it in your source code. Rotate the secret immediately if you suspect it has been exposed.
</Warning>

***

## Custom Apps

Webhooks in Convo are scoped to a **Custom App**. A Custom App is a named integration you create in the dashboard that groups your webhook subscriptions and API credentials together.

* Navigate to **Integrations → Custom Apps** in the Convo dashboard to create a new Custom App.
* Each Custom App receives a unique `app_id`.
* You can create multiple Custom Apps per Project — for example, one for your CRM integration and another for your order management system — each with its own webhook URL and shared secret.
* Deleting a Custom App removes all associated webhook subscriptions.

***

## Webhook Lifecycle

| Action          | How                                                                                                                              |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| **Create**      | Via the Convo dashboard (Integrations → Custom Apps → Add Webhook) or the Partner API.                                           |
| **List**        | Retrieve all webhook subscriptions for a Custom App via the API or view them in the dashboard.                                   |
| **Get details** | Fetch a single webhook subscription by its `id` to inspect topics, URL, and metadata.                                            |
| **Delete**      | Remove a webhook subscription via the dashboard or API. Deletion is immediate — no further events will be delivered to that URL. |

<Note>
  Convo retries failed webhook deliveries (non-2xx responses or timeouts) with exponential back-off. Ensure your endpoint responds within the timeout window and handles duplicate deliveries idempotently, as retries may result in the same event being posted more than once.
</Note>
