BIO.RE
Content

Blog Atom Feed

Atom XML feed of the last 20 published blog posts. Same data as the RSS feed in Atom format. Content-Type application/atom+xml. CDN 15min/30min SWR.

GET /api/v1/public/blog/feed.atom โ€” ๐ŸŒ Public ยท Rate limit: 30 req / minute

Returns the last 20 published blog posts as an Atom XML feed โ€” same data as GET /public/blog/feed (RSS 2.0) in Atom format. Use this for clients that prefer Atom (more strict spec, ISO 8601 timestamps).

Same data, different format. RSS and Atom present the same 20 posts โ€” pick whichever your reader prefers. Most modern feed readers handle both. Atom is generally preferred for new clients (cleaner spec, ISO 8601 timestamps), RSS for compatibility with older readers.

Different response shape from the rest of the portal. Returns raw XML with Content-Type: application/atom+xml; charset=utf-8 โ€” NOT the standard JSON envelope. Same caveat as the RSS feed.

Request

No body, no params, no headers required.

Response headers

HeaderValue
Content-Typeapplication/atom+xml; charset=utf-8
Cache-Controlpublic, s-maxage=900, stale-while-revalidate=1800

Response

200 OK โ€” Atom XML

<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>BIO.RE Blog</title>
  <link href="https://bio.re/blog" rel="alternate"/>
  <link href="https://bio.re/api/v1/public/blog/feed.atom" rel="self"/>
  <id>https://bio.re/blog</id>
  <updated>2026-04-29T20:00:00.000Z</updated>
  <entry>
    <title>Introducing BIO.RE</title>
    <link href="https://bio.re/blog/introducing-biore"/>
    <id>https://bio.re/blog/introducing-biore</id>
    <updated>2026-04-29T20:00:00.000Z</updated>
    <summary><![CDATA[A short excerpt of the post...]]></summary>
  </entry>
</feed>

XML elements

ElementSourceNotes
feed.titlehardcodedBIO.RE Blog
feed.link[rel=alternate]hardcodedhttps://bio.re/blog (the human-readable blog)
feed.link[rel=self]hardcodedThis feed's URL
feed.idhardcodedhttps://bio.re/blog
feed.updatedcomputedThe most recent publishedAt of any item, formatted as ISO 8601 (UTC)
entry.title / entry.link / entry.id / entry.updatedper postIndividual post metadata. Title is XML-escaped server-side.
entry.summaryper postThe post's excerpt (or empty), wrapped in CDATA[]

Note: Atom feed does not include <category> elements (RSS-only). If you need category data, use the JSON GET /public/blog list.

Errors

HTTPReason
429Rate limit exceeded (30 req/min)

Side effects

  1. getBlogFeedItems() โ€” same call as the RSS feed (last 20 published, same selection).
  2. Build Atom XML string by concatenation. Each user-controllable field passes through xmlEscape().
  3. Set Content-Type: application/atom+xml; charset=utf-8 + cache header on the raw response.
  4. Return the XML body. No mutations.

Code samples

curl https://api.bio.re/api/v1/public/blog/feed.atom
https://api.bio.re/api/v1/public/blog/feed.atom

Paste this URL into a feed reader that supports Atom (most modern ones โ€” NetNewsWire, Feedly, Reeder, Inoreader).

// Server-side โ€” fetch + parse with rss-parser (handles Atom too)
import Parser from 'rss-parser';

const parser = new Parser();

async function fetchBlogAtomFeed() {
  const feed = await parser.parseURL('https://api.bio.re/api/v1/public/blog/feed.atom');
  for (const item of feed.items) {
    console.log(item.title, item.link, item.isoDate);
  }
}

Try it

GET
/api/v1/public/blog/feed.atom

Response Body

curl -X GET "https://loading/api/v1/public/blog/feed.atom"
Empty

Source

SourcePathLines
Controllerapps/api-core/src/modules/content/public-content.controller.ts224โ€“237 (getBlogAtomFeed), 145โ€“147 (xmlEscape), 181โ€“207 (buildAtom)
Serviceapps/api-core/src/modules/content/content.service.ts578โ€“... (getBlogFeedItems โ€” shared with RSS feed)
Prisma modelpackages/prisma/prisma/schema.prismaBlogPost (filter status = PUBLISHED)
Bot detection skipapps/api-core/src/common/decorators/skip-bot-detection.decorator.ts@SkipBotDetection()

On this page