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 id | When |
|---|---|
issue_created | First event for a fingerprint |
regression | Resolved issue returns on a newer release |
velocity_spike | Velocity rule fired for an issue |
custom_rule | Custom alert rule matched |
Formats
format | Payload |
|---|---|
slack | Slack incoming webhook JSON |
discord | Discord webhook JSON |
generic | Epure 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
| Result | What happened | What to do |
|---|---|---|
| 400 on create | Bad URL, format, or events array | format ∈ slack/discord/generic; non-empty events |
| 403 | Member session | Admin or Owner |
| Hook never arrives | SSRF block or receiver down | Public URL; check receiver logs |
| Signature mismatch | Wrong secret after rotate | Update verifier with new secret |
FAQ
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.