Skip to content
TasksMate Developers

0.x — pre-release, no compatibility promise yet.What this means

What this is: TasksMate POSTs a signed JSON event to your HTTPS endpoint whenever something you subscribed to changes. When you need it: to react to changes instead of polling the API.

Verify every delivery before you trust it — over the raw body, before parsing:

from tasksmate import webhooks
def receive(headers, raw_body: bytes):
# SECRET: the whsec_… shown once when you created the webhook
if not webhooks.verify(SECRET, headers, raw_body):
return 400
event = webhooks.parse(raw_body) # .id .type_ .org_id .data
return 200 # dedupe on event.id
Something changestask.updatedQueuedone per webhookSigned POSTwebhook-signatureYou verifythe raw body2xx — doneRetry laterre-signedHTTPSanswer 2xxno 2xxagain
One delivery: signed, verified, acknowledged — or retried
  1. You register an endpoint you already run — in Developers → Webhooks or with POST /v1/webhooks — and pick events and projects. The response shows the signing secret once.
  2. Something changes in your organization: a task moves, a project is renamed.
  3. TasksMate queues one delivery per active webhook that wants that event.
  4. TasksMate sends it: a POST signed with your secret, no redirects followed, waiting up to 20 s for your answer.
  5. You verify and answer 2xx. Do the real work after answering.
  6. No 2xx? It is retried at +30 s, +2 m, +10 m, +30 m, +2 h, +6 h, +12 h — 8 attempts in about 20 h 43 m, each re-signed. 410 Gone disables the webhook; 429 with Retry-After is honoured up to 6 h; 10 failures in a row disable it until you re-enable it.
Key Looks like What it does
Webhook secret whsec_… Signs every delivery to you. You verify with it; it is never sent in a delivery.
Access token tm_live_… Authenticates your calls to the API — e.g. fetching the full task an event names.

Don’t mix them up: a delivery carries a signature, never a token. TasksMate stores your secret encrypted and shows it only when a webhook is created or its secret rotated.

HeaderExampleWhat it is
webhook-idWD000001The delivery id — equal to the body's id. Dedupe on it (delivery is at-least-once).
webhook-timestamp1790380800Unix seconds when this attempt was signed. Refuse one more than 5 minutes from now (a replay).
webhook-signaturev1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4=Space-separated v1,<base64> HMAC-SHA256 signatures of {webhook-id}.{webhook-timestamp}.{raw body}, keyed with the base64-decoded part of the secret after whsec_. Two during a rotation's 24 h grace.
X-TasksMate-Eventtask.updatedThe event type (the body's type), for routing before parsing.
User-AgentTasksMate-Webhooks/1Identifies TasksMate's sender.

The body is a WebhookEvent. data.before / data.after carry what changed — never the whole resource. Fetch that with your token.

task.updated
{
"id": "WD000001",
"type": "task.updated",
"api_version": "2026-09-25",
"created_at": "2026-09-25T12:00:00Z",
"org_id": "O0020",
"project_id": "P30104",
"actor": {
"kind": "user",
"id": "406670f1-c819-4d27-9552-1747c551cf5c",
"username": "ada"
},
"data": {
"resource_type": "task",
"resource_id": "T869658",
"before": {
"status": "not_started"
},
"after": {
"status": "in_progress"
}
},
"request_id": "9b2f1c1e-8c1a-4a53-9f9e-0f5f1f2d7c11"
}

Rotate secret reveals a new secret once. For 24 h every delivery carries two signatures (old and new, space-separated), so split the header and accept either while you switch.

  • Hash the raw bytes; re-serialized JSON will not match.
  • Deliveries are at-least-once and may arrive out of order: dedupe on id, order by created_at.
  • Answer fast; queue the work.

Every event you can subscribe to: Events.