curl --request POST \
--url https://app.timelines.ai/integrations/api/webhooks \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"event_type": "message:sent:new",
"url": "http://www.example.com/api/hook",
"enabled": true
}
'import requests
url = "https://app.timelines.ai/integrations/api/webhooks"
payload = {
"event_type": "message:sent:new",
"url": "http://www.example.com/api/hook",
"enabled": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
event_type: 'message:sent:new',
url: 'http://www.example.com/api/hook',
enabled: true
})
};
fetch('https://app.timelines.ai/integrations/api/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://app.timelines.ai/integrations/api/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([
'event_type' => 'message:sent:new',
'url' => 'http://www.example.com/api/hook',
'enabled' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://app.timelines.ai/integrations/api/webhooks"
payload := strings.NewReader("{\n \"event_type\": \"message:sent:new\",\n \"url\": \"http://www.example.com/api/hook\",\n \"enabled\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://app.timelines.ai/integrations/api/webhooks")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"event_type\": \"message:sent:new\",\n \"url\": \"http://www.example.com/api/hook\",\n \"enabled\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.timelines.ai/integrations/api/webhooks")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"event_type\": \"message:sent:new\",\n \"url\": \"http://www.example.com/api/hook\",\n \"enabled\": true\n}"
response = http.request(request)
puts response.read_body{
"status": "ok",
"data": {
"id": 789456,
"event_type": "message:sent:new",
"enabled": true,
"url": "http://www.example.com/api/hook",
"errors_counter": 0
}
}{
"message": "<string>",
"status": "error",
"error_code": "validation_error",
"errors": [
{
"fields": [
"url"
],
"msg": "must be a valid http(s) URL"
}
]
}{
"message": "<string>",
"status": "error",
"error_code": "validation_error",
"errors": [
{
"fields": [
"url"
],
"msg": "must be a valid http(s) URL"
}
]
}{
"message": "<string>",
"status": "error",
"error_code": "validation_error",
"errors": [
{
"fields": [
"url"
],
"msg": "must be a valid http(s) URL"
}
]
}Create Webhook
Create a new webhook subscription for a specified event.
curl --request POST \
--url https://app.timelines.ai/integrations/api/webhooks \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"event_type": "message:sent:new",
"url": "http://www.example.com/api/hook",
"enabled": true
}
'import requests
url = "https://app.timelines.ai/integrations/api/webhooks"
payload = {
"event_type": "message:sent:new",
"url": "http://www.example.com/api/hook",
"enabled": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
event_type: 'message:sent:new',
url: 'http://www.example.com/api/hook',
enabled: true
})
};
fetch('https://app.timelines.ai/integrations/api/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://app.timelines.ai/integrations/api/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([
'event_type' => 'message:sent:new',
'url' => 'http://www.example.com/api/hook',
'enabled' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://app.timelines.ai/integrations/api/webhooks"
payload := strings.NewReader("{\n \"event_type\": \"message:sent:new\",\n \"url\": \"http://www.example.com/api/hook\",\n \"enabled\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://app.timelines.ai/integrations/api/webhooks")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"event_type\": \"message:sent:new\",\n \"url\": \"http://www.example.com/api/hook\",\n \"enabled\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.timelines.ai/integrations/api/webhooks")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"event_type\": \"message:sent:new\",\n \"url\": \"http://www.example.com/api/hook\",\n \"enabled\": true\n}"
response = http.request(request)
puts response.read_body{
"status": "ok",
"data": {
"id": 789456,
"event_type": "message:sent:new",
"enabled": true,
"url": "http://www.example.com/api/hook",
"errors_counter": 0
}
}{
"message": "<string>",
"status": "error",
"error_code": "validation_error",
"errors": [
{
"fields": [
"url"
],
"msg": "must be a valid http(s) URL"
}
]
}{
"message": "<string>",
"status": "error",
"error_code": "validation_error",
"errors": [
{
"fields": [
"url"
],
"msg": "must be a valid http(s) URL"
}
]
}{
"message": "<string>",
"status": "error",
"error_code": "validation_error",
"errors": [
{
"fields": [
"url"
],
"msg": "must be a valid http(s) URL"
}
]
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
A JSON describing webhook.
A client‑defined subscription that instructs TimelinesAI to send an HTTP POST request to the specified url whenever the chosen event_type occurs in the workspace. The POST body is delivered as JSON and contains the event payload.
Event topic that will trigger the webhook. For the current list of supported values see the Webhooks events documentation (for example: message:sent:new, message:received:new).
message:new, message:sent:new, message:received:new, whatsapp:account:connected, whatsapp:account:disconnected, whatsapp:account:suspended, whatsapp:account:resumed, chat:new, chat:incoming:new, chat:outgoing:new, chat:responsible:assigned, chat:responsible:unassigned, call:incoming:missed, call:incoming:ended, call:outgoing:ended, message:reaction, waba:message:received, waba:message:delivered, waba:message:failed, waba:message:read, waba:chat:incoming, waba:chat:outgoing, waba:chat:assigned, waba:chat:unassigned, waba:chat:closed, waba:chat:reopened, waba:account:active, waba:account:disabled, waba:account:disconnected, waba:template:approved, waba:template:rejected, waba:template:disabled "message:sent:new"
Destination HTTPS endpoint that TimelinesAI will call. Must be publicly accessible and respond with 2xx status within 5 seconds. The URL must be a structurally valid http(s):// URL — TimelinesAI rejects URLs that contain characters or shapes that would prevent a standard HTTP client from dispatching to them (for example, unescaped + or = in the userinfo portion). The validator runs on POST /webhooks and PUT /webhooks/{id}; a malformed URL is rejected with 400 validation_error.
4096"http://www.example.com/api/hook"
Flag indicating whether the subscription is active. When false, deliveries are paused but the definition is kept.
true
Response
Success

