PUBlish · Integrations
Publish once on PUBlish. Show up everywhere.
Three integration paths, all free, none require a PUBlish API key:
- Pull a writer’s feed — every author has a live JSON Feed and RSS at predictable URLs. Any site that consumes feeds can subscribe.
- Drop in a verified badge — official Shopify and WordPress plugins, plus a copy-paste HTML snippet that works on any site.
- Build with an AI agent — the URLs and code snippets on this page are plain HTML so ChatGPT, Claude, or Gemini can read them when you ask “how do I import my PUBlish posts into my [Shopify / WordPress / Webflow] site.”
The snippets below use a placeholder slug (your-slug). Sign in and we’ll fill in your real slug everywhere on this page.
Feeds
Your live URLs
Every PUBlish author has these endpoints. Subscribe an RSS reader, point a Next.js fetch, or hand the JSON URL to your LLM.
https://pub-lish.com/en/author/your-slug/feed.jsonhttps://pub-lish.com/en/author/your-slug/feed.xmlhttps://pub-lish.com/author/your-slugAsk AI
Get walked through it
Open the AI you use, the prompt is pre-written with your URLs. The AI will tell you exactly which setting to open in your platform and what to paste.
I want to import the latest pieces from my PUBlish author profile into my [Shopify / WordPress / Webflow / Squarespace / other] site. Walk me through it step-by-step — I'm not technical.
My PUBlish JSON Feed URL: https://pub-lish.com/en/author/your-slug/feed.json
My PUBlish RSS URL: https://pub-lish.com/en/author/your-slug/feed.xml
My PUBlish profile URL: https://pub-lish.com/author/your-slug
Tell me which platform-specific setting to open, what to click, and exactly what to paste. If the platform supports RSS feeds natively (most blog platforms do), prefer that. If it doesn't, write me the smallest possible code snippet that pulls the JSON Feed and renders the posts.WordPress / WooCommerce
Official plugin + RSS subscribe
Easiest: install the PUBlish Author Badge plugin. For full auto-import, paste the PHP below into a custom plugin or your theme's functions.php.
1. Author badge (recommended)
[publish_badge]Install the “PUBlish Author Badge” plugin from the WordPress plugin directory, then drop the shortcode anywhere.
2. Auto-import latest pieces as WP posts
<!-- Add to functions.php or a custom plugin to import latest PUBlish pieces as WP posts -->
add_action('rest_api_init', function () {
register_rest_route('publish/v1', '/sync', [
'methods' => 'POST',
'callback' => function () {
$response = wp_remote_get('https://pub-lish.com/en/author/your-slug/feed.json');
$body = json_decode(wp_remote_retrieve_body($response), true);
foreach ($body['items'] as $item) {
// Idempotent: skip if a post with this PUBlish source URL already exists.
$existing = get_posts(['meta_key' => 'publish_source', 'meta_value' => $item['url'], 'numberposts' => 1]);
if (!empty($existing)) continue;
$post_id = wp_insert_post([
'post_title' => $item['title'],
'post_content' => $item['content_html'],
'post_excerpt' => $item['summary'],
'post_status' => 'publish',
'post_date' => mysql2date('Y-m-d H:i:s', $item['date_published']),
'meta_input' => ['publish_source' => $item['url']],
]);
}
return ['imported' => count($body['items'])];
},
]);
});POSTing to /wp-json/publish/v1/sync pulls the feed and creates one WP post per piece (idempotent — duplicates are skipped). Wire it to a cron job or a Make / Zapier hourly trigger.
Shopify
Theme snippet + badge
Drop the Liquid below into any section to show your latest PUBlish piece on a storefront page. Or install the PUBlish Author Badge from the Shopify App Store for a one-tap setup.
<!-- Add to a theme section to render the latest PUBlish piece on any storefront page -->
<div id="latest-publish-piece" style="padding:24px;background:#FAF7F0;border-radius:8px;">
<p style="font-family:Georgia,serif;font-style:italic;color:#888;margin:0;">Loading latest piece…</p>
</div>
<script>
fetch('https://pub-lish.com/en/author/your-slug/feed.json')
.then(r => r.json())
.then(j => {
var item = j.items[0];
if (!item) return;
document.getElementById('latest-publish-piece').innerHTML =
'<a href="' + item.url + '" target="_blank" rel="noopener" style="text-decoration:none;color:inherit;display:block;">' +
'<p style="font-family:Inter,sans-serif;font-size:11px;font-weight:700;letter-spacing:0.14em;text-transform:uppercase;color:#B8923E;margin:0 0 6px;">Latest on PUBlish</p>' +
'<h3 style="font-family:Georgia,serif;font-weight:600;margin:0 0 8px;font-size:22px;">' + item.title + '</h3>' +
'<p style="font-family:Georgia,serif;font-style:italic;color:#4a4640;margin:0;">' + (item.summary || '') + '</p>' +
'</a>';
});
</script>Add via Shopify admin → Online Store → Themes → Customize → Add Section → Custom Liquid → paste.
Next.js
App Router page that renders the feed
Drop into your site's blog route. Caches for 10 minutes; revalidates on demand. Works with any deployment provider (Vercel, Netlify, self-hosted).
// app/blog/page.tsx — Next.js App Router
export const revalidate = 600; // refresh hourly
export default async function BlogPage() {
const res = await fetch('https://pub-lish.com/en/author/your-slug/feed.json', { next: { revalidate: 600 } });
const feed = await res.json();
return (
<div>
<h1>{feed.title}</h1>
<ul>
{feed.items.map((item: any) => (
<li key={item.id}>
<a href={item.url}>{item.title}</a>
<p>{item.summary}</p>
</li>
))}
</ul>
</div>
);
}Webflow / Squarespace / Wix
Embed element snippet
Most no-code builders support a raw-HTML embed element. Paste the snippet below; it fetches the JSON Feed at runtime and renders the latest 5 pieces.
<!-- Add to a Webflow Embed element. Pulls and renders the latest 5 pieces. -->
<div id="publish-feed" style="display:flex;flex-direction:column;gap:24px;"></div>
<script>
fetch('https://pub-lish.com/en/author/your-slug/feed.json')
.then(r => r.json())
.then(j => {
document.getElementById('publish-feed').innerHTML = j.items.slice(0, 5).map(item =>
'<article><h3><a href="' + item.url + '" target="_blank" rel="noopener">' + item.title + '</a></h3>' +
'<p>' + (item.summary || '') + '</p>' +
'<small>' + new Date(item.date_published).toLocaleDateString() + '</small></article>'
).join('');
});
</script>Realtime push
Publish webhook — auto-syndicate the moment you ship
Set a webhook URL on /desk/edit/online-presence, then every piece you publish on PUBlish POSTs the JSON Feed item to that URL within 5 minutes. Same shape as the JSON Feed; signed with X-Publish-Signature so your receiver can verify it's really PUBlish.
What you receive
POST https://your-site.com/api/publish-webhook
Content-Type: application/json
X-Publish-Event: piece.published
X-Publish-Signature: sha256=<hmac-sha256(secret, raw_body)>
{
"id": "https://pub-lish.com/en/read/<piece-id>",
"url": "https://pub-lish.com/en/read/<piece-id>",
"title": "Your piece headline",
"summary": "Standfirst / first 240 chars of body",
"content_text": "Full markdown body",
"date_published": "2026-06-29T18:00:00.000Z",
"date_modified": "2026-06-29T18:00:00.000Z",
"tags": ["building", "ai"],
"authors": [{ "name": "Jane Novak", "url": "https://pub-lish.com/author/jane-novak", "avatar": "..." }],
"piece": {
"piece_id": "abc-123",
"author_slug": "jane-novak",
"author_avatar_url": "...",
"category": "building",
"kind": "piece"
}
}Verifying the signature (Node.js example)
// In your /api/publish-webhook handler:
import crypto from 'crypto';
const rawBody = await req.text();
const signature = req.headers.get('x-publish-signature');
const expected = 'sha256=' + crypto
.createHmac('sha256', process.env.PUBLISH_WEBHOOK_SECRET)
.update(rawBody)
.digest('hex');
if (signature !== expected) {
return new Response('Bad signature', { status: 401 });
}
const payload = JSON.parse(rawBody);
// payload.piece.piece_id is unique — use it for dedup.
// payload.title, content_text, tags, etc. map to your CMS.Your secret is auto-generated the first time you save a webhook URL on Online presence. Copy it from there into your receiver’s environment variables. We attempt the POST exactly once per piece and log the response code on the submission row.
MCP
Native tools for Claude Desktop, Cursor, MCP agents
PUBlish exposes a Model Context Protocol server with four tools — search_authors, get_author, recent_pieces, get_piece. Add the endpoint to any MCP-capable client and the AI can call PUBlish directly instead of HTTP-fetching JSON.
Claude Desktop config (claude_desktop_config.json)
{
"mcpServers": {
"publish": {
"type": "http",
"url": "https://pub-lish.com/api/mcp"
}
}
}Cursor / other MCP clients
# Add to your client's MCP settings:
https://pub-lish.com/api/mcpAuto-discoverable at https://pub-lish.com/.well-known/mcp.json — clients that scan domains for MCP endpoints find this listed first before any per-company server.
Public API · pieces
Single piece + cross-author recent feed
Read pieces from PUBlish via clean JSON endpoints. Single piece by id; cross-author recent feed filterable by category. Same envelope as the per-author feed.
Get a single piece
GET https://pub-lish.com/api/public/pieces/<piece-id>
Response:
{
"ok": true,
"piece": {
"id": "https://pub-lish.com/en/read/<piece-id>",
"url": "https://pub-lish.com/en/read/<piece-id>",
"title": "...",
"summary": "...",
"content_html": "...",
"content_text": "...",
"date_published": "...",
"date_modified": "...",
"tags": ["building", "ai"],
"category": "building",
"kind": "piece",
"authors": [{
"name": "...",
"slug": "jane-novak",
"url": "...",
"avatar": "...",
"identity_verified": true
}],
"piece": {
"piece_id": "...",
"author_slug": "jane-novak",
"category": "building",
"kind": "piece"
}
}
}Search pieces by content (full-text)
GET https://pub-lish.com/api/public/pieces/search?q=hiring+engineers&limit=20
Optional category filter: &category=building (or leading / culture / money / life)
Limit: 1..100 (default 20)
Response:
{
"ok": true,
"query": "hiring engineers",
"category": null,
"count": 8,
"results": [
{
"id": "https://pub-lish.com/en/read/<piece-id>",
"url": "https://pub-lish.com/en/read/<piece-id>",
"title": "...",
"summary": "...",
"snippet": "…contextual snippet around the match in the body…",
"date_published": "...",
"category": "building",
"match_site": "headline | standfirst | body",
"tags": ["building", "hiring"],
"authors": [{ "name": "...", "slug": "...", "identity_verified": true }]
},
...
]
}Hits rank by match site (headline > standfirst > body), then by recency. snippet is only populated when the match was in the body (not the headline / standfirst — those already speak for themselves). Cached 5 min server-side.
Cross-author recent feed
GET https://pub-lish.com/api/public/pieces/recent?category=building&limit=20
Valid categories: building, leading, culture, money, life
Limit: 1..100 (default 20)
Omit category to get recent across every category.
Response:
{
"ok": true,
"category": "building",
"count": 20,
"items": [
{
"id": "https://pub-lish.com/en/read/<piece-id>",
"url": "https://pub-lish.com/en/read/<piece-id>",
"title": "...",
"summary": "...",
"date_published": "...",
"category": "building",
"tags": ["building", "ai"],
"authors": [{ "name": "...", "slug": "...", "url": "...", "identity_verified": true }]
},
...
]
}Returns up to 100 pieces per call. Cached 10 min server-side; CORS-open. Pieces with editor_status ≠ approved (drafts, pending) never appear here.
Public API · authors
Author + search JSON endpoints
Auth-free, CORS-open JSON endpoints. Same data as the public profile page; structured for LLM ingestion and third-party integrations. No API key required.
Get a single author
GET https://pub-lish.com/api/public/authors/your-slug
Response:
{
"ok": true,
"author": {
"slug": "your-slug",
"name": "...",
"bio": "...",
"role": "...",
"niche": "...",
"avatar_url": "...",
"identity_verified": true,
"website_verified": true,
"socials": { "x": "...", "linkedin": "...", "newsletter": "...", ... },
"stats": { "pieces_count": 42, "last_published_at": "2026-06-29T..." },
"urls": {
"profile": "https://pub-lish.com/author/your-slug",
"badge_svg": "https://pub-lish.com/embed/your-slug/badge.svg",
"feed_json": "https://pub-lish.com/en/author/your-slug/feed.json",
"feed_rss": "https://pub-lish.com/en/author/your-slug/feed.xml"
}
}
}Search authors by topic, name, niche, or bio
GET https://pub-lish.com/api/public/authors/search?q=ai+policy&limit=10
Response:
{
"ok": true,
"query": "ai policy",
"count": 5,
"results": [
{
"slug": "jane-novak",
"name": "Jane Novak",
"role": "Founder",
"niche": "ai policy · regulation",
"bio_snippet": "Reporting on...",
"avatar_url": "...",
"identity_verified": true,
"pieces_count": 14,
"urls": { "profile": "...", "badge_svg": "...", "feed_json": "..." }
},
...
]
}Verified writers rank first; ties broken by piece count. Substring match across display_name, niche, role, and bio. Cached 5 min server-side; CORS-open for any browser host.
One-paste embed
Universal <script> widgets
One <script> tag, four widgets. No platform-specific code, no API keys. Works on any site that accepts a script tag in HTML — including pages built by an LLM. Idempotent re-scans on SPA navigation.
Latest piece card
<div data-publish-widget="card" data-slug="your-slug"></div>
<script src="https://pub-lish.com/embed.js" defer></script>Recent pieces list
<div data-publish-widget="list" data-slug="your-slug" data-limit="5"></div>
<script src="https://pub-lish.com/embed.js" defer></script>Author bio block
<div data-publish-widget="bio" data-slug="your-slug"></div>
<script src="https://pub-lish.com/embed.js" defer></script>Optional attributes: data-theme="dark" for dark backgrounds, data-locale="en" (default en), data-verified="false" on the badge widget to hide the verified tick.
Spec
OpenAPI 3.1 spec
Every public endpoint formally described in OpenAPI 3.1. Drop into Postman, Insomnia, openapi-typescript, swagger-codegen, Stoplight, Redocly — anywhere an OpenAPI-aware tool runs.
https://pub-lish.com/api/openapi.jsonUse cases: auto-generate a typed PUBlish client in Go / Python / Java / Rust / TypeScript in five minutes; render live docs at your own domain via Redocly / Stoplight / Mintlify; import into Postman for an exploratory test collection; feed it to an MCP client that converts OpenAPI to tool calls.
Write API
POST a draft from your CMS or AI agent
The missing half of the syndication story. Mint a Bearer key on /desk/edit/online-presence → API keys, then POST a piece into PUBlish from anywhere. Every API-created piece lands as a DRAFT — the writer reviews and publishes manually. No automation can put live content under a writer's byline.
cURL
curl -X POST https://pub-lish.com/api/v1/pieces \
-H "Authorization: Bearer pk_live_…" \
-H "Content-Type: application/json" \
-d '{
"headline": "The quiet trade-off behind pricing power",
"sub": "Why margin outlasts growth.",
"body_md": "# The quiet trade-off\n\nWhen you raise prices…",
"category": "money",
"tags": ["pricing", "unit economics"],
"external_url": "https://your-site.com/posts/pricing-power"
}'Node
const res = await fetch('https://pub-lish.com/api/v1/pieces', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PUBLISH_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
headline: 'The quiet trade-off behind pricing power',
body_md: '# The quiet trade-off…',
category: 'money',
tags: ['pricing', 'unit economics'],
}),
});
const { id, edit_url } = await res.json();
console.log('Draft landed:', edit_url);Confirm the draft landed
curl https://pub-lish.com/api/v1/pieces/me?status=draft \
-H "Authorization: Bearer pk_live_…"Required fields: headline + body_md. Optional: sub, category, tags, frame, locale, external_url. Limits: headline ≤ 200 chars, sub ≤ 400, body ≤ 100 000, tags ≤ 8 (each ≤ 32 chars). Keys are scoped to pieces:write only — they cannot publish, edit existing pieces, or read other writers’ content.
Schema
JSON Feed 1.1 format
PUBlish follows the standard JSON Feed 1.1 spec. Every item carries id, url, title, summary, content_html, content_text, date_published, date_modified, tags, and authors. Documented at jsonfeed.org/version/1.1.
Tools that consume JSON Feed natively: Feedly, Readwise Reader, Inoreader, NetNewsWire, Reeder. RSS readers consume the /feed.xml endpoint without configuration.