{
  "openapi": "3.0.1",
  "info": {
    "title": "Greenhouse, Lever, Ashby, Workable Jobs Scraper + Job Monitor",
    "description": "Greenhouse, Lever, Ashby, Workable & Recruitee jobs scraper + monitor — open roles from each company's live feed in one normalized schema. $1 per 1,000 jobs, $0 start. Optional diff mode, off by default: the first run bills the jobs delivered; later runs bill new + watched-field changes.",
    "version": "0.2",
    "x-build-id": "2LGK9Gyskbh7RImYU"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/wickfeed~ats-job-aggregator/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-wickfeed-ats-job-aggregator",
        "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/wickfeed~ats-job-aggregator/runs": {
      "post": {
        "operationId": "runs-sync-wickfeed-ats-job-aggregator",
        "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/wickfeed~ats-job-aggregator/run-sync": {
      "post": {
        "operationId": "run-sync-wickfeed-ats-job-aggregator",
        "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": {
          "companies": {
            "title": "Company names or careers URLs",
            "type": "array",
            "description": "Leave this blank to run the 5 prefilled demo boards below. Maximum first-run cost: $0.25. Or type a company NAME (e.g. \"Stripe\") or paste an ATS careers/board URL (e.g. \"https://boards.greenhouse.io/stripe\") — the actor finds the hiring system and board for you, no tokens to hunt. A careers/board URL is the most reliable; a bare name is best-effort (some companies can't be matched by name — those are reported, never charged, with the reason and a prompt to paste the careers URL or { ats, token } instead). Resolution is FREE; you pay only for the jobs the matched boards return. Merges with the preset and Sources lists below.",
            "items": {
              "type": "string"
            }
          },
          "preset": {
            "title": "Company list preset",
            "enum": [
              "none",
              "starter-500",
              "engineering",
              "sales",
              "healthcare",
              "finance",
              "all-verified"
            ],
            "type": "string",
            "description": "Start from a bundled, verified-live company list — no need to hand-type board tokens. Leave this on \"None\" to use the Sources box below (prefilled with 5 demo boards for an instant, low-cost first run — up to about $0.25, usually ~$0.17). Switch to \"Starter 500\" for full coverage: the 500 boards with the most active jobs, all confirmed live on 2026-07-15 (a first full run costs up to about $25 at the default 50-jobs cap — lower \"Max results per source\" to reduce it). A preset is MERGED with anything you add in Sources (duplicates removed by ats:token), so you can layer your own boards on top. Board counts — Starter 500: 500 · Engineering: 457 · Sales: 132 · Healthcare: 53 · Finance: 37 · All verified: 1,925. FIRST-RUN COST CEILING at the default cap (boards × 50 × $1/1,000) — Starter 500 ≈ $25 · Engineering ≈ $23 · Sales ≈ $6.60 · Healthcare ≈ $2.65 · Finance ≈ $1.85 · All verified ≈ $96; these are ceilings and real runs are usually well under (many boards post fewer than 50 jobs, dead boards are never charged). The free plan's $5 monthly credit covers the demo, Finance and Healthcare; lower \"Max results per source\" to shrink any run. In diff mode the first run bills for the whole board like a normal run; later runs charge only for new and changed jobs. Presets currently cover Greenhouse, Ashby, Workable and Recruitee (Lever boards can still be added by hand in Sources).",
            "default": "none"
          },
          "sources": {
            "title": "Sources (advanced — exact boards)",
            "type": "array",
            "description": "The explicit, power-user path: one entry per company job board as { \"ats\": \"greenhouse|lever|ashby|workable|recruitee\", \"token\": \"<board-token>\" }. Prefer the \"Company names or careers URLs\" box above if you don't already know the token — it resolves names/URLs into these entries for you. The token is the company's board identifier in that ATS (e.g. Greenhouse board \"stripe\", Lever site \"spotify\", Ashby org \"ashby\", Workable subdomain \"huggingface\", Recruitee subdomain \"grid\"). Optional — the companies, preset, and this list are all merged (duplicates removed). Malformed or duplicate entries are skipped, not fatal; the run fails only when there is no usable board at all.",
            "items": {
              "type": "object",
              "properties": {
                "ats": {
                  "type": "string",
                  "title": "ATS",
                  "description": "Which applicant-tracking system this board lives on.",
                  "enum": [
                    "greenhouse",
                    "lever",
                    "ashby",
                    "workable",
                    "recruitee"
                  ]
                },
                "token": {
                  "type": "string",
                  "title": "Board token",
                  "description": "The company's board identifier in that ATS, read off its careers URL (e.g. \"stripe\")."
                }
              },
              "required": [
                "ats",
                "token"
              ]
            }
          },
          "maxCompanies": {
            "title": "Max company names to look up per run",
            "minimum": 1,
            "maximum": 200,
            "type": "integer",
            "description": "Advanced. Caps how many entries in \"Company names or careers URLs\" the actor looks up per run (keeps runs fast and predictable). Default 25, max 200. Any extra entries are reported as skipped and never charged. Looking a company up is always free — this only limits how many lookups happen at once.",
            "default": 25
          },
          "diffMode": {
            "title": "Only new & changed jobs (diff mode)",
            "type": "boolean",
            "description": "Get only jobs that are NEW or CHANGED since the last run, not the whole board each time. Each delivered job is tagged changeType (\"new\" or \"changed\") plus a firstSeenAt date, and you pay only for those — unchanged jobs cost nothing. Your first run has no history yet, so it charges for everything; later runs stay small. Best paired with a daily Apify schedule. Jobs that disappeared are listed under CLOSED_JOBS on the run's Storage tab. For a clean monitor of your own hand-entered boards, set a fixed \"Monitoring memory name\" below (preset monitors are already stable). Keep \"Max results per source\" at or above each board's job count for accurate closed-job detection — see the README's diff-mode rules.",
            "default": false
          },
          "diffStateKey": {
            "title": "Monitoring memory name (optional, advanced)",
            "type": "string",
            "description": "Advanced, optional — most people leave this blank. In diff mode the actor remembers what it saw last time so it can show you only what's new; this just gives that memory a name. Leave it blank and the actor names it for you. Set a fixed name only if you want one steady monitor that survives edits to your board list — and if you do, change your keyword/location filters by starting a NEW name rather than editing the old one (editing filters under a fixed name can re-bill jobs). Full rules are in the README under \"Diff mode\". Best to use letters, numbers, dot, dash, and underscore; other characters are made safe automatically, and each distinct name always keeps its own separate memory."
          },
          "keywords": {
            "title": "Keywords",
            "type": "array",
            "description": "Keep only jobs whose title, department or description contains ANY of these (case-insensitive). Leave empty for no keyword filtering.",
            "items": {
              "type": "string"
            }
          },
          "locations": {
            "title": "Locations",
            "type": "array",
            "description": "Keep only jobs whose location contains ANY of these substrings (case-insensitive). Leave empty for no location filtering.",
            "items": {
              "type": "string"
            }
          },
          "remoteOnly": {
            "title": "Remote only",
            "type": "boolean",
            "description": "Keep only jobs the hiring system explicitly marks as remote. Heads-up: jobs where the source didn't say either way are also dropped while this is on, so a board that doesn't tag remote can come back empty — leave this off and filter by Location if you're not sure.",
            "default": false
          },
          "postedAfter": {
            "title": "Posted after",
            "type": "string",
            "description": "Keep only jobs posted on/after this date (e.g. 2026-01-01). Jobs with an unknown post date are excluded when set. An unreadable date is rejected with a clear error — it never silently turns the filter off. Leave blank to not filter by date."
          },
          "maxResultsPerSource": {
            "title": "Max results per source",
            "minimum": 1,
            "maximum": 100000,
            "type": "integer",
            "description": "Cap on the number of MATCHING jobs delivered per board. Your keyword/location/remote/date filters run over the whole board first, then the matches are capped — so a matching job is never hidden past the cap. Defaults to 50 so a first run stays fast and light; raise it once you're happy with the output. In diff mode, keep this at or above each board's number of matching jobs for accurate closed-job detection — if a board has more matching jobs than the cap, the actor skips closed detection for it that run rather than reporting false closures.",
            "default": 50
          },
          "includeHtml": {
            "title": "Include raw HTML description",
            "type": "boolean",
            "description": "Also include the original HTML job description as descriptionHtml. Off by default to keep records lean.",
            "default": false
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}