Example

Zapier — mirror Tidy tasks to your task manager

A Zap that fires on task.created and task.updated and mirrors the task into Todoist, Asana, or Linear — whichever your team uses.

Shape of the Zap

  1. Trigger: Webhooks by Zapier · Catch Raw Hook. Zapier gives you a URL you'll pass to Tidy as the subscription endpoint.
  2. Step 2: Code by Zapier · JavaScript — verify the Tidy-Signature. Abort if invalid.
  3. Step 3: Todoist/Asana/Linear · Create Task, mapping event.data.title → task title and event.data.due_at → due date.

Subscribe Tidy → Zapier

curl -X POST https://qa.tidy.engineering/api/v1/event_subscriptions \
  -H "Authorization: Bearer $TIDY_PAT" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://hooks.zapier.com/hooks/catch/YOUR-ZAP-ID/",
    "event_types": ["task.created", "task.updated"]
  }'

Signature verification in Zapier

Paste this into the Code step. Pass the signing secret via a Zap input variable (don't hardcode it):

const crypto = require('crypto');

const sig = inputData.headers['tidy-signature'];
const secret = inputData.secret;
const body = inputData.bodyRaw;

const parts = Object.fromEntries(
  sig.split(',').map((p) => p.split('='))
);
const expected = crypto.createHmac('sha256', secret)
  .update(`${parts.t}.${body}`)
  .digest('hex');

if (expected !== parts.v1) {
  throw new Error('Tidy signature mismatch — refusing to continue.');
}

return { valid: true, event: JSON.parse(body) };

Why the verification step matters

A Catch-Hook URL is a public endpoint. Without signature verification, anyone who guesses your URL could inject fake tasks into your downstream system. The verification step turns the webhook into an authenticated channel.

Testing in sandbox

When you create the subscription from a sandbox PAT, Zapier's hooks.zapier.com hostname is on the sandbox allow-list and deliveries succeed. Create a task via POST /api/v1/tasks to trigger your first delivery.