Webhooks
Fromenance is a communication provenance platform, and outbound webhooks push every verdict, replay, and new indicator to your own systems within seconds. Each delivery is signed with a per endpoint secret, retried with backoff for about a day, and replayable from the admin app.
By the end you will have an endpoint subscribed to the events you need, know the envelope and headers of each delivery, and know how retries and replays behave.
Events
Section titled “Events”| Event | Fires | data |
|---|---|---|
verdict.created |
Once per verdict, after matching and before the reply is sent | The verdict object: submission_id, outcome, rule, replay, authoritative, matched (communication_id, sent_at, template_id), signals, indicators (kind, value), replied_at, created_at, plus tenant_id |
submission.replay_detected |
When a verdict is flagged as a footer replay, in addition to verdict.created |
submission_id, tenant_id, rule, code |
indicator.new |
The first time an indicator is seen on a non verified submission | tenant_id, indicator (id, kind, value, first_seen, submission_id, priority) |
campaign.detected |
Phase 2, when a cluster becomes a campaign | Subscribable now; nothing is sent until the intelligence tier ships |
The list of events is also returned as events on GET /v1/webhook-endpoints.
Create an endpoint
Section titled “Create an endpoint”Admin app: Webhooks, Add endpoint, URL, events. Or:
curl -X POST https://api.fromenance.com/v1/webhook-endpoints \ -H "Authorization: Bearer fr_live_..." \ -H "Content-Type: application/json" \ -d '{"url":"https://siem.northfieldbank.example/hooks/fromenance","events":["verdict.created","submission.replay_detected","indicator.new"],"description":"Splunk HEC relay"}'The response includes secret (whsec_...), shown once and encrypted at rest with your tenant key. Endpoints default to verdict.created only. PATCH changes the URL, events, description, or status (active, paused); DELETE removes it. A paused endpoint fails pending deliveries with “endpoint disabled” rather than queueing them.
Delivery
Section titled “Delivery”Each delivery is an HTTPS POST with a JSON body:
{ "id": "evt_01J...", "type": "verdict.created", "created_at": "2026-09-26T16:01:04.221Z", "data": { "submission_id": "sub_01J...", "outcome": "not_verified", "rule": "code:replay", "replay": true, "...": "..." }}Headers:
| Header | Value |
|---|---|
content-type |
application/json |
user-agent |
fromenance-webhooks/1.0 |
x-fromenance-event |
The event type |
x-fromenance-delivery |
whd_..., the delivery id. The same id is reused on every retry of one delivery; a replay gets a new id with replay_of pointing at the original |
x-fromenance-timestamp |
Unix seconds when the request was signed |
x-fromenance-signature |
v1=<hex HMAC-SHA256 of "<timestamp>.<raw body>"> keyed with the endpoint secret |
Respond with any 2xx within 10 seconds. Anything else, a timeout, or a connection error counts as a failed attempt. Verify the signature on every request before parsing the body; samples in TypeScript, Python, and Go are on Verify signatures.
Retries
Section titled “Retries”Failed deliveries are retried with backoff: after 1 minute, then 5, 15, and 30 minutes, then 1, 1, 2, 2, 4, 4, and 6 hours, for 12 attempts in total over roughly 21 hours. After the last failure the delivery is marked failed and stays in the log. Deliveries to different endpoints are independent; a slow endpoint never delays another.
Because retries resend the same payload with the same x-fromenance-delivery, make your handler idempotent on that header or on id in the body.
Delivery log and replay
Section titled “Delivery log and replay”Admin app: Webhooks, the endpoint, Deliveries shows every delivery with status (pending, retrying, delivered, failed), attempts, last_status_code, last_error, next_attempt_at, delivered_at, and the payload. API: GET /v1/webhook-endpoints/{id}/deliveries.
Replay re-sends any delivery, delivered or failed, as a new delivery with replay_of set: POST /v1/webhook-endpoints/{id}/deliveries/{delivery_id}/replay. Use it after an outage on your side, or to backfill a new SIEM index. Send test (POST /v1/webhook-endpoints/{id}/test) delivers a synthetic verdict.created so you can confirm signature verification before real traffic.
Payload notes
Section titled “Payload notes”- Payloads never contain the customer’s address, the forwarded message, or its links. Indicators are the extracted values (a phishing domain, a phone number), which is what your SIEM needs.
signalsonverdict.createdis an open object; new keys may be added. Do not fail on unknown keys.- Verdicts on sandbox submissions (from
fr_test_keys) are delivered like any other, so you can test your pipeline without live traffic. Use Send test for a synthetic event with a known shape.