Substack API endpoint
Returns a publication's public profile and its complete subscription offering: every purchasable web plan with per-currency pricing, the separately priced App Store plans, per-tier benefit copy, and the toggles governing which tiers are sold. Identify the publication by name (a subdomain such as semianalysis, or a custom domain such as www.thefp.com) or by numeric publication_id -- exactly one is required. Prefer publication_id when you have it: it reads a compact document, while resolving by name has to parse the publication's full homepage.
/substack/publicationpublication: publication subdomain (semianalysis) or custom domain
(www.thefp.com). A full URL is also accepted and normalized.publication_id: numeric publication id.Exactly one of the two is required.
Prefer publication_id when you have it. It is faster than resolving by name. Both paths return identical data; publication_id is returned by /api/v1/substack/category, /api/v1/substack/leaderboard, and /api/v1/substack/user.
plans: every purchasable web plan. kind is derived and is one of
monthly, annual, weekly, daily, founding, other — Substack
models the founding tier as another annual plan, so kind is the only
field that separates them. amount_cents is in the plan's own currency;
currencies lists the same plan's price in every other currency Substack
offers it in.app_store_plans: Apple in-app-purchase SKUs. These are priced separately
from and usually above the web plans (The Free Press is $14/month via
App Store against $10/month on the web).free_benefits, paid_benefits, founding_benefits: the publication's
own benefit copy per tier.monthly_disabled / annual_disabled: a publication may sell only one
cadence even while both plans exist.payments_state: enabled when the publication sells paid subscriptions.group_discount_percent: discount applied to group/team subscriptions.Subscriber fields follow the same rules as
substack-user: total is opt-in and total_hidden
distinguishes a hidden count from a real zero.
| Field | Filled in, of 2 checked | Values in the sample |
|---|---|---|
| id | 2 | |
| kind | 2 | |
| nickname | 2 | |
| amount_cents | 2 | 5,000 to 50,000, median 5,000 |
| currency | 2 | |
| interval | 2 | |
| interval_count | 2 | 1 |
| active | 2 | true in 2 of 2 |
| currencies | 2 | median 14 entries |
| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| publication | string | No | Publication subdomain or custom domain. Provide this or publication_id. | semianalysis | |
| publication_id | integer | No | Numeric publication id. Cheaper than resolving by name. Provide this or publication. | 6349492 | |
| x-api-key (header) | string | Yes | API key required |
curl -X GET "https://api.crawlora.net/api/v1/substack/publication" \ -H "x-api-key: $CRAWLORA_API_KEY"
{
"code": 200,
"data": {
"id": 6349492,
"name": "SemiAnalysis",
"subdomain": "semianalysis",
"url": "https://semianalysis.substack.com",
"explicit": false,
"invite_only": false,
"subscribers": {
"total": 315000,
"total_hidden": false,
"paid_rough": "Thousands of paid subscribers",
"paid_tier": 1000
},
"subscription": {
"payments_state": "enabled",
"monthly_disabled": true,
"annual_disabled": false,
"pledges_enabled": false,
"free_trial_enabled": false,
"founding_plan_name": "Founding Member",
"group_discount_percent": 20,
"plans": [
{
"id": "yearly500usd_bc37ea9d",
"kind": "annual",
"nickname": "$500 a year",
"amount_cents": 50000,
"currency": "usd",
"interval": "year",
"interval_count": 1,
"active": true,
"currencies": [
{
"currency": "eur",
"amount_cents": 45000
},
{
"currency": "gbp",
"amount_cents": 40000
}
]
}
],
"app_store_plans": [
{
"amount_cents": 6000,
"currency": "usd",
"period": "month",
"is_founding": false,
"display_name": "SemiAnalysis (Monthly)",
"display_price": "$60",
"active": true
}
],
"paid_benefits": [
"Subscriber-only posts and full archive"
]
}
},
"msg": "success"
}Request schema
No body schema
Response schema
#/definitions/substack.publicationResponseDoc
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| code | integer | No | 200 | |||
| data | substack.Publication | No | ||||
| data.author_id | integer | No | ||||
| data.copyright | string | No | ||||
| data.custom_domain | string | No | ||||
| data.explicit | boolean | No | ||||
| data.hero_text | string | No | ||||
| data.id | integer | No | 6349492 | |||
| data.invite_only | boolean | No | ||||
| data.language | string | No | ||||
| data.logo_url | string | No | ||||
| data.name | string | No | SemiAnalysis | |||
| data.subdomain | string | No | ||||
| data.subscribers | substack.SubscriberCounts | No | SubscriberCounts record, 8 fields: follower_count, paid_rough, paid_rough_int, paid_tier, total, total_display, total_hidden, total_rough. Described under Get a public Substack writer profile API. | |||
| data.subscription | substack.Subscription | No | ||||
| data.subscription.annual_disabled | boolean | No | ||||
| data.subscription.app_store_plans | array | No | ||||
| data.subscription.app_store_plans[].active | boolean | No | ||||
| data.subscription.app_store_plans[].amount_cents | integer | No | 1400 | |||
| data.subscription.app_store_plans[].currency | string | No | usd | |||
| data.subscription.app_store_plans[].display_name | string | No | ||||
| data.subscription.app_store_plans[].display_price | string | No | $14 | |||
| data.subscription.app_store_plans[].is_founding | boolean | No | ||||
| data.subscription.app_store_plans[].period | string | No | month | |||
| data.subscription.app_store_plans[].sku | string | No | ||||
| data.subscription.founding_benefits | array | No | ||||
| data.subscription.founding_plan_name | string | No | Founding Member | |||
| data.subscription.free_benefits | array | No | ||||
| data.subscription.free_trial_enabled | boolean | No | ||||
| data.subscription.group_discount_percent | number | No | 20 | |||
| data.subscription.monthly_disabled | boolean | No | ||||
| data.subscription.paid_benefits | array | No | ||||
| data.subscription.payments_state | string | No | enabled | |||
| data.subscription.plans | array | No | ||||
| data.subscription.plans[].active | boolean | No | ||||
| data.subscription.plans[].amount_cents | integer | No | 5000 | |||
| data.subscription.plans[].currencies | array | No | ||||
| data.subscription.plans[].currencies[].amount_cents | integer | No | 900 | |||
| data.subscription.plans[].currencies[].currency | string | No | eur | |||
| data.subscription.plans[].currency | string | No | usd | |||
| data.subscription.plans[].id | string | No | monthly50usd_982ddb86 | |||
| data.subscription.plans[].interval | string | No | month | |||
| data.subscription.plans[].interval_count | integer | No | 1 | |||
| data.subscription.plans[].kind | string | No | monthly | |||
| data.subscription.plans[].nickname | string | No | $50 a month | |||
| data.subscription.plans[].trial_period_days | integer | No | ||||
| data.subscription.pledges_enabled | boolean | No | ||||
| data.url | string | No | https://semianalysis.substack.com | |||
| 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" \
-H "x-api-key: $CRAWLORA_API_KEY"