Events
Personal-space activity never emits webhooks. A subscription can cover all shared spaces or be filtered to one space.
Delivery contract
Deliveries arePOSTs with a JSON body:
X-Coco-Event, X-Coco-Delivery, X-Coco-Webhook, and X-Coco-Signature — an HMAC-SHA256 of the raw body with the webhook’s signing secret, formatted sha256=<hex>.
Verifying a signature
GET /admin/webhooks/:id/deliveries, or the Deliveries panel in the admin UI).
Management (org admin)
GET/POST /admin/webhooks— list / create ({url, events, spaceSlug?, description?}; the signing secret is returned once on create)PATCH /admin/webhooks/:id— update URL, events, space filter, enable/disablePOST /admin/webhooks/:id/rotate-secret— new secret, returned oncePOST /admin/webhooks/:id/test— send awebhook.testdelivery and report the outcomeDELETE /admin/webhooks/:id
Security posture
- Endpoints must be https; plain http requires the deployment to opt in with
COCO_WEBHOOKS_ALLOW_HTTP=1(payloads then transit unencrypted). - SSRF guard: private, loopback, link-local, CGNAT, and reserved addresses (IPv4 and IPv6, including v4-mapped forms) are rejected — literals at create time, and again at delivery time after DNS resolution, so a hostname pointing at an internal address is blocked too (recorded in the delivery log, no retries). A small time-of-check/time-of-use window inherent to DNS remains; deployments with strict requirements should add egress filtering.
COCO_WEBHOOKS_ALLOW_PRIVATE_URLS=1disables the guard for intentionally internal deployments.