API
Fetch your articles via a simple API and publish them to any platform, headless CMS, or custom workflow.
Get your API key
- 1In Zivooo, go to Settings → Integrations and click Connect on API.
- 2Click Generate key and copy it — it's shown only once.
- 3Store it securely (an environment variable, never in code).
Authentication
All requests authenticate with the X-API-Key header and send Content-Type: application/json.
X-API-Key: <your-api-key>
Content-Type: application/jsonBase URL
https://zivooo.com/api/integrations/v1List articles
Fetch a paginated list of your articles. The list returns summaries — use Fetch one article for the full content_html.
curl -H "X-API-Key: <your-key>" \
"https://zivooo.com/api/integrations/v1/articles?limit=50&offset=0"Example response:
{
"articles": [
{
"id": "651f3c2a9b1e4a0012ab34cd",
"title": "How to Do X",
"slug": "how-to-do-x",
"metaDescription": "A practical guide to doing X.",
"heroImageUrl": "https://cdn.example.com/hero.jpg",
"languageCode": "en",
"publicUrl": "https://yoursite.com/blog/how-to-do-x",
"seedKeyword": "how to do x",
"articleType": "how_to",
"wordCount": 1820,
"created": "2026-05-18T09:12:00.000Z",
"updated": "2026-05-20T11:30:00.000Z"
}
],
"limit": 50,
"offset": 0
}Fetch one article
Retrieve a single article by its id (from the list endpoint), including full content and schema.
curl -H "X-API-Key: <your-key>" \
"https://zivooo.com/api/integrations/v1/articles/651f3c2a9b1e4a0012ab34cd"Example response:
{
"id": "651f3c2a9b1e4a0012ab34cd",
"title": "How to Do X",
"slug": "how-to-do-x",
"content_html": "<h1>How to Do X</h1><p>...</p>",
"metaDescription": "A practical guide to doing X.",
"heroImageUrl": "https://cdn.example.com/hero.jpg",
"images": [
{ "url": "https://cdn.example.com/hero.jpg", "alt": "Hero image" },
{ "url": "https://cdn.example.com/step-1.jpg", "alt": "Step 1" }
],
"languageCode": "en",
"jsonLd": { "@context": "https://schema.org", "@type": "Article" },
"faqJsonLd": { "@context": "https://schema.org", "@type": "FAQPage" },
"schemaJsonLd": [ /* full array */ ],
"seedKeyword": "how to do x",
"articleType": "how_to",
"score": 92,
"wordCount": 1820,
"publicUrl": "https://yoursite.com/blog/how-to-do-x",
"created": "2026-05-18T09:12:00.000Z",
"updated": "2026-05-20T11:30:00.000Z"
}content_html includes embedded JSON-LD <script> tags. You also get jsonLd and faqJsonLd as structured objects for easier mapping. images lists every asset (hero + in-content) so you can re-host them — the URLs in content_html point at our CDN and may change.
Report the published URL
After you publish an article on your own site, send its live URL back with a PATCH. This records the canonical publicUrl (returned by future reads) and makes the article eligible for the Zivooo backlink exchange — other sites in your niche can then link to it. Until you report a URL, the article can't receive backlinks.
curl -X PATCH \
-H "X-API-Key: <your-key>" \
-H "Content-Type: application/json" \
-d '{"url": "https://yoursite.com/blog/how-to-do-x"}' \
"https://zivooo.com/api/integrations/v1/articles/651f3c2a9b1e4a0012ab34cd"Example response:
{
"id": "651f3c2a9b1e4a0012ab34cd",
"publicUrl": "https://yoursite.com/blog/how-to-do-x"
}| Field | Description |
|---|---|
url | Required. The live http(s) URL where you published the article. |
externalId | Optional. Your CMS's post id, stored for your reference. |
Pagination & filtering
| Parameter | Description |
|---|---|
limit | Number of articles to return (default 100, max 500). |
offset | Number of articles to skip, for pagination (default 0). |
updatedAfter | ISO 8601 date. Returns only articles created or changed since then, oldest-change first — for incremental syncing. |
# First 5 articles (newest first)
.../articles?limit=5&offset=0
# Next 20 articles (skip 20)
.../articles?limit=20&offset=20Without updatedAfter, articles are sorted newest-published first. If a response returns fewer than limit, you've reached the end.
Incremental sync
To keep an external CMS in sync, store the highest updated timestamp you've seen and pass it as updatedAfter on the next run. This returns new and refreshed articles, ordered oldest-change first, so you can advance your watermark safely.
# Only what changed since your last sync
.../articles?updatedAfter=2026-05-18T09:12:00.000ZNode.js: fetch all articles
async function fetchAllArticles() {
const all = [];
let offset = 0;
const limit = 100;
while (true) {
const res = await fetch(
`https://zivooo.com/api/integrations/v1/articles?limit=${limit}&offset=${offset}`,
{ headers: { "X-API-Key": process.env.ZIVOOO_API_KEY } }
);
if (!res.ok) throw new Error(`API error: ${res.status}`);
const { articles } = await res.json();
if (articles.length === 0) break;
all.push(...articles);
if (articles.length < limit) break;
offset += limit;
}
return all;
}Node.js: send to your CMS
async function syncToCms(id) {
const res = await fetch(
`https://zivooo.com/api/integrations/v1/articles/${id}`,
{ headers: { "X-API-Key": process.env.ZIVOOO_API_KEY } }
);
const article = await res.json();
const created = await fetch("https://your-cms.example.com/posts", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
title: article.title,
slug: article.slug,
content: article.content_html,
description: article.metaDescription,
language: article.languageCode,
}),
}).then((r) => r.json());
// Report the live URL back so the article can earn backlinks.
await fetch(
`https://zivooo.com/api/integrations/v1/articles/${id}`,
{
method: "PATCH",
headers: {
"X-API-Key": process.env.ZIVOOO_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ url: created.url }),
}
);
}Recommended: pair with the Webhook
The API works alongside any publish destination — having an API key doesn't change where Zivooo publishes. For auto-posting to a custom or headless CMS, combine it with the Webhook:
- 1Connect the Webhook so Zivooo notifies your endpoint the moment an article is published.
- 2On receipt, call
GET /articles/:idto pull the full content and schema. - 3Create or update the post in your CMS.
- 4
PATCH /articles/:idwith the liveurlso the article can earn backlinks. - 5Use
updatedAfterperiodically to backfill anything missed while your endpoint was down.
This avoids constant polling: the Webhook tells you *when*, the API gives you the *full article*.
Best practices
- Keep your API key secret; rotate it immediately if exposed.
- Use
content_htmlfor HTML-based CMS platforms — it's ready to render. - Re-host assets from the
imagesarray; don't hot-link our CDN URLs long-term. - Use
jsonLd/faqJsonLdif your CMS supports structured data; otherwise the schema is already embedded incontent_html. - Sync incrementally with
updatedAfterand add exponential backoff to be safe. - Note: rich-text CMS (Contentful, Sanity) need an HTML→their-format conversion step.
Troubleshooting
Getting 401 Unauthorized?
Check your API key and confirm the header is exactly X-API-Key. Regenerate the key if you're unsure it's current.
Getting 404 on an article?
The id may not belong to your account, or the article isn't published yet. List your articles first to confirm valid ids.
What content format do I get?
HTML via content_html, with JSON-LD embedded and also provided as structured jsonLd / faqJsonLd fields. (Markdown is not currently provided.)
Can I use this with any CMS?
Yes — any platform that accepts programmatic content creation. Map the fields you need from the article response.
How do I get notified of new articles?
Use the Webhook integration for push notifications instead of polling this API.