Webhooks
Create Webhook
Register an HTTPS endpoint to receive Connectly webhook events for a given topic 💪
POST
/
v1
/
businesses
/
{businessId}
/
create
/
webhooks
Create Webhook
curl --request POST \
--url https://api.example.com/v1/businesses/{businessId}/create/webhooks \
--header 'Content-Type: application/json' \
--data '
{
"topic": "<string>",
"address": "<string>",
"type": "<string>",
"configuration": {
"echo": true,
"channelTypes": [
{}
],
"filters": [
{
"field": "<string>",
"expression": "<string>"
}
],
"webengageConfiguration": {
"webengageToken": "<string>",
"webengageWebhookUrl": "<string>"
}
}
}
'import requests
url = "https://api.example.com/v1/businesses/{businessId}/create/webhooks"
payload = {
"topic": "<string>",
"address": "<string>",
"type": "<string>",
"configuration": {
"echo": True,
"channelTypes": [{}],
"filters": [
{
"field": "<string>",
"expression": "<string>"
}
],
"webengageConfiguration": {
"webengageToken": "<string>",
"webengageWebhookUrl": "<string>"
}
}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
topic: '<string>',
address: '<string>',
type: '<string>',
configuration: {
echo: true,
channelTypes: [{}],
filters: [{field: '<string>', expression: '<string>'}],
webengageConfiguration: {webengageToken: '<string>', webengageWebhookUrl: '<string>'}
}
})
};
fetch('https://api.example.com/v1/businesses/{businessId}/create/webhooks', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v1/businesses/{businessId}/create/webhooks",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'topic' => '<string>',
'address' => '<string>',
'type' => '<string>',
'configuration' => [
'echo' => true,
'channelTypes' => [
[
]
],
'filters' => [
[
'field' => '<string>',
'expression' => '<string>'
]
],
'webengageConfiguration' => [
'webengageToken' => '<string>',
'webengageWebhookUrl' => '<string>'
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v1/businesses/{businessId}/create/webhooks"
payload := strings.NewReader("{\n \"topic\": \"<string>\",\n \"address\": \"<string>\",\n \"type\": \"<string>\",\n \"configuration\": {\n \"echo\": true,\n \"channelTypes\": [\n {}\n ],\n \"filters\": [\n {\n \"field\": \"<string>\",\n \"expression\": \"<string>\"\n }\n ],\n \"webengageConfiguration\": {\n \"webengageToken\": \"<string>\",\n \"webengageWebhookUrl\": \"<string>\"\n }\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/v1/businesses/{businessId}/create/webhooks")
.header("Content-Type", "application/json")
.body("{\n \"topic\": \"<string>\",\n \"address\": \"<string>\",\n \"type\": \"<string>\",\n \"configuration\": {\n \"echo\": true,\n \"channelTypes\": [\n {}\n ],\n \"filters\": [\n {\n \"field\": \"<string>\",\n \"expression\": \"<string>\"\n }\n ],\n \"webengageConfiguration\": {\n \"webengageToken\": \"<string>\",\n \"webengageWebhookUrl\": \"<string>\"\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/businesses/{businessId}/create/webhooks")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"topic\": \"<string>\",\n \"address\": \"<string>\",\n \"type\": \"<string>\",\n \"configuration\": {\n \"echo\": true,\n \"channelTypes\": [\n {}\n ],\n \"filters\": [\n {\n \"field\": \"<string>\",\n \"expression\": \"<string>\"\n }\n ],\n \"webengageConfiguration\": {\n \"webengageToken\": \"<string>\",\n \"webengageWebhookUrl\": \"<string>\"\n }\n }\n}"
response = http.request(request)
puts response.read_bodyRegister a URL that Connectly will POST to whenever a subscribed event occurs. You can register multiple endpoints per topic — the only restriction is you cannot register the exact same topic + URL pair twice.
Save the returned
Endpoint
POST https://api.connectly.ai/v1/businesses/{businessId}/create/webhooks
Request body
string
required
The event topic to subscribe to.
| Value | Description |
|---|---|
messages | Inbound WhatsApp messages sent by your customers. |
delivery_status | Delivery status updates: sent, delivered, read, delivery_failed. |
string
required
Your publicly accessible HTTPS endpoint URL (e.g.
https://example.com/webhook).string
Integration type for this webhook. Defaults to
custom.| Value | Description |
|---|---|
custom | Your own HTTP endpoint. |
zapier | Zapier integration. |
webengage | WebEngage integration. |
integromat_make | Integromat / Make integration. |
object
Advanced configuration options.
Show configuration properties
Show configuration properties
boolean
When
true, outbound messages sent by your business are echoed back to this webhook in addition to inbound messages.array
List of channel types to filter events by (e.g.
["whatsapp"]). When omitted, events from all channels are delivered.array
List of filter rules to restrict which events are delivered to this endpoint.
Show filter properties
Show filter properties
string
The event field to match on. Supported values:
campaign_name, phoneNumbers, botConversation.Note: campaign_name works on any topic including messages — not just delivery_status. It matches events where the conversation is tagged with that campaign name.string
Glob-style expression to match against the field value. Use
* to match any campaign. Use a specific name like summer-promo-* to match a subset.Examples
Register for inbound messages
Register for inbound messages
curl --request POST \
--url https://api.connectly.ai/v1/businesses/{businessId}/create/webhooks \
--header 'Content-Type: application/json' \
--header 'X-API-Key: YOUR_API_KEY' \
--data '{
"topic": "messages",
"address": "https://example.com/webhook/messages"
}'
Register for delivery status
Register for delivery status
curl --request POST \
--url https://api.connectly.ai/v1/businesses/{businessId}/create/webhooks \
--header 'Content-Type: application/json' \
--header 'X-API-Key: YOUR_API_KEY' \
--data '{
"topic": "delivery_status",
"address": "https://example.com/webhook/delivery"
}'
With campaign filter and channel type
With campaign filter and channel type
curl --request POST \
--url https://api.connectly.ai/v1/businesses/{businessId}/create/webhooks \
--header 'Content-Type: application/json' \
--header 'X-API-Key: YOUR_API_KEY' \
--data '{
"topic": "delivery_status",
"address": "https://example.com/webhook/delivery",
"configuration": {
"channelTypes": ["whatsapp"],
"filters": [
{ "field": "campaign_name", "expression": "summer-promo-*" }
]
}
}'
Multiple endpoints on the same topic
Multiple endpoints on the same topic
You can register multiple webhooks on the same topic pointing to different URLs. All registered endpoints receive matching events — creating a second one does not replace the first.
# First endpoint — receives all inbound messages
curl --request POST \
--url https://api.connectly.ai/v1/businesses/{businessId}/create/webhooks \
--header 'Content-Type: application/json' \
--header 'X-API-Key: YOUR_API_KEY' \
--data '{
"topic": "messages",
"address": "https://example.com/webhook/all-messages"
}'
# Second endpoint — receives only campaign-tagged messages
curl --request POST \
--url https://api.connectly.ai/v1/businesses/{businessId}/create/webhooks \
--header 'Content-Type: application/json' \
--header 'X-API-Key: YOUR_API_KEY' \
--data '{
"topic": "messages",
"address": "https://example.com/webhook/campaign-messages",
"configuration": {
"filters": [{ "field": "campaign_name", "expression": "*" }]
}
}'
Response
{ "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV" }
id — you’ll need it to update or delete this registration.
Error responses
| Status | Meaning |
|---|---|
400 | Malformed body or invalid field values. |
401 | Missing or invalid X-API-Key. |
409 | The exact same topic + URL combination is already registered. |
500 | Internal server error. |
Was this page helpful?
⌘I
