Webhooks
A signed POST to your endpoint when a mention arrives, finishes triage, changes status, or gets a draft.
Webhooks push mentions to you instead of you polling for them. Add one under Settings → Notifications, or as the Call a webhook action on an agent when you only want a subset. There is a setup walkthrough alongside it.
The endpoint must be public HTTPS and answer 2xx within 10 seconds. n8n, Make,
Activepieces and Pipedream webhook triggers all work.
Available on every plan, including Free.
Events
| Event | Fires when |
|---|---|
mention.created | A mention is collected, before triage |
mention.scored | Triage has finished: relevance, labels and the Reply call exist |
reply.drafted | A reply draft is written |
Subscribe to mention.scored unless you have a reason not to — it is the first event
carrying relevance, so it is the first one your
relevance floor can filter on. mention.status_changed
is listed when you pick events but is not sent yet.
A webhook sends each event as it happens. If you turn on batching for it, it also receives
mention.digest, which carries the window and its five most relevant mentions — see
Bursts.
Payload
{
"version": 2,
"id": "mention.scored:wr_41d7:mt_b001",
"type": "mention.scored",
"organizationId": "org_acme",
"projectId": "prj_default",
"occurredAt": "2026-10-19T09:12:44Z",
"data": {
"resourceType": "mention",
"resourceId": "mt_b001",
"mention": {
"id": "mt_b001",
"platform": "reddit",
"url": "https://reddit.com/...",
"title": "Two of us, 400 emails a day, and I am the bottleneck",
"authorHandle": "quietledger",
"postedAt": "2026-10-19T08:40:02Z",
"relevance": 92,
"relevanceReason": "relevant",
"labels": ["asking-for-recommendations", "has-a-problem"],
"labelNames": ["Asking for recommendations", "Has a problem"],
"replyCall": "reply_now",
"replyHint": "answer",
"subject": "topic",
"sentiment": "negative",
"status": "new"
},
"links": {
"self": "https://app.fishout.ai/api/v1/orgs/org_acme/projects/prj_default/mentions/mt_b001",
"app": "https://app.fishout.ai/org/org_acme/project/prj_default/inbox?mt_id=mt_b001"
}
},
"simulated": false
}The payload deliberately stops short of the post text. It carries enough to route, alert
on or ignore the mention; to read the post, fetch data.links.self with an
API key.
replyCall is null off Reddit, Hacker News and YouTube. subject is brand,
competitor or topic for a relevant post, or different_meaning, spam or off_brief
for one that was filtered. relevanceReason says why a post landed where it did, including
below_threshold.
Verifying the signature
Every request is signed with your channel's signing secret, shown once when you create or rotate it. Verify the signature before trusting the payload — an unverified webhook endpoint is a public write API.
X-FishOut-Event: mention.scored
X-FishOut-Event-Id: mention.scored:wr_41d7:mt_b001
X-FishOut-Delivery: dlv_3e9a...
X-FishOut-Timestamp: 1760865164
X-FishOut-Signature: v1=5257a869e7...Compute HMAC-SHA256 of {timestamp}.{raw body} with the signing secret, hex-encode it, and
compare it with the value after v1= in constant time. Reject anything whose timestamp is
more than five minutes old, which stops a captured request being replayed.
Verify against the raw request body, before any JSON parsing. Parsing and re-serialising changes whitespace and key order, and the signature will never match.
Delivery and retries
Return a 2xx quickly — acknowledge first, do the work after. FishOut retries timeouts,
429s and 5xxs with a growing delay, and honours Retry-After. Redirects are not
followed, and other 4xx answers are not retried. Every attempt shows in the channel's
delivery history.
Delivery is at least once, so an event can arrive twice. Make your handler idempotent by
keying on X-FishOut-Event-Id, not by assuming exactly-once delivery.