curl --request POST \
--url https://app.hookie.ai/admin/api/projects/{pid}/webhooks \
--header 'Content-Type: application/json' \
--cookie hookie_session= \
--data '
{
"name": "<string>",
"slug": "<string>",
"dataset": "<string>",
"enabled": true,
"criteria": [
{
"path": "<string>",
"equals": "<string>"
}
],
"mappings": [
{
"path": "<string>",
"key": "<string>"
}
]
}
'const options = {
method: 'POST',
headers: {cookie: 'hookie_session=', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
slug: '<string>',
dataset: '<string>',
enabled: true,
criteria: [{path: '<string>', equals: '<string>'}],
mappings: [{path: '<string>', key: '<string>'}]
})
};
fetch('https://app.hookie.ai/admin/api/projects/{pid}/webhooks', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://app.hookie.ai/admin/api/projects/{pid}/webhooks"
payload = {
"name": "<string>",
"slug": "<string>",
"dataset": "<string>",
"enabled": True,
"criteria": [
{
"path": "<string>",
"equals": "<string>"
}
],
"mappings": [
{
"path": "<string>",
"key": "<string>"
}
]
}
headers = {
"cookie": "hookie_session=",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"id": "<string>",
"slug": "<string>",
"webhook_slug": "<string>"
}{
"error": "<string>",
"retry_after": 123,
"upgrade_url": "<string>"
}{
"error": "<string>",
"retry_after": 123,
"upgrade_url": "<string>"
}{
"error": "<string>",
"retry_after": 123,
"upgrade_url": "<string>"
}{
"error": "<string>",
"retry_after": 123,
"upgrade_url": "<string>"
}{
"error": "<string>",
"retry_after": 123,
"upgrade_url": "<string>"
}{
"error": "<string>",
"retry_after": 123,
"upgrade_url": "<string>"
}Create a webhook endpoint
Top-level alias: POST /admin/api/webhooks. Write role required. The cap is checked before validation, so a full project returns 402 even for an invalid body.
curl --request POST \
--url https://app.hookie.ai/admin/api/projects/{pid}/webhooks \
--header 'Content-Type: application/json' \
--cookie hookie_session= \
--data '
{
"name": "<string>",
"slug": "<string>",
"dataset": "<string>",
"enabled": true,
"criteria": [
{
"path": "<string>",
"equals": "<string>"
}
],
"mappings": [
{
"path": "<string>",
"key": "<string>"
}
]
}
'const options = {
method: 'POST',
headers: {cookie: 'hookie_session=', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
slug: '<string>',
dataset: '<string>',
enabled: true,
criteria: [{path: '<string>', equals: '<string>'}],
mappings: [{path: '<string>', key: '<string>'}]
})
};
fetch('https://app.hookie.ai/admin/api/projects/{pid}/webhooks', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://app.hookie.ai/admin/api/projects/{pid}/webhooks"
payload = {
"name": "<string>",
"slug": "<string>",
"dataset": "<string>",
"enabled": True,
"criteria": [
{
"path": "<string>",
"equals": "<string>"
}
],
"mappings": [
{
"path": "<string>",
"key": "<string>"
}
]
}
headers = {
"cookie": "hookie_session=",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"id": "<string>",
"slug": "<string>",
"webhook_slug": "<string>"
}{
"error": "<string>",
"retry_after": 123,
"upgrade_url": "<string>"
}{
"error": "<string>",
"retry_after": 123,
"upgrade_url": "<string>"
}{
"error": "<string>",
"retry_after": 123,
"upgrade_url": "<string>"
}{
"error": "<string>",
"retry_after": 123,
"upgrade_url": "<string>"
}{
"error": "<string>",
"retry_after": 123,
"upgrade_url": "<string>"
}{
"error": "<string>",
"retry_after": 123,
"upgrade_url": "<string>"
}Authorizations
The console's sealed session cookie, set by WorkOS AuthKit. Mutating requests also require the X-Requested-With CSRF header.
Path Parameters
Project id (UUID) belonging to the caller workspace.
Body
1 - 80The base slug (lowercase letters, digits and hyphens, max 47 characters). This is NOT the public URL - a separate high-entropy slug is generated and returned as webhook_slug.
^[a-z0-9][a-z0-9-]{0,46}$^[A-Za-z][A-Za-z0-9_]{0,62}$Anything other than the literal false is treated as true.
Omitted or empty accepts any payload (the URL already scopes it). The validator rejects more than 10 entries before the documented 20-criteria ceiling can apply.
10Show child attributes
Show child attributes
Omitted or empty means identity - store the whole payload.
50Show child attributes
Show child attributes
Response
Created at version 1, with a mirror mapping rule synced behind it. webhook_slug is the public URL credential and is the only place it is returned in full at creation time.