{
  "openapi": "3.0.1",
  "info": {
    "title": "Hacker News (HN) API Scraper – Who Is Hiring, Tech News API",
    "description": "Search or browse Hacker News stories, comments, Ask HN, Show HN and Who's Hiring threads via the official Algolia API: full-text Hacker News search, Hacker News jobs threads and startup news feeds. Filter by points, date and exclude keywords. Pay per item. Also a keyword monitoring API for alerts.",
    "version": "0.1",
    "x-build-id": "fpEaLyLalcF8Ou1Xr"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/fetchsmith~hacker-news-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-fetchsmith-hacker-news-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/fetchsmith~hacker-news-scraper/runs": {
      "post": {
        "operationId": "runs-sync-fetchsmith-hacker-news-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/fetchsmith~hacker-news-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-fetchsmith-hacker-news-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",
        "properties": {
          "queries": {
            "title": "Search queries",
            "type": "array",
            "description": "Keywords to search for. Leave empty to browse by tag/date only (e.g. latest front-page stories or the newest Who's Hiring thread).",
            "default": [
              "apify"
            ],
            "items": {
              "type": "string"
            }
          },
          "tags": {
            "title": "Filter by tag",
            "type": "array",
            "description": "story, comment, poll, ask_hn, show_hn, job, front_page. Listing several tags returns items matching ANY of them (they are OR-ed): [\"story\",\"comment\"] returns both stories and comments, [\"story\"] alone returns posts only.",
            "default": [
              "story"
            ],
            "items": {
              "type": "string"
            }
          },
          "includeComments": {
            "title": "Include comments",
            "type": "boolean",
            "description": "If tags includes 'comment', set true to fetch comment text too. Set false to drop comments; if 'comment' is the only tag you asked for, the run is skipped with a warning rather than silently widening the search to every other content type.",
            "default": true
          },
          "sortBy": {
            "title": "Sort order",
            "enum": [
              "relevance",
              "date"
            ],
            "type": "string",
            "description": "'relevance' ranks by search relevance and points; 'date' returns the newest items first.",
            "default": "relevance"
          },
          "minPoints": {
            "title": "Minimum points",
            "minimum": 0,
            "type": "integer",
            "description": "Only return stories/comments with at least this many points."
          },
          "minComments": {
            "title": "Minimum comments",
            "minimum": 0,
            "type": "integer",
            "description": "Only return stories with at least this many comments (e.g. find high-engagement discussions)."
          },
          "excludeKeywords": {
            "title": "Exclude keywords",
            "type": "array",
            "description": "Drop any story/comment whose title or text contains any of these words/phrases (case-insensitive). HN's search has no negative-term syntax, so this is applied to the matches after fetching, before you're charged -- e.g. queries:[\"rust\"], excludeKeywords:[\"cryptocurrency\"] keeps rust-the-language discussions and drops rust-the-crypto-project ones.",
            "items": {
              "type": "string"
            }
          },
          "author": {
            "title": "Author username",
            "type": "string",
            "description": "Only return items posted by this exact HN username."
          },
          "usernames": {
            "title": "User profiles to look up",
            "type": "array",
            "description": "HN usernames to fetch profile data for (karma, about text, account creation date) — a separate lookup from the story/comment search above. To fetch ONLY user profiles with no story search, also set 'Search queries' and 'Filter by tag' to empty ([]).",
            "items": {
              "type": "string"
            }
          },
          "postedAfter": {
            "title": "Posted after (ISO date)",
            "type": "string",
            "description": "e.g. 2026-01-01"
          },
          "postedBefore": {
            "title": "Posted before (ISO date)",
            "type": "string",
            "description": "e.g. 2026-09-01"
          },
          "maxItemsPerQuery": {
            "title": "Max items per query",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap per search query/tag combination.",
            "default": 100
          },
          "maxResults": {
            "title": "Max results (total)",
            "minimum": 1,
            "maximum": 5000,
            "type": "integer",
            "description": "Overall cap across all queries.",
            "default": 200
          },
          "watchLabel": {
            "title": "Watch label (only new since last run)",
            "type": "string",
            "description": "Optional. Name a saved search (e.g. \"my-launch-watch\") and this run returns ONLY story/comment/job hits not delivered under that same label and filter set before, instead of the full match set every time. The first run for a label is a free baseline: it records what already matches (up to 5000 hits) and returns zero rows. Run it again later -- on a schedule, typically -- to get only what's new. The baseline is kept in your own Apify account (a named key-value store), keyed by label plus a fingerprint of queries/tags/author/sort/date-range/point-comment thresholds, so changing any of those starts a fresh baseline instead of dumping previously-excluded items as \"new\". Applies to the query/tag search only -- 'User profiles to look up' still runs and is charged normally every time, since a profile snapshot isn't a discrete new item."
          },
          "watchChanges": {
            "title": "Also alert when a watched item hits a points/comments milestone",
            "type": "boolean",
            "description": "Only used with a Watch label. By default watch mode alerts on brand-new items only: a story you were already delivered goes quiet forever, even if it later climbs to the front page, because its HN id never changes. Turn this on and an already-delivered item is re-delivered (and charged again, like a new row) when its points or comment count CROSSES one of the milestones below -- so you hear about a story breaking 100 or 500 points, not about every single upvote. Each milestone pays out at most once per item: a story crawling from 51 to 99 points over twenty scheduled runs returns nothing, then returns once when it reaches 100. Re-delivered rows carry _watchChangeType, _watchPrevious and _watchMilestone so you can see exactly what moved. Off by default.",
            "default": false
          },
          "watchPointMilestones": {
            "title": "Points milestones",
            "type": "string",
            "description": "Comma-separated point thresholds for the option above, e.g. \"25,50,100,250,500,1000,2500,5000\" (the default). Pick a ladder that matches your queries: Show HN and niche-tag watches rarely pass 100, while a front-page watch spends most of its life above it, and a ladder that is too fine re-charges you more often than you want. Leave EMPTY to disable points alerts and keep comment alerts only. Ignored unless the option above is on.",
            "default": "25,50,100,250,500,1000,2500,5000"
          },
          "watchCommentMilestones": {
            "title": "Comment-count milestones",
            "type": "string",
            "description": "Comma-separated comment-count thresholds, same rules as the points ladder above -- a discussion crossing 50 or 100 comments is usually the signal people watch for. Default \"25,50,100,250,500,1000\". Leave EMPTY to disable comment alerts and keep points alerts only. Ignored unless 'Also alert when a watched item hits a points/comments milestone' is on.",
            "default": "25,50,100,250,500,1000"
          },
          "enrichGithubLinks": {
            "title": "Enrich GitHub links",
            "type": "boolean",
            "description": "When a story/comment's URL or text links to a GitHub repo (common on Show HN and technical discussions), looks it up on GitHub's public API and adds star count, primary language, last-push date, and open-issue count. Checks the item's own URL first, then its text, then its title -- for a comment (which has no URL of its own), that means the PARENT STORY's linked repo wins over any different repo the comment's own text names, whenever the story links to GitHub. Off by default -- adds one extra request per distinct repo found, bounded to 200 lookups per run against GitHub's unauthenticated 60/hour limit; repos already looked up earlier in the same run are cached, not re-fetched.",
            "default": false
          },
          "webhookUrl": {
            "title": "Webhook URL (notify on completion)",
            "type": "string",
            "description": "Optional. An http(s) URL to POST a small JSON summary to when the run finishes -- items pushed, hits scanned, and (when Watch label is set) whether this was a baseline run plus the new/skipped counts, along with the run's dataset ID so you can fetch the results. A convenience for callers who want a completion ping without setting up an Apify platform webhook (which needs separate Console/API configuration per Task, not per run). Best-effort: a failed or slow webhook is logged as a warning and never fails the run or affects charging -- it fires after every item has already been pushed and charged. Leave empty to skip."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}