API Reference
Complete reference for the Stackhooks REST API.
Getting Started
Authentication
All API requests require an API key passed in the Authorization header. You can create API keys in your dashboard.
curl https://stackhooks.com/v1/publications/platformer \
-H "Authorization: Bearer sk_live_your_api_key"Base URL
All endpoints are prefixed with the following base URL. Responses are JSON with a { data: ... } envelope.
https://stackhooks.com/v1/Endpoints
Get Publication
Retrieve metadata for a Substack publication including name, description, logo, and author list.
/v1/publications/:slugParameters
Example Request
curl https://stackhooks.com/v1/publications/platformer \
-H "Authorization: Bearer sk_live_abc123..."Example Response
{
"data": {
"slug": "platformer",
"name": "Platformer",
"description": "Casey Newton covers the intersection of Silicon Valley and democracy.",
"base_url": "https://www.platformer.news",
"logo_url": "https://substackcdn.com/image/fetch/f_auto,q_auto:good/...",
"hero_image_url": "https://substackcdn.com/image/fetch/...",
"twitter_handle": "platformer",
"author_count": 1,
"authors": [
{
"id": 2013012,
"name": "Casey Newton",
"handle": "caseynewton",
"photo_url": "https://substackcdn.com/image/...",
"bio": "I write Platformer, a newsletter about Big Tech and democracy."
}
]
}
}List Posts
Retrieve a paginated list of posts from a publication. Returns post metadata without full body content.
/v1/publications/:slug/postsParameters
Example Request
curl "https://stackhooks.com/v1/publications/platformer/posts?limit=2" \
-H "Authorization: Bearer sk_live_abc123..."Example Response
{
"data": [
{
"id": 150847302,
"slug": "why-meta-is-going-all-in-on-ai",
"title": "Why Meta is going all in on AI",
"subtitle": "The company is betting its future on artificial intelligence",
"publication_slug": "platformer",
"date": "2025-03-15T12:00:00.000Z",
"url": "https://www.platformer.news/p/why-meta-is-going-all-in-on-ai",
"cover_image": "https://substackcdn.com/image/...",
"word_count": 2450,
"like_count": 342,
"comment_count": 87,
"is_paid": false,
"authors": [
{
"id": 2013012,
"name": "Casey Newton",
"handle": "caseynewton",
"photo_url": "...",
"bio": "..."
}
]
}
],
"pagination": {
"offset": 0,
"limit": 2,
"has_more": true
}
}Get Post by URL
Retrieve a full post by its Substack URL. Supports both substack.com subdomains and custom domains. Returns full HTML/text body with paywall detection.
/v1/posts/by-urlParameters
Example Request
curl "https://stackhooks.com/v1/posts/by-url?url=https://platformer.substack.com/p/why-meta-is-going-all-in" \
-H "Authorization: Bearer sk_live_abc123..."Example Response
{
"data": {
"id": 150847302,
"slug": "why-meta-is-going-all-in-on-ai",
"title": "Why Meta is going all in on AI",
"subtitle": "The company is betting its future on artificial intelligence",
"publication_slug": "platformer",
"date": "2025-03-15T12:00:00.000Z",
"url": "https://www.platformer.news/p/why-meta-is-going-all-in-on-ai",
"is_paid": true,
"word_count": 2450,
"body_html": "<div class=\"body markup\">...</div>",
"body_text": "Full plaintext content of the post...",
"free_text": "Content visible to all readers...",
"paid_text": "Content behind the paywall..."
}
}Get Post
Retrieve a full post by its slug and publication. Returns full HTML/text body with automatic free/paid content splitting.
/v1/posts/:slugParameters
Example Request
curl "https://stackhooks.com/v1/posts/why-meta-is-going-all-in?publication=platformer" \
-H "Authorization: Bearer sk_live_abc123..."Example Response
{
"data": {
"id": 150847302,
"slug": "why-meta-is-going-all-in-on-ai",
"title": "Why Meta is going all in on AI",
"publication_slug": "platformer",
"is_paid": true,
"body_html": "<div class=\"body markup\">...</div>",
"body_text": "Full plaintext content...",
"free_text": "Content visible to all readers...",
"paid_text": "Content behind the paywall..."
}
}Get Comments
Retrieve all comments on a post, including nested reply threads. Comments are returned as a recursive tree.
/v1/posts/:slug/commentsParameters
Example Request
curl "https://stackhooks.com/v1/posts/why-meta-is-going-all-in/comments?publication=platformer" \
-H "Authorization: Bearer sk_live_abc123..."Example Response
{
"data": [
{
"id": 98765432,
"body_html": "<p>Great analysis!</p>",
"body_text": "Great analysis!",
"date": "2025-03-15T14:30:00.000Z",
"author_name": "Jane Doe",
"author_photo_url": "https://substackcdn.com/image/...",
"like_count": 12,
"children": [
{
"id": 98765433,
"body_html": "<p>Agreed, very insightful.</p>",
"body_text": "Agreed, very insightful.",
"date": "2025-03-15T15:00:00.000Z",
"author_name": "John Smith",
"author_photo_url": "https://substackcdn.com/image/...",
"like_count": 3,
"children": []
}
]
}
]
}Types
TypeScript-style definitions of all response objects.
Publication
interface Publication {
slug: string;
name: string;
description: string;
base_url: string;
logo_url: string;
hero_image_url: string;
twitter_handle: string;
author_count: number;
authors: Author[];
}Post
interface Post {
id: number;
slug: string;
title: string;
subtitle: string;
publication_slug: string;
date: string; // ISO 8601
url: string;
cover_image: string;
word_count: number;
like_count: number;
comment_count: number;
is_paid: boolean;
authors: Author[];
// Included on single-post endpoints:
body_html?: string; // Full HTML content
body_text?: string; // Plaintext content
free_text?: string; // Content before paywall
paid_text?: string; // Content after paywall
}Author
interface Author {
id: number;
name: string;
handle: string;
photo_url: string;
bio: string;
}Comment
interface Comment {
id: number;
body_html: string;
body_text: string;
date: string; // ISO 8601
author_name: string;
author_photo_url: string;
like_count: number;
children: Comment[]; // Recursive nested replies
}Errors
Error responses include a code and human-readable message.
{
"error": {
"code": "not_found",
"message": "Fetch publication homepage nonexistent: 404 Not Found"
}
}Rate Limits
Rate limits are applied per API key. Exceeding limits returns a 429 response. Every response includes rate limit headers.
Response Headers
Every /v1/* response includes these headers:
X-RateLimit-Limit-Minute: 10
X-RateLimit-Remaining-Minute: 7
X-RateLimit-Limit-Day: 100
X-RateLimit-Remaining-Day: 93