Skip to content

Latest commit

 

History

History
276 lines (185 loc) · 5.51 KB

File metadata and controls

276 lines (185 loc) · 5.51 KB

TaskNotes Webhooks

TaskNotes webhooks send HTTP POST requests when selected events occur.

Prerequisites

  1. Enable HTTP API in Settings -> TaskNotes -> Integrations -> HTTP API.
  2. Create at least one webhook (settings UI or API).
  3. Subscribe it to one or more events.

Event Types

Task events:

  • task.created
  • task.updated
  • task.deleted
  • task.completed
  • task.archived
  • task.unarchived

Time events:

  • time.started
  • time.stopped

Pomodoro events:

  • pomodoro.started
  • pomodoro.completed
  • pomodoro.interrupted

Recurring events:

  • recurring.instance.completed
  • recurring.instance.skipped

Reminder events:

  • reminder.triggered

Payload Shape

All webhook payloads use the same top-level envelope:

{
  "event": "task.created",
  "timestamp": "2026-02-21T10:30:00.000Z",
  "vault": {
    "name": "My Vault",
    "path": "/path/to/vault"
  },
  "data": {}
}

data is event-specific.

Register and Manage Webhooks via API

Create

POST /api/webhooks

Required fields:

  • url (string)
  • events (non-empty array)

Optional fields:

  • id
  • secret (auto-generated if omitted)
  • active (default true)
  • transformFile
  • corsHeaders (default true)

Example:

curl -X POST http://localhost:8080/api/webhooks \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/tasknotes",
    "events": ["task.completed", "task.created"],
    "transformFile": "TaskNotes/webhooks/slack.json"
  }'

List

GET /api/webhooks

Returns registered hooks. Secrets are not returned.

Delete

DELETE /api/webhooks/:id

Delivery History

GET /api/webhooks/deliveries

Returns last 100 in-memory deliveries.

Delivery Behavior

Current implementation behavior:

  • Webhook processing is asynchronous (fire-and-forget from task operation).
  • Each delivery starts with one attempt.
  • Failed deliveries retry with exponential backoff: 1s, 2s, 4s.
  • Maximum retries: 3 retries after initial attempt (up to 4 attempts total).
  • If cumulative failureCount for a webhook exceeds 10, webhook is auto-disabled.
  • No explicit request timeout is set in delivery fetch.

Because retries and duplicates are possible, handlers should be idempotent.

Signature Verification

When corsHeaders is enabled (default), delivery includes:

  • X-TaskNotes-Event
  • X-TaskNotes-Signature
  • X-TaskNotes-Delivery-ID

Signature is HMAC-SHA256 over JSON.stringify(payload) using webhook secret.

Node.js example:

const crypto = require("crypto");

function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(JSON.stringify(payload))
    .digest("hex");
  return signature === expected;
}

Payload Transformations

A webhook can specify transformFile pointing to a file in your vault.

Supported file types:

  • .js: JavaScript transform function
  • .json: event template map with variable interpolation

If transform execution fails, TaskNotes falls back to original payload.

JavaScript Transform Files

Expected format:

function transform(payload) {
  return payload;
}

Execution model:

  • File is read from the vault.
  • Code is executed with new Function(...).
  • Returned value becomes the outgoing request body.

Important behavior:

  • Returning null does not skip delivery. Payload body becomes JSON null.
  • Returning an array does not fan out to multiple URLs. Array is posted to the configured single URL.
  • console.log is available because code runs in plugin runtime context.

Example:

function transform(payload) {
  if (payload.event === "task.completed") {
    return {
      text: `Completed: ${payload.data.task.title}`,
      event: payload.event,
      at: payload.timestamp,
    };
  }

  return payload;
}

JSON Transform Files

Structure:

{
  "task.completed": {
    "text": "Task completed: ${data.task.title}",
    "vault": "${vault.name}"
  },
  "default": {
    "text": "TaskNotes event: ${event}"
  }
}

Rules:

  • Matching order: exact event key, then default.
  • Variables use ${path.to.value}.
  • Missing variables are left unchanged.

CORS and Headers

Webhook delivery requests are outbound server-side requests from TaskNotes.

corsHeaders behavior:

  • true (default): sends TaskNotes custom headers including signature.
  • false: only sends Content-Type: application/json.

Disable custom headers for endpoints that reject non-standard headers.

Testing

Local Test Server

Use repository script:

node test-webhook.js

Optional custom port:

node test-webhook.js 8080

Default server values:

  • URL: http://localhost:3000/webhook
  • Test secret: test-secret-key-for-tasknotes-webhooks

External Inspection

For quick inspection, use a request-bin tool such as webhook.site.

Troubleshooting

No deliveries

  1. Confirm HTTP API is enabled.
  2. Confirm webhook is active.
  3. Confirm event is subscribed.

Signature mismatch

  1. Confirm secret matches webhook config.
  2. Verify your verifier hashes the exact JSON body.
  3. Verify hex digest comparison.

Webhook disabled automatically

If failures continue and failureCount exceeds 10, webhook is disabled.

  1. Fix endpoint availability or response handling.
  2. Re-enable webhook in TaskNotes settings, or recreate it via POST /api/webhooks.

Transform errors

  1. Confirm transformFile exists in vault.
  2. For JS, ensure transform function is defined.
  3. Check Obsidian console logs for transform exceptions.