> **For coding agents and LLMs:** This is one Social Fetch marketing page (markdown export). For API orientation start with [`/llms.txt`](https://www.socialfetch.dev/llms.txt); for auth and crawl rules use [`/agents.txt`](https://www.socialfetch.dev/agents.txt); for every operation use [`/llms-endpoints.txt`](https://www.socialfetch.dev/llms-endpoints.txt).

## This page

- **On-site (HTML):** <https://www.socialfetch.dev/platforms/substack>
- **Markdown (.mdx) URL:** <https://www.socialfetch.dev/platforms/substack.mdx>

---

# Substack API. Publications, posts and Notes as JSON.

Read publication metadata by id, subdomain, host or URL, and its archive, sitemap and feed by subdomain, host or URL. Follow posts into comments and reactions, with readers, Notes, search and categories covered too.

- Publication and reader routes
- 1 credit per request
- Typed not_found

Social Fetch exposes 26 routes under `/v1/substack`. Publication metadata takes a publication as a numeric id (`89120`), a Substack subdomain (`astralcodexten`), a host (`www.astralcodexten.com`) or a full publication URL. The archive, bulk posts, sitemap, in-publication search and feed routes take a subdomain, host or URL; a numeric id is refused there with a 400. Recommendations accept either a numeric id or a host. Post routes take a numeric post id or a canonical post URL; comments need the post URL. Reader routes take the handle shown on the profile.

Publication routes cover the publication itself, its archive in `new`, `top` or `pinned` order, bulk posts with full free bodies, the per-publication sitemap, in-publication search with highlighted snippets, its recommendations and its feed. Post routes return one post with a full free body or a paid preview, the whole comment tree, and the people who reacted or restacked. Reader routes return a public profile, the posts across that person's publications, their Notes and replies, and the publications they show publicly. Search, category, explore and directory routes cover discovery.

Every lookup answers HTTP 200 with `data.lookupStatus`, so a missing publication, post, reader or note is a typed `not_found`, not an error. Lists use an opaque `cursor` where Substack allows deep paging, or an offset or page number where it does not. The response also reports `page.hasMore` and the next cursor, offset or page. Publication and podcast search sometimes cannot be answered reliably; the request then returns 503 and is not charged. For dependable publication discovery, use `search.profiles` or `categories.publications.list`.

## What you can get

- Publication metadata: plans, audience bands, sections, contributors, podcast details, links and benefits.
- Archive listings from the first page, bulk posts with full free bodies and cursors, the sitemap, and in-publication search snippets.
- Posts by id or URL, with `bodyHtml`, a paid preview flag, tags, authors, audio and video details.
- The whole nested comment tree, up to the 100 reactors and Substack's restacker cap of about 96 per post, each with `truncated` when the list is at that limit.
- Reader profiles with roles and links, posts across publications, Notes history, replies and public subscriptions.
- Top search, profile search, podcast search, categories and leaderboards, the explore feed and the global publication directory.

## Substack endpoints

| Endpoint | Request | Credits | Docs |
| --- | --- | --- | --- |
| Publication | GET /v1/substack/publications/{publication} | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/publications/publication/get) |
| Posts | GET /v1/substack/publications/{publication}/posts | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/publications/publication/posts/get) |
| Post bodies | GET /v1/substack/publications/{publication}/posts/bodies | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/publications/publication/posts/bodies/get) |
| Post index | GET /v1/substack/publications/{publication}/posts/index | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/publications/publication/posts/index/get) |
| Search posts | GET /v1/substack/publications/{publication}/posts/search | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/publications/publication/posts/search/get) |
| Recommendations | GET /v1/substack/publications/{publication}/recommendations | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/publications/publication/recommendations/get) |
| Publication feed | GET /v1/substack/publications/{publication}/feed | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/publications/publication/feed/get) |
| Post | GET /v1/substack/posts/{post} | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/posts/post/get) |
| Comments | GET /v1/substack/posts/{post}/comments | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/posts/post/comments/get) |
| Reactors | GET /v1/substack/posts/{post}/reactors | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/posts/post/reactors/get) |
| Restackers | GET /v1/substack/posts/{post}/restackers | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/posts/post/restackers/get) |
| Profile | GET /v1/substack/profiles/{handle} | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/profiles/handle/get) |
| Profile posts | GET /v1/substack/profiles/{handle}/posts | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/profiles/handle/posts/get) |
| Notes | GET /v1/substack/profiles/{handle}/notes | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/profiles/handle/notes/get) |
| Subscriptions | GET /v1/substack/profiles/{handle}/subscriptions | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/profiles/handle/subscriptions/get) |
| Note | GET /v1/substack/notes/{noteId} | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/notes/noteid/get) |
| Note replies | GET /v1/substack/notes/{noteId}/replies | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/notes/noteid/replies/get) |
| Note restacks | GET /v1/substack/notes/{noteId}/restacks | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/notes/noteid/restacks/get) |
| Profile search | GET /v1/substack/search/profiles | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/search/profiles/get) |
| Top search | GET /v1/substack/search | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/search/get) |
| Publication search | GET /v1/substack/search/publications | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/search/publications/get) |
| Podcast search | GET /v1/substack/search/podcasts | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/search/podcasts/get) |
| Categories | GET /v1/substack/categories | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/categories/get) |
| Category leaderboard | GET /v1/substack/categories/{categoryId}/publications | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/categories/categoryid/publications/get) |
| Explore feed | GET /v1/substack/notes/explore | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/notes/explore/get) |
| Directory | GET /v1/substack/directory | 1 credit Failed requests are free | [docs](https://www.socialfetch.dev/docs/api/v1/substack/directory/get) |

## How to start

1. **Create an API key.** Sign up at Social Fetch and copy a key (`sfk_...`). New accounts get 100 free credits, enough to try every Substack route on a few publications.
2. **Name the publication or entity.** Use `GET /v1/substack/publications/astralcodexten/posts` for an archive, `GET /v1/substack/posts/223208969` for one post, or `GET /v1/substack/profiles/dieworkwear/notes` for a reader's Notes. Send `x-api-key` on every request.
3. **Branch on lookupStatus, then page.** Check `data.lookupStatus` before storing a row. Keep calling with `page.nextCursor`, `page.nextOffset` or `page.nextPage` while `page.hasMore` is true, and bill from `meta.creditsCharged`.

## Pricing

Each Substack route charges 1 credit per completed request, and each page of a list is its own request. Credits never expire on pay-as-you-go packs, and `meta.creditsCharged` on every response is the billing source of truth. A request that ends in `503` is not charged.

## Compared with the official API

Substack has no documented public API for publication, post, comment, Notes and search data. Its surfaces return different shapes: a publication page, a reader profile and a search page each nest their fields differently. Social Fetch gives every route one JSON shape, typed `lookupStatus`, stable paging, and the same field names across publications and custom domains.

## FAQ

### Is there a Substack API for publications, posts and Notes?

Yes. Social Fetch has 26 Substack routes under /v1/substack covering publications, archives, post bodies, sitemaps, in-publication search, recommendations, feeds, posts, comments, reactors, restackers, reader profiles, Notes, subscriptions, search, categories, the explore feed and the publication directory. Authenticate with your Social Fetch API key in x-api-key.

### How do I identify a publication?

Publication metadata takes a numeric id (89120), a Substack subdomain (astralcodexten), a host (www.astralcodexten.com) or a full publication URL. The archive, bulk posts, sitemap, in-publication search and feed routes take a subdomain, host or URL; a numeric id returns a 400 there. Recommendations accept a numeric id or a host. A host or URL is the safest choice when the publication uses a custom domain.

### Can I get full post bodies?

Free posts return bodyHtml with the whole body. Paid posts return the preview the publication makes public and set bodyIsPreview to true, so a preview is never mistaken for the full text. Use publication.posts.bodies.list to pull up to 50 posts with their bodies per cursor page.

### Why can publication search return 503?

Publication search sometimes cannot be answered reliably. The request then returns 503 and is not charged, rather than an empty list that could be mistaken for no matches. search.profiles and categories.publications.list are the dependable ways to find a publication. Podcast search follows the same rule.

### What does a comment response include?

post.comments.list returns the whole nested tree in comments, the number of top-level and nested nodes in returnedCount, and commentsHidden true when a paid post does not serve comments publicly. Use the post URL, not a numeric id. When more than 5,000 nodes are present the list is cut and truncated is true.

### How deep can I page?

Archive listings serve up to 23 rows and page by the `page.nextCursor` each response carries; a `page` above 0 returns a 400. Bulk posts, Notes, subscriptions, restacks, podcast search and the explore feed also use an opaque cursor. In-publication post search, profile search, publication search and category leaderboards use a page number; profile and publication search run from page 0 to page 3, in-publication post search runs to page 20, and a category leaderboard runs from page 0 to page 20. A page past the last one returns an empty list with `hasMore: false`. Top search uses a cursor. Every list reports page.hasMore and the next value.

### What is in a reader profile?

profile.get returns name, handle, bio, photoUrl, follower and subscriber labels, badges, links, publications with their role and primary flag, public subscriptions, and counts. profile.notes.list returns the Notes and replies history, and profile.subscriptions.list returns the publications that person shows publicly.

### Can I list publications by category?

Yes. categories.list returns top-level categories with subcategories and the recommended view. categories.publications.list returns one page of a leaderboard for a category id, ranking all, paid or trending, with 25 publications a page, pages 0 to 20. The global directory route lists publication subdomains, one file of about 16,000 at a time and up to 5,000 entries a page.

### What is in the sitemap response?

`publication.posts.index.list` splits the sitemap into `posts` (only `/p/{slug}` URLs) and `pages` (everything else, such as `/archive` and `/about`). Every row carries `kind`, `url`, `slug`, `lastModified` and `changeFrequency`, and `publicationId` is filled when the publication is known.

### Does HTTP 200 mean the publication or post exists?

No. HTTP 200 means the request finished. Check data.lookupStatus: not_found means the publication, post, reader or note does not exist, and restricted means the publication exists but does not serve that surface publicly.

### Can I use these routes from agents or MCP?

Yes. Every Substack route is reachable from the hosted MCP server and through Ask (POST /v1/ask) in plain English, with the same credit metering as REST. Use the typed routes for production jobs.

## Related

- [Substack Publication API](https://www.socialfetch.dev/platforms/substack/publications-publication): Metadata, plans, audience bands and sections (`GET /v1/substack/publications/{publication}`).
- [Substack Archive API](https://www.socialfetch.dev/platforms/substack/publications-publication-posts): Newest, top or pinned posts with cursor paging (`GET /v1/substack/publications/{publication}/posts`).
- [Substack Post API](https://www.socialfetch.dev/platforms/substack/posts-post): One post by id or URL, free body or paid preview (`GET /v1/substack/posts/{post}`).
- [Substack Profile API](https://www.socialfetch.dev/platforms/substack/profiles-handle): A reader's public profile, roles and subscriptions (`GET /v1/substack/profiles/{handle}`).
- [Ask in plain English](https://www.socialfetch.dev/ask): Route a natural-language question about a publication or post to the matching Substack route.
- [Hosted MCP](https://www.socialfetch.dev/mcp): Call Substack tools from Cursor or Claude with the same credit metering as REST.
