Register a webhook endpoint
Register an endpoint to receive signed event deliveries.
HMAC_SHA256(secret, "<t>.<raw body>") and comparing it to the v1
value in the X-Exo-Signature header.
The url must be https and must resolve to a public address: private,
loopback, link-local, CGNAT, reserved and tunnelled ranges are rejected at
registration and again at every delivery, and redirects are never followed.
Unknown event types are rejected so a typo fails here rather than silently
never firing; a subscribed type that no emitter publishes yet comes back in
inactiveEventTypes for the same reason.
An organization may register at most 20 endpoints (409
webhook_limit_reached beyond that). A retried Idempotency-Key
returns the original registration but with the secret field replaced by
a marker: the plaintext is never persisted anywhere, including the replay
store.
WHAT AN ENDPOINT RECEIVES. Registering does not widen what the key behind it
can see. Events about the ORGANIZATION (insight.proposed,
brain.trained) are delivered to every endpoint. Events about a PERSON
(job.completed, basin.shifted, contradiction.detected,
belief.superseded) are delivered only to endpoints registered by that
person, mirroring the API, where another member’s job returns 404 and
identity reads are self-or-admin. Events about a PROVISIONED SUBJECT are
delivered to every endpoint, because any key in the organization can already
read that subject’s data with X-Exo-Subject.
Authorization
This route requires thewrite scope.
A missing or invalid credential returns 401 authentication_error. A valid credential without the scope returns 403 permission_denied, and the problem body names the exact scope required.
Headers
These are request conventions the contract does not declare as parameters, so they do not appear in the schema tables below.Success responses
Errors
webhook_limit_reached, idempotency_in_flight, idempotency_key_reuse. Every problem body names its own code, and the type URI always resolves to the matching page.
Every error is an RFC 9457 application/problem+json body carrying a stable code, a requestId, and a suggestedAction where Exo has one. See Errors.
Notes
- The signing secret is in this response and nowhere else. No route returns it again. Store it before you close the connection.
- A replayed
Idempotency-Keyreturns the registration with the secret redacted, not in the clear. The replay still proves the endpoint was created once. - The URL must be https and must resolve to a public address. Private, loopback, link-local, CGNAT, reserved and tunnelled ranges are rejected at registration and again at every delivery, and redirects are never followed.
- Unknown event types are rejected here so a typo fails at registration rather than silently never firing.
Authorizations
An Exo API key (exo_...) sent as the X-Exo-API-Key header.
Body
Response
Successful Response
Registration response: the ONLY place the signing secret is returned.
The signing secret. Shown once, at registration, and never retrievable again -- not by a read route and not by an idempotent replay, which returns a marker in its place. Store it now; if it is lost, register a new endpoint.
Subscribed event types that no emitter publishes yet, so nothing will be delivered for them. The subscription is kept and starts delivering as soon as the emitter ships; this field exists so you never wait on an event silently.