{
  "openapi": "3.0.1",
  "info": {
    "title": "ATS Jobs Openings Scraper – Greenhouse, Ashby, Lever, Recruitee",
    "description": "Live jobs from Greenhouse, Ashby, Lever, Recruitee, Workable, SmartRecruiters and Workday in one schema, auto-detected from the slug. Top-level department plus team, not the nested cost-centre name. City/region/country from free text. Pay ranges, even in-posting ones. Filter before you pay.",
    "version": "0.1",
    "x-build-id": "QL3qmBfCPE1G2QHee"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/fetchsmith~ats-jobs-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-fetchsmith-ats-jobs-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~ats-jobs-scraper/runs": {
      "post": {
        "operationId": "runs-sync-fetchsmith-ats-jobs-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~ats-jobs-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-fetchsmith-ats-jobs-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": [
          "companies"
        ],
        "properties": {
          "companies": {
            "title": "Companies",
            "type": "array",
            "description": "List of {\"ats\": \"auto|greenhouse|ashby|lever|recruitee|workable|smartrecruiters|workday\", \"slug\": \"<company-slug-from-their-career-board-url>\"}. Omit \"ats\" or set it to \"auto\" to auto-detect the platform from the slug alone (tries all 6 non-Workday platforms and keeps whichever one actually has a board there) — useful when you know a company's slug but not which ATS they use. Examples when you do know the platform: careers.airbnb.com/... uses Greenhouse slug \"airbnb\"; jobs.ashbyhq.com/ramp uses Ashby slug \"ramp\"; apply.workable.com/getresponse uses Workable slug \"getresponse\"; jobs.smartrecruiters.com/BMWDealerCareers uses SmartRecruiters slug \"BMWDealerCareers\" (case-sensitive); Workday uses \"<host>/<site>\" from the board's own URL, e.g. \"okgov.wd1.myworkdayjobs.com/okgovjobs\" — Workday cannot be auto-detected and always needs an explicit \"ats\": \"workday\".",
            "default": [
              {
                "ats": "greenhouse",
                "slug": "airbnb"
              },
              {
                "ats": "ashby",
                "slug": "ramp"
              },
              {
                "ats": "lever",
                "slug": "leverdemo"
              },
              {
                "ats": "recruitee",
                "slug": "vandebron"
              },
              {
                "ats": "workable",
                "slug": "getresponse"
              },
              {
                "ats": "smartrecruiters",
                "slug": "ElasticBandCompany"
              },
              {
                "ats": "workday",
                "slug": "okgov.wd1.myworkdayjobs.com/okgovjobs"
              }
            ]
          },
          "titleKeyword": {
            "title": "Title keyword filter",
            "type": "string",
            "description": "Only keep postings whose title contains this text (case-insensitive). Leave empty for all titles."
          },
          "titleExcludeKeyword": {
            "title": "Title exclude keyword",
            "type": "string",
            "description": "Drop postings whose title contains this text (case-insensitive), e.g. \"Senior\" to filter out senior roles. Leave empty for no exclusion."
          },
          "locationKeyword": {
            "title": "Location keyword filter",
            "type": "string",
            "description": "Only keep postings whose location/city/region/country contains this text (case-insensitive). City, region and country are the normalized breakdown, so \"United States\" matches a posting whose own text only reads \"San Francisco, CA\". Leave empty for all locations."
          },
          "locationExcludeKeyword": {
            "title": "Location exclude keyword",
            "type": "string",
            "description": "Drop postings whose location/city/region/country/secondary locations contains this text (case-insensitive), e.g. a country you don't hire in. Matching uses the normalized breakdown too, so \"United States\" also drops a posting whose own text only reads \"San Francisco, CA\". Leave empty for no exclusion."
          },
          "employmentTypeKeyword": {
            "title": "Employment type filter",
            "type": "string",
            "description": "Only keep postings whose employmentType field contains this text, matched case- and separator-insensitively (spaces/hyphens/underscores ignored on both sides, so \"full-time\" matches Ashby's \"FullTime\"), e.g. \"full-time\" or \"contract\". Leave empty for all employment types. Not every ATS publishes this field; postings where the ATS never exposes it are dropped when this filter is set."
          },
          "departmentKeyword": {
            "title": "Department filter",
            "type": "string",
            "description": "Only keep postings whose department, team or department path contains this text (case-insensitive), e.g. \"Engineering\" or \"Sales\". On Greenhouse, `department` is the board's top-level department and `team` is the sub-team the role sits in, and this filter searches the whole chain. Leave empty for all departments. Not every ATS publishes a department; postings where it is missing are dropped when this filter is set."
          },
          "descriptionKeyword": {
            "title": "Description keyword filter",
            "type": "string",
            "description": "Only keep postings whose full job description text contains this text (case-insensitive), e.g. \"Kubernetes\" or \"visa sponsorship\" — the things a title never says. Matched against the plain text, not the HTML. Leave empty for no description filter."
          },
          "descriptionExcludeKeyword": {
            "title": "Description exclude keyword",
            "type": "string",
            "description": "Drop postings whose job description text contains this text (case-insensitive), e.g. \"security clearance\". Leave empty for no exclusion."
          },
          "hasSalary": {
            "title": "Only postings with salary",
            "type": "boolean",
            "description": "Only keep postings that come back with a salaryMin or salaryMax — either a compensation field the ATS exposes (Ashby, Lever, Recruitee) or a pay-transparency range printed inside the posting body (Greenhouse). The Actor reads no pay from Workable, SmartRecruiters or Workday, so their postings are always dropped when this is on; so are Greenhouse boards that never turned pay transparency on.",
            "default": false
          },
          "minSalary": {
            "title": "Min salary",
            "minimum": 0,
            "type": "integer",
            "description": "Only keep postings whose salary range overlaps this floor or higher, e.g. 100000. Compared against the number as the ATS posted it — no currency conversion and no pay-interval normalization (salaryInterval varies: year, month, week, day, hour — check salaryCurrency/salaryInterval on the output row). Postings with no salary at all never match. Leave empty for no floor."
          },
          "maxSalary": {
            "title": "Max salary",
            "minimum": 0,
            "type": "integer",
            "description": "Only keep postings whose salary range overlaps this ceiling or lower. Same currency/interval caveat as Min salary. Leave empty for no ceiling."
          },
          "remoteOnly": {
            "title": "Remote only",
            "type": "boolean",
            "description": "Only keep postings the ATS itself marks as remote.",
            "default": false
          },
          "postedAfter": {
            "title": "Posted after (ISO date)",
            "type": "string",
            "description": "Only keep postings published on or after this date, e.g. 2026-08-01. The whole day named is INCLUDED (the bound starts at 00:00:00 UTC). Must be YYYY-MM-DD or a full ISO datetime (2026-08-01T12:00:00Z) — US-style (06/15/2026), partial (2026-8-1) and calendar-impossible (2026-02-30) values STOP the run with an error instead of being guessed at or dropped, because a silently-dropped date bound would return the unfiltered set and you would be billed for every row it should have removed. Leave empty for no date filter."
          },
          "postedBefore": {
            "title": "Posted before (ISO date)",
            "type": "string",
            "description": "Only keep postings published on or before this date, e.g. 2026-09-01. The whole day named is INCLUDED (the bound ends at 23:59:59.999 UTC), so postedAfter 2026-08-01 + postedBefore 2026-08-31 is exactly August. Same strict parsing as \"Posted after\": an unparseable date stops the run rather than quietly widening your window. Pair with \"Posted after\" for a date window, e.g. everything a company opened during one quarter. Leave empty for no upper bound."
          },
          "includeDescriptions": {
            "title": "Include job descriptions",
            "type": "boolean",
            "description": "Include the full HTML and plain-text job description. Turn off for a smaller/faster dataset. The description keyword filters still work with this off — the text is fetched, matched, then dropped from the rows.",
            "default": true
          },
          "maxJobsPerCompany": {
            "title": "Max jobs per company",
            "minimum": 1,
            "maximum": 5000,
            "type": "integer",
            "description": "Cap on how many postings that pass your filters are kept per company (the filters are applied first, then this cap). Kept low by default so a run with no input at all finishes fast and cheap on a first try; raise it explicitly for bulk pulls.",
            "default": 50
          },
          "maxResults": {
            "title": "Max results (total)",
            "minimum": 1,
            "maximum": 100000,
            "type": "integer",
            "description": "Stop the whole run after this many postings are pushed, across all companies. Kept low by default so a run with no input at all finishes fast and cheap on a first try; raise it explicitly for bulk pulls.",
            "default": 300
          },
          "watchLabel": {
            "title": "Watch label (only new postings since last run)",
            "type": "string",
            "description": "Optional. Name a saved job alert (e.g. \"backend-remote-eu\") and this run returns ONLY postings that were not delivered under that same label and filter set before, instead of the whole open-roles list every time. The first run for a label is a free baseline: it records which postings are already open (up to 5000) and returns zero rows, charging nothing. Run it again later -- on a schedule, typically -- to get only the roles that opened since then. The baseline lives in your own Apify account (a named key-value store, \"fetchsmith-ats-watch\"), keyed by the label plus a fingerprint of the company list and every filter, so changing any of those starts a fresh baseline instead of dumping previously-excluded postings as \"new\"."
          },
          "watchEvents": {
            "title": "Watch events to report",
            "type": "array",
            "description": "Optional. Only report these kinds of change in watch mode — e.g. pick \"Salary appeared\" alone to be alerted only when an already-delivered posting later gains a salary (a pay-transparency add-on or a plain edit), and never pay for anything else. Leave empty for both. Greenhouse, Ashby, Lever, and Recruitee postings commonly publish without a salary and add one later under the same posting id — without this event that already-delivered posting looks identical to a watch forever. Postings on SmartRecruiters/Workable/Workday never carry a salary at all, so salaryAdded never fires for those. The change event compares against the salary state recorded the last time the posting was delivered, so it only starts firing on the second run after a baseline created before this feature existed. Ignored when \"Watch label\" is empty.",
            "items": {
              "type": "string",
              "enum": [
                "new",
                "salaryAdded"
              ],
              "enumTitles": [
                "New posting",
                "Salary appeared (posting already delivered, now shows a salary)"
              ]
            },
            "default": []
          },
          "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 — job postings pushed, companies scanned and how many boards errored, plus watch-label new/skipped counts if Watch label is set, and 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 posting has already been pushed and charged. Leave empty to skip."
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Route requests through Apify Proxy (recommended, on by default).",
            "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
                  },
                  "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}