Content

Content Ingestion

Mirror an external blog or knowledge base into the widget via RSS or signed webhook push

Instead of writing help articles and news posts by hand, you can ingest them from an external source. One source can feed multiple widgets, and both kinds share the same field mapping and lifecycle.

KindDirectionUse when
RSSWexio polls your feedYou publish a public RSS/Atom feed (blog, changelog, docs).
Webhook pushYour system posts to WexioYou'd rather push on publish than be polled.

Imported items land in News and Help next to the ones you write.

Source Lifecycle

Sources are created disabled, so you can test the mapping before going live.

  1. Create the source (RSS feed URL, or a webhook connection).
  2. Test it. RSS fetches one item; a webhook returns the last captured payload.
  3. Preview the field mapping. Each target column shows its resolved value.
  4. Activate. Validation confirms the required fields (externalId, title, body) resolve, then the source goes live.

Deactivating a source is a kill switch, and the config is kept. Deleting a source does not remove the articles already imported.

RSS

RSS 2.0 and Atom work with the default field map. Set the poll interval in minutes, from 1440 (1 day) to 10080 (7 days). The default is 1440.

Only public https:// feeds are supported. A feed that points at a private, loopback or link-local address is refused, both when you save the source and on every poll. Redirects are not followed.

LimitValue
Feed size5,000,000 bytes
Feed fetch time10 seconds per request, 30 seconds in total
Items per poll1000
Title300 characters
Body100,000 characters

What Wexio Stores From a Feed Item

  • Body. Sanitized and stored as clean HTML.
  • Excerpt. Plain text, with no markup. For an RSS source (News and Help) that uses the default field map, Wexio cuts the excerpt at 500 characters, with no ellipsis. If the source sets a custom excerpt mapping, the excerpt is not cut. Excerpts from a webhook are not cut either. The widget shortens long excerpts for display, so the full text stays in Wexio.
  • Cover image (News only). Taken from the feed item (enclosure, media tags or the first image in the item). If the feed has none, Wexio uses the og:image of the post page. The image is copied to Wexio storage and never linked from the original site.

Only real images are kept: PNG, JPEG, GIF, WebP and AVIF, up to 8,000,000 bytes. If the file is not an image or the copy fails, the post has no cover. Wexio looks up covers for the 20 newest new items per poll. Older items in that poll get no cover.

Edits and Re-Polls

Import is insert-only. Once a post or article is imported, later polls never change it. Anything you edit by hand stays as you left it, and so does a change made at the source.

Wexio RSS Extension

For stable slugs that survive label edits, add the Wexio namespace to your feed:

<rss xmlns:wexio="https://wexio.io/rss-extension">
  <channel>
    <item>
      <wexio:slug>hello-world</wexio:slug>
      <wexio:category slug="product-launches">Product Launches</wexio:category>
      <wexio:tag slug="multi-tenant">Multi-tenant</wexio:tag>
    </item>
  </channel>
</rss>

Webhook Push

Point your outbound webhook at the inbound endpoint and sign the body. The canonical payload is a list of items:

{
  "items": [
    {
      "id": "post-1234",
      "title": "Acme launches multi-tenant billing",
      "body": "<p>HTML or markdown body…</p>",
      "bodyFormat": "html",
      "excerpt": "One-sentence summary shown in the feed card.",
      "slug": "acme-launches-multi-tenant-billing",
      "locale": "en",
      "sourceUrl": "https://blog.acme.io/posts/multi-tenant-billing",
      "publishedAt": "2026-05-01T10:00:00Z",
      "coverImageUrl": "https://cdn.acme.io/billing.png",
      "categories": [{ "slug": "product", "label": "Product" }],
      "tags": [{ "slug": "billing", "label": "Billing" }]
    }
  ]
}

Help items use the same shape but carry a folder (with optional parentSlug) instead of categories/coverImageUrl.

Signing

Send an HMAC-SHA256 of the raw body (before JSON parsing), keyed with the connection's signing secret, in the X-Webhook-Signature header:

const signature = crypto
  .createHmac("sha256", SIGNING_SECRET)
  .update(rawBody)          // bytes, before JSON.parse
  .digest("hex");
// header: X-Webhook-Signature: <signature>
HeaderPurpose
Content-Type: application/jsonRequired.
X-Webhook-SignatureHMAC-SHA256 of the raw body. Mismatch is rejected with 403.
X-Idempotency-KeyRecommended. The result is cached for 24h; a resend with the same key returns a replay without re-ingesting.

Field Mapping

If your payload does not match the canonical shape, map each target column to a path in your data (dot notation).

  • Dedupe. externalId is the dedupe key (with the source). Re-pushing the same externalId is a no-op, so your operators' manual edits survive.
  • Body format. bodyFormat is html or markdown. Help auto-detects when unset; markdown is converted to HTML on ingest.
  • Fields by tab. News-only: coverImageUrl, audienceMode, categories. Help-only: folder, folderAncestors.

Items deleted upstream are not removed from Wexio. Delete them in the dashboard if needed.

Outbound: news.published

When a news post is published (natively or by the scheduler), Wexio emits a news.published outbound webhook, so your own systems can react to it.

Was this page helpful?

  • News - posts, scheduling and taxonomy.
  • Help Center - articles, folders and the AI knowledge base.

On this page