Skip to content

Documentation

Webhooks

Have Folevi tell your server when notes, tasks and comments change, with signed requests you can verify.

Updated

A webhook is an address on your server that Folevi calls when something happens in your notes: a note is created, changed or moved to Trash, a task is added or completed, a comment is written. It’s how Zapier, n8n, Make and your own code hear about changes without asking over and over. To read or add things, use the REST API.

Add a webhook

Open Settings → Connected apps and choose Add webhook under Webhooks. Enter an address that starts with https://, choose the events and the places (your Personal, and any workspaces you pick), then copy the signing secret. It starts with whsec_ and is shown only once. You can have up to five webhooks. Send test event sends a webhook.test event to check your setup, and Recent deliveries shows the last 20 attempts with their status codes.

EventWhen it’s sent
note.createdA note is created. Sent about 30 seconds later, so the title typed right after is included.
note.updatedA note’s text or title changes. At most once a minute per note: edits in that minute are one event.
note.deletedA note is moved to Trash.
task.createdA to-do is added to a note.
task.completedA to-do is checked off.
comment.createdA comment or a reply is written.

You only get events for notes you can open yourself, in the places you chose. A page restricted to other people sends you nothing.

What Folevi sends

Each event is a POST with a JSON body. Payloads are small on purpose: a note’s title and link, never its content. Tasks include their text, since that’s what a task is. Comments include ids and the note’s link, not what was written. Fetch more through the REST API if you need it.

{
  "id": "evt_01JA2Z6Q3M8V4C2P9K7T5R1B0N",
  "type": "task.completed",
  "createdAt": "2026-10-14T09:12:44.000Z",
  "place": { "id": "personal", "name": "Personal" },
  "data": {
    "id": "01JA2Z5X1T9QH3E8D2W6M4R7AA",
    "text": "Send the summary",
    "status": "done",
    "dueDate": "2026-10-15",
    "dueTime": null,
    "priority": "high",
    "note": { "id": "01JA2YQ8...", "title": "Meeting notes", "url": "https://app.folevi.com/d/01JA2YQ8..." },
    "url": "https://app.folevi.com/d/01JA2YQ8...#block-01JA2Z5X..."
  }
}

Requests also carry Folevi-Event-Id and Folevi-Event-Type headers. The event id stays the same on every retry, so use it to ignore an event you’ve already handled.

Check the signature

Every request has a Folevi-Signature header like t=1792234364,v1=5257a8…. t is when it was sent (Unix seconds) and v1 is the HMAC-SHA256, in hex, of t, a full stop and the raw request body, keyed with your signing secret. Compute it yourself and compare, and turn away requests whose t is more than five minutes old. In Node:

import crypto from "node:crypto";
import express from "express";

const secret = process.env.FOLEVI_WEBHOOK_SECRET; // whsec_...
const app = express();

// Read the body raw: the signature covers the exact bytes Folevi sent.
app.post("/folevi", express.raw({ type: "application/json" }), (req, res) => {
  const parts = Object.fromEntries((req.get("Folevi-Signature") ?? "").split(",").map((p) => p.split("=")));
  const expected = crypto.createHmac("sha256", secret).update(`${parts.t}.${req.body}`).digest("hex");
  const valid = typeof parts.v1 === "string" && parts.v1.length === expected.length && crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
  const recent = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
  if (!valid || !recent) return res.status(400).send("Bad signature");

  const event = JSON.parse(req.body);
  console.log(event.type, event.data.id);
  res.sendStatus(200);
});

app.listen(3000);

Answers, retries and turning off

Answer with any 2xx status within 10 seconds. Anything else counts as a failure, and so do redirects: Folevi never follows them. A failed event is tried again after 1 minute, 10 minutes, 1 hour, 6 hours and 16 hours, six attempts over about a day.

If three events in a row fail every attempt, Folevi turns the webhook off and tells you in the notifications bell. Fix the endpoint, then switch it back on in Settings. A test event never counts toward this.

Security

  • Only https addresses on the standard port are accepted, without a user name or password in them.
  • Folevi looks up the address before every attempt and never sends to private, local or link-local networks.
  • Your signing secret is stored encrypted and shown only when you add the webhook. If it leaks, delete the webhook and add it again.
  • Folevi doesn’t read or keep your server’s answer, only its status code and how long it took.

Still stuck? Contact support or write to support@folevi.com.