{
  "openapi": "3.0.1",
  "info": {
    "title": "Substack Scraper - Posts, Markdown & New-Post Feed",
    "description": "Extract public posts from any Substack newsletter, custom domains included: title, date, authors, audience, paywall flag, likes, comment counts, podcast audio and the body as Markdown, text or HTML. Built-in new-posts feed between runs and a publication info row with plan prices.",
    "version": "1.0",
    "x-build-id": "3iWFA5N18ZhT1UrWM"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/cedarfetch~substack-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-cedarfetch-substack-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/cedarfetch~substack-scraper/runs": {
      "post": {
        "operationId": "runs-sync-cedarfetch-substack-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/cedarfetch~substack-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-cedarfetch-substack-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "required": [
          "publications"
        ],
        "properties": {
          "publications": {
            "title": "Newsletters or post URLs",
            "type": "array",
            "description": "One per line. Accepts a Substack subdomain (simonw.substack.com, or just simonw), a custom domain (www.lennysnewsletter.com), a full URL (https://www.noahpinion.blog/archive), or a post URL (https://simonw.substack.com/p/some-post or open.substack.com/pub/simonw/p/some-post) to read only that post. Links on substack.com itself (profiles, the app feed, search) are not supported.",
            "items": {
              "type": "string"
            }
          },
          "maxPostsPerPublication": {
            "title": "Max posts per newsletter",
            "minimum": 0,
            "type": "integer",
            "description": "Stop after this many matching posts per newsletter. 0 means the whole archive. Keeps test runs and samples cheap.",
            "default": 0
          },
          "sort": {
            "title": "Order",
            "enum": [
              "new",
              "top"
            ],
            "type": "string",
            "description": "\"new\": newest first (fastest with a postedAfter date, because reading stops at the first older post). \"top\": the newsletter's most popular posts first, as Substack ranks them.",
            "default": "new"
          },
          "coverage": {
            "title": "Which posts to look at",
            "enum": [
              "archive_and_sections",
              "everything",
              "archive"
            ],
            "type": "string",
            "description": "Publishers can hide posts from their main archive (whole sections, or podcast episodes). \"archive_and_sections\" (default): the main archive plus every section hidden from it; cheap, 1 request per 25 posts. \"everything\": also every other post in the public sitemap that no listing shows (often podcast episodes); 1 extra request per such post, so slower on big newsletters. \"archive\": only what the main /archive page lists.",
            "default": "archive_and_sections"
          },
          "postedAfter": {
            "title": "Only posts published after",
            "type": "string",
            "description": "Optional. Keep only posts published on or after this moment. An ISO date (2026-11-01 or 2026-11-01T12:00:00Z) or a relative value such as \"30 days\", \"2 weeks\", \"24 hours\" or \"6 months\"."
          },
          "postedBefore": {
            "title": "Only posts published before",
            "type": "string",
            "description": "Optional. Keep only posts published before this moment. Same formats as \"Only posts published after\"."
          },
          "includeContent": {
            "title": "Include the post body",
            "type": "boolean",
            "description": "Fetch each post's body (one extra request per post). Free posts come in full. Paywalled posts contain only the public preview Substack shows to visitors, marked isPaywalled: true and contentAvailable: \"preview\". Turn off for a fast metadata-only list (about one request per 25 posts).",
            "default": true
          },
          "contentFormat": {
            "title": "Body format",
            "enum": [
              "markdown",
              "text",
              "html"
            ],
            "type": "string",
            "description": "\"markdown\": headings, links, lists, quotes, code, images and footnotes as Markdown, Substack's buttons and widgets removed (best for AI and RAG). \"text\": plain text. \"html\": the body exactly as Substack serves it.",
            "default": "markdown"
          },
          "postTypes": {
            "title": "Only these post types",
            "type": "array",
            "description": "Optional. Keep only these types as Substack labels them: newsletter (regular posts), podcast, thread, video. Empty means all types.",
            "items": {
              "type": "string",
              "enum": [
                "newsletter",
                "podcast",
                "thread",
                "video"
              ],
              "enumTitles": [
                "Newsletter posts",
                "Podcast episodes",
                "Threads",
                "Video posts"
              ]
            },
            "default": []
          },
          "onlyFree": {
            "title": "Only free posts",
            "type": "boolean",
            "description": "Skip posts that are paywalled or require a subscription, so every delivered row has the full body.",
            "default": false
          },
          "includePublicationInfo": {
            "title": "Add a publication info row",
            "type": "boolean",
            "description": "Add one free row per newsletter (recordType \"publication\") with its name, description, author name, language, logo, whether paid subscriptions are on, public plan prices and the number of posts in its sitemap. Costs one extra request per newsletter.",
            "default": true
          },
          "trackChanges": {
            "title": "Track changes between runs",
            "type": "boolean",
            "description": "Compare every post with the previous run and add changeType (new, updated, unchanged, removed), the list of changes, and previous values. The snapshot is kept in a named key-value store in your account, so it survives between runs. Schedule the Actor to get a daily feed.",
            "default": false
          },
          "changesOnly": {
            "title": "Output only new and updated posts",
            "type": "boolean",
            "description": "Requires change tracking. Skips unchanged posts, so you receive (and pay for) only new, updated and removed posts: a \"new posts since last run\" feed. Bodies are downloaded only for those posts.",
            "default": false
          },
          "snapshotStoreName": {
            "title": "Snapshot store name",
            "type": "string",
            "description": "Name of the key-value store that holds the change-tracking snapshots. Use a different name to run independent feeds on the same newsletters. Lowercase letters, digits and hyphens.",
            "default": "substack-scraper-snapshots"
          },
          "concurrency": {
            "title": "Parallel requests per newsletter",
            "minimum": 1,
            "maximum": 5,
            "type": "integer",
            "description": "How many requests run at once against one newsletter. Substack rate-limits busy clients (HTTP 429): 1 request at a time with a 1 s pause ran clean in testing, 2 at a time with 0.5 s hit rate limits after about 100 requests. On a 429 the Actor slows itself down automatically.",
            "default": 1
          },
          "requestDelayMs": {
            "title": "Delay between requests (ms)",
            "minimum": 0,
            "maximum": 60000,
            "type": "integer",
            "description": "Pause after each request to the same newsletter, with small random jitter. Doubled automatically (up to 10 s) after a rate-limit answer and eased back after 20 clean answers.",
            "default": 1000
          },
          "maxConcurrentPublications": {
            "title": "Newsletters in parallel",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "How many different newsletters are read at the same time.",
            "default": 3
          },
          "requestTimeoutSecs": {
            "title": "Request timeout",
            "minimum": 5,
            "maximum": 120,
            "type": "integer",
            "description": "Give up on a single request after this many seconds (it is then retried).",
            "default": 30
          },
          "maxRetries": {
            "title": "Max retries",
            "minimum": 0,
            "maximum": 8,
            "type": "integer",
            "description": "Retries for rate-limit (429), server-error (5xx) and network failures, with jittered exponential backoff that honours Retry-After. 401/403 and bot-protection pages are never retried.",
            "default": 4
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}