Webhooks API reference
Reference documentation for the Webhooks HTTP endpoints.
The Webhooks API lets you programmatically interact with and monitor webhooks.
In addition to webhooks, you can also react to document changes with Sanity Functions.
Authentication
- All requests must be authenticated.
- Managing webhooks requires the webhooks permission on the project: read to list or get webhooks, create to create or update them, and delete to delete them.
Webhook types
Sanity provides two types of webhooks, transaction and document. Document webhooks are preferred because they are more flexible and powerful.
Document webhooks
A document webhook triggers every time a document is created, updated, or deleted. If a transaction updates three documents, three webhooks are executed. Document webhooks also allow for more granular filtering and customizable payloads with GROQ.
Transaction webhooks
A transaction webhook triggers once per dataset, meaning if you batch together multiple document mutations in one transaction, only one webhook is executed.
Base API server URL
Sanity API base URL
https://{projectId}.api.sanity.io/{apiVersion}Variables
- projectIdstringdefault:
"projectId"Project ID
- apiVersionstringdefault:
"v2025-02-19"API version
Endpoints
List all webhooks
/hooks/projects/{projectId}Path parameters
Responses
List of webhooks
Must be 'document'
Name of webhook
The endpoint to which the webhook request is sent. Must start with
http://orhttps://, and must not resolve to a private address.Which dataset should this trigger for. Use a dataset name (letters, numbers,
_, and-, stored lowercase), or*for all datasets in the project.- descriptionstring|null
Optional description to add helpful context to the webhook
- ruleobject
Configuration for when and how the webhook should trigger
Show child attributes
Webhooks can be triggered when a document is created, updated, deleted, or any combination of these
Show child attributes
items
- stringenum:
"create", "update", "delete"
- filterstring
A GROQ filter specifying which documents will, when changed, trigger your webhook. A filter is what you commonly see between the
*[and]in a GROQ query. This field supports all the GROQ functions you'd expect and has additional support for functions in the delta:: namespace, as well as before() and after(). If left empty, it will apply to all documents (*[]) - projectionstring
A GROQ projection defining the payload (or body) of the outgoing webhook request. This field supports GROQ functions in the delta:: namespace, as well as before() and after(). If left empty, it will include the whole document after the change that triggered it
Which API version to use for the GROQ filter and projection. Use the format
vYYYY-MM-DD, orvX.This field configures the webhook's HTTP request method. It can be set to POST, PUT, PATCH, DELETE, or GET. Some endpoints require incoming requests to use a specific method to work
Set to trigger on changes to draft documents.
Set to trigger on changes to version documents.
- headersobject
Additional HTTP headers. You can add multiple headers. A common example is adding an
Authorization: Bearer <token>header to authenticate the webhook request. The total size of all headers can not exceed 2 kB. Header names can only contain letters, numbers, and hyphens, and values must be ASCII without line breaks. Thecontent-length,connection,keep-alive,proxy-authenticate,proxy-authorization,te,trailer,transfer-encoding, andupgradeheaders are not allowed. - secretstring|null
To let receiving services verify the origin of any outgoing webhook, you may add a secret that will be hashed and included as part of the webhook request's headers
- isDisabledByUserboolean
Set to 'true' to disable the webhook and prevent it from triggering
- idstring
Unique identifier for the webhook
- projectIdstring
ID of the Sanity project
- createdAtstring (date-time)
Timestamp when the webhook was created
- createdByUserIdstring
ID of the user who created the webhook
- isDisabledboolean
Whether the webhook is currently disabled
- deletedAtstring|null (date-time)
Timestamp when the webhook was deleted, if applicable
Legacy per-event filter object. Use
rule.filterinstead.Legacy per-event projection object. Use
rule.projectioninstead.
Set to 'transaction', or omit. Requests without a type create a transaction webhook.
Name of webhook
The endpoint to which the webhook request is sent. Must start with
http://orhttps://, and must not resolve to a private address.Which dataset should this trigger for. Use a dataset name (letters, numbers,
_, and-, stored lowercase), or*for all datasets in the project.- descriptionstring|null
Optional description to add helpful context to the webhook
- isDisabledByUserboolean
Set to 'true' to disable the webhook and prevent it from triggering
- idstring
Unique identifier for the webhook
- projectIdstring
ID of the Sanity project
- createdAtstring (date-time)
Timestamp when the webhook was created
- createdByUserIdstring
ID of the user who created the webhook
- isDisabledboolean
Whether the webhook is currently disabled
- deletedAtstring|null (date-time)
Timestamp when the webhook was deleted, if applicable
Missing or invalid token, or the token lacks the required webhooks grant. For example, User must have grant sanity.project.webhooks/read to perform this operation.
Create a webhook
/hooks/projects/{projectId}Path parameters
Request body application/json
Must be 'document'
Name of webhook
The endpoint to which the webhook request is sent. Must start with
http://orhttps://, and must not resolve to a private address.Which dataset should this trigger for. Use a dataset name (letters, numbers,
_, and-, stored lowercase), or*for all datasets in the project.- descriptionstring|null
Optional description to add helpful context to the webhook
- ruleobject
Configuration for when and how the webhook should trigger
Show child attributes
Webhooks can be triggered when a document is created, updated, deleted, or any combination of these
Show child attributes
items
- stringenum:
"create", "update", "delete"
- filterstring
A GROQ filter specifying which documents will, when changed, trigger your webhook. A filter is what you commonly see between the
*[and]in a GROQ query. This field supports all the GROQ functions you'd expect and has additional support for functions in the delta:: namespace, as well as before() and after(). If left empty, it will apply to all documents (*[]) - projectionstring
A GROQ projection defining the payload (or body) of the outgoing webhook request. This field supports GROQ functions in the delta:: namespace, as well as before() and after(). If left empty, it will include the whole document after the change that triggered it
Which API version to use for the GROQ filter and projection. Use the format
vYYYY-MM-DD, orvX.This field configures the webhook's HTTP request method. It can be set to POST, PUT, PATCH, DELETE, or GET. Some endpoints require incoming requests to use a specific method to work
Set to trigger on changes to draft documents.
Set to trigger on changes to version documents.
- headersobject
Additional HTTP headers. You can add multiple headers. A common example is adding an
Authorization: Bearer <token>header to authenticate the webhook request. The total size of all headers can not exceed 2 kB. Header names can only contain letters, numbers, and hyphens, and values must be ASCII without line breaks. Thecontent-length,connection,keep-alive,proxy-authenticate,proxy-authorization,te,trailer,transfer-encoding, andupgradeheaders are not allowed. - secretstring|null
To let receiving services verify the origin of any outgoing webhook, you may add a secret that will be hashed and included as part of the webhook request's headers
- isDisabledByUserboolean
Set to 'true' to disable the webhook and prevent it from triggering
Set to 'transaction', or omit. Requests without a type create a transaction webhook.
Name of webhook
The endpoint to which the webhook request is sent. Must start with
http://orhttps://, and must not resolve to a private address.Which dataset should this trigger for. Use a dataset name (letters, numbers,
_, and-, stored lowercase), or*for all datasets in the project.- descriptionstring|null
Optional description to add helpful context to the webhook
- isDisabledByUserboolean
Set to 'true' to disable the webhook and prevent it from triggering
Responses
Created webhook
Must be 'document'
Name of webhook
The endpoint to which the webhook request is sent. Must start with
http://orhttps://, and must not resolve to a private address.Which dataset should this trigger for. Use a dataset name (letters, numbers,
_, and-, stored lowercase), or*for all datasets in the project.- descriptionstring|null
Optional description to add helpful context to the webhook
- ruleobject
Configuration for when and how the webhook should trigger
Show child attributes
Webhooks can be triggered when a document is created, updated, deleted, or any combination of these
Show child attributes
items
- stringenum:
"create", "update", "delete"
- filterstring
A GROQ filter specifying which documents will, when changed, trigger your webhook. A filter is what you commonly see between the
*[and]in a GROQ query. This field supports all the GROQ functions you'd expect and has additional support for functions in the delta:: namespace, as well as before() and after(). If left empty, it will apply to all documents (*[]) - projectionstring
A GROQ projection defining the payload (or body) of the outgoing webhook request. This field supports GROQ functions in the delta:: namespace, as well as before() and after(). If left empty, it will include the whole document after the change that triggered it
Which API version to use for the GROQ filter and projection. Use the format
vYYYY-MM-DD, orvX.This field configures the webhook's HTTP request method. It can be set to POST, PUT, PATCH, DELETE, or GET. Some endpoints require incoming requests to use a specific method to work
Set to trigger on changes to draft documents.
Set to trigger on changes to version documents.
- headersobject
Additional HTTP headers. You can add multiple headers. A common example is adding an
Authorization: Bearer <token>header to authenticate the webhook request. The total size of all headers can not exceed 2 kB. Header names can only contain letters, numbers, and hyphens, and values must be ASCII without line breaks. Thecontent-length,connection,keep-alive,proxy-authenticate,proxy-authorization,te,trailer,transfer-encoding, andupgradeheaders are not allowed. - secretstring|null
To let receiving services verify the origin of any outgoing webhook, you may add a secret that will be hashed and included as part of the webhook request's headers
- isDisabledByUserboolean
Set to 'true' to disable the webhook and prevent it from triggering
- idstring
Unique identifier for the webhook
- projectIdstring
ID of the Sanity project
- createdAtstring (date-time)
Timestamp when the webhook was created
- createdByUserIdstring
ID of the user who created the webhook
- isDisabledboolean
Whether the webhook is currently disabled
- deletedAtstring|null (date-time)
Timestamp when the webhook was deleted, if applicable
Legacy per-event filter object. Use
rule.filterinstead.Legacy per-event projection object. Use
rule.projectioninstead.
Set to 'transaction', or omit. Requests without a type create a transaction webhook.
Name of webhook
The endpoint to which the webhook request is sent. Must start with
http://orhttps://, and must not resolve to a private address.Which dataset should this trigger for. Use a dataset name (letters, numbers,
_, and-, stored lowercase), or*for all datasets in the project.- descriptionstring|null
Optional description to add helpful context to the webhook
- isDisabledByUserboolean
Set to 'true' to disable the webhook and prevent it from triggering
- idstring
Unique identifier for the webhook
- projectIdstring
ID of the Sanity project
- createdAtstring (date-time)
Timestamp when the webhook was created
- createdByUserIdstring
ID of the user who created the webhook
- isDisabledboolean
Whether the webhook is currently disabled
- deletedAtstring|null (date-time)
Timestamp when the webhook was deleted, if applicable
Bad request. For example, Hostname not allowed when the URL resolves to a private address, Hostname not resolvable: <hostname> when the URL's hostname can't be resolved, or You have used all the included webhooks in your plan. In order to add more webhooks, you need to upgrade your plan. when the project has reached its document webhook quota.
Missing or invalid token, or the token lacks the required webhooks grant. For example, User must have grant sanity.project.webhooks/read to perform this operation.
A hook with this name already exists for this project
Get a webhook by ID
/hooks/projects/{projectId}/{id}Responses
Webhook details
Must be 'document'
Name of webhook
The endpoint to which the webhook request is sent. Must start with
http://orhttps://, and must not resolve to a private address.Which dataset should this trigger for. Use a dataset name (letters, numbers,
_, and-, stored lowercase), or*for all datasets in the project.- descriptionstring|null
Optional description to add helpful context to the webhook
- ruleobject
Configuration for when and how the webhook should trigger
Show child attributes
Webhooks can be triggered when a document is created, updated, deleted, or any combination of these
Show child attributes
items
- stringenum:
"create", "update", "delete"
- filterstring
A GROQ filter specifying which documents will, when changed, trigger your webhook. A filter is what you commonly see between the
*[and]in a GROQ query. This field supports all the GROQ functions you'd expect and has additional support for functions in the delta:: namespace, as well as before() and after(). If left empty, it will apply to all documents (*[]) - projectionstring
A GROQ projection defining the payload (or body) of the outgoing webhook request. This field supports GROQ functions in the delta:: namespace, as well as before() and after(). If left empty, it will include the whole document after the change that triggered it
Which API version to use for the GROQ filter and projection. Use the format
vYYYY-MM-DD, orvX.This field configures the webhook's HTTP request method. It can be set to POST, PUT, PATCH, DELETE, or GET. Some endpoints require incoming requests to use a specific method to work
Set to trigger on changes to draft documents.
Set to trigger on changes to version documents.
- headersobject
Additional HTTP headers. You can add multiple headers. A common example is adding an
Authorization: Bearer <token>header to authenticate the webhook request. The total size of all headers can not exceed 2 kB. Header names can only contain letters, numbers, and hyphens, and values must be ASCII without line breaks. Thecontent-length,connection,keep-alive,proxy-authenticate,proxy-authorization,te,trailer,transfer-encoding, andupgradeheaders are not allowed. - secretstring|null
To let receiving services verify the origin of any outgoing webhook, you may add a secret that will be hashed and included as part of the webhook request's headers
- isDisabledByUserboolean
Set to 'true' to disable the webhook and prevent it from triggering
- idstring
Unique identifier for the webhook
- projectIdstring
ID of the Sanity project
- createdAtstring (date-time)
Timestamp when the webhook was created
- createdByUserIdstring
ID of the user who created the webhook
- isDisabledboolean
Whether the webhook is currently disabled
- deletedAtstring|null (date-time)
Timestamp when the webhook was deleted, if applicable
Legacy per-event filter object. Use
rule.filterinstead.Legacy per-event projection object. Use
rule.projectioninstead.
Set to 'transaction', or omit. Requests without a type create a transaction webhook.
Name of webhook
The endpoint to which the webhook request is sent. Must start with
http://orhttps://, and must not resolve to a private address.Which dataset should this trigger for. Use a dataset name (letters, numbers,
_, and-, stored lowercase), or*for all datasets in the project.- descriptionstring|null
Optional description to add helpful context to the webhook
- isDisabledByUserboolean
Set to 'true' to disable the webhook and prevent it from triggering
- idstring
Unique identifier for the webhook
- projectIdstring
ID of the Sanity project
- createdAtstring (date-time)
Timestamp when the webhook was created
- createdByUserIdstring
ID of the user who created the webhook
- isDisabledboolean
Whether the webhook is currently disabled
- deletedAtstring|null (date-time)
Timestamp when the webhook was deleted, if applicable
Missing or invalid token, or the token lacks the required webhooks grant. For example, User must have grant sanity.project.webhooks/read to perform this operation.
Hook not found, or Document hook not supported in this API version when requesting a document webhook with an API version earlier than v2021-10-04.
Update a webhook
/hooks/projects/{projectId}/{id}Request body application/json
- namestring
Name of webhook
- urlstring
The endpoint to which the webhook request is sent
- datasetstring
Which dataset should this trigger for. '*' means all datasets in the project
- descriptionstring
Optional description to add helpful context to the webhook
- ruleobject
Configuration for when and how the webhook should trigger
Show child attributes
Show child attributes
items
- stringenum:
"create", "update", "delete"
- filterstring
GROQ filter specifying which documents trigger the webhook
- projectionstring
GROQ projection defining the payload of the webhook request
- apiVersionstring
Which API version to use for the GROQ filter and projection. Use the format
vYYYY-MM-DD, orvX. - httpMethodstring
HTTP method of the webhook request
- includeDraftsboolean
Set to trigger on changes to draft documents.
- includeAllVersionsboolean
Set to trigger on changes to version documents.
- headersobject
Additional HTTP headers sent with the webhook request
- secretstring
Secret used to sign outgoing webhook requests
- isDisabledByUserboolean
Set to 'true' to disable the webhook and prevent it from triggering
Responses
Updated webhook
Must be 'document'
Name of webhook
The endpoint to which the webhook request is sent. Must start with
http://orhttps://, and must not resolve to a private address.Which dataset should this trigger for. Use a dataset name (letters, numbers,
_, and-, stored lowercase), or*for all datasets in the project.- descriptionstring|null
Optional description to add helpful context to the webhook
- ruleobject
Configuration for when and how the webhook should trigger
Show child attributes
Webhooks can be triggered when a document is created, updated, deleted, or any combination of these
Show child attributes
items
- stringenum:
"create", "update", "delete"
- filterstring
A GROQ filter specifying which documents will, when changed, trigger your webhook. A filter is what you commonly see between the
*[and]in a GROQ query. This field supports all the GROQ functions you'd expect and has additional support for functions in the delta:: namespace, as well as before() and after(). If left empty, it will apply to all documents (*[]) - projectionstring
A GROQ projection defining the payload (or body) of the outgoing webhook request. This field supports GROQ functions in the delta:: namespace, as well as before() and after(). If left empty, it will include the whole document after the change that triggered it
Which API version to use for the GROQ filter and projection. Use the format
vYYYY-MM-DD, orvX.This field configures the webhook's HTTP request method. It can be set to POST, PUT, PATCH, DELETE, or GET. Some endpoints require incoming requests to use a specific method to work
Set to trigger on changes to draft documents.
Set to trigger on changes to version documents.
- headersobject
Additional HTTP headers. You can add multiple headers. A common example is adding an
Authorization: Bearer <token>header to authenticate the webhook request. The total size of all headers can not exceed 2 kB. Header names can only contain letters, numbers, and hyphens, and values must be ASCII without line breaks. Thecontent-length,connection,keep-alive,proxy-authenticate,proxy-authorization,te,trailer,transfer-encoding, andupgradeheaders are not allowed. - secretstring|null
To let receiving services verify the origin of any outgoing webhook, you may add a secret that will be hashed and included as part of the webhook request's headers
- isDisabledByUserboolean
Set to 'true' to disable the webhook and prevent it from triggering
- idstring
Unique identifier for the webhook
- projectIdstring
ID of the Sanity project
- createdAtstring (date-time)
Timestamp when the webhook was created
- createdByUserIdstring
ID of the user who created the webhook
- isDisabledboolean
Whether the webhook is currently disabled
- deletedAtstring|null (date-time)
Timestamp when the webhook was deleted, if applicable
Legacy per-event filter object. Use
rule.filterinstead.Legacy per-event projection object. Use
rule.projectioninstead.
Set to 'transaction', or omit. Requests without a type create a transaction webhook.
Name of webhook
The endpoint to which the webhook request is sent. Must start with
http://orhttps://, and must not resolve to a private address.Which dataset should this trigger for. Use a dataset name (letters, numbers,
_, and-, stored lowercase), or*for all datasets in the project.- descriptionstring|null
Optional description to add helpful context to the webhook
- isDisabledByUserboolean
Set to 'true' to disable the webhook and prevent it from triggering
- idstring
Unique identifier for the webhook
- projectIdstring
ID of the Sanity project
- createdAtstring (date-time)
Timestamp when the webhook was created
- createdByUserIdstring
ID of the user who created the webhook
- isDisabledboolean
Whether the webhook is currently disabled
- deletedAtstring|null (date-time)
Timestamp when the webhook was deleted, if applicable
Bad request. For example, Hostname not allowed when the URL resolves to a private address, Hostname not resolvable: <hostname>, Invalid fields specified for transaction hook, or Hook does not belong to this project.
Missing or invalid token, or the token lacks the required webhooks grant. For example, User must have grant sanity.project.webhooks/read to perform this operation.
Hook with the given ID does not exist
A hook with this name already exists for this project
Delete a webhook
/hooks/projects/{projectId}/{id}List webhook attempts
/hooks/projects/{projectId}/{id}/attemptsQuery parameters
Number of attempts to skip before returning results
Number of attempts to return
- statestring
Only return successful or failed attempts
Responses
List of webhook attempts
- idstring
Unique identifier for the webhook attempt
- projectIdstring
ID of the Sanity project
- inProgressboolean
Whether the webhook attempt is currently in progress
- resultBodystring|null
Response body from the webhook endpoint
- durationinteger
Duration of the webhook attempt in milliseconds
- isFailureboolean
Whether the webhook attempt failed
- failureReasonstring|null
Reason for failure if the webhook attempt failed. Document webhooks always report
otherfor failed attempts. - resultCodeinteger|null
HTTP status code from the webhook endpoint, or
nullif no response was received - createdAtstring (date-time)
Timestamp when the webhook attempt was created
- updatedAtstring (date-time)
Timestamp when the webhook attempt was last updated
- deletedAtstring|null (date-time)
Timestamp when the webhook attempt was deleted, if applicable
- messageIdstring
Unique identifier for the message that triggered the webhook
- hookIdstring
ID of the webhook that was triggered
items
Hook does not belong to given project
Missing or invalid token, or the token lacks the required webhooks grant. For example, User must have grant sanity.project.webhooks/read to perform this operation.
Hook does not exist
List attempts for a webhook message
/hooks/projects/{projectId}/{id}/messages/{messageId}/attemptsPath parameters
ID of the webhook
ID of the webhook message
Query parameters
Number of attempts to skip before returning results
Number of attempts to return
- statestring
Only return successful or failed attempts
Responses
List of attempts for the message
- idstring
Unique identifier for the webhook attempt
- projectIdstring
ID of the Sanity project
- inProgressboolean
Whether the webhook attempt is currently in progress
- resultBodystring|null
Response body from the webhook endpoint
- durationinteger
Duration of the webhook attempt in milliseconds
- isFailureboolean
Whether the webhook attempt failed
- failureReasonstring|null
Reason for failure if the webhook attempt failed. Document webhooks always report
otherfor failed attempts. - resultCodeinteger|null
HTTP status code from the webhook endpoint, or
nullif no response was received - createdAtstring (date-time)
Timestamp when the webhook attempt was created
- updatedAtstring (date-time)
Timestamp when the webhook attempt was last updated
- deletedAtstring|null (date-time)
Timestamp when the webhook attempt was deleted, if applicable
- messageIdstring
Unique identifier for the message that triggered the webhook
- hookIdstring
ID of the webhook that was triggered
items
Hook does not belong to given project
Missing or invalid token, or the token lacks the required webhooks grant. For example, User must have grant sanity.project.webhooks/read to perform this operation.
Hook does not exist
Get a webhook attempt by ID
/hooks/projects/{projectId}/attempts/{attemptId}Returns a single delivery attempt for a transaction webhook. Attempts for document webhooks are not available from this endpoint and return 404; use the attempt list endpoints for the webhook instead.
Responses
Webhook attempt details
- idstring
Unique identifier for the webhook attempt
- projectIdstring
ID of the Sanity project
- inProgressboolean
Whether the webhook attempt is currently in progress
- resultBodystring|null
Response body from the webhook endpoint
- durationinteger
Duration of the webhook attempt in milliseconds
- isFailureboolean
Whether the webhook attempt failed
- failureReasonstring|null
Reason for failure if the webhook attempt failed. Document webhooks always report
otherfor failed attempts. - resultCodeinteger|null
HTTP status code from the webhook endpoint, or
nullif no response was received - createdAtstring (date-time)
Timestamp when the webhook attempt was created
- updatedAtstring (date-time)
Timestamp when the webhook attempt was last updated
- deletedAtstring|null (date-time)
Timestamp when the webhook attempt was deleted, if applicable
- messageIdstring
Unique identifier for the message that triggered the webhook
- hookIdstring
ID of the webhook that was triggered
Attempt does not belong to given project
Missing or invalid token, or the token lacks the required webhooks grant. For example, User must have grant sanity.project.webhooks/read to perform this operation.
Attempt not found
List webhook messages
/hooks/projects/{projectId}/{id}/messagesQuery parameters
Number of messages to return
Number of messages to skip before returning results
Responses
List of webhook messages
- idstring
Unique identifier for the webhook message
- createdAtstring (date-time)
Timestamp when the message was created
- projectIdstring
ID of the Sanity project
- datasetstring
Which dataset the message belongs to
- failureCountinteger
Number of times the message has failed
- resultCodeinteger|null
HTTP status code from the most recent response from the webhook endpoint
- statusstring
Status of the message. Document webhooks can also report
transientFailureandcanceled. - payloadstring
Payload of the message as defined by the webhook rule.
- attemptsarray
Delivery attempts for the message, newest first. Document webhooks only.
Show child attributes
items
- idstring
Unique identifier for the webhook attempt
- inProgressboolean
Whether the attempt is currently in progress
- createdAtstring (date-time)
Timestamp when the attempt was made
- updatedAtstring (date-time)
Timestamp when the attempt was last updated
- messageIdstring
ID of the webhook message that the attempt belongs to
- hookIdstring
ID of the webhook that was triggered
- durationinteger
Duration of the attempt in milliseconds
- projectIdstring
ID of the Sanity project
- resultBodystring|null
Response body from the webhook endpoint, or
nullif no response was received - isFailureboolean
Whether the attempt failed
- failureReasonstring|null
otherif the attempt failed, otherwisenull. - resultCodeinteger|null
HTTP status code from the webhook endpoint, or
nullif no response was received
- hookIdstring
ID of the webhook. Transaction webhooks only.
- updatedAtstring (date-time)
Timestamp when the message was last updated. Transaction webhooks only.
- deletedAtstring|null (date-time)
Timestamp when the message was deleted, if applicable. Transaction webhooks only.
items
Hook does not belong to given project
Missing or invalid token, or the token lacks the required webhooks grant. For example, User must have grant sanity.project.webhooks/read to perform this operation.
Hook does not exist