Webhooks

An outbound webhook notifies your system whenever something changes in Orkestra. To go the other way — your system creating tasks or updating states — use a personal token with the REST API.

Outbound webhooks

When an event happens in your organization (task created, state changed, comment added, etc.), Orkestra sends a POST to the URL you configure. Events are HMAC-signed so you can verify they come from Orkestra.

Which projects it sends

Whoever receives a webhook reads everything it gets, and has no Orkestra account that says what they may see. So if you choose nothing, a webhook only sends what happens in projects the whole organization can see, plus goals that belong to no project. Private and area projects stay in.

To send them, choose what the webhook sends: a project you choose goes out even if it is private, and an area sends its projects and those of the areas below it, except private ones. A webhook with something chosen sends only that.

Supported events

The events you can subscribe to:

  • task.created — new task
  • task.updated — something about the task changed (also when you move it to another column or change who it is assigned to)
  • task.moved — the task changed column; it carries the column it left (fromState) and the one it reached (toState). Moving a task inside the same column does not send it
  • task.assigned — someone was put on the task, either the first assignment or a person added to those already there (addedAssigneeIds). Saving the same list of people, or removing someone, does not send it
  • task.reassigned — the task passed from one person to another (fromUserId, toUserId)
  • task.deadline_approaching — less than a day is left before the task’s due date
  • task.overdue — the due date has passed and the task is still not finished
  • task.deleted — task deleted
  • comment.created, comment.updated, comment.deleted
  • subtask.created, subtask.updated, subtask.deleted
  • goal.created, goal.updated, goal.deleted

task.deadline_approaching and task.overdue go out once per due date: if you change the date, they go out again for the new one. A finished task sends neither. The new task events above follow what you chose under “Which projects it sends”; people appear only by their identifier, never with a name or a phone number.

To react to a change, listen to the webhook instead of polling the API: the API limits how many requests you can make.

A full example, with your own WhatsApp bot, is in Connect your WhatsApp bot.

Payload format

Each webhook receives a JSON with this structure:

  • event — event name (e.g. task.moved); it also travels in the X-Orkestra-Event header
  • timestamp — ISO 8601 date and time
  • organizationId — ID of the organization where it happened
  • data — object with the affected resource; for tasks, projectId and task with id and title

HMAC verification

Each request includes an X-Orkestra-Signature header with an HMAC-SHA256 of the body using your webhook secret. To verify:

  1. Take the raw body of the request (unparsed).
  2. Compute HMAC-SHA256(body, your_secret).
  3. Compare with the header in constant time (use crypto.timingSafeEqual in Node).

Smart retry

Orkestra retries failed deliveries with this logic:

  • 5xx / timeout: retry with exponential backoff (1s, 5s, 30s, 2min, 10min, 1h).
  • 4xx (except 429): permanent failure, no retry. You’ll see the error in the log.
  • 429: respects Retry-After if you send it, or applies exponential backoff.
  • After 6 failed attempts, the webhook is marked as failed and the admin is notified.

Creating things from your system

For an external service to create tasks or update states, use a personal token with the REST API (in beta). Everything it does is signed with your name and the token’s, and you can revoke it whenever you want.

Signed entries (beta)

Another way, with no code against the API: in Settings → Connections → Webhooks create an entry. Choose whether it drops a task (in a project) or a row (in a table) and tie it to one of your personal tokens. What arrives is filed under your name with that token’s permissions; if you revoke it or it expires, the entry stops receiving.

Each message is a POST with a JSON record to the entry’s address, signed with its secret:

  • X-Orkestra-Timestamp: the time in seconds.
  • X-Orkestra-Signature: v1= followed by the hex HMAC-SHA256 of timestamp.body.

A message is good for 5 minutes and is never accepted twice. Tasks: title (required), description, priority, deadline (ISO 8601), labels. Rows: { "values": { "Column": "value" } }, by column name or id. A field that does not exist is refused with a clear error. Each organization can send up to 120 messages per minute.

Monitoring

Every webhook has a log with the last 30 days of activity: status, latency, payload, response. Useful for debugging when something isn’t working.

Webhooks consume dedicated rate limits (100 req/minute). If your service generates many events, use batching instead of one event per change.