> ## Documentation Index
> Fetch the complete documentation index at: https://octolens.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> Pipe any feed into your own systems. Send new mentions as JSON to any URL.

A webhook is a [destination](/quickstart/destinations) that sends matching mentions to a URL you control. Every [feed](/quickstart/feeds) can fan out to a webhook. Point it at Zapier, an internal API, a Discord webhook, or anything else that accepts an HTTPS POST.

Webhooks are available on every plan, alongside email and Slack [destinations](/quickstart/destinations).

## Set up a webhook

The setup flow is the same as any other destination. See [Destinations](/quickstart/destinations) for the full walkthrough. The short version:

<Steps>
  <Step title="Open any feed and click Set up alert">
    In the top-right of the feed.
  </Step>

  <Step title="Toggle on Webhook">
    Enter your **Webhook URL**, click **Test** to verify it's reachable, and choose a **Frequency**: Instantly, Hourly, Daily, or Weekly.
  </Step>

  <Step title="Save">
    Click **Add alert** to start delivery.
  </Step>
</Steps>

<Tip>
  **Discord-compatible.** Octolens webhooks work directly with Discord channel webhook URLs. Create a webhook in your Discord channel settings, copy the URL, paste it into the Webhook URL field, and mentions will post straight into the channel. No Zapier or middleware needed.
</Tip>

You can enable the webhook alongside Email and Slack on the same feed. All three fire off the same feed.

## Receiving webhook requests

Octolens sends webhooks as HTTPS `POST` requests with a JSON body.

* **Content-Type**: `application/json`
* **Expected response**: return any `2xx` status to acknowledge receipt
* **Timeout**: reply promptly (under a few seconds). If your processing is slow, acknowledge first and queue the work.

<Note>
  Webhook signing is not currently available. For now, we recommend using a unique, unguessable endpoint URL or a secret query parameter, and validating it server-side. Do not reuse production credentials in the webhook URL.
</Note>

## Payload format

Octolens sends one mention per request. The top-level `action` field indicates what triggered the webhook:

* `mention_created`: a new mention matched the feed

### Example

```json theme={null}
{
  "action": "mention_created",
  "data": {
    "title": "...",
    "body": "...",
    "url": "https://...",
    "timestamp": "2024-12-04T13:55:32.000Z",
    "imageUrl": "...",
    "author": "...",
    "authorName": "...",
    "authorAvatarUrl": "...",
    "authorProfileLink": "https://...",
    "authorFollowerCount": 1234,
    "source": "reddit",
    "sourceId": "111111111",
    "relevanceScore": "high",
    "relevanceComment": "...",
    "keyword": "Octolens",
    "keywords": ["Octolens", "social listening"],
    "sentimentLabel": "Neutral",
    "tags": ["Own Brand Mention"],
    "language": "en",
    "subreddit": "r/subreddit",
    "viewId": 111,
    "viewName": "Feed name",
    "viewKeywords": ["Octolens"]
  }
}
```

### Field reference

| Field                      | Type      | Description                                                                                                                                              |
| -------------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `action`                   | string    | Currently always `mention_created`.                                                                                                                      |
| `data.title`               | string    | Post title, if the platform has one (e.g. Reddit). Can be empty on platforms without titles.                                                             |
| `data.body`                | string    | The post text.                                                                                                                                           |
| `data.url`                 | string    | Canonical URL to the post on the source platform.                                                                                                        |
| `data.timestamp`           | string    | ISO 8601 timestamp of when the post was published.                                                                                                       |
| `data.imageUrl`            | string    | URL of the attached image, if any.                                                                                                                       |
| `data.author`              | string    | The author's handle or username on the source platform.                                                                                                  |
| `data.authorName`          | string    | The author's display name.                                                                                                                               |
| `data.authorAvatarUrl`     | string    | URL to the author's avatar image.                                                                                                                        |
| `data.authorProfileLink`   | string    | Link to the author's profile.                                                                                                                            |
| `data.authorFollowerCount` | number    | The author's follower count on the source platform, if available.                                                                                        |
| `data.source`              | string    | The platform the mention came from (e.g. `reddit`, `twitter`, `github`).                                                                                 |
| `data.sourceId`            | string    | The platform's native ID for the post.                                                                                                                   |
| `data.relevanceScore`      | string    | Relevance assigned by the AI. One of `high`, `medium`, or `low`.                                                                                         |
| `data.relevanceComment`    | string    | One-sentence explanation of why the mention matched.                                                                                                     |
| `data.keyword`             | string    | The first (primary) keyword that matched this post. Kept for backward compatibility; new integrations should use `keywords`.                             |
| `data.keywords`            | string\[] | All of your keywords that matched this post. A post can match more than one.                                                                             |
| `data.sentimentLabel`      | string    | `Positive`, `Neutral`, or `Negative`.                                                                                                                    |
| `data.tags`                | string\[] | AI-assigned tags on the mention (e.g. `Own Brand Mention`, `Buy Intent`). See [AI Relevance & Tags](/learn/ai-relevance).                                |
| `data.language`            | string    | ISO 639-1 language code detected for the post (e.g. `en`, `es`, `de`).                                                                                   |
| `data.subreddit`           | string    | Subreddit name. Only present for Reddit mentions.                                                                                                        |
| `data.viewId`              | number    | ID of the feed that fired this webhook. (Field name kept for backward compatibility — feeds were previously called views.)                               |
| `data.viewName`            | string    | Name of the feed that fired this webhook.                                                                                                                |
| `data.viewKeywords`        | string\[] | The keywords configured on the feed that fired this webhook. Useful for distinguishing which feed-filter matched when one feed covers multiple keywords. |

<Note>
  Webhook field names differ slightly from the [REST API](/api/v2/overview) response. For example, the API returns `sentiment` while webhooks use `sentimentLabel`, and the API returns `keywords` as an array of objects like `{id, keyword}` while webhooks send `keywords` as an array of strings (plus `keyword` as a single string for backward compatibility). If you're wiring up both, map them explicitly.
</Note>

## Use cases

Webhooks turn mentions into events in the rest of your stack. Common patterns:

* **Discord:** paste a channel webhook URL straight into Octolens; mentions post into your channel
* **CRMs:** create or update leads in Salesforce, HubSpot, Pipedrive, or Zoho when someone expresses buy intent
* **Task managers:** open tickets in Linear, Asana, ClickUp, Monday, Trello, or Todoist from Bug Reports or User Feedback mentions
* **Chat:** Microsoft Teams, or extra Slack workspaces beyond your primary connection
* **Databases:** append to Notion, Airtable, or Google Sheets for custom reporting
* **Support:** auto-create Intercom or Zendesk conversations from product questions
* **AI agents:** trigger an agent run via [MCP](/mcp/overview) or your own orchestrator on every new buy-intent mention

Don't have a direct integration? Point the webhook at **Zapier**, **n8n**, or **Make** and fan out from there to hundreds of other apps.

## Customize your payload with Val Town

If you want more control than a direct webhook gives (custom message formatting, interactive buttons in Discord or Slack, per-mention routing logic, filtering before delivery) a small piece of code in the middle gets you there.

[Val Town](https://val.town) is a serverless JavaScript platform built for exactly this pattern. You paste your Val Town URL into Octolens as the Webhook URL, and the val receives the payload, transforms it however you want, then forwards it on.

**What this unlocks:**

* Reformat the Octolens payload into a rich Discord embed or Slack Block Kit message with buttons
* Drop fields you don't need, or enrich the payload with data from another API before it lands
* Edit the code in the browser and redeploy instantly. No build step, no hosting to manage

**Start here:**

* [Creating a webhook in Val Town](https://docs.val.town/guides/creating-a-webhook/): the pattern for receiving any incoming webhook
* [Send a Discord message via webhook](https://docs.val.town/guides/discord/send-message/): forward to Discord with custom formatting
* [Sending Slack messages](https://docs.val.town/guides/slack/send-messages-to-slack/): forward to Slack with Block Kit

## Next steps

* [Destinations](/quickstart/destinations): the full destination setup flow (recipients, frequency, editing)
* [API Reference](/api/v2/overview): pull-based alternative if you prefer polling
* [MCP Server](/mcp/overview): connect mentions to AI agents via MCP
