Substack API endpoint
Returns one page of a publication's public post archive with title, subtitle, canonical URL, publish date, engagement counts, and whether each post is paywalled. search filters the publication's own posts full-text; a query with no matches returns an empty list rather than the unfiltered archive.
/substack/publication/postspublication: required publication subdomain (semianalysis) or custom
domain (www.thefp.com).sort: optional archive ordering. Allowed values: new, top,
community. Defaults to new.offset: optional zero-based row offset. Defaults to 0.limit: optional rows per page, 1-50. Defaults to 12.audience is the upstream's own visibility label (everyone, only_paid,
and similar). paywalled is derived from it: true for anything other than
everyone. Post bodies are not returned — only metadata, the canonical
url, and engagement counts.
| Field | Filled in, of 20 checked | Values in the sample |
|---|---|---|
| id | 20 | |
| title | 20 | |
| slug | 20 | |
| url | 20 | newsletter.semianalysis.com |
| type | 20 | |
| audience | 20 | |
| published_at | 20 | 2026-08-21 to 2026-10-08 |
| paywalled | 20 | true in 20 of 20 |
| cover_image_url | 20 | substack-post-media.s3.amazonaws.com and 1 other host |
| description | 20 | median 105 characters |
| comment_count | 12 | 1 to 6, median 2 |
| reaction_count | 20 | 89 to 276, median 140 |
| subtitle | 19 | median 127 characters |
| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| publication | string | Yes | Publication subdomain or custom domain | semianalysis | |
| search | string | No | Full-text filter over the publication's own posts | nvidia | |
| sort | string | No | Archive ordering Allowed values: new, top, community. | ||
| offset | integer | No | Zero-based row offset | ||
| limit | integer | No | Rows per page, 1-50 | ||
| x-api-key (header) | string | Yes | API key required |
curl -X GET "https://api.crawlora.net/api/v1/substack/publication/posts?publication=semianalysis&sort=new&limit=10" \ -H "x-api-key: $CRAWLORA_API_KEY"
{
"code": 200,
"data": {
"publication": "semianalysis.substack.com",
"sort": "new",
"offset": 0,
"limit": 12,
"posts": [
{
"id": 213613469,
"title": "Korea's Trillion-Dollar Sovereign AI Investment",
"slug": "koreas-trillion-dollar-sovereign",
"url": "https://newsletter.semianalysis.com/p/koreas-trillion-dollar-sovereign",
"type": "newsletter",
"audience": "only_paid",
"published_at": "2026-09-01T20:14:32.560Z",
"paywalled": true,
"comment_count": 1,
"reaction_count": 162
}
]
},
"msg": "success"
}Request schema
No body schema
Response schema
#/definitions/substack.postsResponseDoc
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| code | integer | No | 200 | |||
| data | substack.PostsResult | No | ||||
| data.limit | integer | No | ||||
| data.offset | integer | No | ||||
| data.posts | array | No | Post record, 13 fields: audience, comment_count, cover_image_url, description, id, paywalled, published_at, reaction_count, slug, subtitle, title, type and 1 more. Described under Substack Search API. | |||
| data.publication | string | No | semianalysis | |||
| data.search | string | No | nvidia | |||
| data.sort | string | No | new | |||
| msg | string | No | success |
| Status | Description | Schema |
|---|---|---|
| 400 | Bad Request | #/definitions/app.Response |
| 404 | Not Found | #/definitions/app.Response |
| 429 | Too Many Requests | #/definitions/app.Response |
| 503 | Service Unavailable | #/definitions/app.Response |
Use environment variables for secrets and keep Crawlora API keys server-side.
curl -X GET "https://api.crawlora.net/api/v1/substack/publication/posts?publication=semianalysis&sort=new&limit=10" \
-H "x-api-key: $CRAWLORA_API_KEY"