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.
| Kind | Direction | Use when |
|---|---|---|
| RSS | Wexio polls your feed | You publish a public RSS/Atom feed (blog, changelog, docs). |
| Webhook push | Your system posts to Wexio | You'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.
- Create the source (RSS feed URL, or a webhook connection).
- Test it. RSS fetches one item; a webhook returns the last captured payload.
- Preview the field mapping. Each target column shows its resolved value.
- 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.
| Limit | Value |
|---|---|
| Feed size | 5,000,000 bytes |
| Feed fetch time | 10 seconds per request, 30 seconds in total |
| Items per poll | 1000 |
| Title | 300 characters |
| Body | 100,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
500characters, 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:imageof 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>| Header | Purpose |
|---|---|
Content-Type: application/json | Required. |
X-Webhook-Signature | HMAC-SHA256 of the raw body. Mismatch is rejected with 403. |
X-Idempotency-Key | Recommended. 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.
externalIdis the dedupe key (with the source). Re-pushing the sameexternalIdis a no-op, so your operators' manual edits survive. - Body format.
bodyFormatishtmlormarkdown. 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.
Related
- News - posts, scheduling and taxonomy.
- Help Center - articles, folders and the AI knowledge base.