Skip to content

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.

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.

Admin app: Webhooks, Add endpoint, URL, events. Or:

Terminal window
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.

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.

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.

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.

  • 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.
  • signals on verdict.created is 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.