Webhooks

Send Netzo events to your service, signed: event types, setup, payload, signature and delivery.

A webhook sends a signed HTTP request to your URL when an event happens in Netzo.

salesorders.approvePOST your URL (signed)2xxno 2xx, or no answer in 10 s: Netzo retries up to 3 timesNetzoYour serviceNetzoYour service

Event types

The event type is <table>.<event>:

EventSent whenExample
An actionthe action runssalesorders.approve, salesquotes.send
A declared eventthe record reaches a state on its ownfinancesinvoices.overdue

Each table in Domains lists its actions and events. An agent reads the event catalog of the tables it can see in the MCP resource netzo://events/catalog; a program reads it in the webhooks section of OpenAPI.

Create a webhook

In Administration → Integrations → Webhooks, choose the table, the event, an optional condition and your URL. Copy the signing secret (whsec_…). Webhooks are records too, so the API, the CLI and MCP can create them.

Payload

The body is:

{
  "type": "salesorders.approve",
  "timestamp": "2026-11-10T14:03:12.000Z",
  "data": {
    "id": "evt_…",
    "tableUid": "salesorders",
    "event": "approve",
    "recordId": "so_…",
    "dataBefore": { },
    "dataAfter": { },
    "diff": { },
    "userId": "usr_…"
  }
}

Signature

Every request carries three headers:

HeaderHolds
webhook-idThe event id, the same on every retry
webhook-timestampWhen Netzo sent the request, in Unix seconds
webhook-signatureAn HMAC-SHA256 of the request with your signing secret (whsec_…)

Reject a request whose timestamp is more than 5 minutes away from your clock. Netzo follows Standard Webhooks. Use any Standard Webhooks library with your signing secret; it checks the signature and the time for you:

import { Webhook } from 'standardwebhooks'

const wh = new Webhook(process.env.NETZO_WEBHOOK_SECRET)
const event = wh.verify(rawBody, headers) // throws when the signature or the time is wrong

Delivery

RuleValue
SuccessAny 2xx answer
Timeout10 seconds
RetriesUp to 3, when there is no 2xx or no answer

data.id is the same on every retry: store it and skip an event you already processed.