Docs Developers

Webhooks

Events sent to your server as they happen, signed.

A webhook tells your server when something happens in your Space, as it happens: a task changes, a message is posted, an invoice is paid.

task.updated

Something changes in the Space

POST

JSON to your address, signed

HMAC SHA-256

You check the signature

200

And answer quickly

Not a 2xx? It's tried again, up to five times, a little later each time.

Adding one

In API and MCP, under webhooks, give the address on your server and pick the events. Copy its secret: you'll use it to check that a call really came from NextIS. Pause a webhook to stop calls for a while.

Events

  • task.created, task.updated, task.deleted
  • mission.created, mission.updated, mission.deleted
  • message.created, message.updated: posts in Talk
  • comment.created: comments on tasks
  • invoice.created, invoice.updated
  • time.logged

What arrives

A POST with JSON, and headers saying what it is: X-NextIS-Event, X-NextIS-Delivery (an id for the delivery) and X-NextIS-Signature.

Body
{
  "event": "task.updated",
  "space_id": "…",
  "delivered_at": "2026-10-27T09:14:03Z",
  "data": { "id": "…", "title": "Pricing page copy", "status": "review" }
}

Checking the signature

The signature is sha256= and the HMAC-SHA256 of the raw body with your webhook's secret, in hex. Compute it the same way and compare.

Node.js
import crypto from "node:crypto"

function fromNextIS(rawBody, header, secret) {
  const expected = "sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex")
  return crypto.timingSafeEqual(Buffer.from(header), Buffer.from(expected))
}
Python
import hmac, hashlib

def from_nextis(raw_body: bytes, header: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(header, expected)