Skip to main content
A Destination is where Brein’s events leave for another system. Give it an address and the event types you care about; Brein sends each one, signed with Standard Webhooks 1.0.0, as soon as it happens.

Create a Destination

Through the API, with an API key from the workspace owner or an admin.
  • Address: public https, port 443 or 8443, up to 2048 characters. Private and internal addresses are refused, and Brein checks again on every send.
  • Events: 1 to 12 types from the catalog. You can change them later; an added type only receives what happens from then on, not history.
  • Secret: whsec_…, shown once.
A test workspace has no Destinations: nothing leaves Brein from there.

What you receive

The body is the full CloudEvent. webhook-id is the event id and does not change between retries: use it to drop duplicates.

Verify the signature

Verify before trusting the body. Use the bytes exactly as they arrived, not re-serialized JSON.
More than one signature may come, separated by spaces: after you rotate the secret, for 24 hours Brein signs with the new one and the previous one. Accept if any matches.

Responses and retries

Answer 2xx quickly and process afterwards. Brein waits 10 seconds at most and does not follow redirects. Ten attempts. After each failure it waits 5 s, 5 min, 30 min, 2 h, 5 h, 10 h, 14 h, 20 h and 24 h: about 75 hours from the first to the last. Each retry carries the same webhook-id and a fresh signature. If the last five finished deliveries all ran out of attempts, the Destination is disabled. The same event can arrive more than once. That is how Standard Webhooks works: better than losing it. Drop duplicates by webhook-id. Order is not guaranteed either: use time and subject.

An agent that answers never wakes itself

An agent that receives a delivery often writes back through the MCP or the API, and that write can produce an event of the same type it listens to. To stop the loop, send the id of the event you received in the X-Brein-Cause header of every call you make in answer (on the MCP, the same header on the request). Brein then records that event as the causationid of whatever you write, and never delivers to your Destination an event whose cause it already delivered to you. Other Destinations still receive it. An id that is not an event of your workspace is refused with X-Brein-Cause as the field.

Event types that were retired

The path of an arrival (arrival.received, .accepted, .decided, .rejected, .quarantined, .reprocessed) is no longer in the catalog. A Destination that was subscribed to one keeps the subscription stored but receives nothing for it, and it no longer shows in its list; saving the list again removes it. Deliveries already queued are still sent.

Inspect, test and redeliver

All through the API, with the same key: Routes start with https://api.trybrein.com/api/v1/workspaces/<slug>. Brein does not store what your server answers, only the status and the time. A paused Destination keeps what is pending and sends it on resume. The sample event is not written to your ledger. Missed something during a long outage? Read the ledger from your last cursor.