Skip to content
AnswerixAI

Webhooks

Receive AnswerixAI webhooks for content opportunities sent to your workflow, Daily Pulse digests and tests, with exact payloads and how to verify the secret.

Updated

AnswerixAI webhooks push data from AnswerixAI to your own endpoint, such as an n8n, Make or Zapier workflow or your CMS. They carry content opportunities you send to your workflow, Daily Pulse digests, and test events. Each brand has its own webhook, and a single content opportunity can override it.

How do I set up a webhook?

  1. Open Content in the sidebar with the brand selected.
  2. Click Webhook Settings.
  3. Enter the Webhook URL.
  4. Optionally enter a Secret Key (optional). AnswerixAI sends it with every delivery so your endpoint can check the request.
  5. Leave the switch on Active. Set it to Inactive to pause deliveries without deleting the settings.
  6. Click Test Webhook to send a test event, then Save Webhook.

Changing webhook settings needs the Admin or Manager role.

How do I send one article to a different URL?

Open the opportunity on the Content page and click the settings icon labeled Article webhook settings. The Article Webhook dialog has the same fields. When an active article webhook exists, Send to Workflow for that opportunity uses it instead of the brand default. Daily Pulse digests always use the brand default.

Which events does AnswerixAI send?

AnswerixAI sends three webhook events: opportunity.sent when you send a content opportunity to your workflow, daily_pulse.created when a Daily Pulse digest is created for the brand, and webhook.test when you click Test Webhook. Each one is an HTTP POST with a JSON body.

Event Sent when Sent to
opportunity.sent You click Send to Workflow on an opportunity, or Send All for selected opportunities. The opportunity's active article webhook, otherwise the brand's active webhook.
daily_pulse.created A Daily Pulse digest is created for the brand. The brand's active webhook.
webhook.test You click Test Webhook. The URL currently entered in the dialog.

Every delivery is an HTTP POST with a JSON body and Content-Type: application/json. The event name is in the body's event field.

opportunity.sent

The AnswerixAI opportunity.sent webhook is sent when you deliver a content opportunity to your workflow with Send to Workflow or Send All. It includes the brief and the saved content draft, if they exist.

{
  "event": "opportunity.sent",
  "opportunity": {
    "id": "0f6b3c1e-6a2d-4a8e-9a57-1d2c3b4a5e6f",
    "title": "Publish a comparison of agency PM tools",
    "description": "…",
    "type": "owned",
    "impact": "high",
    "opportunity_score": 82
  },
  "prompt": { "text": "best project management tool for agencies", "category": "…" },
  "data": {},
  "brief": {
    "suggestedTitle": "…",
    "contentType": "…",
    "targetWordCount": 1800,
    "outline": [],
    "targetKeywords": [],
    "competitorInsights": "…",
    "callToAction": "…"
  },
  "content": {
    "html": "<h2>…</h2>",
    "metaTitle": "…",
    "metaDescription": "…",
    "slug": "…",
    "faqs": [],
    "keyTakeaways": [],
    "structuredDataJsonLd": "…"
  },
  "brand": { "name": "Acme", "domain": "acme.com", "industry": "Software" },
  "callback_url": "https://answerixai.com/api/content/0f6b3c1e-6a2d-4a8e-9a57-1d2c3b4a5e6f/status"
}
Field Meaning
opportunity The opportunity's ID, title, description, type (owned or earned), impact (high, medium, low) and score.
prompt The related prompt's text and category, or null.
data The tracking signals behind the opportunity, the same as source_data in the REST API.
brief The content brief, or null if none was generated.
content The content draft, or null if none was generated.
brand The brand's name, primary domain and industry.
callback_url A dashboard URL for status updates.

After the request, AnswerixAI marks the opportunity Sent to Workflow and stores your endpoint's HTTP status and the first 1,000 characters of its response body. Both appear under Webhook Status and Webhook Response on the opportunity. The opportunity is marked sent whenever your endpoint responds, even with an error status; only a connection failure or timeout leaves it unchanged.

daily_pulse.created

The AnswerixAI daily_pulse.created webhook is sent to the brand's active webhook when AnswerixAI creates a Daily Pulse digest for the brand. Digests are created only when Digest frequency in Settings → Notifications is Daily or Weekly; with Off, no event is sent. Weekly digests go out on Mondays.

A digest is created after the brand's daily tracking run and only when that period has new results. Email recipients are optional: the webhook is sent even if no one gets the email. See Daily Pulse.

{
  "event": "daily_pulse.created",
  "brand": { "id": "5d1c2f0e-8a4b-4c3e-9f6a-2b7d1e0c9a88", "name": "Acme", "domain": "acme.com" },
  "pulse": {
    "date": "2026-09-27",
    "frequency": "daily",
    "windowDays": 1,
    "kpis": {
      "visibilityRate": 38.6,
      "visiblePrompts": 17,
      "promptCount": 40,
      "weekRate": 37.9,
      "prevWeekRate": 36.2,
      "weekTrend": 1.7,
      "mentions": 31,
      "mentionsChange": 4,
      "citations": 12,
      "citationsChange": -1,
      "sentimentPct": 68,
      "sentimentChange": 2,
      "totalResults": 80
    },
    "highlights": [
      { "type": "first_citation", "key": "first_citation:https://acme.com/guide", "url": "https://acme.com/guide", "label": "…", "promptText": "…" }
    ],
    "warnings": [
      { "type": "competitor_surge", "key": "competitor_surge:…", "competitorName": "Globex", "from": 20.1, "to": 31.4 }
    ],
    "degradedPlatforms": [],
    "insightsUrl": "https://answerixai.com/dashboard/insights",
    "settingsUrl": "https://answerixai.com/dashboard/settings?tab=notifications"
  }
}
Field Meaning
brand The brand's ID, name and primary domain.
pulse.date The digest date.
pulse.frequency daily or weekly.
pulse.windowDays 1 for daily digests, 7 for weekly digests.
pulse.kpis.visibilityRate Despite its name, the 0–100 Visibility score for the window, not a coverage rate. Coverage is reported separately: you appeared in visiblePrompts of promptCount tracked prompts.
pulse.kpis.weekRate, prevWeekRate, weekTrend The score over the last 7 days, the 7 days before, and the difference in points.
pulse.kpis.mentions, citations, sentimentPct Totals for the window, each with a …Change against the previous window.
pulse.kpis.totalResults AI answers in the window.
pulse.highlights Good news. type is first_citation, prompt_gain, competitor_overtaken or new_engine.
pulse.warnings Things to check. type is sharp_drop, visibility_slipping, competitor_surge, competitor_crossed or lost_citations. The same warning isn't repeated within 7 days.
pulse.degradedPlatforms Platform slugs with collection problems during the window.
pulse.insightsUrl, pulse.settingsUrl Links to the Visibility page and the notification settings.

Every highlight and warning has a type and a key; the other fields depend on the type.

webhook.test

The AnswerixAI webhook.test event is sent when you click Test Webhook in the webhook dialog. It goes to the URL typed in the dialog, before you save, so you can check your endpoint.

{
  "event": "webhook.test",
  "message": "This is a test webhook from AEO platform.",
  "timestamp": "2026-09-27T10:00:00+00:00"
}

The dialog shows "Webhook responded successfully!" for a 2xx response, and the failure reason otherwise. The test waits up to 10 seconds for a response.

How do I verify a webhook?

AnswerixAI doesn't sign payloads. If you set a secret, it is sent unchanged in the X-Webhook-Secret header of every delivery, including tests. Verify a delivery by comparing that header with your stored secret using a constant-time comparison, and reject the request if it is missing or different. Always use an https:// URL so the secret is encrypted in transit.

import crypto from 'node:crypto';

const WEBHOOK_SECRET = 'your-shared-secret'; // load from your secret store

function isFromAnswerix(req) {
  const received = Buffer.from(req.get('X-Webhook-Secret') ?? '', 'utf8');
  const expected = Buffer.from(WEBHOOK_SECRET, 'utf8');
  return received.length === expected.length && crypto.timingSafeEqual(received, expected);
}
import hmac

WEBHOOK_SECRET = "your-shared-secret"  # load from your secret store

def is_from_answerix(headers) -> bool:
    received = headers.get("X-Webhook-Secret", "")
    return hmac.compare_digest(received, WEBHOOK_SECRET)

How are webhooks delivered?

AnswerixAI delivers each webhook event in a single attempt with no retries, and waits up to 15 seconds for your endpoint to respond (10 seconds for Test Webhook). Return any 2xx status quickly and do slow work afterwards.

  • One attempt: each event is sent once. There are no retries.
  • Timeout: AnswerixAI waits up to 15 seconds for your response (10 seconds for Test Webhook).
  • Your response: return any 2xx status quickly and do slow work afterwards.
  • Missed deliveries: if an opportunity.sent delivery can't connect or times out, the opportunity stays New, so you can click Send to Workflow again. A missed daily_pulse.created event isn't resent; the same data is in the Daily Pulse email and on the Visibility page.

Was this page helpful?