Skip to main content
Webhooks deliver signed event payloads to your URL when nodes or phases are created, updated, or deleted. Use them to connect ProductBrain to Make.com, Zapier, n8n, or any workflow tool.

Register a webhook

POST /api/v1/webhooks
{
  "projectId": "my-project",
  "url": "https://your-endpoint.example.com/webhook",
  "events": ["node.added", "node.updated"]
}
  • url must be HTTPS and publicly routable
  • events is optional — omit to subscribe to all six event types
  • Maximum 10 webhooks per project
Response:
{
  "id": "wh_abc123",
  "url": "https://your-endpoint.example.com/webhook",
  "events": ["node.added", "node.updated"],
  "secret": "whsec_..."
}
The secret is returned once at registration. Store it — you’ll need it to verify signatures.

Event types

EventFires when
node.addedA node is created
node.updatedA node’s data changes (label, status, phase, etc.)
node.deletedA node is deleted
iteration.addedA phase is created
iteration.updatedA phase is renamed or status changes
iteration.deletedA phase is deleted
Phases are named iteration in the API. The event names and the payload field are the stable API identifier and won’t change; the product UI calls the same thing a phase.

Payload

{
  "event": "node.updated",
  "project_id": "my-project",
  "timestamp": "2026-06-11T10:30:00Z",
  "node": {
    "id": "job-42",
    "type": "job",
    "parentId": "approach-1",
    "data": {
      "label": "Price comparison shows for scanned barcode",
      "status": "delivered",
      "iteration": "MVP"
    }
  }
}
For iteration events, the payload includes iteration instead of node. Rename events include previous_name.

Headers

HeaderDescription
X-ProductBrain-EventEvent type (e.g. node.updated)
X-ProductBrain-DeliveryDelivery ID — stable across all retries of one event. Dedup on it to stay idempotent.
X-ProductBrain-Signaturesha256=<HMAC-SHA256 hex digest of raw body>

Verifying signatures

const crypto = require('crypto');

function verify(body, signature, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Delivery semantics

At-least-once. Every event is persisted durably before the first attempt, so a receiver that’s briefly down never loses it. We attempt delivery immediately; if your endpoint returns a non-2xx status or doesn’t respond within 5 seconds, we retry with exponential backoff (~2, 4, 8, 16, 32 minutes) up to 6 attempts total, then mark the delivery failed. Because it’s at-least-once, your receiver must be idempotent — the same event can arrive more than once (e.g. you process it but acknowledge past the 5-second window, so we retry). Dedup on X-ProductBrain-Delivery, which is stable across every retry of one event. Each attempt re-signs the body with your webhook’s current secret, so rotating the secret never breaks an in-flight retry.
  • Health monitoringGET /api/v1/webhooks returns the last delivery time and HTTP status per webhook; poll it to monitor health.
  • Reconcile failures — a delivery that exhausts all 6 attempts is marked failed and not retried further; catch up by reading GET /api/v1/nodes.

List webhooks

GET /api/v1/webhooks?projectId=my-project

Delete a webhook

DELETE /api/v1/webhooks?projectId=my-project&webhookId=wh_abc123

Integration guides

Webhooks power the delivery tracker integrations via Make.com: