Webhooks

Send annotation events to external services automatically

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.

Browser
Agentation
Webhook
Server
Service
Slack, GitHub...
annotation.addPOST /slack200 OKsubmitPOST /github/issues201 Created
request
response

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