{
  "openapi": "3.0.1",
  "info": {
    "title": "Hacker News API: Search, Comments, Users & Who Is Hiring",
    "description": "Everything public on Hacker News through its two official APIs: keyword search over 2007-present, the six feeds, full comment trees flattened with depth, user profiles, and the monthly Who Is Hiring thread parsed into structured jobs. Plus a monitor that bills only new hits. No API key.",
    "version": "0.1",
    "x-build-id": "W3hgzAbG4b6CDm7Ex"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/insight.solutions~hacker-news-api/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-insight.solutions-hacker-news-api",
        "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/insight.solutions~hacker-news-api/runs": {
      "post": {
        "operationId": "runs-sync-insight.solutions-hacker-news-api",
        "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/insight.solutions~hacker-news-api/run-sync": {
      "post": {
        "operationId": "run-sync-insight.solutions-hacker-news-api",
        "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",
        "properties": {
          "mode": {
            "title": "Mode",
            "enum": [
              "search",
              "feed",
              "items",
              "users",
              "whoIsHiring",
              "monitor"
            ],
            "type": "string",
            "description": "What to read. `search` runs keyword searches over everything Hacker News has indexed since 2007. `feed` pulls one of the six ranked lists (front page, new, best, Ask, Show, jobs). `items` returns specific stories and their whole comment trees. `users` returns profiles. `whoIsHiring` parses the monthly \"Ask HN: Who is hiring?\" thread into structured jobs. `monitor` returns only what is new since your last run. Inputs belonging to the other modes are ignored, not errors.",
            "default": "search"
          },
          "keywords": {
            "title": "Keywords",
            "type": "array",
            "description": "One Algolia query per entry, e.g. `[\"web scraping\", \"rust\"]`. Results are deduplicated across keywords and every row lists the keywords that matched it in `matchedKeywords`. Leave empty for \"everything the other filters allow\". Used by `search` and `monitor`.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "tags": {
            "title": "Tags",
            "type": "array",
            "description": "Which kinds of item to return. `story`, `comment`, `poll`, `show_hn`, `ask_hn`, `launch_hn`, `front_page` and `job` are Hacker News's own tags. You can also type `author_<username>` or `story_<id>` by hand. Used by `search` and `monitor`.",
            "default": [
              "story"
            ],
            "items": {
              "type": "string"
            }
          },
          "tagsMode": {
            "title": "Combine tags with",
            "enum": [
              "all",
              "any"
            ],
            "type": "string",
            "description": "`all` requires every tag (`story` **and** `show_hn`). `any` accepts any of them (`story` **or** `poll`). Author filters are always required on top of whichever you pick, because \"stories or polls by pg\" is the only reading anybody means.",
            "default": "all"
          },
          "sort": {
            "title": "Sort",
            "enum": [
              "date",
              "relevance"
            ],
            "type": "string",
            "description": "`date` returns newest first and is the order to use when you are pulling a window of time. `relevance` returns Hacker News search's own ranking, which is not time-ordered.",
            "default": "date"
          },
          "feeds": {
            "title": "Feeds",
            "type": "array",
            "description": "Which ranked lists to pull, in Hacker News's own order. `front` is the top 500 stories, `new` the newest 500, `best` the top 200; `ask`, `show` and `jobs` are as long as Hacker News currently lists, which is often far shorter (28 and 31 on the day this was built). The free `feed-summary` row carries the real length. Used by `feed`.",
            "items": {
              "type": "string",
              "enum": [
                "front",
                "new",
                "best",
                "ask",
                "show",
                "jobs"
              ],
              "enumTitles": [
                "Front page",
                "New",
                "Best",
                "Ask HN",
                "Show HN",
                "Jobs"
              ]
            },
            "default": [
              "front"
            ]
          },
          "maxItemsPerFeed": {
            "title": "Items per feed",
            "minimum": 1,
            "maximum": 500,
            "type": "integer",
            "description": "How far down each feed to go. 30 is one front page.",
            "default": 30
          },
          "itemIds": {
            "title": "Item ids",
            "type": "array",
            "description": "Specific Hacker News item ids, e.g. `[\"4058874\"]`. Used by `items`.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "itemUrls": {
            "title": "Item URLs",
            "type": "array",
            "description": "Item links instead of ids — `https://news.ycombinator.com/item?id=4058874` or `https://hn.algolia.com/api/v1/items/4058874`. The id is read out of the link; the page is never fetched.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "usernames": {
            "title": "Usernames",
            "type": "array",
            "description": "Hacker News usernames, e.g. `[\"pg\"]`. **Case-sensitive.** Used by `users`.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "includeSubmissions": {
            "title": "Include recent submissions",
            "type": "boolean",
            "description": "Also return each user's most recent stories and comments as ordinary rows. They come from one search request, not from resolving the account's whole submission history — pg alone has 15,565 submissions.",
            "default": false
          },
          "hiringThread": {
            "title": "Hiring thread",
            "enum": [
              "who-is-hiring",
              "who-wants-to-be-hired",
              "freelancer"
            ],
            "type": "string",
            "description": "Which of the three monthly threads to parse. All three are posted by the same account on the first working day of the month.",
            "default": "who-is-hiring"
          },
          "months": {
            "title": "Months",
            "type": "array",
            "description": "Which months' threads to parse, e.g. `[\"2026-09\", \"2026-08\"]`. Matched against the `(Month YYYY)` in the thread's own title, not against when it was posted — the August 2026 thread went up on the 3rd. Leave empty and Months back is used instead.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "monthsBack": {
            "title": "Months back",
            "minimum": 1,
            "maximum": 24,
            "type": "integer",
            "description": "How many recent threads to parse when Months is empty. 1 is the current month's.",
            "default": 1
          },
          "lookbackHours": {
            "title": "Lookback hours",
            "minimum": 1,
            "maximum": 720,
            "type": "integer",
            "description": "How far back the monitor looks when it has no stored state yet.",
            "default": 24
          },
          "firstRunBehavior": {
            "title": "First monitor run",
            "enum": [
              "emit-all",
              "baseline-only"
            ],
            "type": "string",
            "description": "What the very first monitor run against an empty store does. `emit-all` returns and bills up to Max items; every later run bills only what is new. `baseline-only` returns nothing, bills nothing, and writes the baseline so the next run has something to compare against.",
            "default": "emit-all"
          },
          "dateFrom": {
            "title": "From",
            "type": "string",
            "description": "Only items posted on or after this. Accepts a date (`2026-01-01`), a full timestamp (`2026-01-01T12:00:00Z`) or a relative window (`7d`, `30d`, `12h`). A relative window means the same thing on every run of a schedule."
          },
          "dateTo": {
            "title": "To",
            "type": "string",
            "description": "Only items posted on or before this. Same formats as From. A plain date covers the whole day."
          },
          "minPoints": {
            "title": "Minimum points",
            "type": "integer",
            "description": "Only stories with at least this many points. Hacker News does not publish comment scores, so this cannot be applied to a comments-only search — ask for it and you get a free `invalid-input` row explaining why, and the rest of the query still runs."
          },
          "maxItems": {
            "title": "Max items",
            "minimum": 0,
            "maximum": 5000,
            "type": "integer",
            "description": "The most paid rows this run may return. 0 means \"everything the filters allow\", up to the 5,000-row run ceiling. Free summary and diagnostic rows do not count against it.",
            "default": 200
          },
          "maxPoints": {
            "title": "Maximum points",
            "type": "integer",
            "description": "Only stories with at most this many points. Useful for finding things that were posted and went nowhere."
          },
          "minComments": {
            "title": "Minimum comments",
            "type": "integer",
            "description": "Only stories with at least this many comments. Stories only, for the same reason as Minimum points."
          },
          "maxComments": {
            "title": "Maximum comments",
            "type": "integer",
            "description": "Only stories with at most this many comments."
          },
          "authors": {
            "title": "Authors",
            "type": "array",
            "description": "Only items by these usernames. Hacker News usernames are **case-sensitive**: `pg` and `PG` are not the same account, and only the first one exists.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "excludeKeywords": {
            "title": "Exclude keywords",
            "type": "array",
            "description": "Drop any row whose title, text or URL contains one of these. Applied before anything is charged, so excluded rows cost you nothing.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "hitsPerPage": {
            "title": "Results per request",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "How many results to ask for per request. Bigger pages mean fewer requests. Hacker News search returns at most 1,000 results per query however you page it; past that this Actor walks backwards through time in slices and tells you in a free summary row when it still had to stop.",
            "default": 100
          },
          "includeComments": {
            "title": "Include comments",
            "type": "boolean",
            "description": "Return each story's whole comment tree as `comment` rows, with `depth`, `parentId` and `storyId` on every one. On by default in `items` mode, off by default in `feed` mode — a front page with comments is roughly 900 extra rows."
          },
          "maxCommentsPerStory": {
            "title": "Comments per story",
            "minimum": 0,
            "maximum": 5000,
            "type": "integer",
            "description": "Cap on comment rows per story. 0 means every comment in the tree.",
            "default": 50
          },
          "maxCommentDepth": {
            "title": "Comment depth",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "How deep into the reply tree to go. 1 is top-level comments only.",
            "default": 10
          },
          "commentsMinLength": {
            "title": "Minimum comment length",
            "minimum": 0,
            "maximum": 10000,
            "type": "integer",
            "description": "Drop comments shorter than this many characters. Applied before the charge, so a run that only wants substantial comments does not pay for one-word replies.",
            "default": 0
          },
          "maxSubmissionsPerUser": {
            "title": "Submissions per user",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "How many recent submissions to return per user, newest first.",
            "default": 20
          },
          "submissionTypes": {
            "title": "Submission types",
            "type": "array",
            "description": "Which of a user's submissions to return.",
            "items": {
              "type": "string",
              "enum": [
                "story",
                "comment"
              ],
              "enumTitles": [
                "Stories",
                "Comments"
              ]
            },
            "default": [
              "story",
              "comment"
            ]
          },
          "threadIds": {
            "title": "Thread ids",
            "type": "array",
            "description": "Parse these specific thread ids instead of looking them up by month.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "maxJobsPerThread": {
            "title": "Jobs per thread",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on postings read from each thread. A busy month is around 264 top-level comments.",
            "default": 300
          },
          "remoteOnly": {
            "title": "Remote only",
            "type": "boolean",
            "description": "Only postings whose first line carries a REMOTE token. Applied before the charge.",
            "default": false
          },
          "salaryMin": {
            "title": "Minimum salary",
            "minimum": 0,
            "type": "integer",
            "description": "Only postings whose parsed salary reaches this. Roughly a quarter of postings state pay at all; the rest have no salary to compare and are excluded when you set this."
          },
          "filterKeywords": {
            "title": "Must contain",
            "type": "array",
            "description": "Only postings whose text contains one of these, e.g. `[\"rust\", \"golang\"]`. Applied before the charge.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "minParseConfidence": {
            "title": "Minimum parse confidence",
            "minimum": 0,
            "maximum": 1,
            "type": "number",
            "description": "Every job row carries a `parseConfidence` from 0 to 1. Postings below this are returned free as diagnostics with their full text, never as paid rows. On the September 2026 thread the score was bimodal: 247 postings at 0.6 or above and 17 at 0.2 or below, with nothing in between.",
            "default": 0.3
          },
          "includeUnparsed": {
            "title": "Include unparsed comments",
            "type": "boolean",
            "description": "Return the comments that did not parse as free diagnostic rows carrying their full text, so you can see what the parser left behind. Never charged either way.",
            "default": true
          },
          "enrichPoster": {
            "title": "Enrich the poster",
            "type": "boolean",
            "description": "Add `posterKarma`, `posterCreated`, `posterAccountAgeDays` and `posterTrust` to every job row. One request per distinct poster, cached for the run. A failed lookup leaves the four columns null and never fails the row.",
            "default": true
          },
          "includeReplies": {
            "title": "Include replies",
            "type": "boolean",
            "description": "Also try to parse replies to postings. Off by default: of the 120 deeper replies in the September 2026 thread, exactly 2 looked like job posts. Replies are discussion.",
            "default": false
          },
          "includeText": {
            "title": "Include text",
            "type": "boolean",
            "description": "Include `text` and `textHtml` on stories and comments. Turning it off keeps the rows small when you only want titles, scores and links.",
            "default": true
          },
          "includeSummary": {
            "title": "Include summary rows",
            "type": "boolean",
            "description": "Add the free summary rows: what this run was asked to do, how many hits each query had, how long each feed really is, how many postings parsed, and what the monitor saw. Never charged.",
            "default": true
          },
          "stateStoreName": {
            "title": "State store name",
            "type": "string",
            "description": "The named key-value store the monitor remembers previous runs in. Every scheduled run of the same monitor must use the same name. Letters, digits and dashes, 3–63 characters.",
            "default": "hacker-news-api-state"
          },
          "maxConcurrency": {
            "title": "Max concurrency",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "How many targets to work on at once. The Actor holds itself to 5 requests a second against the search API and 10 against the official API whatever you set here.",
            "default": 4
          },
          "maxRunSecs": {
            "title": "Time budget (seconds)",
            "minimum": 30,
            "maximum": 3600,
            "type": "integer",
            "description": "Stop after this many seconds. Rows already returned are kept and a free `timeout` row says what was left.",
            "default": 240
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "Both Hacker News APIs answered every request from the Apify datacenter proxy and from no proxy at all, so datacenter is the default and residential buys nothing here at forty times the price.",
            "default": {
              "useApifyProxy": true
            }
          }
        }
      },
      "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
                  }
                }
              },
              "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}