Skip to content

Webhooks

NoteTrace can send a signed HTTP POST when something happens, for wiring notes into n8n, Home Assistant, Node-RED, or your own scripts without polling. Webhooks are off by default.

Enable

WEBHOOKS_ENABLED=1
# Only if the target is on a private or loopback address (a Home Assistant
# container on the same Docker network, for example):
ALLOW_PRIVATE_WEBHOOK_URLS=1

Then add a webhook under Settings, Webhooks (admin, multi-user mode). Enter the target URL and choose events. A signing secret is generated (or supply your own) and shown once; save it to verify deliveries. Send test event checks the target without waiting for a real event.

Events

Event Fires when data
note.created A note is created from any device, including through sync { "note_id", "title", "kind" }
checklist.completed The last unchecked item on a checklist is checked { "note_id", "title" }
reminder.fired A reminder occurrence comes due (once per occurrence of a repeat) { "note_id", "title", "reminder_at", "repeat" }

Imports don't fire note.created, so a large Google Keep import doesn't flood the receiver. Events go to webhooks owned by the note's owner.

reminder.fired is sent by the server's reminder check, which runs every minute. reminder_at is the occurrence time in ISO 8601 UTC and repeat is daily, weekly, monthly, yearly, or null. It fires whether or not a push service is set up, which makes it a good trigger for smart-home announcements.

Payload and signature

{
  "event": "reminder.fired",
  "timestamp": "2026-09-14T12:00:04.211Z",
  "data": { "note_id": 42, "title": "Water the plants", "reminder_at": "2026-09-14T12:00:00.000Z", "repeat": "weekly" }
}

Headers:

X-NoteTrace-Signature: sha256=<hex HMAC-SHA256 of the raw body with your secret>
X-NoteTrace-Event: reminder.fired
X-NoteTrace-Delivery: <unique id per delivery attempt>

Verify by computing the HMAC over the exact bytes received:

import { createHmac, timingSafeEqual } from 'node:crypto';

function verify(rawBody, header, secret) {
  const expected = createHmac('sha256', secret).update(rawBody).digest('hex');
  return timingSafeEqual(Buffer.from(expected), Buffer.from(header.replace('sha256=', '')));
}

Retries

A delivery that errors, times out, or gets a non-2xx response is tried up to 3 times with a short backoff. There's no long-term queue: if the receiver is down for more than a few seconds, that event isn't sent later. The last result for each webhook shows in Settings.