Create a webhook
curl --request POST \
--url https://agp.eu.hcompany.ai/api/v2/webhooks \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"url": "<string>",
"enabled_events": [
"<string>"
],
"description": "<string>"
}
'import requests
url = "https://agp.eu.hcompany.ai/api/v2/webhooks"
payload = {
"url": "<string>",
"enabled_events": ["<string>"],
"description": "<string>"
}
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({url: '<string>', enabled_events: ['<string>'], description: '<string>'})
};
fetch('https://agp.eu.hcompany.ai/api/v2/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://agp.eu.hcompany.ai/api/v2/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([
'url' => '<string>',
'enabled_events' => [
'<string>'
],
'description' => '<string>'
]),
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://agp.eu.hcompany.ai/api/v2/webhooks"
payload := strings.NewReader("{\n \"url\": \"<string>\",\n \"enabled_events\": [\n \"<string>\"\n ],\n \"description\": \"<string>\"\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://agp.eu.hcompany.ai/api/v2/webhooks")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"url\": \"<string>\",\n \"enabled_events\": [\n \"<string>\"\n ],\n \"description\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://agp.eu.hcompany.ai/api/v2/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 \"url\": \"<string>\",\n \"enabled_events\": [\n \"<string>\"\n ],\n \"description\": \"<string>\"\n}"
response = http.request(request)
puts response.read_bodyWebhooks
Create a webhook
Register a URL to receive signed event notifications.
POST
/
api
/
v2
/
webhooks
Create a webhook
curl --request POST \
--url https://agp.eu.hcompany.ai/api/v2/webhooks \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"url": "<string>",
"enabled_events": [
"<string>"
],
"description": "<string>"
}
'import requests
url = "https://agp.eu.hcompany.ai/api/v2/webhooks"
payload = {
"url": "<string>",
"enabled_events": ["<string>"],
"description": "<string>"
}
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({url: '<string>', enabled_events: ['<string>'], description: '<string>'})
};
fetch('https://agp.eu.hcompany.ai/api/v2/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://agp.eu.hcompany.ai/api/v2/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([
'url' => '<string>',
'enabled_events' => [
'<string>'
],
'description' => '<string>'
]),
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://agp.eu.hcompany.ai/api/v2/webhooks"
payload := strings.NewReader("{\n \"url\": \"<string>\",\n \"enabled_events\": [\n \"<string>\"\n ],\n \"description\": \"<string>\"\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://agp.eu.hcompany.ai/api/v2/webhooks")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"url\": \"<string>\",\n \"enabled_events\": [\n \"<string>\"\n ],\n \"description\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://agp.eu.hcompany.ai/api/v2/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 \"url\": \"<string>\",\n \"enabled_events\": [\n \"<string>\"\n ],\n \"description\": \"<string>\"\n}"
response = http.request(request)
puts response.read_bodyRegisters a webhook for your organization. The response includes the signing
secret. This is the only time it is returned, so store it securely.
Returns 201 with the created webhook object plus its secret.
The
secret cannot be retrieved later. To replace it, use Rotate.Request body
Target URL for deliveries. Must be
https:// and publicly reachable: the platform sends a HEAD request at creation time and rejects the webhook if the endpoint cannot be reached. Any HTTP status counts as reachable; your endpoint does not need to accept HEAD.Event types delivered to this webhook.
"*" subscribes to the session.status_updated firehose; granular session.* types are delivered only when listed explicitly. See the event catalog for supported types.Optional label for the webhook (max 255 characters).
Examples
curl -X POST https://agp.eu.hcompany.ai/api/v2/webhooks \
-H "Authorization: Bearer $HAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/hooks/h",
"enabled_events": ["session.status_updated"],
"description": "Production listener"
}'
from hai_agents import Client
client = Client()
webhook = client.webhooks.create_webhook(
url="https://example.com/hooks/h",
enabled_events=["session.status_updated"],
description="Production listener",
)
print(webhook.secret) # shown only once; store it securely
import { HaiAgentsClient } from "hai-agents";
const client = new HaiAgentsClient();
const webhook = await client.webhooks.createWebhook({
url: "https://example.com/hooks/h",
enabledEvents: ["session.status_updated"],
description: "Production listener",
});
console.log(webhook.secret); // shown only once; store it securely
Response
{
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"url": "https://example.com/hooks/h",
"enabled_events": ["session.status_updated"],
"description": "Production listener",
"disabled": false,
"last_delivery_status": null,
"last_delivery_error": null,
"last_delivery_at": null,
"last_success_at": null,
"consecutive_failures": 0,
"created_at": "2026-06-11T15:04:05Z",
"updated_at": "2026-06-11T15:04:05Z",
"secret": "whsec_k3TQyhq2mPv8WdJ4cN7xLbR9sF1aZ6uE0gYoHiC5jXw"
}
Errors
| Status | Cause |
|---|---|
400 | Organization webhook limit reached (10), URL does not resolve to a public address, or the endpoint could not be reached. |
422 | Body failed validation: non-https URL, empty or unknown enabled_events. |
Was this page helpful?
⌘I