Everything you need to drive Polyblog from your own code: a REST API with scoped keys, endpoints for articles, blogs and topics, and signed webhooks for every change.
AI integrations
Polyblog has one hosted Model Context Protocol server for Claude, ChatGPT and other compatible clients. OAuth signs you in and limits every call to the Polyblog organization your own account can access.
https://mcp.polyblog.io/mcpRead and search blogs and articles, compare configured locales with available translations, inspect validated sitemap links, research topic ideas from bounded Reddit and RSS sources, create or edit drafts, publish only when requested, and generate a text-only SEO draft. Two inline views show a compact blog overview and a bounded article preview.
Every create, update, generation and deletion is marked as a destructive write so your host can request confirmation. Topic refresh and article generation may spend paid model or source-fetching usage. Lists and previews are bounded, and the connector does not expose credentials, sender configuration, contacts or organization identifiers.
The public MCP deliberately does not expose AI cover-image generation or the image-generating autopilot. The generate_article tool always disables inline and cover images. Those media features remain available in the Polyblog dashboard, REST API and CLI, but are outside the connector submitted to software directories.
Remove Polyblog from your host’s connector settings to revoke that host’s access. Your normal Polyblog permissions continue to decide which blogs and articles are visible.
API keys
The Polyblog REST API is what you use to publish from a CMS, a static site generator, a CI pipeline or any backend of your own. Every request is authenticated with an API key you create yourself.
Send the secret as HTTP Basic credentials. All endpoints are relative to https://api.polyblog.io.
Authorization: Basic base64(<your key secret>)A key pinned to a blog can only ever touch that blog, and a key can only ever touch the organization it was created in — the tenant is read from the key, never from the request.
Quick start
List the articles of a blog. Anonymous callers only ever see published articles; with a key of the owning organization you also get drafts.
curl "https://api.polyblog.io/api/articles?blogId=YOUR_BLOG_ID&locale=en" \
-H "Authorization: Basic $(printf %s YOUR_API_KEY_SECRET | base64)"Posting an article publishes it on your blog and fires the article.created webhook.
curl -X POST "https://api.polyblog.io/api/articles" \
-H "Authorization: Basic $(printf %s YOUR_API_KEY_SECRET | base64)" \
-H "Content-Type: application/json" \
-d '{
"blogId": "YOUR_BLOG_ID",
"locale": "en",
"title": "Hello from the API",
"description": "A short summary used in listings and meta tags.",
"content": "<p>Written straight from my own backend.</p>",
"published": true
}'Browse the full API reference — every endpoint with its parameters, request body, responses and required scope.
CLI
The same blogs, articles, topic research and article generation are available from your terminal through the polyblog CLI. Install it globally with npm, or run it ad hoc with npx.
Authentication is one command: polyblog login opens your browser to sign in to your Polyblog account and stores a session for later commands — no API key to paste.
# Install once, globally
npm install -g polyblog
# or run it ad hoc without installing
npx polyblog --help
# Log in — opens your browser to sign in and stores a session
polyblog login
# The blogs of your account, with their ids
polyblog blogs list
# The 10 most recent articles of a blog
polyblog articles list --blogId YOUR_BLOG_ID
# Research article ideas from your configured Reddit and RSS sources
polyblog topics refresh
polyblog topics list
# Generate a full SEO article as a draft
polyblog articles generate --topic "How to localize a SaaS blog"The CLI is open source at github.com/polyblog-io/cli and published as polyblog on npm. Run any command with --help to see its options.
Agent Skills
Polyblog ships Agent Skills — guides following the agentskills.io standard that teach coding agents how to run editorial and localization workflows with the polyblog CLI and the MCP connector, instead of guessing at commands and tools.
# Install the Polyblog skills into your coding agent
npx skills add polyblog-io/skillsOne command installs the skills into Claude Code, Cursor, Codex, Gemini CLI and any other agent that follows the Skills standard. The CLI also bundles the same guides, version-matched to the commands it ships: polyblog skills get <name> prints one on demand.
The skills are open source at github.com/polyblog-io/skills. Claude users can also install the Polyblog Claude plugin, which bundles the connector together with the editorial skill: github.com/polyblog-io/claude-plugin.
Scopes
Each key carries a set of per-resource scopes, so an integration that only needs to read articles cannot delete them. New keys start read-only; widen them explicitly.
A request made with a key that lacks the required scope is refused with 403. Keys are also rate limited, and a request over the limit is refused with 429.
Webhooks
Subscribe an endpoint of yours and Polyblog POSTs each matching event to it as it happens. A subscription can cover the whole organization or a single blog, and can filter the events it wants.
POST https://your-server.com/polyblog-webhook
X-Polyblog-Event: article.created
X-Polyblog-Signature: t=1719000000,v1=<hmac-sha256 hex>
Content-Type: application/json
{
"event": "article.created",
"timestamp": 1719000000,
"data": { "...": "..." }
}Every delivery carries an X-Polyblog-Signature header of the form t=timestamp,v1=signature. The signature is an HMAC-SHA256 of timestamp.body keyed by your subscription secret; recompute it over the raw body and compare before trusting the payload.
import crypto from 'node:crypto'
// body must be the RAW request body, byte for byte
function isSignatureValid({ header, body, secret }) {
const [t, v1] = header.split(',')
const timestamp = t.slice(2)
const signature = v1.slice(3)
const expected = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${body}`)
.digest('hex')
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected),
)
}Delivery is one best-effort attempt with a 5 second timeout and no retries. Failures are counted, and a subscription that fails 20 times in a row is deactivated until you re-enable it.
Subscriptions are managed from your dashboard or through the webhook subscriptions endpoints in the API reference.
Start building