{
  "openapi": "3.0.1",
  "info": {
    "title": "HN Who is Hiring — AI Structured Jobs",
    "description": "Hacker News monthly 'Who is hiring?' posts parsed by AI into clean job rows: salary range, remote regions, visa, tech stack, apply links.",
    "version": "0.1",
    "x-build-id": "iAhP8LXwD2ghiUeAJ"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/arthur_taken~hn-who-is-hiring-ai/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-arthur_taken-hn-who-is-hiring-ai",
        "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/arthur_taken~hn-who-is-hiring-ai/runs": {
      "post": {
        "operationId": "runs-sync-arthur_taken-hn-who-is-hiring-ai",
        "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/arthur_taken~hn-who-is-hiring-ai/run-sync": {
      "post": {
        "operationId": "run-sync-arthur_taken-hn-who-is-hiring-ai",
        "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": {
          "months": {
            "title": "Months",
            "type": "array",
            "description": "Which monthly threads to search: 'latest' (newest month with data), 'all' (every month covered, about the last 12), or YYYY-MM such as '2026-09'. More months = more rows and more cost. If a month has no data, the run log and status message list the months that do.",
            "items": {
              "type": "string",
              "pattern": "^(latest|all|\\d{4}-\\d{1,2})$"
            },
            "default": [
              "latest"
            ]
          },
          "workModes": {
            "title": "Work mode",
            "type": "array",
            "description": "Keep only these work modes. For remote jobs, include both 'remote' and 'remote_or_onsite' (roles where the candidate can choose). Empty = all modes, including 'unspecified'.",
            "items": {
              "type": "string",
              "enum": [
                "remote",
                "hybrid",
                "onsite",
                "remote_or_onsite"
              ],
              "enumTitles": [
                "Remote",
                "Hybrid",
                "Onsite",
                "Remote or onsite"
              ]
            }
          },
          "techStack": {
            "title": "Tech stack (any of)",
            "type": "array",
            "description": "Keep roles whose tech_stack contains at least one of these names. Exact name match, case-insensitive, so use canonical names: 'PostgreSQL' (not 'Postgres'), 'Node.js', 'Go', 'Kubernetes'. Add aliases when unsure, e.g. ['Rails', 'Ruby on Rails'] or ['GCP', 'Google Cloud Platform']. For looser text search use keywords.",
            "items": {
              "type": "string"
            }
          },
          "regions": {
            "title": "Regions / locations (any of)",
            "type": "array",
            "description": "Keep roles whose remote regions or office locations contain one of these terms (case-insensitive, matched at word start). Common remote regions: US, Worldwide, EU, Europe, Canada, UK, LATAM. Office locations are free text such as 'Berlin, Germany' or 'Austin, TX', so 'US' does not match 'Austin, TX' — add city or state names if you need onsite roles.",
            "items": {
              "type": "string"
            }
          },
          "keywords": {
            "title": "Keywords (any of)",
            "type": "array",
            "description": "Free-text filter over job title, company name, company summary and tech stack (case-insensitive, matched at word start: 'engineer' matches 'Engineering', 'ML' does not match 'HTML'). Use it for roles or domains, e.g. 'data engineer', 'infrastructure', 'fintech'.",
            "items": {
              "type": "string"
            }
          },
          "requireVisaSponsorship": {
            "title": "Only jobs that offer visa sponsorship",
            "type": "boolean",
            "description": "Keep only roles whose post explicitly offers visa sponsorship (visa_sponsorship = 'yes'). Most posts don't mention visas, so this removes about 98% of rows.",
            "default": false
          },
          "excludeCitizenshipRequired": {
            "title": "Exclude jobs requiring citizenship or security clearance",
            "type": "boolean",
            "description": "Drop roles that state a citizenship/residency requirement or require a security clearance. Useful for candidates outside the hiring country.",
            "default": false
          },
          "seniority": {
            "title": "Seniority (any of)",
            "type": "array",
            "description": "Keep only these seniority levels. Most posts don't state seniority ('unspecified' is about 40% of rows), so include 'unspecified' if you don't want to miss roles.",
            "items": {
              "type": "string",
              "enum": [
                "intern",
                "junior",
                "mid",
                "senior",
                "staff",
                "principal",
                "lead",
                "manager",
                "director",
                "executive",
                "unspecified"
              ]
            }
          },
          "categories": {
            "title": "Job category (any of)",
            "type": "array",
            "description": "Keep only these job families (inferred from the title and duties), e.g. 'data', 'ml_ai', 'devops_infra'.",
            "items": {
              "type": "string",
              "enum": [
                "software_engineering",
                "data",
                "ml_ai",
                "devops_infra",
                "security",
                "product",
                "design",
                "research",
                "sales_marketing",
                "operations",
                "hardware",
                "other"
              ]
            }
          },
          "employmentTypes": {
            "title": "Employment type (any of)",
            "type": "array",
            "description": "Keep only these contract types. Most roles are 'full_time'.",
            "items": {
              "type": "string",
              "enum": [
                "full_time",
                "part_time",
                "contract",
                "internship",
                "unspecified"
              ]
            }
          },
          "minAnnualSalary": {
            "title": "Minimum annual salary",
            "minimum": 0,
            "type": "integer",
            "description": "Keep roles whose stated salary (upper bound, or lower bound if no upper bound) is at least this much per year. Hourly and monthly pay are converted (x2080, x12). Roles without a stated salary (about 70%) are dropped. Combine with salaryCurrencies to avoid mixing currencies."
          },
          "salaryCurrencies": {
            "title": "Salary currencies (any of)",
            "type": "array",
            "description": "Keep roles paid in these ISO 4217 currencies, e.g. USD, EUR, GBP. Roles without a stated salary are dropped when this is set.",
            "items": {
              "type": "string"
            }
          },
          "postedAfter": {
            "title": "Posted after",
            "pattern": "^(\\d{4}-\\d{2}-\\d{2}.*|\\d+\\s*days?)$",
            "type": "string",
            "description": "Keep posts published on or after this date: '2026-09-15' or relative like '7 days'. Applies within the selected months, so use months ['all'] for ranges that cross a month."
          },
          "excludeReposts": {
            "title": "Exclude reposts",
            "type": "boolean",
            "description": "Drop roles that the same company already posted with the same title in an earlier month (is_repost = true). Useful to see only genuinely new openings.",
            "default": false
          },
          "onlyNew": {
            "title": "Only rows I haven't received yet",
            "type": "boolean",
            "description": "For scheduled runs: return only job rows you haven't received from this Actor with the same filters. Seen job IDs are kept in a key-value store named 'hn-who-is-hiring-state' in your account. With months 'latest', the last 2 months are checked so late posts are not missed.",
            "default": false
          },
          "maxItems": {
            "title": "Max results",
            "minimum": 1,
            "type": "integer",
            "description": "Maximum number of job rows to return. Each row is billed, so this caps your cost. Empty = all matching rows (about 500-650 per month when no other filter is set)."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}