Skip to content
KnockDevelopers

Webhook events

Every event Knock sends to your webhooks: the envelope and headers, then each event type with its fields and an example payload.

Chat with a Developer

Knock POSTs an event to your webhooks when something happens in your account, such as a contact booking a meeting. Manage your webhooks with the /v1/webhooks endpoints: authenticate with your API key in the x-api-key header.

Every delivery is a JSON POST to your HTTPS URL with an envelope (id, type, apiVersion, occurredAt, requestId, data). Delivery is at least once: deduplicate on webhook-id, and do not rely on order. Answer 2xx within 5 seconds; Knock retries failures for up to 72 hours.

Knock does not sign deliveries. To check that a request comes from Knock, set a secret token: Knock sends it in the knock-webhook-token header.

The envelope

Every delivery is a JSON body with the same envelope, whatever the event type. Read type to know the shape of data.

meeting.booked
{
  "id": "0b4c7f9e-1d2a-4e3b-8c5d-6f7a8b9c0d1e",
  "type": "meeting.booked",
  "apiVersion": "2026-11-01",
  "occurredAt": "2026-11-02T12:00:05.000Z",
  "data": {
    "meetingId": "2e4f6a8c-0b1d-4c3e-9f5a-7b8c9d0e1f2a",
    "contactId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
    "status": "booked",
    "bookingSource": "meeting_link",
    "bookedAt": "2026-11-02T12:00:00.000Z",
    "startAt": "2026-11-09T15:00:00.000Z",
    "endAt": "2026-11-09T15:30:00.000Z",
    "updatedAt": "2026-11-02T12:00:00.000Z",
    "firstName": "Jane",
    "lastName": "Doe",
    "companyName": "Acme",
    "companyDomain": "acme.com",
    "segment": "Enterprise",
    "ownerId": "4c3b2a19-0f8e-4d7c-9b6a-5e4d3c2b1a09",
    "ownerName": "Alex Kim"
  }
}
FieldTypePresentDescription
idstring (uuid)AlwaysID of the event, also sent as the webhook-id header. It is the same on every retry, and on every webhook the event is sent to: use it to ignore an event you already processed.
typestringAlwaysThe event type.
apiVersionstringAlwaysVersion of this payload format.
occurredAtstring (date-time)AlwaysWhen the event happened.
requestIdstring (uuid)OptionalThe X-Request-Id of the API call that caused the event. Absent when no API call did (for example a booking made by a contact).
dataobjectAlwaysThe event's details. Its fields depend on type, and are listed under each event below.

Timestamps are ISO 8601 strings in UTC. apiVersion is the version of the payload format: every event type is 2026-11-01. Fields can be added within a version, so ignore the ones you don't know.

The headers

HeaderSentDescription
content-typeAlwaysapplication/json.
user-agentAlwaysIdentifies Knock as the sender.
webhook-idAlwaysID of the event, the same as the body's id. Use it to ignore an event you already processed: it is the same on every retry.
webhook-timestampAlwaysWhen Knock sent this attempt, in Unix seconds. It changes on every retry.
knock-webhook-idAlwaysID of the webhook this delivery is for (00000000-0000-0000-0000-000000000000 for a URL test, which has no webhook yet).
knock-webhook-tokenOnly while the webhook has a secret tokenThe secret token you set on this webhook (secretToken on POST /v1/webhooks or PATCH /v1/webhooks/{webhookId}), as is. Sent only while the webhook has one; each webhook has its own. Knock reads it when it sends each attempt, so a new token applies from the next attempt, retries included. Knock does not sign deliveries: compare this header with the webhook's token (in constant time) and reject the request when it is missing or different.

Header names are case-insensitive. The knock-webhook-token header is the only proof that a delivery came from Knock: compare it with the secret token you set on the webhook (see Verify webhooks). Answer with any 2xx within 5 seconds: Knock does not follow redirects and never reads the response body (see Delivery and retries).

Meetings

Events about the meetings contacts book with your team.

Meeting booked

postmeeting.booked

A contact booked a meeting with your team through Knock. data is the meeting as GET /v1/meetings returns it, at the time Knock sent the event. Test bookings and meetings between members of your own team are not sent, and nor is a meeting cancelled before Knock sent the event. occurredAt is when Knock announced the booking, which can be later than bookedAt when Knock held it back (for example while it qualified the contact).

Header Parameters

user-agent*string

Identifies Knock as the sender.

Value"Knock-Webhooks/1"
webhook-id*string<uuid>

ID of the event, the same as the body's id. Use it to ignore an event you already processed: it is the same on every retry.

webhook-timestamp*string

When Knock sent this attempt, in Unix seconds. It changes on every retry.

knock-webhook-id*string<uuid>

ID of the webhook this delivery is for (00000000-0000-0000-0000-000000000000 for a URL test, which has no webhook yet).

knock-webhook-token?string

The secret token you set on this webhook (secretToken on POST /v1/webhooks or PATCH /v1/webhooks/{webhookId}), as is. Sent only while the webhook has one; each webhook has its own. Knock reads it when it sends each attempt, so a new token applies from the next attempt, retries included. Knock does not sign deliveries: compare this header with the webhook's token (in constant time) and reject the request when it is missing or different.

Request Body

application/json

The body of each meeting.booked delivery.

id*string<uuid>

ID of the event, also sent as the webhook-id header. It is the same on every retry, and on every webhook the event is sent to: use it to ignore an event you already processed.

type*string

The event type.

Value"meeting.booked"
apiVersion*string

Version of this payload format.

Value"2026-11-01"
occurredAt*string<date-time>

When the event happened.

requestId?string<uuid>

The X-Request-Id of the API call that caused the event. Absent when no API call did (for example a booking made by a contact).

data*object

The meeting, as GET /v1/meetings returns it.

meetingId*string<uuid>

ID of the meeting.

contactId*string<uuid> | null

ID of the contact who booked the meeting.

status*string

Status of the meeting, at the time Knock sent the event:

  • booked: The meeting is booked. Always the status of meeting.booked and meeting.rescheduled.
  • completed: The meeting time has passed (Knock does not know who attended). Always the status of meeting.completed.
  • cancelled: The meeting was cancelled. Always the status of meeting.cancelled.
One of"booked""completed""cancelled"
bookingSource*string | null

How the contact booked:

  • messaging_app: Booked in a chat: the contact picked a time offered in the conversation, or a team member booked it for them from Slack.
  • meeting_link: Booked through one of your Knock meeting links, which use your routing rules to pick the team member.
  • personal_link: Booked through a team member's personal scheduling link, directly with that team member.
One of"messaging_app""meeting_link""personal_link"null
bookedAt*string<date-time> | null

When the meeting was booked.

startAt*string<date-time> | null

When the meeting starts.

endAt*string<date-time> | null

When the meeting ends.

updatedAt*string<date-time>

When Knock last updated the meeting.

firstName*string | null

Contact's first name.

lastName*string | null

Contact's last name.

companyName*string | null

Contact's company name.

companyDomain*string | null

Contact's company domain.

segment*string | null

Segment the meeting was routed to.

ownerId*string<uuid> | null

ID of the team member who hosts the meeting, or the contact's owner when Knock has no host for it.

ownerName*string | null

That team member's name.

Response Body

Delivered. Answer within 5 seconds, before you process the event: Knock waits no longer, and does not read the response body.

Example Requests
POST/meeting.booked

The body of each meeting.booked delivery.

Request Body
application/json
{  "id": "0b4c7f9e-1d2a-4e3b-8c5d-6f7a8b9c0d1e",  "type": "meeting.booked",  "apiVersion": "2026-11-01",  "occurredAt": "2026-11-02T12:00:05.000Z",  "data": {    "meetingId": "2e4f6a8c-0b1d-4c3e-9f5a-7b8c9d0e1f2a",    "contactId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",    "status": "booked",    "bookingSource": "meeting_link",    "bookedAt": "2026-11-02T12:00:00.000Z",    "startAt": "2026-11-09T15:00:00.000Z",    "endAt": "2026-11-09T15:30:00.000Z",    "updatedAt": "2026-11-02T12:00:00.000Z",    "firstName": "Jane",    "lastName": "Doe",    "companyName": "Acme",    "companyDomain": "acme.com",    "segment": "Enterprise",    "ownerId": "4c3b2a19-0f8e-4d7c-9b6a-5e4d3c2b1a09",    "ownerName": "Alex Kim"  }}
Header Parameters
{  "user-agent": "Knock-Webhooks/1",  "webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "webhook-timestamp": "string",  "knock-webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}

Meeting rescheduled

postmeeting.rescheduled

A meeting booked through Knock moved to a new time through Knock. Every reschedule is a separate event with its own id. data is the meeting at its new time, plus previousStartAt and previousEndAt. A meeting moved directly in a calendar is not sent.

Header Parameters

user-agent*string

Identifies Knock as the sender.

Value"Knock-Webhooks/1"
webhook-id*string<uuid>

ID of the event, the same as the body's id. Use it to ignore an event you already processed: it is the same on every retry.

webhook-timestamp*string

When Knock sent this attempt, in Unix seconds. It changes on every retry.

knock-webhook-id*string<uuid>

ID of the webhook this delivery is for (00000000-0000-0000-0000-000000000000 for a URL test, which has no webhook yet).

knock-webhook-token?string

The secret token you set on this webhook (secretToken on POST /v1/webhooks or PATCH /v1/webhooks/{webhookId}), as is. Sent only while the webhook has one; each webhook has its own. Knock reads it when it sends each attempt, so a new token applies from the next attempt, retries included. Knock does not sign deliveries: compare this header with the webhook's token (in constant time) and reject the request when it is missing or different.

Request Body

application/json

The body of each meeting.rescheduled delivery.

id*string<uuid>

ID of the event, also sent as the webhook-id header. It is the same on every retry, and on every webhook the event is sent to: use it to ignore an event you already processed.

type*string

The event type.

Value"meeting.rescheduled"
apiVersion*string

Version of this payload format.

Value"2026-11-01"
occurredAt*string<date-time>

When the event happened.

requestId?string<uuid>

The X-Request-Id of the API call that caused the event. Absent when no API call did (for example a booking made by a contact).

data*object

The meeting at its new time, and the time it had before.

meetingId*string<uuid>

ID of the meeting.

contactId*string<uuid> | null

ID of the contact who booked the meeting.

status*string

Status of the meeting, at the time Knock sent the event:

  • booked: The meeting is booked. Always the status of meeting.booked and meeting.rescheduled.
  • completed: The meeting time has passed (Knock does not know who attended). Always the status of meeting.completed.
  • cancelled: The meeting was cancelled. Always the status of meeting.cancelled.
One of"booked""completed""cancelled"
bookingSource*string | null

How the contact booked:

  • messaging_app: Booked in a chat: the contact picked a time offered in the conversation, or a team member booked it for them from Slack.
  • meeting_link: Booked through one of your Knock meeting links, which use your routing rules to pick the team member.
  • personal_link: Booked through a team member's personal scheduling link, directly with that team member.
One of"messaging_app""meeting_link""personal_link"null
bookedAt*string<date-time> | null

When the meeting was booked.

startAt*string<date-time> | null

When the meeting starts.

endAt*string<date-time> | null

When the meeting ends.

updatedAt*string<date-time>

When Knock last updated the meeting.

firstName*string | null

Contact's first name.

lastName*string | null

Contact's last name.

companyName*string | null

Contact's company name.

companyDomain*string | null

Contact's company domain.

segment*string | null

Segment the meeting was routed to.

ownerId*string<uuid> | null

ID of the team member who hosts the meeting, or the contact's owner when Knock has no host for it.

ownerName*string | null

That team member's name.

previousStartAt*string<date-time> | null

When the meeting started before this reschedule. Null when Knock does not know.

previousEndAt*string<date-time> | null

When the meeting ended before this reschedule. Null when Knock does not know.

Response Body

Delivered. Answer within 5 seconds, before you process the event: Knock waits no longer, and does not read the response body.

Example Requests
POST/meeting.rescheduled

The body of each meeting.rescheduled delivery.

Request Body
application/json
{  "id": "0b4c7f9e-1d2a-4e3b-8c5d-6f7a8b9c0d1e",  "type": "meeting.rescheduled",  "apiVersion": "2026-11-01",  "occurredAt": "2026-11-02T12:00:05.000Z",  "data": {    "meetingId": "2e4f6a8c-0b1d-4c3e-9f5a-7b8c9d0e1f2a",    "contactId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",    "status": "booked",    "bookingSource": "meeting_link",    "bookedAt": "2026-11-02T12:00:00.000Z",    "startAt": "2026-11-10T15:00:00.000Z",    "endAt": "2026-11-10T15:30:00.000Z",    "updatedAt": "2026-11-02T12:00:05.000Z",    "firstName": "Jane",    "lastName": "Doe",    "companyName": "Acme",    "companyDomain": "acme.com",    "segment": "Enterprise",    "ownerId": "4c3b2a19-0f8e-4d7c-9b6a-5e4d3c2b1a09",    "ownerName": "Alex Kim",    "previousStartAt": "2026-11-09T15:00:00.000Z",    "previousEndAt": "2026-11-09T15:30:00.000Z"  }}
Header Parameters
{  "user-agent": "Knock-Webhooks/1",  "webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "webhook-timestamp": "string",  "knock-webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}

Meeting declined

postmeeting.declined

A contact declined the calendar invitation of a meeting booked through Knock. data is the meeting as GET /v1/meetings returns it, at the time Knock sent the event, whatever its status, plus declinedByContactId: the contact who booked it or another guest from outside your team. Declines by members of your team are not sent, and nor are meetings between members of your own team. Every decline is a separate event with its own id; accepting again sends nothing. When every contact invited has declined, Knock also cancels the meeting and sends meeting.cancelled. occurredAt is when Knock read the decline from the host's calendar.

Header Parameters

user-agent*string

Identifies Knock as the sender.

Value"Knock-Webhooks/1"
webhook-id*string<uuid>

ID of the event, the same as the body's id. Use it to ignore an event you already processed: it is the same on every retry.

webhook-timestamp*string

When Knock sent this attempt, in Unix seconds. It changes on every retry.

knock-webhook-id*string<uuid>

ID of the webhook this delivery is for (00000000-0000-0000-0000-000000000000 for a URL test, which has no webhook yet).

knock-webhook-token?string

The secret token you set on this webhook (secretToken on POST /v1/webhooks or PATCH /v1/webhooks/{webhookId}), as is. Sent only while the webhook has one; each webhook has its own. Knock reads it when it sends each attempt, so a new token applies from the next attempt, retries included. Knock does not sign deliveries: compare this header with the webhook's token (in constant time) and reject the request when it is missing or different.

Request Body

application/json

The body of each meeting.declined delivery.

id*string<uuid>

ID of the event, also sent as the webhook-id header. It is the same on every retry, and on every webhook the event is sent to: use it to ignore an event you already processed.

type*string

The event type.

Value"meeting.declined"
apiVersion*string

Version of this payload format.

Value"2026-11-01"
occurredAt*string<date-time>

When the event happened.

requestId?string<uuid>

The X-Request-Id of the API call that caused the event. Absent when no API call did (for example a booking made by a contact).

data*object

The meeting, and the contact who declined it.

meetingId*string<uuid>

ID of the meeting.

contactId*string<uuid> | null

ID of the contact who booked the meeting.

status*string

Status of the meeting, at the time Knock sent the event:

  • booked: The meeting is booked. Always the status of meeting.booked and meeting.rescheduled.
  • completed: The meeting time has passed (Knock does not know who attended). Always the status of meeting.completed.
  • cancelled: The meeting was cancelled. Always the status of meeting.cancelled.
One of"booked""completed""cancelled"
bookingSource*string | null

How the contact booked:

  • messaging_app: Booked in a chat: the contact picked a time offered in the conversation, or a team member booked it for them from Slack.
  • meeting_link: Booked through one of your Knock meeting links, which use your routing rules to pick the team member.
  • personal_link: Booked through a team member's personal scheduling link, directly with that team member.
One of"messaging_app""meeting_link""personal_link"null
bookedAt*string<date-time> | null

When the meeting was booked.

startAt*string<date-time> | null

When the meeting starts.

endAt*string<date-time> | null

When the meeting ends.

updatedAt*string<date-time>

When Knock last updated the meeting.

firstName*string | null

Contact's first name.

lastName*string | null

Contact's last name.

companyName*string | null

Contact's company name.

companyDomain*string | null

Contact's company domain.

segment*string | null

Segment the meeting was routed to.

ownerId*string<uuid> | null

ID of the team member who hosts the meeting, or the contact's owner when Knock has no host for it.

ownerName*string | null

That team member's name.

declinedByContactId*string<uuid>

ID of the contact who declined: the contact who booked the meeting (contactId) or another guest from outside your team.

Response Body

Delivered. Answer within 5 seconds, before you process the event: Knock waits no longer, and does not read the response body.

Example Requests
POST/meeting.declined

The body of each meeting.declined delivery.

Request Body
application/json
{  "id": "0b4c7f9e-1d2a-4e3b-8c5d-6f7a8b9c0d1e",  "type": "meeting.declined",  "apiVersion": "2026-11-01",  "occurredAt": "2026-11-02T12:00:05.000Z",  "data": {    "meetingId": "2e4f6a8c-0b1d-4c3e-9f5a-7b8c9d0e1f2a",    "contactId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",    "status": "booked",    "bookingSource": "meeting_link",    "bookedAt": "2026-11-02T12:00:00.000Z",    "startAt": "2026-11-09T15:00:00.000Z",    "endAt": "2026-11-09T15:30:00.000Z",    "updatedAt": "2026-11-02T12:00:00.000Z",    "firstName": "Jane",    "lastName": "Doe",    "companyName": "Acme",    "companyDomain": "acme.com",    "segment": "Enterprise",    "ownerId": "4c3b2a19-0f8e-4d7c-9b6a-5e4d3c2b1a09",    "ownerName": "Alex Kim",    "declinedByContactId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"  }}
Header Parameters
{  "user-agent": "Knock-Webhooks/1",  "webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "webhook-timestamp": "string",  "knock-webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}

Meeting cancelled

postmeeting.cancelled

A meeting booked through Knock was cancelled, by the contact or by your team. data is the meeting as GET /v1/meetings returns it, with status cancelled, plus cancelledBy. Meetings between members of your own team are not sent, and nor is a cancellation undone before Knock sent the event. A booking cancelled before Knock announced it sends meeting.cancelled without meeting.booked. A meeting cancelled because every contact declined comes back, with no event, when one of them accepts again; cancelling it again is a separate event with its own id. occurredAt is when Knock recorded the cancellation.

Header Parameters

user-agent*string

Identifies Knock as the sender.

Value"Knock-Webhooks/1"
webhook-id*string<uuid>

ID of the event, the same as the body's id. Use it to ignore an event you already processed: it is the same on every retry.

webhook-timestamp*string

When Knock sent this attempt, in Unix seconds. It changes on every retry.

knock-webhook-id*string<uuid>

ID of the webhook this delivery is for (00000000-0000-0000-0000-000000000000 for a URL test, which has no webhook yet).

knock-webhook-token?string

The secret token you set on this webhook (secretToken on POST /v1/webhooks or PATCH /v1/webhooks/{webhookId}), as is. Sent only while the webhook has one; each webhook has its own. Knock reads it when it sends each attempt, so a new token applies from the next attempt, retries included. Knock does not sign deliveries: compare this header with the webhook's token (in constant time) and reject the request when it is missing or different.

Request Body

application/json

The body of each meeting.cancelled delivery.

id*string<uuid>

ID of the event, also sent as the webhook-id header. It is the same on every retry, and on every webhook the event is sent to: use it to ignore an event you already processed.

type*string

The event type.

Value"meeting.cancelled"
apiVersion*string

Version of this payload format.

Value"2026-11-01"
occurredAt*string<date-time>

When the event happened.

requestId?string<uuid>

The X-Request-Id of the API call that caused the event. Absent when no API call did (for example a booking made by a contact).

data*object

The cancelled meeting, and who cancelled it.

meetingId*string<uuid>

ID of the meeting.

contactId*string<uuid> | null

ID of the contact who booked the meeting.

status*string

Status of the meeting, at the time Knock sent the event:

  • booked: The meeting is booked. Always the status of meeting.booked and meeting.rescheduled.
  • completed: The meeting time has passed (Knock does not know who attended). Always the status of meeting.completed.
  • cancelled: The meeting was cancelled. Always the status of meeting.cancelled.
One of"booked""completed""cancelled"
bookingSource*string | null

How the contact booked:

  • messaging_app: Booked in a chat: the contact picked a time offered in the conversation, or a team member booked it for them from Slack.
  • meeting_link: Booked through one of your Knock meeting links, which use your routing rules to pick the team member.
  • personal_link: Booked through a team member's personal scheduling link, directly with that team member.
One of"messaging_app""meeting_link""personal_link"null
bookedAt*string<date-time> | null

When the meeting was booked.

startAt*string<date-time> | null

When the meeting starts.

endAt*string<date-time> | null

When the meeting ends.

updatedAt*string<date-time>

When Knock last updated the meeting.

firstName*string | null

Contact's first name.

lastName*string | null

Contact's last name.

companyName*string | null

Contact's company name.

companyDomain*string | null

Contact's company domain.

segment*string | null

Segment the meeting was routed to.

ownerId*string<uuid> | null

ID of the team member who hosts the meeting, or the contact's owner when Knock has no host for it.

ownerName*string | null

That team member's name.

cancelledBy*string

Who cancelled the meeting:

  • contact: The contact cancelled the meeting, or every contact invited to it declined.
  • team: A member of your team cancelled the meeting or deleted its calendar event, or every member of your team invited to it declined.
One of"contact""team"

Response Body

Delivered. Answer within 5 seconds, before you process the event: Knock waits no longer, and does not read the response body.

Example Requests
POST/meeting.cancelled

The body of each meeting.cancelled delivery.

Request Body
application/json
{  "id": "0b4c7f9e-1d2a-4e3b-8c5d-6f7a8b9c0d1e",  "type": "meeting.cancelled",  "apiVersion": "2026-11-01",  "occurredAt": "2026-11-02T12:00:05.000Z",  "data": {    "meetingId": "2e4f6a8c-0b1d-4c3e-9f5a-7b8c9d0e1f2a",    "contactId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",    "status": "cancelled",    "bookingSource": "meeting_link",    "bookedAt": "2026-11-02T12:00:00.000Z",    "startAt": "2026-11-09T15:00:00.000Z",    "endAt": "2026-11-09T15:30:00.000Z",    "updatedAt": "2026-11-02T12:00:05.000Z",    "firstName": "Jane",    "lastName": "Doe",    "companyName": "Acme",    "companyDomain": "acme.com",    "segment": "Enterprise",    "ownerId": "4c3b2a19-0f8e-4d7c-9b6a-5e4d3c2b1a09",    "ownerName": "Alex Kim",    "cancelledBy": "contact"  }}
Header Parameters
{  "user-agent": "Knock-Webhooks/1",  "webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "webhook-timestamp": "string",  "knock-webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}

Meeting completed

postmeeting.completed

A meeting booked through Knock ended. data is the meeting as GET /v1/meetings returns it, with status completed. Knock marks a meeting completed from the host's calendar once its end time has passed; it does not know who attended. A meeting whose host disconnected their calendar is never completed. Sent once per meeting. Meetings between members of your own team are not sent. occurredAt is when Knock marked the meeting completed, usually minutes after it ended.

Header Parameters

user-agent*string

Identifies Knock as the sender.

Value"Knock-Webhooks/1"
webhook-id*string<uuid>

ID of the event, the same as the body's id. Use it to ignore an event you already processed: it is the same on every retry.

webhook-timestamp*string

When Knock sent this attempt, in Unix seconds. It changes on every retry.

knock-webhook-id*string<uuid>

ID of the webhook this delivery is for (00000000-0000-0000-0000-000000000000 for a URL test, which has no webhook yet).

knock-webhook-token?string

The secret token you set on this webhook (secretToken on POST /v1/webhooks or PATCH /v1/webhooks/{webhookId}), as is. Sent only while the webhook has one; each webhook has its own. Knock reads it when it sends each attempt, so a new token applies from the next attempt, retries included. Knock does not sign deliveries: compare this header with the webhook's token (in constant time) and reject the request when it is missing or different.

Request Body

application/json

The body of each meeting.completed delivery.

id*string<uuid>

ID of the event, also sent as the webhook-id header. It is the same on every retry, and on every webhook the event is sent to: use it to ignore an event you already processed.

type*string

The event type.

Value"meeting.completed"
apiVersion*string

Version of this payload format.

Value"2026-11-01"
occurredAt*string<date-time>

When the event happened.

requestId?string<uuid>

The X-Request-Id of the API call that caused the event. Absent when no API call did (for example a booking made by a contact).

data*object

The meeting, as GET /v1/meetings returns it.

meetingId*string<uuid>

ID of the meeting.

contactId*string<uuid> | null

ID of the contact who booked the meeting.

status*string

Status of the meeting, at the time Knock sent the event:

  • booked: The meeting is booked. Always the status of meeting.booked and meeting.rescheduled.
  • completed: The meeting time has passed (Knock does not know who attended). Always the status of meeting.completed.
  • cancelled: The meeting was cancelled. Always the status of meeting.cancelled.
One of"booked""completed""cancelled"
bookingSource*string | null

How the contact booked:

  • messaging_app: Booked in a chat: the contact picked a time offered in the conversation, or a team member booked it for them from Slack.
  • meeting_link: Booked through one of your Knock meeting links, which use your routing rules to pick the team member.
  • personal_link: Booked through a team member's personal scheduling link, directly with that team member.
One of"messaging_app""meeting_link""personal_link"null
bookedAt*string<date-time> | null

When the meeting was booked.

startAt*string<date-time> | null

When the meeting starts.

endAt*string<date-time> | null

When the meeting ends.

updatedAt*string<date-time>

When Knock last updated the meeting.

firstName*string | null

Contact's first name.

lastName*string | null

Contact's last name.

companyName*string | null

Contact's company name.

companyDomain*string | null

Contact's company domain.

segment*string | null

Segment the meeting was routed to.

ownerId*string<uuid> | null

ID of the team member who hosts the meeting, or the contact's owner when Knock has no host for it.

ownerName*string | null

That team member's name.

Response Body

Delivered. Answer within 5 seconds, before you process the event: Knock waits no longer, and does not read the response body.

Example Requests
POST/meeting.completed

The body of each meeting.completed delivery.

Request Body
application/json
{  "id": "0b4c7f9e-1d2a-4e3b-8c5d-6f7a8b9c0d1e",  "type": "meeting.completed",  "apiVersion": "2026-11-01",  "occurredAt": "2026-11-02T12:00:05.000Z",  "data": {    "meetingId": "2e4f6a8c-0b1d-4c3e-9f5a-7b8c9d0e1f2a",    "contactId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",    "status": "completed",    "bookingSource": "meeting_link",    "bookedAt": "2026-10-26T09:00:00.000Z",    "startAt": "2026-11-02T11:30:00.000Z",    "endAt": "2026-11-02T12:00:00.000Z",    "updatedAt": "2026-11-02T12:00:05.000Z",    "firstName": "Jane",    "lastName": "Doe",    "companyName": "Acme",    "companyDomain": "acme.com",    "segment": "Enterprise",    "ownerId": "4c3b2a19-0f8e-4d7c-9b6a-5e4d3c2b1a09",    "ownerName": "Alex Kim"  }}
Header Parameters
{  "user-agent": "Knock-Webhooks/1",  "webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "webhook-timestamp": "string",  "knock-webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}

Meeting rejected

postmeeting.rejected

Knock did not let a contact book a meeting, because your routing rules disqualified them or they used a personal email. data is the contact, the email address they submitted and the reason. It carries no meeting: most contacts are turned away before they pick a time, and a time a contact had already picked is released. Knock can also disqualify a contact up to about ten minutes after they submitted their email, once it has enriched them. Every rejection is a separate event with its own id, so a contact turned away again on a later attempt sends another one. Test sessions and members of your own team are not sent, and nor is a rejection in a scheduling window your website loaded but the contact never opened. occurredAt is when Knock rejected the contact.

Header Parameters

user-agent*string

Identifies Knock as the sender.

Value"Knock-Webhooks/1"
webhook-id*string<uuid>

ID of the event, the same as the body's id. Use it to ignore an event you already processed: it is the same on every retry.

webhook-timestamp*string

When Knock sent this attempt, in Unix seconds. It changes on every retry.

knock-webhook-id*string<uuid>

ID of the webhook this delivery is for (00000000-0000-0000-0000-000000000000 for a URL test, which has no webhook yet).

knock-webhook-token?string

The secret token you set on this webhook (secretToken on POST /v1/webhooks or PATCH /v1/webhooks/{webhookId}), as is. Sent only while the webhook has one; each webhook has its own. Knock reads it when it sends each attempt, so a new token applies from the next attempt, retries included. Knock does not sign deliveries: compare this header with the webhook's token (in constant time) and reject the request when it is missing or different.

Request Body

application/json

The body of each meeting.rejected delivery.

id*string<uuid>

ID of the event, also sent as the webhook-id header. It is the same on every retry, and on every webhook the event is sent to: use it to ignore an event you already processed.

type*string

The event type.

Value"meeting.rejected"
apiVersion*string

Version of this payload format.

Value"2026-11-01"
occurredAt*string<date-time>

When the event happened.

requestId?string<uuid>

The X-Request-Id of the API call that caused the event. Absent when no API call did (for example a booking made by a contact).

data*object

The contact Knock did not let book a meeting, and why.

contactId*string<uuid>

ID of the contact.

email*string<email> | null

The email address the contact submitted. Null when Knock does not know it.

reason*string

Why Knock did not let the contact book:

  • disqualified: Your routing rules sent the contact to a segment that disqualifies them, either when they submitted their email or once Knock finished enriching them (a time they had already picked is then released).
  • private_email: The contact submitted a personal email address (such as Gmail or Yahoo) on a meeting link that requires a work email.
One of"disqualified""private_email"

Response Body

Delivered. Answer within 5 seconds, before you process the event: Knock waits no longer, and does not read the response body.

Example Requests
POST/meeting.rejected

The body of each meeting.rejected delivery.

Request Body
application/json
{  "id": "0b4c7f9e-1d2a-4e3b-8c5d-6f7a8b9c0d1e",  "type": "meeting.rejected",  "apiVersion": "2026-11-01",  "occurredAt": "2026-11-02T12:00:05.000Z",  "data": {    "contactId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",    "email": "jane@acme.com",    "reason": "disqualified"  }}
Header Parameters
{  "user-agent": "Knock-Webhooks/1",  "webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "webhook-timestamp": "string",  "knock-webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}

LinkedIn outreach

Events about the LinkedIn invitations Knock sends from your team members' accounts.

LinkedIn invitation sent

postoutreach.linkedin_invite_sent

Knock sent a LinkedIn connection invitation to a contact from a team member's account. data names the contact, the team member whose account sent the invitation, why Knock sent it (source, plus meetingId when a booked meeting led to it), the contact's profile and the note sent with it. Every invitation is a separate event with its own id, so inviting the same contact again sends another one. Invitations team members send from LinkedIn themselves are not sent. Knock can hold an invitation back to respect LinkedIn's limits: it is sent when the invitation goes out, which can be days after the activity that led to it. occurredAt is when Knock sent the invitation.

Header Parameters

user-agent*string

Identifies Knock as the sender.

Value"Knock-Webhooks/1"
webhook-id*string<uuid>

ID of the event, the same as the body's id. Use it to ignore an event you already processed: it is the same on every retry.

webhook-timestamp*string

When Knock sent this attempt, in Unix seconds. It changes on every retry.

knock-webhook-id*string<uuid>

ID of the webhook this delivery is for (00000000-0000-0000-0000-000000000000 for a URL test, which has no webhook yet).

knock-webhook-token?string

The secret token you set on this webhook (secretToken on POST /v1/webhooks or PATCH /v1/webhooks/{webhookId}), as is. Sent only while the webhook has one; each webhook has its own. Knock reads it when it sends each attempt, so a new token applies from the next attempt, retries included. Knock does not sign deliveries: compare this header with the webhook's token (in constant time) and reject the request when it is missing or different.

Request Body

application/json

The body of each outreach.linkedin_invite_sent delivery.

id*string<uuid>

ID of the event, also sent as the webhook-id header. It is the same on every retry, and on every webhook the event is sent to: use it to ignore an event you already processed.

type*string

The event type.

Value"outreach.linkedin_invite_sent"
apiVersion*string

Version of this payload format.

Value"2026-11-01"
occurredAt*string<date-time>

When the event happened.

requestId?string<uuid>

The X-Request-Id of the API call that caused the event. Absent when no API call did (for example a booking made by a contact).

data*object

The LinkedIn invitation Knock sent, the profile it went to and its note.

contactId*string<uuid>

ID of the contact Knock invited.

memberId*string<uuid>

ID of the team member whose LinkedIn account sent the invitation.

memberName*string | null

That team member's name. Null when Knock has none.

meetingId*string<uuid> | null

ID of the meeting that led Knock to invite the contact, as GET /v1/meetings lists it. Null when no booked meeting did.

source*string | null

Why Knock invited the contact, null when Knock does not know:

  • meeting_link: A meeting booked through one of your Knock meeting links: the contact booked it or is a guest on it.
  • personal_link: A meeting booked through a team member's personal scheduling link: the contact booked it or is a guest on it.
  • qualified_not_booked: The contact qualified for a meeting on one of your Knock meeting links or a team member's personal scheduling link, but did not book a time.
  • form: One of your form workflows picked the contact after they submitted a form.
  • tag: One of your tag workflows picked the contact after Knock identified them on your website.
  • product: One of your product workflows picked the contact from their activity in your product.
One of"meeting_link""personal_link""qualified_not_booked""form""tag""product"null
linkedinProfileUrl*string | null

URL of the contact's LinkedIn profile the invitation went to. Null when Knock does not know it.

note*string | null

The note sent with the invitation. Null when the invitation went without one (LinkedIn limits the notes a free account can send).

Response Body

Delivered. Answer within 5 seconds, before you process the event: Knock waits no longer, and does not read the response body.

Example Requests
POST/outreach.linkedin_invite_sent

The body of each outreach.linkedin_invite_sent delivery.

Request Body
application/json
{  "id": "0b4c7f9e-1d2a-4e3b-8c5d-6f7a8b9c0d1e",  "type": "outreach.linkedin_invite_sent",  "apiVersion": "2026-11-01",  "occurredAt": "2026-11-02T12:00:05.000Z",  "data": {    "contactId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",    "memberId": "4c3b2a19-0f8e-4d7c-9b6a-5e4d3c2b1a09",    "memberName": "Alex Kim",    "meetingId": "2e4f6a8c-0b1d-4c3e-9f5a-7b8c9d0e1f2a",    "source": "meeting_link",    "linkedinProfileUrl": "https://www.linkedin.com/in/jane-doe",    "note": "Hi Jane, looking forward to our meeting next week."  }}
Header Parameters
{  "user-agent": "Knock-Webhooks/1",  "webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "webhook-timestamp": "string",  "knock-webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}

LinkedIn invitation accepted

postoutreach.linkedin_invite_accepted

A contact accepted a LinkedIn connection invitation Knock sent from a team member's account. data is the invitation as outreach.linkedin_invite_sent described it, without the profile and the note: the same contactId, memberId, meetingId and source. Sent once per invitation, often days after outreach.linkedin_invite_sent; deliveries can arrive in either order. Knock can miss an acceptance, so a missing event does not mean the contact declined. occurredAt is when Knock detected the acceptance, which can be later than when the contact accepted.

Header Parameters

user-agent*string

Identifies Knock as the sender.

Value"Knock-Webhooks/1"
webhook-id*string<uuid>

ID of the event, the same as the body's id. Use it to ignore an event you already processed: it is the same on every retry.

webhook-timestamp*string

When Knock sent this attempt, in Unix seconds. It changes on every retry.

knock-webhook-id*string<uuid>

ID of the webhook this delivery is for (00000000-0000-0000-0000-000000000000 for a URL test, which has no webhook yet).

knock-webhook-token?string

The secret token you set on this webhook (secretToken on POST /v1/webhooks or PATCH /v1/webhooks/{webhookId}), as is. Sent only while the webhook has one; each webhook has its own. Knock reads it when it sends each attempt, so a new token applies from the next attempt, retries included. Knock does not sign deliveries: compare this header with the webhook's token (in constant time) and reject the request when it is missing or different.

Request Body

application/json

The body of each outreach.linkedin_invite_accepted delivery.

id*string<uuid>

ID of the event, also sent as the webhook-id header. It is the same on every retry, and on every webhook the event is sent to: use it to ignore an event you already processed.

type*string

The event type.

Value"outreach.linkedin_invite_accepted"
apiVersion*string

Version of this payload format.

Value"2026-11-01"
occurredAt*string<date-time>

When the event happened.

requestId?string<uuid>

The X-Request-Id of the API call that caused the event. Absent when no API call did (for example a booking made by a contact).

data*object

A LinkedIn connection invitation Knock sent to a contact from a team member's account.

contactId*string<uuid>

ID of the contact Knock invited.

memberId*string<uuid>

ID of the team member whose LinkedIn account sent the invitation.

memberName*string | null

That team member's name. Null when Knock has none.

meetingId*string<uuid> | null

ID of the meeting that led Knock to invite the contact, as GET /v1/meetings lists it. Null when no booked meeting did.

source*string | null

Why Knock invited the contact, null when Knock does not know:

  • meeting_link: A meeting booked through one of your Knock meeting links: the contact booked it or is a guest on it.
  • personal_link: A meeting booked through a team member's personal scheduling link: the contact booked it or is a guest on it.
  • qualified_not_booked: The contact qualified for a meeting on one of your Knock meeting links or a team member's personal scheduling link, but did not book a time.
  • form: One of your form workflows picked the contact after they submitted a form.
  • tag: One of your tag workflows picked the contact after Knock identified them on your website.
  • product: One of your product workflows picked the contact from their activity in your product.
One of"meeting_link""personal_link""qualified_not_booked""form""tag""product"null

Response Body

Delivered. Answer within 5 seconds, before you process the event: Knock waits no longer, and does not read the response body.

Example Requests
POST/outreach.linkedin_invite_accepted

The body of each outreach.linkedin_invite_accepted delivery.

Request Body
application/json
{  "id": "0b4c7f9e-1d2a-4e3b-8c5d-6f7a8b9c0d1e",  "type": "outreach.linkedin_invite_accepted",  "apiVersion": "2026-11-01",  "occurredAt": "2026-11-02T12:00:05.000Z",  "data": {    "contactId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",    "memberId": "4c3b2a19-0f8e-4d7c-9b6a-5e4d3c2b1a09",    "memberName": "Alex Kim",    "meetingId": "2e4f6a8c-0b1d-4c3e-9f5a-7b8c9d0e1f2a",    "source": "meeting_link"  }}
Header Parameters
{  "user-agent": "Knock-Webhooks/1",  "webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "webhook-timestamp": "string",  "knock-webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}

Team

Events about the members of your team.

Team member LinkedIn status changed

postmember.linkedin_status_changed

The connection between a team member's LinkedIn account and Knock changed. data is the team member and the new status of their LinkedIn account: connected, disconnected (Knock lost access and the team member needs to reconnect it) or removed (the account was removed from Knock). Every change is a separate event with its own id. occurredAt is when Knock recorded the change: deliveries can arrive out of order, so keep the status with the latest occurredAt.

Header Parameters

user-agent*string

Identifies Knock as the sender.

Value"Knock-Webhooks/1"
webhook-id*string<uuid>

ID of the event, the same as the body's id. Use it to ignore an event you already processed: it is the same on every retry.

webhook-timestamp*string

When Knock sent this attempt, in Unix seconds. It changes on every retry.

knock-webhook-id*string<uuid>

ID of the webhook this delivery is for (00000000-0000-0000-0000-000000000000 for a URL test, which has no webhook yet).

knock-webhook-token?string

The secret token you set on this webhook (secretToken on POST /v1/webhooks or PATCH /v1/webhooks/{webhookId}), as is. Sent only while the webhook has one; each webhook has its own. Knock reads it when it sends each attempt, so a new token applies from the next attempt, retries included. Knock does not sign deliveries: compare this header with the webhook's token (in constant time) and reject the request when it is missing or different.

Request Body

application/json

The body of each member.linkedin_status_changed delivery.

id*string<uuid>

ID of the event, also sent as the webhook-id header. It is the same on every retry, and on every webhook the event is sent to: use it to ignore an event you already processed.

type*string

The event type.

Value"member.linkedin_status_changed"
apiVersion*string

Version of this payload format.

Value"2026-11-01"
occurredAt*string<date-time>

When the event happened.

requestId?string<uuid>

The X-Request-Id of the API call that caused the event. Absent when no API call did (for example a booking made by a contact).

data*object

The team member, and the new status of their LinkedIn account's connection to Knock.

memberId*string<uuid>

ID of the team member.

memberName*string | null

The team member's name. Null when Knock has none.

status*string

The new status of the team member's LinkedIn account:

  • connected: The account is connected to Knock: the team member connected it for the first time or reconnected it, or it recovered.
  • disconnected: Knock lost access to the account, for example because LinkedIn signed it out: the team member needs to reconnect it.
  • removed: The account was removed from Knock: the team member needs to connect it again.
One of"connected""disconnected""removed"

Response Body

Delivered. Answer within 5 seconds, before you process the event: Knock waits no longer, and does not read the response body.

Example Requests
POST/member.linkedin_status_changed

The body of each member.linkedin_status_changed delivery.

Request Body
application/json
{  "id": "0b4c7f9e-1d2a-4e3b-8c5d-6f7a8b9c0d1e",  "type": "member.linkedin_status_changed",  "apiVersion": "2026-11-01",  "occurredAt": "2026-11-02T12:00:05.000Z",  "data": {    "memberId": "4c3b2a19-0f8e-4d7c-9b6a-5e4d3c2b1a09",    "memberName": "Alex Kim",    "status": "disconnected"  }}
Header Parameters
{  "user-agent": "Knock-Webhooks/1",  "webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "webhook-timestamp": "string",  "knock-webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}

Enrichment

Events about your enrichment requests.

Enrichment request completed

postenrichment_request.completed

An enrichment request you submitted finished. The event carries no results: fetch them with GET /v1/enrichment-requests/{enrichRequestId}. occurredAt is the request's completedAt. Deliveries can be delayed or fail, so keep a slow poll for requests whose event you never received.

Header Parameters

user-agent*string

Identifies Knock as the sender.

Value"Knock-Webhooks/1"
webhook-id*string<uuid>

ID of the event, the same as the body's id. Use it to ignore an event you already processed: it is the same on every retry.

webhook-timestamp*string

When Knock sent this attempt, in Unix seconds. It changes on every retry.

knock-webhook-id*string<uuid>

ID of the webhook this delivery is for (00000000-0000-0000-0000-000000000000 for a URL test, which has no webhook yet).

knock-webhook-token?string

The secret token you set on this webhook (secretToken on POST /v1/webhooks or PATCH /v1/webhooks/{webhookId}), as is. Sent only while the webhook has one; each webhook has its own. Knock reads it when it sends each attempt, so a new token applies from the next attempt, retries included. Knock does not sign deliveries: compare this header with the webhook's token (in constant time) and reject the request when it is missing or different.

Request Body

application/json

The body of each enrichment_request.completed delivery.

id*string<uuid>

ID of the event, also sent as the webhook-id header. It is the same on every retry, and on every webhook the event is sent to: use it to ignore an event you already processed.

type*string

The event type.

Value"enrichment_request.completed"
apiVersion*string

Version of this payload format.

Value"2026-11-01"
occurredAt*string<date-time>

When the event happened.

requestId?string<uuid>

The X-Request-Id of the API call that caused the event. Absent when no API call did (for example a booking made by a contact).

data*object

The finished enrichment request, without its results.

enrichRequestId*string<uuid>

ID of the enrichment request. Fetch the results with GET /v1/enrichment-requests/{enrichRequestId}.

type*string

Whether the request enriched people or companies.

One of"people""companies"
status*string

How the request ended:

  • completed: Every item was enriched or not found.
  • partially_completed: Some items failed; the others were enriched or not found.
  • failed: Every item failed.
One of"completed""partially_completed""failed"
itemCounts*object

How many items of the request ended in each state.

total*integer

Items in the request.

completed*integer

Items Knock enriched.

notFound*integer

Items Knock found no data for.

failed*integer

Items that failed.

createdAt*string<date-time>

When you submitted the request.

completedAt*string<date-time>

When the request finished.

Response Body

Delivered. Answer within 5 seconds, before you process the event: Knock waits no longer, and does not read the response body.

Example Requests
POST/enrichment_request.completed

The body of each enrichment_request.completed delivery.

Request Body
application/json
{  "id": "0b4c7f9e-1d2a-4e3b-8c5d-6f7a8b9c0d1e",  "type": "enrichment_request.completed",  "apiVersion": "2026-11-01",  "occurredAt": "2026-11-02T12:00:05.000Z",  "data": {    "enrichRequestId": "7d0f4f1e-2c3b-4a8e-9a51-0e6f3b8c2d14",    "type": "people",    "status": "completed",    "itemCounts": {      "total": 3,      "completed": 2,      "notFound": 1,      "failed": 0    },    "createdAt": "2026-11-02T11:58:35.000Z",    "completedAt": "2026-11-02T12:00:05.000Z"  }}
Header Parameters
{  "user-agent": "Knock-Webhooks/1",  "webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "webhook-timestamp": "string",  "knock-webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}

Testing

The test event Knock sends when you ping a webhook or test a URL.

Webhook ping

postwebhook.ping

A test event Knock sends when you ping a webhook or test a URL. It goes only to the webhook you pinged (POST /v1/webhooks/{webhookId}/ping), or to the URL you test before you create its webhook (POST /v1/webhooks/test). Answer it like any other event. A ping is never retried, and every ping is a new event with its own id.

Header Parameters

user-agent*string

Identifies Knock as the sender.

Value"Knock-Webhooks/1"
webhook-id*string<uuid>

ID of the event, the same as the body's id. Use it to ignore an event you already processed: it is the same on every retry.

webhook-timestamp*string

When Knock sent this attempt, in Unix seconds. It changes on every retry.

knock-webhook-id*string<uuid>

ID of the webhook this delivery is for (00000000-0000-0000-0000-000000000000 for a URL test, which has no webhook yet).

knock-webhook-token?string

The secret token you set on this webhook (secretToken on POST /v1/webhooks or PATCH /v1/webhooks/{webhookId}), as is. Sent only while the webhook has one; each webhook has its own. Knock reads it when it sends each attempt, so a new token applies from the next attempt, retries included. Knock does not sign deliveries: compare this header with the webhook's token (in constant time) and reject the request when it is missing or different.

Request Body

application/json

The body of each webhook.ping delivery.

id*string<uuid>

ID of the event, also sent as the webhook-id header. It is the same on every retry, and on every webhook the event is sent to: use it to ignore an event you already processed.

type*string

The event type.

Value"webhook.ping"
apiVersion*string

Version of this payload format.

Value"2026-11-01"
occurredAt*string<date-time>

When the event happened.

requestId?string<uuid>

The X-Request-Id of the API call that caused the event. Absent when no API call did (for example a booking made by a contact).

data*object

The webhook that was pinged.

webhookId*string<uuid>

ID of the webhook you pinged, or 00000000-0000-0000-0000-000000000000 when you tested a URL that has no webhook yet (POST /v1/webhooks/test).

Response Body

Delivered. Answer within 5 seconds, before you process the event: Knock waits no longer, and does not read the response body.

Example Requests
POST/webhook.ping

The body of each webhook.ping delivery.

Request Body
application/json
{  "id": "0b4c7f9e-1d2a-4e3b-8c5d-6f7a8b9c0d1e",  "type": "webhook.ping",  "apiVersion": "2026-11-01",  "occurredAt": "2026-11-02T12:00:05.000Z",  "data": {    "webhookId": "5b1e2d3c-4f5a-4b6c-8d7e-9f0a1b2c3d4e"  }}
Header Parameters
{  "user-agent": "Knock-Webhooks/1",  "webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "webhook-timestamp": "string",  "knock-webhook-id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"}