Webhooks
Webhooks and their deliveries.
/v1/webhooksList webhooks
Newest first. The signing secret is never returned after creation.
Query parameters
limitintegerPage size, 1-200 (default 50).
cursorstringThe
nextCursorof the previous page.
Returns
200 A page of webhooks. A page: data is a list of Webhook, and nextCursor fetches the next page.
Fields of data
idstringrequiredWebhook id (
wh_…).pattern `^wh_.*`
urlstringrequiredWhere deliveries go: a public https address, checked again before every attempt.
descriptionstring | nullrequiredeventsstring[]requiredThe event types it receives; ["*"] = every type except transcript.final, which must be named.
includeConversationbooleanrequiredSend conversation words to this webhook where Zentiq's privacy rules allow them: transcript.final (sessions your app started through the API, and only when named in
events), session.ended's and report.produced's summaries, report feedback lines and quotes, a visitor's own words (need, budget, timeline, a lead's answers, a hand-off's summary and reason), a rating's comment, knowledge.gap's questions and case_link.opened's case summary. Never from a child's, a candidate's (any hiring session), a practice, a held or a safety-flagged session. Off by default. Turning it on needs a key holdingtranscripts:read; every change is recorded in the organisation's activity log. Refused, and off, while the organisation has zero data retention on.activebooleanrequiredFalse while switched off, and after three days of failed deliveries (then
pausedAtsays when).pausedAtstring (date-time) | nullrequiredWhen it was paused after failing every delivery for three days; PATCH { active: true } resumes it.
apiVersion"2026-07-08" | "2026-10-01"requiredThe contract its deliveries are written in (the creating key's; PATCH to move it).
createdAtstring (date-time)requiredISO 8601 UTC timestamp.
updatedAtstring (date-time)requiredISO 8601 UTC timestamp.
Errors
invalid_requestunauthorizedforbiddenupgrade_requiredrate_limitedserver_error
Request
curl "https://app.zentiqai.com/v1/webhooks?limit=20" \
-H "Authorization: Bearer $ZENTIQ_API_KEY"import { Zentiq } from "@zentiq/node";
const zentiq = new Zentiq({ apiKey: process.env.ZENTIQ_API_KEY });
const page = await zentiq.listWebhooks({
limit: 20,
});import os
from zentiq import Zentiq
zentiq = Zentiq(api_key=os.environ["ZENTIQ_API_KEY"])
page = zentiq.list_webhooks(limit=20)Example answer
{
"data": [
{
"id": "wh_cmfq2b7x10000abcd1234",
"url": "https://www.example.com",
"description": "…",
"events": [
"…"
],
"includeConversation": true,
"active": true
}
],
"error": null,
"requestId": "req_4f1c2e9a7b3d5e6f7a8b9c0d",
"nextCursor": null
}/v1/webhooksCreate a webhook
Registers a signed webhook for sendable event types (GET /v1/event-types) or "*". The address must be a public https one; it is checked again before every delivery, and redirects are never followed. Deliveries are written in the contract this request runs in. The signing secret is returned once. includeConversation: true needs a key holding transcripts:read; transcript.final needs it and must be named. While the organisation has zero data retention on, includeConversation: true is refused (409 conflict, details.reason zero_retention).
Body
urlstringrequiredA public https address. Private and local addresses are refused; redirects are never followed.
at most 2,048 characters
eventsstring[]Event types, or ["*"] (the default). transcript.final needs
includeConversation: true.at most 100 items
descriptionstringat most 200 characters
includeConversationbooleanSend conversation words to this webhook where Zentiq's privacy rules allow them: transcript.final (sessions your app started through the API, and only when named in
events), session.ended's and report.produced's summaries, report feedback lines and quotes, a visitor's own words (need, budget, timeline, a lead's answers, a hand-off's summary and reason), a rating's comment, knowledge.gap's questions and case_link.opened's case summary. Never from a child's, a candidate's (any hiring session), a practice, a held or a safety-flagged session. Off by default. Turning it on needs a key holdingtranscripts:read; every change is recorded in the organisation's activity log. Refused, and off, while the organisation has zero data retention on.
Returns
201 Created; the secret is shown once. data is WebhookWithSecret.
Fields of data
idstringrequiredWebhook id (
wh_…).pattern `^wh_.*`
urlstringrequiredWhere deliveries go: a public https address, checked again before every attempt.
descriptionstring | nullrequiredeventsstring[]requiredThe event types it receives; ["*"] = every type except transcript.final, which must be named.
includeConversationbooleanrequiredSend conversation words to this webhook where Zentiq's privacy rules allow them: transcript.final (sessions your app started through the API, and only when named in
events), session.ended's and report.produced's summaries, report feedback lines and quotes, a visitor's own words (need, budget, timeline, a lead's answers, a hand-off's summary and reason), a rating's comment, knowledge.gap's questions and case_link.opened's case summary. Never from a child's, a candidate's (any hiring session), a practice, a held or a safety-flagged session. Off by default. Turning it on needs a key holdingtranscripts:read; every change is recorded in the organisation's activity log. Refused, and off, while the organisation has zero data retention on.activebooleanrequiredFalse while switched off, and after three days of failed deliveries (then
pausedAtsays when).pausedAtstring (date-time) | nullrequiredWhen it was paused after failing every delivery for three days; PATCH { active: true } resumes it.
apiVersion"2026-07-08" | "2026-10-01"requiredThe contract its deliveries are written in (the creating key's; PATCH to move it).
createdAtstring (date-time)requiredISO 8601 UTC timestamp.
updatedAtstring (date-time)requiredISO 8601 UTC timestamp.
secretstringrequiredThe signing secret: returned once, at creation.
Errors
invalid_requestunauthorizedforbiddenupgrade_requiredconflictidempotency_conflictidempotency_in_progressrate_limitedserver_error
Request
curl -X POST "https://app.zentiqai.com/v1/webhooks" \
-H "Authorization: Bearer $ZENTIQ_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"url": "https://www.example.com"
}'import { Zentiq } from "@zentiq/node";
const zentiq = new Zentiq({ apiKey: process.env.ZENTIQ_API_KEY });
const result = await zentiq.createWebhook({
url: "https://www.example.com",
});import os
from zentiq import Zentiq
zentiq = Zentiq(api_key=os.environ["ZENTIQ_API_KEY"])
result = zentiq.create_webhook({
"url": "https://www.example.com",
})Example answer
{
"data": {
"id": "wh_cmfq2b7x10000abcd1234",
"url": "https://www.example.com",
"description": "…",
"events": [
"…"
],
"includeConversation": true,
"active": true
},
"error": null,
"requestId": "req_4f1c2e9a7b3d5e6f7a8b9c0d"
}/v1/webhooks/{id}Get a webhook
Path parameters
idstringrequiredWebhook id (
wh_…); the id without its prefix is accepted too.
Returns
200 The webhook. data is Webhook.
Fields of data
idstringrequiredWebhook id (
wh_…).pattern `^wh_.*`
urlstringrequiredWhere deliveries go: a public https address, checked again before every attempt.
descriptionstring | nullrequiredeventsstring[]requiredThe event types it receives; ["*"] = every type except transcript.final, which must be named.
includeConversationbooleanrequiredSend conversation words to this webhook where Zentiq's privacy rules allow them: transcript.final (sessions your app started through the API, and only when named in
events), session.ended's and report.produced's summaries, report feedback lines and quotes, a visitor's own words (need, budget, timeline, a lead's answers, a hand-off's summary and reason), a rating's comment, knowledge.gap's questions and case_link.opened's case summary. Never from a child's, a candidate's (any hiring session), a practice, a held or a safety-flagged session. Off by default. Turning it on needs a key holdingtranscripts:read; every change is recorded in the organisation's activity log. Refused, and off, while the organisation has zero data retention on.activebooleanrequiredFalse while switched off, and after three days of failed deliveries (then
pausedAtsays when).pausedAtstring (date-time) | nullrequiredWhen it was paused after failing every delivery for three days; PATCH { active: true } resumes it.
apiVersion"2026-07-08" | "2026-10-01"requiredThe contract its deliveries are written in (the creating key's; PATCH to move it).
createdAtstring (date-time)requiredISO 8601 UTC timestamp.
updatedAtstring (date-time)requiredISO 8601 UTC timestamp.
Errors
invalid_requestunauthorizedforbiddenupgrade_requirednot_foundrate_limitedserver_error
Request
curl "https://app.zentiqai.com/v1/webhooks/wh_123" \
-H "Authorization: Bearer $ZENTIQ_API_KEY"import { Zentiq } from "@zentiq/node";
const zentiq = new Zentiq({ apiKey: process.env.ZENTIQ_API_KEY });
const result = await zentiq.getWebhook("wh_123");import os
from zentiq import Zentiq
zentiq = Zentiq(api_key=os.environ["ZENTIQ_API_KEY"])
result = zentiq.get_webhook("wh_123")Example answer
{
"data": {
"id": "wh_cmfq2b7x10000abcd1234",
"url": "https://www.example.com",
"description": "…",
"events": [
"…"
],
"includeConversation": true,
"active": true
},
"error": null,
"requestId": "req_4f1c2e9a7b3d5e6f7a8b9c0d"
}/v1/webhooks/{id}Change a webhook
Change its address, events, description, contract or conversation option; active: true resumes a webhook paused after three days of failed deliveries, false switches it off. Turning includeConversation on needs transcripts:read, and so does changing the address, events or contract of a webhook that receives conversation words, or switching it back on (switching the words off never does); every change of the option is recorded in the organisation's activity log. While the organisation has zero data retention on, any change that leaves includeConversation on is refused (409 conflict, details.reason zero_retention); switching it off always works.
Path parameters
idstringrequiredWebhook id (
wh_…); the id without its prefix is accepted too.
Body
urlstringat most 2,048 characters
eventsstring[]at most 100 items
descriptionstring | nullactivebooleantrue resumes a paused webhook (its failing run starts again); false switches it off.
apiVersion"2026-07-08" | "2026-10-01"Move its deliveries to another contract.
includeConversationbooleanSend conversation words to this webhook where Zentiq's privacy rules allow them: transcript.final (sessions your app started through the API, and only when named in
events), session.ended's and report.produced's summaries, report feedback lines and quotes, a visitor's own words (need, budget, timeline, a lead's answers, a hand-off's summary and reason), a rating's comment, knowledge.gap's questions and case_link.opened's case summary. Never from a child's, a candidate's (any hiring session), a practice, a held or a safety-flagged session. Off by default. Turning it on needs a key holdingtranscripts:read; every change is recorded in the organisation's activity log. Refused, and off, while the organisation has zero data retention on.
Returns
200 The webhook as changed. data is Webhook.
Fields of data
idstringrequiredWebhook id (
wh_…).pattern `^wh_.*`
urlstringrequiredWhere deliveries go: a public https address, checked again before every attempt.
descriptionstring | nullrequiredeventsstring[]requiredThe event types it receives; ["*"] = every type except transcript.final, which must be named.
includeConversationbooleanrequiredSend conversation words to this webhook where Zentiq's privacy rules allow them: transcript.final (sessions your app started through the API, and only when named in
events), session.ended's and report.produced's summaries, report feedback lines and quotes, a visitor's own words (need, budget, timeline, a lead's answers, a hand-off's summary and reason), a rating's comment, knowledge.gap's questions and case_link.opened's case summary. Never from a child's, a candidate's (any hiring session), a practice, a held or a safety-flagged session. Off by default. Turning it on needs a key holdingtranscripts:read; every change is recorded in the organisation's activity log. Refused, and off, while the organisation has zero data retention on.activebooleanrequiredFalse while switched off, and after three days of failed deliveries (then
pausedAtsays when).pausedAtstring (date-time) | nullrequiredWhen it was paused after failing every delivery for three days; PATCH { active: true } resumes it.
apiVersion"2026-07-08" | "2026-10-01"requiredThe contract its deliveries are written in (the creating key's; PATCH to move it).
createdAtstring (date-time)requiredISO 8601 UTC timestamp.
updatedAtstring (date-time)requiredISO 8601 UTC timestamp.
Errors
invalid_requestunauthorizedforbiddenupgrade_requirednot_foundconflictrate_limitedserver_error
Request
curl -X PATCH "https://app.zentiqai.com/v1/webhooks/wh_123" \
-H "Authorization: Bearer $ZENTIQ_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'import { Zentiq } from "@zentiq/node";
const zentiq = new Zentiq({ apiKey: process.env.ZENTIQ_API_KEY });
const result = await zentiq.updateWebhook("wh_123", {});import os
from zentiq import Zentiq
zentiq = Zentiq(api_key=os.environ["ZENTIQ_API_KEY"])
result = zentiq.update_webhook("wh_123", {})Example answer
{
"data": {
"id": "wh_cmfq2b7x10000abcd1234",
"url": "https://www.example.com",
"description": "…",
"events": [
"…"
],
"includeConversation": true,
"active": true
},
"error": null,
"requestId": "req_4f1c2e9a7b3d5e6f7a8b9c0d"
}/v1/webhooks/{id}Delete a webhook
Deletes the webhook and its delivery log.
Path parameters
idstringrequiredWebhook id (
wh_…); the id without its prefix is accepted too.
Returns
200 Deleted. data is WebhookDeleted.
Fields of data
deletedtruerequiredidstringrequiredWebhook id (
wh_…).pattern `^wh_.*`
Errors
invalid_requestunauthorizedforbiddenupgrade_requirednot_foundrate_limitedserver_error
Request
curl -X DELETE "https://app.zentiqai.com/v1/webhooks/wh_123" \
-H "Authorization: Bearer $ZENTIQ_API_KEY"import { Zentiq } from "@zentiq/node";
const zentiq = new Zentiq({ apiKey: process.env.ZENTIQ_API_KEY });
const result = await zentiq.deleteWebhook("wh_123");import os
from zentiq import Zentiq
zentiq = Zentiq(api_key=os.environ["ZENTIQ_API_KEY"])
result = zentiq.delete_webhook("wh_123")Example answer
{
"data": {
"deleted": true,
"id": "wh_cmfq2b7x10000abcd1234"
},
"error": null,
"requestId": "req_4f1c2e9a7b3d5e6f7a8b9c0d"
}/v1/webhooks/deliveriesThe delivery log
Each event's delivery to each webhook, newest first, with its last attempt and, while it is retried, the next one (1 min, 5 min, 30 min, 2 h, 6 h, 12 h and 24 h after the first). Filter by webhook, event, state, success and time.
Query parameters
limitintegerPage size, 1-200 (default 50).
cursorstringThe
nextCursorof the previous page.webhookIdstringWebhook id (
wh_…).eventIdstringEvent id (
evt_…).statestringOne or more of pending, retrying, delivered, failed, comma-separated.
ok"true" | "false"fromstringDeliveries created at or after this moment.
tostringDeliveries created before this moment.
Returns
200 A page of deliveries. A page: data is a list of WebhookDelivery, and nextCursor fetches the next page.
Fields of data
idstringrequiredwhd_…(sent as X-Zentiq-Delivery-Id). Keys on the 2026-07-08 contract receive the id without its prefix.webhookIdstringrequiredWebhook id (
wh_…).pattern `^wh_.*`
eventIdstring | nullrequiredThe event delivered (
evt_…, the envelope'sid); null for deliveries logged before the outbox.eventstringrequiredThe event's type.
state"pending" | "retrying" | "delivered" | "failed"requiredpending (the first attempt is under way), retrying (the next attempt is at
nextAttemptAt), delivered, failed (no attempt left, or closed: seeerrorCode).attemptsintegerrequiredstatusinteger | nullrequiredThe HTTP status of the last attempt; null when none was reached.
okbooleanrequiredresponseMsinteger | nullrequirederrorCodestring | nullrequiredWhy the last attempt failed or the delivery closed: http_status, redirect, timeout, network, address_refused, internal_error, webhook_inactive, webhook_paused, unsubscribed, withdrawn, event_gone.
nextAttemptAtstring (date-time) | nullrequiredcreatedAtstring (date-time)requiredISO 8601 UTC timestamp.
Errors
invalid_requestunauthorizedforbiddenupgrade_requiredrate_limitedserver_error
Request
curl "https://app.zentiqai.com/v1/webhooks/deliveries?limit=20" \
-H "Authorization: Bearer $ZENTIQ_API_KEY"import { Zentiq } from "@zentiq/node";
const zentiq = new Zentiq({ apiKey: process.env.ZENTIQ_API_KEY });
const page = await zentiq.webhookDeliveries({
limit: 20,
});import os
from zentiq import Zentiq
zentiq = Zentiq(api_key=os.environ["ZENTIQ_API_KEY"])
page = zentiq.webhook_deliveries(limit=20)Example answer
{
"data": [
{
"id": "whd_123",
"webhookId": "wh_cmfq2b7x10000abcd1234",
"eventId": "evt_cmfq2b7x10000abcd1234",
"event": "…",
"state": "pending",
"attempts": 1
}
],
"error": null,
"requestId": "req_4f1c2e9a7b3d5e6f7a8b9c0d",
"nextCursor": null
}