Webhooks

Create, test, and verify outbound webhooks for issue_created, regression, and velocity_spike with Slack, Discord, or generic HTTPS.

Webhooks POST from Epure to your HTTPS endpoint when lifecycle events fire. Configure in the UI at /p/:projectId/settings/webhooks or with the session API below.

UI walkthrough and RBAC: Settings. Alert kinds that drive events: Alerts.

Event types

Event idWhen
issue_createdFirst event for a fingerprint
regressionResolved issue returns on a newer release
velocity_spikeVelocity rule fired for an issue
custom_ruleCustom alert rule matched

Formats

formatPayload
slackSlack incoming webhook JSON
discordDiscord webhook JSON
genericEpure JSON document

URLs must be public HTTPS. Loopback and private IPs are blocked unless EPURE_WEBHOOK_ALLOW_PRIVATE=1 (dev/tests only).

Create a webhook

Admin or Owner session required.

Create generic webhook

command

curl -sS -b cookies.txt -X POST \
"http://localhost:8080/api/v1/webhooks" \
-H "Content-Type: application/json" \
-d '{"project_id":"550e8400-e29b-41d4-a716-446655440000","url":"https://hooks.example.com/epure","format":"generic","events":["issue_created","regression","velocity_spike"]}'

Expected

HTTP/1.1 201 Created

{ "id": "…", "signing_secret": "<shown once>", "secret_prefix": "…" }

List: GET /api/v1/webhooks?project_id={uuid}. Update: PATCH /api/v1/webhooks/{id}. Delete: DELETE /api/v1/webhooks/{id}.

Signing secret

On create (and on rotate), Epure returns a signing secret once. Each delivery includes an HMAC-SHA256 signature header — verify on your receiver before trusting the body.

Rotate without changing the URL: POST /api/v1/webhooks/{id}/rotate-secret.

Test delivery: POST /api/v1/webhooks/{id}/test → { "sent": true }.

SSRF guard

Production must not set EPURE_WEBHOOK_ALLOW_PRIVATE. If hooks never arrive, check URL is public HTTPS, not an internal IP.

Common failures

ResultWhat happenedWhat to do
400 on createBad URL, format, or events arrayformat ∈ slack/discord/generic; non-empty events
403Member sessionAdmin or Owner
Hook never arrivesSSRF block or receiver downPublic URL; check receiver logs
Signature mismatchWrong secret after rotateUpdate verifier with new secret
Does ingest use webhooks?

No. Ingest is inbound DSN only. Webhooks are outbound notifications after Epure processes an event.

Can one webhook subscribe to all projects?

Each webhook row is scoped to one project_id. Create one hook per project or fan-in on your receiver.

Is a DSN the same as a session?

Webhook CRUD uses a session cookie. DSN on /api/v1/webhooks returns 401: Authentication.