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

# Webhooks

> Have Ciarem send an HTTPS request to your server the moment a contact, conversation, or message changes.

A webhook is a request Ciarem sends **to your server** when something happens in your account: a contact is created, a conversation is assigned, a customer writes in. You give Ciarem a URL, pick the events you care about, and each matching event arrives as a signed `POST` within seconds.

Use webhooks when you want to react to changes instead of asking the [API](https://help.ciarem.ai/api-reference/quickstart.md) over and over whether anything is new. Typical uses:

* Keep your own CRM or data warehouse in step with Ciarem contacts.
* Notify a team in Slack when a conversation is assigned or closed.
* Start an automation in your backend when a customer sends a message.

> [!NOTE]
>
> You don't need webhooks to use Ciarem. They are a tool for developers who connect Ciarem to their own systems. You need a server that can receive HTTPS requests from the internet.

## Before you start

| | |
| - | - |
| **Plan** | Webhooks are part of API access: **Growth**, **Scale**, or the **free trial**. |
| **Who can set them up** | Organization **admins** in the dashboard, or any integration holding an [API key](https://help.ciarem.ai/api-reference/authentication.md). |
| **Your endpoint** | A public **HTTPS** URL that answers `POST` requests. See [what Ciarem accepts](#url-requirements). |

## Set up your first endpoint

**In the dashboard**

**1. Open Webhooks**

Go to **Settings**, then **Webhooks**, and click **Add endpoint**.

**2. Enter your URL**

Paste the HTTPS address of your server under **Endpoint URL**. Add a description if you want to remember what the endpoint is for.

**3. Pick the events**

Leave **Send all events** on to receive everything, including event types added in the future, or turn it off and tick only the events you need. See the [event catalog](https://help.ciarem.ai/webhooks/events.md).

**4. Copy the signing secret**

After you save, Ciarem shows the endpoint's **signing secret**. It starts with `whsec_`. Store it on your server: you use it to [check that each request really comes from Ciarem](https://help.ciarem.ai/webhooks/signatures.md). You can see it again later on the endpoint's page with **Show secret**.

**5. Send a test event**

Open the endpoint, choose an event under **Test event**, and click **Send test event**. Ciarem sends it right away and tells you what your server answered.

**With the API**

Create the endpoint:

```bash theme={null}
curl https://api.ciarem.ai/v1/webhook-endpoints \
  -H "Authorization: Bearer oak_YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/hooks/ciarem",
    "description": "Sync contacts to our CRM",
    "events": ["contact.created", "contact.updated", "contact.deleted"]
  }'
```

The response is the endpoint plus its signing secret:

```json theme={null}
{
  "id": "whe_…",
  "url": "https://example.com/hooks/ciarem",
  "description": "Sync contacts to our CRM",
  "events": ["contact.created", "contact.deleted", "contact.updated"],
  "enabled": true,
  "disabled_reason": null,
  "created_at": "2026-10-09T15:04:05.123456Z",
  "updated_at": "2026-10-09T15:04:05.123456Z",
  "secret": "whsec_…"
}
```

> [!WARNING]
>
> The API returns `secret` **only in this response**. Store it now. An admin can still read it later in the dashboard (**Settings → Webhooks →** the endpoint **→ Show secret**), but no API call returns it again.

Then send a test event to confirm your server receives it:

```bash theme={null}
curl -X POST https://api.ciarem.ai/v1/webhook-endpoints/whe_…/test \
  -H "Authorization: Bearer oak_YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"event_type": "contact.created"}'
```

```json theme={null}
{
  "delivered": true,
  "response_status": 200,
  "error": null,
  "payload": { "id": "evt_test_…", "type": "contact.created", "…": "…" }
}
```

To receive every event type, including ones added later, send `"events": ["*"]`. The `*` must be the only item in the list.

## What Ciarem sends

Every event is one `POST` request with a JSON body:

```http theme={null}
POST /hooks/ciarem HTTP/1.1
Host: example.com
Content-Type: application/json
User-Agent: Ciarem-Webhooks/1.0 (+https://ciarem.ai)
Ciarem-Signature: t=1760022245,v1=5f8a…c2e1

{"id":"evt_…","type":"contact.created","api_version":"v1","created_at":"2026-10-09T15:04:05.123456Z","data":{"contact":{"id":"cnt_…","first_name":"Ana","…":"…"}}}
```

| Part | What it is |
| - | - |
| `Ciarem-Signature` | Proof the request comes from Ciarem and was not altered. [Verify it](https://help.ciarem.ai/webhooks/signatures.md) before you trust the body. |
| `id` | The event's unique id. The same event always carries the same `id`, also when it is retried. Use it to [ignore duplicates](https://help.ciarem.ai/webhooks/deliveries.md#duplicates-and-order). |
| `type` | Which event this is, for example `contact.created`. See the [event catalog](https://help.ciarem.ai/webhooks/events.md). |
| `api_version` | Always `v1` today. |
| `created_at` | When the event happened in Ciarem, in UTC. |
| `data` | The details. Its shape depends on `type`. |

## What your server must do

1. **Answer with a `2xx` status within 10 seconds.** Any `2xx` counts as received. Anything else, including a redirect, a timeout, or a connection error, counts as a failure and is [retried](https://help.ciarem.ai/webhooks/deliveries.md#retries).
2. **Verify the signature** before acting on the body. See [Verify signatures](https://help.ciarem.ai/webhooks/signatures.md).
3. **Answer first, work later.** If handling an event takes time, save it to a queue and return `200` right away. Ciarem does not read your response body.
4. **Expect duplicates and out-of-order events.** The same event can arrive more than once, and two events can arrive in a different order than they happened. See [Duplicates and order](https://help.ciarem.ai/webhooks/deliveries.md#duplicates-and-order).
5. **Ignore what you don't recognize.** New event types and new fields are added over time. Skip unknown `type` values with a `200`, and don't reject bodies with extra fields.

## URL requirements

Ciarem only sends to URLs that are safe to call from the public internet:

* The URL must start with `https://`. Plain `http://` is refused.
* The host must resolve to a **public** IP address. `localhost`, private network ranges (such as `10.x.x.x` or `192.168.x.x`), and link-local addresses are refused, both when you save the endpoint and on every delivery.
* Your server must present a valid TLS certificate for that hostname.
* Redirects are **not followed**. A `301` or `302` is recorded as a failed delivery, so register the final URL.
* The URL can be up to 2,048 characters and may include a path, a port, and a query string.

> [!TIP]
>
> To test against a server on your own computer, expose it through a tunnel that gives you a public HTTPS address, such as ngrok or Cloudflare Tunnel, and register the tunnel's URL.

## Limits

| | |
| - | - |
| Endpoints per organization | 10 |
| Response time allowed | 10 seconds |
| Retries of a failed delivery | For up to 3 days, see [Retries](https://help.ciarem.ai/webhooks/deliveries.md#retries) |
| Delivery log kept for | 30 days |
| Description length | 500 characters |

## Next steps

> **[Event catalog](https://help.ciarem.ai/webhooks/events.md)**
>
> Every event type and the exact body it carries.

> **[Verify signatures](https://help.ciarem.ai/webhooks/signatures.md)**
>
> Check that a request comes from Ciarem, with code you can copy.

> **[Deliveries and retries](https://help.ciarem.ai/webhooks/deliveries.md)**
>
> Retries, the delivery log, sending again, and troubleshooting.


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