Custom

How to Build a Custom Webhook Receiver for Share2Agent

Build a custom webhook receiver for Share2Agent in any language. This guide covers the full payload schema, working examples in Python and Node.js, and a curl command for testing.


Prerequisites

  • Python 3.x or Node.js 18+ (depending on your stack)
  • Share2Agent Chrome extension installed

Payload Schema

Share2Agent sends a POST request with a JSON body. Here is every field:

FieldTypeRequiredDescription
urlstringyesThe page URL
titlestringyesThe page title (from <title> tag)
contentstringyesExtracted clean text (HTML stripped, whitespace normalized)
commentstringnoUser's instruction or note (empty string if not provided)
timestampstringyesISO 8601 timestamp of when the page was shared
metaobjectyesMetadata object (see below)

meta object:

FieldTypeDescription
descriptionstringPage meta description
og_imagestringOpen Graph image URL
authorstringPage author (from meta tags)
languagestringPage language code (e.g., en, de)

Example payload:

json
{
  "url": "https://example.com/article",
  "title": "Understanding WebSockets",
  "content": "WebSockets provide full-duplex communication channels...",
  "comment": "Save for later review",
  "timestamp": "2026-03-28T12:00:00.000Z",
  "meta": {
    "description": "A guide to WebSocket protocol",
    "og_image": "https://example.com/og.png",
    "author": "Jane Smith",
    "language": "en"
  }
}

Python Receiver (Flask)

A minimal receiver in 15 lines:

python
from flask import Flask, request, jsonify
 
app = Flask(__name__)
 
@app.route("/", methods=["POST"])
def receive():
    data = request.get_json()
    if not data or "content" not in data:
        return jsonify({"error": "Missing content"}), 400
 
    print(f"Received: {data.get('title', 'untitled')}")
    print(f"URL: {data.get('url', '')}")
    print(f"Comment: {data.get('comment', '')}")
    print(f"Content length: {len(data.get('content', ''))} chars")
 
    # --- Your logic here ---
    # Save to database, call an API, trigger a pipeline, etc.
 
    return jsonify({"status": "ok"})
 
if __name__ == "__main__":
    app.run(port=9876)

Run it:

bash
pip install flask
python3 receiver.py

Node.js Receiver (Express)

The same receiver in Node.js:

javascript
const express = require("express");
const app = express();
 
app.use(express.json({ limit: "5mb" }));
 
app.post("/", (req, res) => {
  const { title, url, content, comment, meta } = req.body;
  if (!content) return res.status(400).json({ error: "Missing content" });
 
  console.log(`Received: ${title || "untitled"}`);
  console.log(`URL: ${url || ""}`);
  console.log(`Comment: ${comment || ""}`);
  console.log(`Content length: ${(content || "").length} chars`);
 
  // --- Your logic here ---
 
  res.json({ status: "ok" });
});
 
app.listen(9876, () => console.log("Listening on :9876"));

Run it:

bash
npm install express
node receiver.js

Testing with curl

Simulate a Share2Agent webhook to test your receiver without the browser extension:

bash
curl -X POST http://localhost:9876 \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/test",
    "title": "Test Page",
    "content": "This is a test of the webhook receiver.",
    "comment": "Testing integration",
    "timestamp": "2026-03-28T12:00:00.000Z",
    "meta": {
      "description": "Test page",
      "og_image": "",
      "author": "",
      "language": "en"
    }
  }'

Expected response:

json
{"status": "ok"}

Tips

  • Validate Content-Type -- check that the request has Content-Type: application/json before parsing. Share2Agent always sends JSON, but other sources might not.
  • Handle empty comments -- the comment field is an empty string when the user does not type anything. Check for this before using it as a prompt or instruction.
  • Set a max body size -- Share2Agent caps payloads at 5 MB. Set the same limit on your receiver to prevent abuse (express.json({ limit: "5mb" }) in Node, or check Content-Length in Python).
  • Return CORS headers -- if you test from a browser, add Access-Control-Allow-Origin: * and handle OPTIONS preflight requests. Share2Agent sends requests from a Chrome extension context, which requires CORS headers.
  • Respond quickly -- Share2Agent waits for a response. If your processing takes more than a few seconds, accept the webhook with a 200 immediately and process in the background.

What's Next?

  • Add authentication -- include a secret token in the webhook URL (e.g., http://localhost:9876?token=mysecret) and validate it in your receiver.
  • Build a processing pipeline -- chain your receiver with a message queue (Redis, RabbitMQ) to handle multiple pages concurrently.
  • Deploy publicly -- put your receiver behind a reverse proxy (Caddy, nginx) with HTTPS so you can share pages from any device, not just your local machine.