Webhooks

Webhooks let you receive real-time notifications from DocuWriter.ai whenever something happens in your account. When an event occurs, such as a new generation or a repository sync suggestion, DocuWriter.ai sends an HTTP POST request to a URL you specify.

Webhooks are outgoing only. DocuWriter.ai pushes data to your endpoint. They work with any service that can receive HTTP POST requests, such as n8n, Zapier, Make, or your own server.


Using the Platform AI Agent with webhooks

The Platform AI Agent can explain webhook events, help you choose which events to subscribe to, and troubleshoot common setup questions.

Examples:

  • "Which webhook event should I use for Autopilot suggestions?"
  • "Why was my webhook disabled?"
  • "How do I verify webhook delivery?"
  • "Explain the repository_sync.suggestions_ready payload"

Creating, enabling, disabling, and deleting webhook subscriptions happens from Settings > Integrations so you can review the endpoint URL, selected events, and delivery logs before making changes.


Setup

  1. Click your avatar in the top-right corner and open Settings.
  2. Go to the Integrations tab.
  3. Enter the URL of your webhook receiver.
  4. Select the events you want to receive.
  5. Click Create webhook subscription.
  6. Trigger one of the selected events and check Webhook logs to verify delivery.

Available events

Event When it fires
generation.created A new generation is created, such as documentation, tests, diagrams, or optimization.
generation.updated An existing generation is modified.
repository_sync.suggestions_ready Repository Sync finishes analyzing code changes and has documentation suggestions ready for review.
repository_sync.suggestion_applied A repository sync suggestion is approved and applied.
repository_sync.suggestion_discarded A repository sync suggestion is rejected.

Payload examples

Every delivered webhook is wrapped as:

{
  "event": "event.name",
  "timestamp": "2026-06-12T10:30:14.786225Z",
  "webhook_id": 42,
  "data": {}
}

generation.created

{
  "event": "generation.created",
  "timestamp": "2026-06-12T10:30:14.786225Z",
  "webhook_id": 42,
  "data": {
    "id": 12345,
    "uuid": "89683484-f946-4184-98f9-9d89a0e9f26b",
    "filename": "UserController.php",
    "generation_type": "documentation",
    "generated_by_user": "[email protected]",
    "created_at": "2026-06-12T10:30:14.000000Z",
    "tag": null
  }
}

generation.updated

{
  "event": "generation.updated",
  "timestamp": "2026-06-12T10:35:14.786225Z",
  "webhook_id": 42,
  "data": {
    "id": 12345,
    "uuid": "89683484-f946-4184-98f9-9d89a0e9f26b",
    "filename": "UserController.php",
    "generation_type": "documentation",
    "generated_by_user": "[email protected]",
    "updated_at": "2026-06-12T10:35:14.000000Z",
    "tag": null
  }
}

repository_sync.suggestions_ready

{
  "event": "repository_sync.suggestions_ready",
  "timestamp": "2026-06-12T10:30:14.786225Z",
  "webhook_id": 42,
  "data": {
    "batch_id": 1,
    "space_id": 100,
    "space_name": "My Project Docs",
    "title": "Batch title",
    "suggestions_count": 3,
    "suggestions": [
      {
        "id": 10,
        "type": "update",
        "target_name": "Authentication Guide",
        "summary": "Updated OAuth2 flow documentation",
        "suggested_markdown": "...",
        "original_markdown": "..."
      }
    ],
    "repository": {
      "provider": "github",
      "identifier": "org/repo",
      "branch": "main",
      "commit_sha": "abc123",
      "commit_range": "abc123..def456",
      "pr_number": 42
    },
    "review_url": "https://app.docuwriter.ai/space/100/repository-sync/batch/1"
  }
}

repository_sync.suggestion_applied / suggestion_discarded

{
  "event": "repository_sync.suggestion_applied",
  "timestamp": "2026-06-12T10:30:14.786225Z",
  "webhook_id": 42,
  "data": {
    "suggestion_id": 10,
    "batch_id": 1,
    "space_id": 100,
    "space_name": "My Project Docs",
    "suggestion_type": "update",
    "target_item": {
      "id": 200,
      "name": "Authentication Guide"
    },
    "summary": "Updated OAuth2 flow documentation",
    "suggested_markdown": "...",
    "original_markdown": "...",
    "applied_by": {
      "id": 1,
      "email": "[email protected]"
    },
    "applied_at": "2026-06-12T10:30:14.786225Z",
    "repository": {
      "provider": "github",
      "identifier": "org/repo",
      "branch": "main",
      "commit_sha": "abc123",
      "pr_number": 42
    }
  }
}

For repository_sync.suggestion_discarded, the action fields use discarded_by and discarded_at.


Security

Every webhook request includes these headers:

Header Description
X-DocuWriter-Signature HMAC-SHA256 signature, formatted as sha256=<hash>.
X-DocuWriter-Event The event name, such as generation.created.
User-Agent DocuWriter-Webhook/1.0.

The signature is computed using your subscription's secret key over the raw JSON request body. Always verify the signature against the raw request body before processing the webhook to ensure the request is authentic.


Failure handling

If your endpoint fails to respond, times out after 30 seconds, or returns a non-2xx status code, DocuWriter.ai tracks consecutive failures.

  • After 5 consecutive failures, the webhook is automatically disabled and you receive an email notification.
  • You can re-enable the webhook from Settings > Integrations. This resets the failure counter.
  • Failure notifications are sent at most once per day.

Quick implementation example

A minimal Node.js Express server that receives and verifies DocuWriter.ai webhooks:

const express = require("express");
const crypto = require("crypto");

const app = express();

const WEBHOOK_SECRET = "your-webhook-secret";

app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
  const rawBody = req.body;
  const signature = req.headers["x-docuwriter-signature"];
  const expected =
    "sha256=" +
    crypto
      .createHmac("sha256", WEBHOOK_SECRET)
      .update(rawBody)
      .digest("hex");

  if (signature !== expected) {
    return res.status(401).json({ error: "Invalid signature" });
  }

  const payload = JSON.parse(rawBody.toString("utf8"));
  const { event, data } = payload;

  switch (event) {
    case "generation.created":
      console.log(`New generation: ${data.filename} (${data.generation_type})`);
      break;
    case "repository_sync.suggestions_ready":
      console.log(`${data.suggestions_count} suggestions ready for ${data.space_name}`);
      break;
    default:
      console.log(`Received event: ${event}`);
  }

  res.status(200).json({ received: true });
});

app.listen(3000, () => console.log("Webhook server running on port 3000"));

Managing subscriptions

From Settings > Integrations you can:

  • Verify delivery: trigger a selected event and inspect Webhook logs
  • Enable / Disable: toggle a subscription on or off without deleting it
  • Delete: permanently remove a subscription
  • View logs: see recent delivery attempts, status codes, and response times