Quickstart
You need your site ID and anything that can make an HTTP request.
-
Read the manifest. It names the current build. There is no key and no header to set.
Terminal window curl https://feeds.citedseo.ai/YOUR_SITE_ID/feed/index.jsonconst feed = 'https://feeds.citedseo.ai/YOUR_SITE_ID';const manifest = await fetch(`${feed}/feed/index.json`).then((res) => res.json());import requestsfeed = "https://feeds.citedseo.ai/YOUR_SITE_ID"manifest = requests.get(f"{feed}/feed/index.json", timeout=10).json()200 OK {"buildId": "01JA2M7Q4K8ZP3","total": 42,"pageCount": 3,"pageSize": 20,"latestModifiedAt": "2026-10-11T02:05:00.000Z","generatedAt": "2026-10-11T02:05:04.000Z"} -
Read the pages of articles from that build. They are numbered from 1 to the manifest’s
pageCount, which is 0 when nothing is live, and hold 20 articles each, newest first.Terminal window curl https://feeds.citedseo.ai/YOUR_SITE_ID/b/BUILD_ID/page-1.jsonconst articles = [];for (let n = 1; n <= manifest.pageCount; n++) {const page = await fetch(`${feed}/b/${manifest.buildId}/page-${n}.json`).then((res) => res.json());articles.push(...page.articles);}articles = []for n in range(1, manifest["pageCount"] + 1):page = requests.get(f"{feed}/b/{manifest['buildId']}/page-{n}.json", timeout=10).json()articles.extend(page["articles"])200 OK {"articles": [{"id": "0b6f6c1e-3f0a-4a59-9d0e-2f8f4c1f7a31","slug": "how-to-brew-green-tea","url": "https://example.com/blog/how-to-brew-green-tea","title": "How to brew green tea","description": "Brew green tea at 80°C for two minutes. Here is why the temp…","cover": {"src": "https://example.com/images/green-tea.webp","alt": "A glass teapot of green tea"},"author": {"name": "Sam Lee","url": "https://example.com/authors/sam-lee"},"publishedAt": "2026-10-09T02:05:00.000Z","modifiedAt": "2026-10-11T02:05:00.000Z","html": "<p class=\"citedseo-answer\"><strong>Brew green tea at 80°C for two minutes. Hot…","markdown": "**Brew green tea at 80°C for two minutes. Hotter water makes…","structuredData": {"@context": "https://schema.org","@graph": ["…"]}}]} -
List your articles. Each has a
slug, the last part of its address, to route by.for (const article of articles) {console.log(`/blog/${article.slug}`, article.title);} -
Show one. Read it by its slug, used as it is: an article’s
slugis already URL-encoded. The body comes as HTML and as Markdown, without the title or cover, so you place those yourself.const article = articles[0];if (!article) throw new Error('Nothing is live yet');const res = await fetch(`${feed}/b/${manifest.buildId}/by-slug/${article.slug}.json`);if (res.status === 404) throw new Error('No such article');if (!res.ok) throw new Error(`The feed answered ${res.status}`);const { article: whole } = await res.json();document.querySelector('h1').textContent = whole.title;document.querySelector('article').innerHTML = whole.html;
Your frameworkA blog index and article page in Next.js, Astro, React Router, Nuxt or SvelteKit.
The articleEvery field, with a full example.
Update the moment you publishUse a webhook instead of waiting for the next read.