AuthorityWriter / Docs
Integration 2 · Custom Webhooks

Custom webhook integration

Receive an article payload on your own website, CMS, serverless function, or automation platform when AuthorityWriter delivers an article.

Setup

  1. Create a public HTTPS endpoint on your website.
  2. Configure the endpoint URL in AuthorityWriter Website Settings → Custom Webhook.
  3. Configure a strong webhook secret.
  4. Read the raw request body before parsing JSON.
  5. Verify the HMAC signature before processing the article.
  6. Return a 2xx response after successful validation and processing.

Request

AuthorityWriter sends an HTTP POST to your configured URL.

POST https://your-site.example/api/authoritywriter/webhook
Content-Type: application/json
Accept: application/json
X-AuthorityWriter-Event: article.published
X-AuthorityWriter-Signature: <hex HMAC-SHA256>

Payload example

{
  "event": "article.published",
  "timestamp": "2026-09-10T20:00:00+00:00",
  "article_id": 428,
  "website_id": 12,
  "website_name": "Example Website",
  "title": "How to Choose Running Shoes for Flat Feet",
  "slug": "running-shoes-for-flat-feet",
  "focus_keyword": "running shoes for flat feet",
  "secondary_keywords": ["stability shoes", "arch support"],
  "format": "buying_guide",
  "html_content": "<p>Article HTML...</p>",
  "plain_content": "Article text...",
  "meta_description": "Learn how to choose comfortable running shoes for flat feet.",
  "featured_image": "https://cdn.example.com/images/article-header.jpg",
  "featured_image_alt": "Running shoes selected for flat feet",
  "inline_images": [
    {
      "url": "https://authoritywriter.com/storage/article-images/ai-img-example.jpg",
      "alt": "Illustration explaining stability features for flat feet",
      "order": 1,
      "section_title": "Choosing Stability Features",
      "placement": "after_section_heading"
    }
  ],
  "category": "Running Gear",
  "sub_category": "Buying Guides",
  "schema_markup": {"@type": "Article"},
  "target_status": "draft"
}

Payload fields

FieldTypeDescription
eventstringCurrently article.published.
timestampISO 8601Time the webhook payload was generated.
article_idintegerAuthorityWriter article ID.
website_idintegerAuthorityWriter website ID.
title / slugstringArticle title and URL slug.
focus_keywordstringPrimary SEO keyword.
secondary_keywordsstring[]Supporting SEO keywords.
formatstringArticle format such as guide or buying_guide.
html_contentstringHTML article content, including schema markup when enabled.
plain_contentstringText-only article content.
meta_descriptionstringGenerated description, limited to approximately 160 characters.
inline_imagesobject[]Unique in-article image references extracted from html_content. Each item has url and alt.
categorystring|nullPrimary article category. Map this to your CMS category, taxonomy, or collection.
sub_categorystring|nullOptional child category. Map this beneath category where your CMS supports hierarchical taxonomies.
schema_markupobject|nullDecoded JSON-LD schema when enabled.
target_statusstringConfigured publishing status, usually draft or publish.

HTML content and supported elements

The html_content field contains the article body as HTML, not Markdown. Your receiver should store or render this field as HTML after signature verification and sanitization. Apply your own site stylesheet to the elements below; AuthorityWriter does not require a specific CSS framework or class naming convention.

ElementHow it is usedRecommended receiver styling
h2, h3Article section and subsection headings.Add spacing, readable font sizes, and an anchored heading hierarchy.
p, strong, emParagraphs, bold emphasis, and italic emphasis.Set line-height, paragraph spacing, and accessible contrast.
ul, ol, liBulleted and numbered lists.Restore list markers and left padding; do not flatten into plain text.
aLinks included in the article.Style links visibly and preserve the href and link text.
blockquoteQuoted or highlighted guidance.Use a visible border/background and distinguish it from normal paragraphs.
table, thead, tbody, tr, th, tdComparison tables, specifications, statistics, and feature summaries.Use responsive horizontal scrolling on small screens, borders, cell padding, and a distinct header row.
figure, img, figcaptionIn-article images with alt text and captions.Make images responsive, preserve alt text, and style captions below the image.
divLayout wrappers, including responsive video wrappers.Allow only the classes/attributes you trust or map them to your own design system.
script[type=application/ld+json]Schema markup may be appended when schema markup is enabled.Keep it in the document head or body as valid JSON-LD; do not display it as article text.
Security: Treat html_content as untrusted input. Verify the HMAC first, then sanitize HTML with an allowlist. Never allow arbitrary scripts, event-handler attributes such as onclick, unsafe URLs, or untrusted iframe sources. Escape content if your CMS stores plain text instead of HTML.

Example HTML sent in html_content

<h2>Choosing the right option</h2>
<p>A short explanation with <strong>important terms</strong>.</p>
<ul><li>First benefit</li><li>Second benefit</li></ul>
<table><thead><tr><th>Feature</th><th>Details</th></tr></thead><tbody><tr><td>Support</td><td>All-day comfort</td></tr></tbody></table>
<figure><img src="https://..." alt="Descriptive image text"><figcaption>Optional caption</figcaption></figure>

YouTube video embeds

When the article includes a relevant YouTube video, the HTML can contain a responsive iframe embed. The video is not uploaded to your website; the iframe loads the video from YouTube. Your receiver should preserve the iframe or convert it to the embed format supported by its CMS.

<div class="aspect-video my-4 rounded-xl overflow-hidden">
  <iframe src="https://www.youtube.com/embed/VIDEO_ID" class="w-full h-full" frameborder="0" allowfullscreen></iframe>
</div>
AttributePurposeReceiver guidance
srcYouTube embed URL containing the video ID.Allow only https://www.youtube.com/embed/... or your approved YouTube embed host.
allowfullscreenAllows viewers to expand the video.Preserve it if your sanitizer supports boolean iframe attributes.
classResponsive sizing and visual styling.Keep the classes if using Tailwind, or replace them with your own responsive video CSS.

If your CMS strips iframes, extract the YouTube video ID from the approved embed URL and use your CMS’s native YouTube block/oEmbed feature. Do not permit arbitrary iframe domains or JavaScript URLs.

Category mapping

The article category is sent separately from the article body. Use category as the primary taxonomy and sub_category as its child taxonomy when your CMS supports hierarchical categories.

// Example mapping
$category = $payload['category'] ?? null;
$subCategory = $payload['sub_category'] ?? null;

$parentId = find_or_create_category($category);
$childId = $subCategory
    ? find_or_create_category($subCategory, $parentId)
    : null;

assign_article_taxonomy($articleId, $parentId, $childId);

If either value is null, do not create an empty category. Custom integrations may map these values to categories, tags, collections, folders, or another taxonomy system.

Each item in inline_images includes placement metadata. Use section_title to match the image to the corresponding <h2> in html_content, and use order as the fallback sequence.

FieldMeaningReceiver action
order1-based image order in the article.Use when matching by sequence.
section_titleNearest preceding H2 section title.Find the exact H2 in html_content.
placementafter_section_heading or inline_content.Insert after that H2, or preserve the original HTML position.
altDescriptive alternative text.Preserve it when importing the image.
// Recommended placement algorithm
foreach ($payload['inline_images'] as $image) {
    $imageUrl = import_to_media_library($image['url']);
    $alt = $image['alt'];
    $heading = $image['section_title'];

    // Find the matching H2 in html_content and place the image
    // immediately after its opening section, preserving order.
    $html = insert_after_h2($html, $heading, $imageUrl, $alt);
}

Important: The original html_content already contains the correct image position. The metadata is a reliable guide for importing the image and rewriting its URL. Do not append all images at the bottom of the article.

The signature is a lowercase hexadecimal HMAC-SHA256 digest of the exact raw JSON request body, calculated with your webhook secret.

// PHP
$rawBody = file_get_contents('php://input');
$secret = getenv('AUTHORITYWRITER_WEBHOOK_SECRET');
$expected = hash_hmac('sha256', $rawBody, $secret);
$provided = $_SERVER['HTTP_X_AUTHORITYWRITER_SIGNATURE'] ?? '';

if (!$provided || !hash_equals($expected, $provided)) {
    http_response_code(401);
    exit('Invalid signature');
}

$payload = json_decode($rawBody, true, 512, JSON_THROW_ON_ERROR);
// Process $payload only after signature verification.
http_response_code(200);
Important: Do not parse and re-encode the JSON before signature verification. Whitespace or key-order changes produce a different digest.

Image transfer

Images are transferred as references in the JSON payload, not as multipart uploads.

Featured image

The featured_image field contains either an HTTPS image URL or a supported data URL. Your website should download the URL, store it in its own media library, and use featured_image_alt for accessibility.

Inline images

Inline images are already referenced inside html_content. Extract each <img src="...">, download remote URLs if required, rewrite the URL to your local media URL, and preserve the alt attribute.

Recommended receiver flow

  1. Verify the webhook signature using the raw request body.
  2. Read featured_image; download it over HTTPS with a timeout and file-size limit.
  3. Validate the downloaded MIME type and image dimensions before saving.
  4. Store the image in your media library and attach it as the article’s featured image.
  5. Parse html_content and optionally import inline img sources.
  6. Rewrite imported image URLs and preserve each supplied alt text.
WordPress: The WordPress integration automatically downloads the featured image into the WordPress Media Library, sets it as the post thumbnail, and saves the alt text. Inline images remain in the article HTML and must be publicly reachable or imported by your WordPress media workflow.
Security: Do not blindly fetch arbitrary URLs. Allow only HTTPS, restrict redirects and file size, validate the actual file type, and protect your server against SSRF.

Return any successful 2xx response after processing. Return 401 for an invalid signature and a non-2xx response for temporary processing failures. Make your receiver idempotent using article_id plus slug, because a delivery may be retried by the sender or network.

HTTP/1.1 200 OK
Content-Type: application/json

{"received":true}