Custom webhook

Receive every article as JSON and publish it on any platform.

A webhook connects ProgSEO to any platform: Next.js, Webflow via your own middleware, a headless CMS, a Zapier/Make scenario, or your own backend. When something happens to an article, ProgSEO sends a POST request with a JSON payload to your URL.

Set up a webhook

  1. 1

    Create an endpoint

    Create a URL on your server that accepts POST requests with a JSON body.

  2. 2

    Add it to ProgSEO

    Open Integrate → Webhooks, paste the Webhook URL, set a Webhook Secret and press Save.

  3. 3

    Verify requests

    Every request carries Authorization: Bearer your_secret. Reject requests where it doesn't match.

  4. 4

    Acknowledge

    Return a 2xx status once you have stored the article. Other responses are recorded as failed deliveries.

Events

EventWhen it fires
post_createdA new article is generated and published.
post_updatedAn article is edited and republished, or a change request is accepted.
post_deletedReserved for future use — not sent yet.

post_created

Payload
{
  "event": "post_created",
  "timestamp": "2026-03-26T12:00:00Z",
  "site": "your-site-slug",
  "data": {
    "slug": "how-to-optimize-your-landing-page",
    "title": "How to Optimize Your Landing Page",
    "description": "A guide to...",
    "author": "Editorial Team",
    "tags": ["seo", "landing-pages"],
    "publishedAt": "2026-03-26",
    "readingTime": "8 min read",
    "blocks": [
      { "type": "hero", "title": "...", "subtitle": "..." },
      { "type": "text", "content": "..." }
    ]
  }
}

post_updated

Payload
{
  "event": "post_updated",
  "timestamp": "2026-03-26T14:30:00Z",
  "site": "your-site-slug",
  "data": {
    "slug": "how-to-optimize-your-landing-page",
    "oldPost": { "slug": "...", "title": "...", "blocks": [ ... ] },
    "newPost": { "slug": "...", "title": "...", "blocks": [ ... ] },
    "updatedFields": ["blocks"],
    "updatedAt": "2026-03-26T14:30:00Z",
    "changeRequestId": "cr_123"
  }
}

changeRequestId is only present when the update came from an accepted change request.

Content blocks

Article content is an ordered blocks array. Each block has a type: hero, text, heading, list, image, table, quote, code, divider, faq, features, stats, cta, youtube and author. Render the types you support and skip the rest. If you'd rather receive ready-made HTML-like content, look at the Markdown and TSX exports.

Example handler (Node.js)

server.js
app.post("/api/webhook", (req, res) => {
  if (req.headers["authorization"] !== "Bearer " + process.env.WEBHOOK_SECRET) {
    return res.status(401).json({ error: "Unauthorized" });
  }

  const { event, data } = req.body;

  switch (event) {
    case "post_created":
      // save data.slug, data.title, data.blocks ...
      break;
    case "post_updated":
      // replace the post matching data.slug with data.newPost
      break;
  }

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

Delivery log and retries

Once a webhook URL is saved, Integrate → Webhooks shows recent deliveries with the status code your server returned. Failed deliveries can be retried from there after you fix the endpoint.

Tip

Use the article slug as the unique key on your side. Both post_created and post_updated can then be handled as an upsert.

Still stuck? Email [email protected] and we'll help.