Skip to content

Writer plan · read-only

Posts & Archive API

Your whole Substack archive as clean JSON, Markdown or HTML: list, get, search, tags, authors and images.

In one paragraph

The Posts & Archive API turns your own Substack publication into a read-only REST API that returns every post as clean JSON, Markdown or HTML. You connect by pasting your publication URL: new posts arrive from your public RSS feed, and the full archive, including paid posts, comes from a one-time upload of your own Substack export. You get list, get and full-text search endpoints, plus tags, sections, authors and re-hosted images.

Why people want this

“The real blocker seems to be that Substack doesn’t offer an API, which makes consolidating your own data almost impossible.”
r/Substack, 2026-03-10
“There is still no API for writers. There is still no support for Markdown.”
@herbertyang on X, 2026-09-05
“My first rule for any software I use: it must have an API, so my business can get its data in and out.”
@apievangelist on X, 2026-10-15
“Substack has been annoying lately with no MCP or API/CLI support.”
@ka1n0s on X, 2026-10-11

How it works

  1. Paste your publication URL (yourpub.substack.com or your custom domain). We start reading its public RSS feed, which carries free posts in full and paid posts truncated.
  2. Optionally upload the export zip from your Substack settings (Settings → Exports) once. It contains your full archive, including paid posts, so the API can serve every post in full.
  3. We convert each post to clean JSON, Markdown and HTML, extract tags, sections and authors, and re-host images so links don't break.
  4. Call the REST endpoints with a read-only API key scoped to your publication, or point an AI agent at the MCP server.
  5. New posts appear automatically from RSS. Re-upload an export whenever you want paid posts refreshed.

Endpoints

Example responses are illustrative.

GET/v1/publications/{publication}/posts

List posts, newest first, with cursor pagination and filters.

ParamInTypeDescription
publication*pathstringYour publication's subdomain or custom domain, e.g. yourpub.substack.com
tagquerystringOnly posts with this tag or section slug
audiencequery"free" | "paid" | "all"Filter by audience; paid posts need an uploaded export
sincequerydateOnly posts published on or after this date (YYYY-MM-DD)
limitqueryinteger1–100, default 20
cursorquerystringCursor from the previous page
{
  "data": [
    {
      "id": "post_8f2c1a",
      "slug": "why-we-moved-our-blog",
      "title": "Why we moved our blog",
      "subtitle": "And what we learned in the first 90 days",
      "audience": "free",
      "published_at": "2026-09-30T14:00:00Z",
      "url": "https://yourpub.substack.com/p/why-we-moved-our-blog",
      "tags": [
        "company",
        "notes"
      ],
      "authors": [
        {
          "name": "Alex Writer",
          "handle": "alexwriter"
        }
      ],
      "word_count": 1480,
      "cover_image": "https://cdn.newsletterapi.io/yourpub/img/7a1e.jpg",
      "source": "rss"
    }
  ],
  "next_cursor": "eyJwIjoyMH0"
}
GET/v1/publications/{publication}/posts/{slug}

Get one post with its full body in the format you ask for.

ParamInTypeDescription
publication*pathstringYour publication's subdomain or custom domain, e.g. yourpub.substack.com
slug*pathstringThe post slug from its URL
formatquery"markdown" | "html" | "json"Body format, default markdown
{
  "id": "post_8f2c1a",
  "slug": "why-we-moved-our-blog",
  "title": "Why we moved our blog",
  "audience": "free",
  "published_at": "2026-09-30T14:00:00Z",
  "format": "markdown",
  "body": "## The short version\n\nWe wanted one place to write...\n\n![Chart](https://cdn.newsletterapi.io/yourpub/img/91bd.png)",
  "images": [
    {
      "original": "https://substack-post-media.s3.amazonaws.com/...",
      "hosted": "https://cdn.newsletterapi.io/yourpub/img/91bd.png"
    }
  ],
  "source": "export"
}
GET/v1/publications/{publication}/search

Full-text search across titles, subtitles and bodies of your archive.

ParamInTypeDescription
publication*pathstringYour publication's subdomain or custom domain, e.g. yourpub.substack.com
q*querystringSearch query
limitqueryinteger1–50, default 10
{
  "query": "pricing experiment",
  "results": [
    {
      "slug": "what-our-pricing-test-taught-us",
      "title": "What our pricing test taught us",
      "published_at": "2026-05-12T13:00:00Z",
      "score": 0.92,
      "snippet": "…the <mark>pricing experiment</mark> ran for six weeks…"
    }
  ]
}
GET/v1/publications/{publication}/tags

List tags and sections with post counts.

ParamInTypeDescription
publication*pathstringYour publication's subdomain or custom domain, e.g. yourpub.substack.com
{
  "data": [
    {
      "slug": "company",
      "name": "Company",
      "post_count": 42
    },
    {
      "slug": "notes",
      "name": "Field notes",
      "post_count": 17
    }
  ]
}
GET/v1/publications/{publication}/authors

List authors on the publication with their post counts.

ParamInTypeDescription
publication*pathstringYour publication's subdomain or custom domain, e.g. yourpub.substack.com
{
  "data": [
    {
      "name": "Alex Writer",
      "handle": "alexwriter",
      "post_count": 118
    },
    {
      "name": "Sam Guest",
      "handle": "samguest",
      "post_count": 6
    }
  ]
}
POST/v1/publications/{publication}/exports

Upload your Substack export zip to load the full archive, including paid posts.

ParamInTypeDescription
publication*pathstringYour publication's subdomain or custom domain, e.g. yourpub.substack.com
file*bodymultipart file (.zip)The zip from Settings → Exports in your Substack dashboard
{
  "id": "exp_31c9",
  "status": "processing",
  "received_at": "2026-10-21T09:12:00Z",
  "posts_found": 214,
  "images_queued": 1290
}

MCP tools for your AI agent

list_posts

List your posts with optional tag, audience and date filters.

Try: “List everything I published about pricing since January.”

get_post

Get one post as Markdown or HTML.

Try: “Get my post 'why-we-moved-our-blog' as Markdown.”

search_archive

Full-text search across your archive.

Try: “Find my posts that mention onboarding emails.”

What people will build with it

Your posts on your own site

Render your Substack archive in a Next.js, Astro or WordPress site from clean JSON instead of parsing the RSS feed yourself.

A searchable archive

Add full-text search over years of posts to a docs site, an internal wiki or a reader-facing archive page.

Data in, data out

Pull posts into Notion, Airtable or a data warehouse for content audits and reporting.

Agents that know your writing

Give Claude, ChatGPT or an n8n workflow read access to your archive through the same API or the MCP server.

Questions

Does Substack have a public posts API?
As of October 2026, Substack does not publish a general-purpose public API for reading your posts. Writers can use the public RSS feed (free posts in full, paid posts truncated) and the export in their settings. This API combines both into one clean interface.
Can it return my paid posts?
Yes, after you upload your own Substack export once. The RSS feed only carries truncated paid posts, so the full paid archive comes from your export file.
Does it need my password?
No. We never ask for your Substack login or session. We read your public RSS feed and the export files you download from your own Substack settings and upload to us.
Is this affiliated with Substack?
No. newsletterapi.io is an independent tool for Substack writers. It is not made, endorsed or approved by Substack, Inc.
How do I get access?
Email hello@newsletterapi.io or use the Get access form, and we set up your account.

Read more