API Reference

Here is all the info you need to pull data from NeuraFeed. We kept it super simple.

Test It Without Coding

You do not even need to write any code to test our API! Just click this link to open it in your browser and see the raw data output for yourself: https://feed.neuraspheres.com/api/latest-news.

Available Endpoints

GET /api/latest-news

Try it

This endpoint gives you the absolute newest article our system generated. You do not need any API keys or login to use this. Just make a request and get your data.

GET https://feed.neuraspheres.com/api/latest-news

What you get back (200 OK)

{
  "success": true,
  "article": {
    "id": "firestoreDocumentId",
    "title": "Article headline",
    "summary": "2 to 3 sentence executive summary.",
    "article": "<h2>Subtopic</h2><p>Content with inline citation.<sup>[1]</sup></p>...",
    "whyItMatters": "2 to 3 sentences explaining significance.",
    "tags": ["AI", "OpenAI", "GPT-4"],
    "sources": [
      "[1] TechCrunch: https://techcrunch.com/...",
      "[2] The Verge: https://www.theverge.com/..."
    ],
    "sourceDetails": [
      { "id": "source-1", "number": 1, "title": "TechCrunch", "url": "https://techcrunch.com/...", "domain": "techcrunch.com" }
    ],
    "citations": [
      { "id": "citation-1", "text": "A supported sentence.", "marker": "[1]", "sourceIds": ["source-1"], "sourceNumbers": [1] }
    ],
    "topic": "Detected trending topic name",
    "category": "technology",
    "coverImage": "https://cdn.vox-cdn.com/uploads/chorus_image/image/12345/hero.jpg",
    "imageSource": "theverge.com",
    "imageSourceUrl": "https://www.theverge.com/2026/4/26/article-slug",
    "embedMedia": {
      "type": "youtube",
      "id": "dQw4w9WgXcQ",
      "title": "Video title from YouTube",
      "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
    },
    "media": [
      { "id": "media-abc", "type": "image", "url": "https://cdn.example.com/image.jpg", "caption": "Related reporting image", "sourceName": "theverge.com", "sourceUrl": "https://www.theverge.com/...", "afterSection": 1 }
    ],
    "contentVersion": 2,
    "createdAt": "2026-04-26T03:00:00.000Z"
  }
}

GET /api/recent-news

Try it

If you want to build a feed or show more than one article, use this endpoint. It returns an array of the latest articles. Like the other one, it is completely open and needs no authentication.

You can add a limit parameter to the URL to choose how many articles you want. If you do not pass one, you get the 20 most recent. You can ask for up to 100 at a time.

GET https://feed.neuraspheres.com/api/recent-news
GET https://feed.neuraspheres.com/api/recent-news?limit=5
GET https://feed.neuraspheres.com/api/recent-news?limit=50

What you get back (200 OK)

{
  "success": true,
  "articles": [
    {
      "id": "firestoreDocumentId1",
      "title": "Most recent article",
      "summary": "...",
      "article": "...",
      "whyItMatters": "...",
      "tags": ["..."],
      "sources": ["..."],
      "sourceDetails": [{ "id": "source-1", "number": 1, "title": "...", "url": "...", "domain": "..." }],
      "citations": [{ "id": "citation-1", "text": "...", "marker": "[1]", "sourceIds": ["source-1"], "sourceNumbers": [1] }],
      "topic": "...",
      "category": "politics",
      "coverImage": "https://cdn.vox-cdn.com/uploads/chorus_image/image/12345/hero.jpg",
      "imageSource": "theverge.com",
      "imageSourceUrl": "https://www.theverge.com/2026/4/26/article-slug",
      "embedMedia": {
        "type": "youtube",
        "id": "dQw4w9WgXcQ",
        "title": "Video title from YouTube",
        "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
      },
      "media": [{ "id": "media-abc", "type": "image", "url": "...", "caption": "...", "sourceName": "...", "sourceUrl": "...", "afterSection": 1 }],
      "contentVersion": 2,
      "createdAt": "2026-04-26T03:00:00.000Z"
    },
    {
      "id": "firestoreDocumentId2",
      "title": "Older article with no media",
      "summary": "...",
      "article": "...",
      "whyItMatters": "...",
      "tags": ["..."],
      "sources": ["..."],
      "sourceDetails": [],
      "citations": [],
      "topic": "...",
      "category": "technology",
      "coverImage": null,
      "imageSource": null,
      "imageSourceUrl": null,
      "embedMedia": null,
      "media": [],
      "contentVersion": 1,
      "createdAt": "2026-04-25T03:00:00.000Z"
    }
  ]
}

GET /api/articles

Try it

Use this one when you want to page through the whole archive rather than just the newest handful. It uses a cursor instead of an offset, so pages stay stable even when a new article publishes midway through your crawl.

Pass limit (default 12, max 50) and after, which is the id of the last article from the previous page. Leave after off for the first page.

GET https://feed.neuraspheres.com/api/articles
GET https://feed.neuraspheres.com/api/articles?limit=12
GET https://feed.neuraspheres.com/api/articles?limit=12&after=lastArticleIdFromPreviousPage

What you get back (200 OK)

{
  "success": true,
  "articles": [ /* same article objects as the other endpoints */ ],
  "nextCursor": "qK27BIMwsBJ0abc",
  "hasMore": true
}

Keep requesting while hasMore is true, passing the previous nextCursor as after.

// Walk the whole archive, one page at a time.
async function* allArticles(limit = 50) {
  let after = null;

  while (true) {
    const url = new URL('https://feed.neuraspheres.com/api/articles');
    url.searchParams.set('limit', limit);
    if (after) url.searchParams.set('after', after);

    const { articles, nextCursor, hasMore } = await fetch(url).then((r) => r.json());
    yield* articles;

    // Stop on hasMore, not on an empty page: nextCursor is the id of the last
    // article you already received, so reusing it forever would loop.
    if (!hasMore || !nextCursor) return;
    after = nextCursor;
  }
}

Calling From a Browser

These endpoints do not send an Access-Control-Allow-Origin header, so a fetch() straight from browser JavaScript on your own domain will be blocked by CORS. This is deliberate rather than an oversight.

Call the API from your server instead: a Next.js server component, an API route, a serverless function, or any backend. If you genuinely need the data client-side, proxy it through a one-line route on your own origin and fetch that. There is an example in the Implementation Guide.

Categories

Every article belongs to one category, exposed as the category field. NeuraFeed leads with technology but is not limited to it: about half of all articles are technology and the remainder are spread across the other four.

ValueCovers
technologyAI, software, hardware, platforms, and the companies building them
politicsGovernment, legislation, elections, regulation, and public policy
economicsMarkets, monetary policy, trade, labour, and corporate finance
societyPublic health, education, inequality, civil rights, and community impact
worldInternational affairs, conflict, climate, energy, and global science

There is no category filter on the endpoints yet, so filter client-side on the field.

Articles published before categories existed omit the key entirely rather than defaulting it, so article.category is undefined on older records. Read it defensively, for example article.category ?? "technology", since everything published before the feature was technology coverage.

Understanding the Data Fields

Every article object comes with a few standard fields. Here is a breakdown of what they are and how to use them.

FieldTypeDescription
idstringThe unique database ID for the article. Good for React keys.
titlestringThe main headline. It is just plain text.
summarystringA quick text summary of the whole article.
articleHTML stringThis is the actual written content. It already has HTML tags like headings and paragraphs, so you have to render it as raw HTML.
whyItMattersstringA short text block that explains why this news is actually important.
tagsarrayA list of string tags so you can categorize the news.
sourcesarrayThe links we used to write the article. They come in a specific text format like [1] Name: URL.
sourceDetailsarrayMachine-friendly sources with stable id, number, title, url, and domain fields.
citationsarrayStructured cited passages. Each record links its text and marker to one or more sourceIds, matching the inline data-citation-id marker.
topicstringThe specific story the AI researched, e.g. "Nvidia Q3 Earnings". This is the individual event, not the section.
categorystringThe section the article belongs to: technology, politics, economics, society, or world. Use this to group or filter; use topic for the headline subject. Absent on articles published before categories existed — treat a missing value as technology.
coverImagestring | nullURL of the article cover image. Sourced from the og:image of one of the grounding pages. Can be a direct CDN link or a Cloudinary URL. Null if no image could be found.
imageSourcestring | nullThe hostname of the page the cover image came from, e.g. theverge.com. Use this for attribution. Null when coverImage is null.
imageSourceUrlstring | nullThe full URL of the source article the image was taken from. Link this when showing the image to give proper credit. Null when coverImage is null.
embedMediaobject | nullA related YouTube video when one is found. Contains type (youtube), id (the video ID), title, and url. Null when no video was found.
mediaarrayZero to three attributed inline assets. Types can be image, youtube, audio, or video. Use afterSection for placement and always show sourceName/sourceUrl.
contentVersionnumberSchema version. Version 2 adds structured citations and rich media while keeping legacy fields. Older articles report 1 and have empty sourceDetails, citations, and media.
generationMetaobject | nullInternal build info about the run (model used, token counts, settings snapshot). Exposed for transparency but not part of the stable contract — do not build on its shape. It also adds roughly 1.5 KB to every article, so strip it if you are caching large pages.
createdAtstringA standard timestamp showing exactly when we published the article.

Just a Heads Up

  • Most of the fields like title, summary, and whyItMatters are plain text. You can drop them right into your UI.
  • The article field is full of HTML. Make sure you render it correctly or your users will just see a bunch of raw code tags.
  • coverImage, imageSource, and imageSourceUrl can all be null. Not every article has an image, so always check before rendering.
  • When you show a cover image, link it back to imageSourceUrl and label it with imageSource so the original publisher gets proper credit.
  • media is the preferred rich-media field. It can be an empty array. embedMedia remains for backward compatibility with older consumers.
  • For custom footnotes, use citations plus sourceDetails. You can keep the inline markers, turn them into popovers, or rebuild the source list without parsing source strings.
  • Expect far fewer inline markers than sources. An article typically carries 5 to 7 <sup> markers but 10 to 20 entries in sourceDetails. That is intentional: attribution mostly lives in the prose ("according to Reuters") and markers are reserved for load-bearing claims. Do not assume every source has a matching marker, and do not hide a source just because it is not cited inline.
  • Browser JavaScript cannot call these endpoints cross-origin. Fetch from your server and pass the data to the client.
  • New articles publish twice a day, around 00:17 and 12:17 UTC, give or take scheduling delay. Cache accordingly — polling more often than hourly gains you nothing.
  • We do not rate-limit these endpoints, but please cache the responses on your end. The news does not update every single second.