POST /webhooks
Register a signed outbound webhook for one or more Taskade events.
Each delivery is a POST with a JSON body and three signature headers:
X-Taskade-Signature:sha256=<hex>, the HMAC-SHA256 of the raw body, keyed with yoursecret.X-Taskade-Timestamp: the send time, in unix seconds.X-Taskade-Signature-V2:sha256=<hex>, the HMAC-SHA256 of<timestamp>.<raw body>, keyed with yoursecret.
To verify V2:
- Read the raw request body before you parse the JSON.
- Compute the HMAC-SHA256 of the
X-Taskade-Timestampvalue, a period (.) and the raw body. Use yoursecretas the key. - Compare
sha256=<your hex>withX-Taskade-Signature-V2in constant time. - Reject the request if the timestamp is more than 5 minutes away from your clock.
The timestamp is part of the signed data, so a captured delivery fails the check after 5 minutes. A copy that arrives inside those 5 minutes still passes, so make your handler idempotent, or record each delivery that you process and skip a repeat. X-Taskade-Signature does not change, and receivers that verify it keep working.
Base URL: https://www.taskade.com/api/v2
Authentication
Send a personal access token or an OAuth 2.0 access token as a bearer token. Create a personal access token at taskade.com/settings/api.
Authorization: Bearer tskdp_your_token_here
Request body
application/json
| Field | Type | Required | Description |
|---|---|---|---|
targetUrl |
string |
Yes | — |
events |
string[] |
Yes | — |
spaceIds |
string[] |
No | — |
Example request
curl -X POST "https://www.taskade.com/api/v2/webhooks" \
-H "Authorization: Bearer $TASKADE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"targetUrl":"<targetUrl>","events":["task.due"]}'
Responses
200 — Default response
| Field | Type | Required | Description |
|---|---|---|---|
ok |
boolean |
Yes | — |
webhook |
object |
Yes | — |
webhook.id |
string |
Yes | Endpoint id - the target URL (use URL-encoded as the :id path param). |
webhook.url |
string |
Yes | — |
webhook.events |
string[] |
Yes | — |
webhook.spaceIds |
string[] |
Yes | Spaces this webhook is scoped to; empty = all spaces. |
webhook.createdAt |
string |
Yes | — |
secret |
string |
Yes | HMAC signing secret - shown once. Store it now. |
A nested field marked Yes is required whenever its parent object is present.
Errors
Errors return an ok: false envelope. Rate limiting returns 429 with x-rate-limit-limit, x-rate-limit-remaining and x-rate-limit-reset headers. x-rate-limit-reset is the number of seconds until the window reopens. Retry-After is not sent, so schedule retries from x-rate-limit-reset; retrying sooner will fail again.
{ "ok": false, "message": "Unauthorized", "code": "UNAUTHORIZED" }
Rate limits for this version: enforced per endpoint; ceilings are not published and can change without notice. A 429 response carries x-rate-limit-limit, x-rate-limit-remaining, and x-rate-limit-reset (seconds until the window reopens). Back off from those headers rather than hardcoding numbers. If you need sustained throughput, prefer batching (operations like /createTask accept arrays) over tightening polling loops. See Rate limits.