ClickUp
Configure and test ClickUp webhook delivery to ZenML.
The ClickUp webhook provider authenticates Workspace webhook deliveries and maps supported ClickUp payloads to a small catalog of semantic events. Consumers can use this provider-owned event model instead of depending on ClickUp's raw payload structure. Webhook triggers are the currently documented consumer that exposes this event configuration.
ClickUp registers webhooks through its API and generates the signing secret itself. Create the ZenML webhook first so you have an intake URL, then store ClickUp's secret on the ZenML webhook.
Create the webhook in ZenML
Create a ClickUp webhook in the active project:
zenml webhook create clickup-ops --type clickupDescribe the webhook and copy its endpoint URL:
zenml webhook describe clickup-opsVia the SDK:
from zenml.client import Client
from zenml.webhooks.providers import BuiltinWebhookType
client = Client()
result = client.create_webhook(
name="clickup-ops",
webhook_type=BuiltinWebhookType.CLICKUP,
)
endpoint_url = result.endpoint_urlYou can ignore the generated ZenML secret. ClickUp will issue a different shared secret when you register the endpoint, and that is the value ZenML must verify. See Create a webhook for secret-management and rotation options.
Register the webhook in ClickUp
ClickUp does not provide a repository-style webhook settings page. Create the subscription with the Create Webhook API using a personal API token and your ClickUp Workspace ID.
In ClickUp, open Settings and create a personal API token.
Copy the Workspace ID for the Workspace that should send events. You can also list authorized Workspaces with
GET https://api.clickup.com/api/v2/teamand use theidof the Workspace you want.Send a
POSTrequest that points ClickUp at the ZenML endpoint URL.
Copy webhook.secret from the response. You can optionally include space_id, folder_id, list_id, or task_id so ClickUp only sends events from one location. ZenML trigger filters still apply to whatever ClickUp delivers.
ClickUp sends an X-Signature header containing a raw hexadecimal HMAC-SHA256 digest of the exact request body. There is no sha256= prefix. ZenML verifies this signature before it parses or forwards the delivery.
Store ClickUp's signing secret
Rotate the ZenML webhook secret to the value ClickUp returned. Until this step succeeds, real ClickUp deliveries fail authentication with 401 Unauthorized. ClickUp suspends the webhook after that response.
Via the SDK:
Supported events and filters
The provider reads the ClickUp event name from the JSON event field and maps qualifying payloads to ZenML semantic events with the same names:
Task created
taskCreated
task_id, list_id, space_id, folder_id
Task updated
taskUpdated
task_id, list_id, space_id, folder_id
Task deleted
taskDeleted
task_id, list_id, space_id, folder_id
Task status updated
taskStatusUpdated
task_id, list_id, space_id, folder_id, status
Task moved
taskMoved
task_id, list_id, space_id, folder_id
Task assignee updated
taskAssigneeUpdated
task_id, list_id, space_id, folder_id
Task comment posted
taskCommentPosted
task_id, list_id, space_id, folder_id
List created
listCreated
list_id, space_id, folder_id
List updated
listUpdated
list_id, space_id, folder_id
List deleted
listDeleted
list_id, space_id, folder_id
Event names match ClickUp's camelCase identifiers. Resource IDs are compared as strings, even when ClickUp sends a numeric list_id, space_id, or folder_id. Each event type has its own typed target class, such as TaskStatusUpdated or ListCreated, so filters that do not apply to that event are rejected at configuration time.
status is only available on taskStatusUpdated. It is the post-change value from the last history_items entry: a string after value, or after.status when after is an object. If you filter on status and the payload has no after-value, the event does not match. List events do not accept task_id, and task events other than taskStatusUpdated do not accept status.
A ClickUp event that is missing from this catalog can still authenticate and return 202 Accepted. It is not mapped to a semantic event, so webhook triggers do not match it. A missing or empty event or webhook_id field returns 400 Bad Request.
String filters
Semantic event fields use ZenML string filters (StringFilterOption). You can use:
a plain string for exact equality, such as
list_id: "162641285";equals:,notequals:,contains:,notcontains:,startswith:, andendswith:expressions;oneof:with a non-empty JSON list for exact alternatives, such asstatus: 'oneof:["done","complete"]';notoneof:with a non-empty JSON list for exclusions; anda YAML list to OR multiple expressions for one field.
All filter fields in the table support these generic webhook string operators. Values configured for the same field use OR logic; different populated fields use AND logic. Omitted fields match any value. If a configured field is absent from a delivery, it does not match. See the complete string filter operator reference.
For example, this target matches status updates to done on one list:
See Webhook triggers for a complete example that uses this configuration to execute a pipeline snapshot.
Mock a signed ClickUp delivery
You can test the endpoint without asking ClickUp to send a delivery. This example uses a minimal ClickUp-like status payload; the important part is signing and sending exactly the same bytes.
Set the endpoint and the ClickUp signing secret stored on the ZenML webhook:
Write the request body without adding a trailing newline:
Calculate the raw hexadecimal signature over the file's exact bytes:
Send those same bytes with the ClickUp signature header:
A valid delivery returns 202 Accepted. This confirms webhook intake, not that a consumer matched or a pipeline run started.
To confirm that signature verification is active, send the same body with an invalid signature:
This request returns 401 Unauthorized. If a calculated signature fails, verify that the bytes passed to --data-binary are the bytes used to calculate the digest; even a whitespace or newline change produces a different signature. Do not prefix the digest with sha256=.
ClickUp immediately suspends a webhook after an unauthorized response, so align the signing secret before ClickUp starts delivering events.
Related pages
Last updated
Was this helpful?