Webhooks
Receive signed HTTP POSTs whenever tasks or projects change — with HMAC-SHA256 signing and exponential-backoff retries.
Webhooks let your system react to Projects events in real time. Register a URL, subscribe to event types, and Workestra POSTs you a signed JSON payload every time one of those events happens.
Screenshot needed — add an annotated image showing this UI
Creating a Webhook
- Go to Settings → Integrations → Webhooks (or Project → Settings → Integrations → Webhooks for project-scoped hooks)
- Click New Webhook
- Fill in:
| Field | Notes |
|---|---|
| URL | Your HTTPS endpoint that accepts POSTs |
| Events | Check the event types you want to subscribe to |
| Secret | Generate and copy — used to verify signatures |
- Save
Event Types
| Event | When it Fires |
|---|---|
task.created | New task |
task.updated | Any task field changed |
task.status_changed | Status transition |
task.assigned | Assignee set or changed |
task.completed | Moved to a "done" status |
task.deleted | Moved to Trash |
task.comment_added | Someone posted a comment |
project.created | New project |
project.updated | Project field changed |
project.archived | Project archived |
project.deleted | Project moved to Trash |
cycle.started | Cycle transitioned to Active |
cycle.completed | Cycle transitioned to Completed |
Payload
{
"id": "evt_1234567890",
"type": "task.status_changed",
"created_at": "2026-04-23T12:34:56Z",
"workspace_id": "ws_abc123",
"data": {
"task_id": "task_def456",
"project_id": "proj_ghi789",
"title": "Fix login timeout",
"old_status": "in_progress",
"new_status": "in_review",
"changed_by": "user_jkl012"
}
}Signature Verification
Every request includes a signature header:
X-Workestra-Signature: sha256=<hex>The signature is HMAC-SHA256 of the raw request body using your webhook secret.
Verification (Node.js)
const crypto = require('crypto');
function verify(rawBody, signatureHeader, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader)
);
}Verification (Python)
import hmac, hashlib
def verify(raw_body: bytes, signature_header: str, secret: str) -> bool:
expected = 'sha256=' + hmac.new(
secret.encode(), raw_body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature_header)Reject any request where verification fails.
Retry Policy
If your endpoint responds with a non-2xx or times out, Workestra retries with exponential backoff:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | ~1 minute |
| 3 | ~5 minutes |
| 4 | ~30 minutes |
| 5 | ~2 hours |
| 6 | ~12 hours |
After 6 failures, the delivery is marked permanently failed. The webhook stays active — future events still fire — but that specific delivery won't be retried.
Best Practices
- Respond fast — return 2xx within a few seconds, then process async
- Be idempotent — handle the same
idtwice gracefully (retries are possible) - Verify signatures on every request
- Log unverified events with enough info to debug without exposing the secret
Delivery History
At Settings → Integrations → Webhooks → [your webhook] → Deliveries, you can see:
- Event ID and type
- Timestamp
- HTTP status code returned
- Response body (first 1 KB)
- Redelivery button
Click any failed delivery to inspect and optionally redeliver.
Next Steps
- REST API — pull instead of push
- Automations — the
webhookaction fires the same way - General webhooks overview — cross-module webhook reference