Overview

Webhooks allow you to receive annotation data at external URLs when users interact with annotations. This enables integrations with Slack, Discord, custom backends, CI/CD pipelines, and more.

Configure a webhook URL via the webhookUrl prop, and events will be sent automatically when annotations are created, updated, deleted, or submitted.

Configuration

Add the webhookUrl prop to enable webhooks:

import { Agentation } from "agentation";

function App() {
  return (
    <> 
      <YourApp />
      <Agentation webhookUrl="https://your-server.com/webhook" />
    </>
  );
}

With a webhook URL configured, you have two options: enable Auto-Send to fire events automatically, or click "Send Annotations" in the toolbar manually. When Auto-Send is on, the toolbar button is hidden.

Events

Webhooks fire for the following events:

  • annotation.add — New annotation created
  • annotation.delete — Annotation deleted
  • annotation.update — Annotation comment edited
  • annotations.clear — All annotations cleared
  • submit — "Send Annotations" clicked

Webhook Payload

All events send a POST request with the following JSON structure:

{
  "event": "annotation.add",
  "timestamp": 1706234567890,
  "url": "https://example.com/dashboard",
  "annotation": {
    "id": "1706234567890",
    "comment": "Button is cut off on mobile",
    "element": "button",
    "elementPath": "body > main > form > button.submit-btn",
    "timestamp": 1706234567890
  }
}

Event-specific payloads

annotation.add / annotation.delete / annotation.update

{
  "event": "annotation.add",
  "timestamp": 1706234567890,
  "url": "https://example.com/page",
  "annotation": { ... }
}

annotations.clear

{
  "event": "annotations.clear",
  "timestamp": 1706234567890,
  "url": "https://example.com/page",
  "annotations": [ ... ]
}

submit

{
  "event": "submit",
  "timestamp": 1706234567890,
  "url": "https://example.com/page",
  "output": "# Page Feedback\n\n...",
  "annotations": [ ... ]
}

Combining with Callbacks

You can use webhooks alongside the onSubmit and other callback props. Both will fire when events occur:

<Agentation
  webhookUrl="https://your-server.com/webhook"
  onSubmit={(output, annotations) => {
    // This fires in addition to the webhook
    console.log("Submitted:", annotations.length, "annotations");
  }}
  onAnnotationAdd={(annotation) => {
    // Track in analytics
    analytics.track("annotation_created");
  }}
/>

Use Cases

Slack Notifications

// Server webhook handler
app.post("/webhook/agentation", async (req, res) => {
  const { event, annotation, url } = req.body;

if (event === "annotation.add") {
    await fetch(process.env.SLACK_WEBHOOK_URL, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        text: `New annotation on ${url}: "${annotation.comment}"`,
      }),
    });
  }

res.json({ ok: true });
});

GitHub Issue Creation

app.post("/webhook/agentation", async (req, res) => {
  const { event, output, annotations } = req.body;

if (event === "submit" && annotations.length > 0) {
    await fetch("https://api.github.com/repos/owner/repo/issues", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        title: `[Feedback] ${annotations.length} annotation(s)`,
        body: output,
        labels: ["feedback"],
      }),
    });
  }

res.json({ ok: true });
});

Real-time Dashboard

// Server with WebSocket broadcast
app.post("/webhook/agentation", (req, res) => {
  const { event, annotation, url } = req.body;

// Broadcast to connected dashboard clients
  wss.clients.forEach((client) => {
    client.send(JSON.stringify({
      type: "annotation_event",
      event,
      annotation,
      url,
    }));
  });

res.json({ ok: true });
});

Security Considerations

  • Use HTTPS — Always use encrypted connections for webhook URLs
  • Validate origin — Check the request origin if your webhook is public
  • Rate limiting — Implement rate limits to prevent abuse
  • Sanitize content — Annotation comments may contain user-generated content; sanitize before rendering

Testing Webhooks

Tools for testing webhooks during development:

  • webhook.site — Free public endpoint for testing payloads
  • ngrok — Expose local server for testing with real URLs
  • RequestBin — Inspect and debug webhook payloads

Quick Test Setup

// Use webhook.site for testing
<Agentation webhookUrl="https://webhook.site/your-unique-id" />

// Then create annotations and check webhook.site for payloads