OuterciteOutercite

Webhooks

Send events to your own systems as they happen: the event list, the payload, the signature header, and the retry behaviour.

A webhook pushes an event to your endpoint as it happens, so your own systems can react without polling.

What you'll learn

  • The events you can subscribe to
  • How a delivery is signed, and how to verify it
  • Retry behaviour and what to build for

Create one

  1. Open API settings.
  2. Add an endpoint URL and choose the events. Leave the event list empty to receive all of them.
  3. Save, and keep the secret. It is what signs every delivery.
  4. Send a test delivery.

Webhooks are a plan feature. See plans and limits.

The events

EventFires when
citation.gainedA prompt starts being cited
citation.lostA prompt stops being cited
citation.negativeAn answer mentions you negatively
competitor.detectedA new competitor appears in your answers
insight.generatedAn insight is produced
action.createdAn action is created
brief.generatedAn agent brief is produced
score.changedA headline score moves
prediction.completedA forecast run finishes
recommendation.createdA change is proposed
recommendation.generatedA change is generated
recommendation.criticalA change is flagged critical
recommendation.actionedA change is approved or actioned
recommendation.dismissedA change is dismissed
agent.episode.completedAn agent run finishes
agent.alert.dispatchedAn agent alert is sent
pipeline.first_ai_visitThe first AI-sourced visit is seen for a prompt
pipeline.conversion_attributedA conversion is attributed to an AI referral
pipeline.impact_measuredAn impact measurement lands
coverage.exhaustedYour coverage wallet emptied and work paused
coverage.not_allocatedA coverage lane has no allocation at all, which is a billing fault on our side

The last two are separate on purpose. Exhaustion means you spent what you bought. Not allocated means something went wrong before you could spend anything, and it deserves a different alarm.

The delivery

A POST with a JSON body and three headers:

HeaderContents
X-Signature-256sha256= followed by the HMAC-SHA256 of the raw body, keyed with your secret
X-Webhook-EventThe event type
X-Webhook-DeliveryA unique id for this delivery

Verify the signature

Compute the HMAC-SHA256 of the raw body, not of a re-serialised object, and compare with the header value after the sha256= prefix. Use a constant-time comparison. Reject anything that does not match.

import crypto from 'crypto'

function verify(rawBody, header, secret) {
  const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex')
  const a = Buffer.from(header ?? '')
  const b = Buffer.from(expected)
  return a.length === b.length && crypto.timingSafeEqual(a, b)
}

Retries and timeouts

  • A delivery is attempted up to three times, with exponential backoff starting at five seconds.
  • Each attempt has a ten second timeout, so answer fast and do the work afterwards.
  • Return a 2xx as soon as you have the payload safely stored. Anything else is treated as a failure and retried.

Build your handler to be idempotent: use X-Webhook-Delivery as the deduplication key, since a retry after a timeout can deliver an event your system already processed.

Endpoint requirements

Your URL must be publicly reachable over HTTPS. Deliveries go through a fetch that rejects private address ranges and revalidates redirects, so an endpoint on a private network or behind a redirect to one will not receive anything.

Try this in Outercite

Create an endpoint subscribed to citation.lost and coverage.exhausted only. Those two carry the events that should wake up a system rather than a person.

Was this helpful?

Last updated on