Skip to main content
Webhooks deliver HMAC-signed JSON 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.
Webhooks are owner-only. A member’s key gets 403 { "error": "Not your project" }; an unknown project is 404.

Register a webhook

  • url must be https and publicly routable. http:// returns 400 "url must use https"; localhost and private ranges return 400 "url must be publicly routable".
  • events is optional. Omit it to subscribe to all six event types. An unknown event returns 400 "Invalid events: ... Valid: ...".
  • Maximum 10 webhooks per project (400 at the cap).
Response:
The id is a UUID. The secret lives inside webhook, not at the top level, and is returned once. Store it; you need it to verify signatures. Listing never returns it again.

List webhooks

lastDeliveryAt and lastStatus (the HTTP status your endpoint last returned) are the health signal. Poll them to spot a failing receiver.

Update a webhook in place

Change the URL or events without minting a new secret. The id stays the same and your receiver keeps verifying. Prefer this over delete and re-register, which mints a new secret and breaks the receiver.
Body: { projectId, id, url?, events?, rotateSecret? }. At least one of url, events, rotateSecret is required (400 otherwise). Unknown id: 404 "Webhook not found".

Rotate the secret

The response has the same shape as registration, with the new secret inside webhook, shown once. The old secret stops working immediately. In-flight retries are re-signed with the current secret, so rotation never breaks a pending delivery.

Delete a webhook

The query parameter is id. Any other name (webhookId, for example) returns 400 { "error": "id is required" }. An unknown id returns 404 { "error": "Webhook not found" }.

Event types

Phases are named iteration in the API. The event names and the payload field are the stable API identifier. The product UI calls the same thing a phase.

Payload

status: "done" means the job is live in production. You may still see "delivered" on nodes written by older integrations; it is deprecated and means “not done yet”. Phase events carry iteration instead of node: { "iteration": { "name": "MVP", "status": "done" } }. iteration.updated includes status only when the update changed it; a rename carries { "name": "<new>" } plus previous_name.

Headers

Verifying signatures

Sign the raw request bytes, not a re-serialised object.

Delivery semantics

At-least-once. Every event is persisted before the first attempt, so a receiver that is briefly down never loses it. Delivery is attempted immediately. If your endpoint returns a non-2xx status or does not respond within 5 seconds, the event is retried with exponential backoff, up to 6 attempts in total, then marked failed. The backoff between attempts is 2, 4, 8, 16 and 32 minutes (capped at 60). Retries are picked up by a scheduler that runs every 2 minutes, so each wait can be up to 2 minutes longer than the nominal figure. A delivery that fails every attempt is exhausted roughly an hour after the first try. Because delivery is at-least-once, your receiver must be idempotent. The same event can arrive more than once (for example you process it but acknowledge past the 5-second window). Dedup on X-ProductBrain-Delivery.
  • Health monitoring. GET /webhooks returns lastDeliveryAt and lastStatus per webhook.
  • Reconcile failures. A delivery that exhausts all 6 attempts is marked failed and not retried further. Catch up by reading GET /nodes.

Integration guides

Webhooks power the delivery-tracker integrations via Make.com: