{
  "openapi": "3.0.1",
  "info": {
    "title": "s1jobs Scraper – Scotland & UK Jobs, Salaries & Details",
    "description": "Scrape jobs from s1jobs.com across Scotland and the UK. Search by keyword, location, or URLs. Returns title, parsed salary band, company, logo, GPS location, skills, contract type, and 90+ fields per job, with optional full description, postcode, and apply links.",
    "version": "1.0",
    "x-build-id": "KEl9UeWnrbbG64Fz0"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/abotapi~s1jobs-com-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-abotapi-s1jobs-com-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/abotapi~s1jobs-com-scraper/runs": {
      "post": {
        "operationId": "runs-sync-abotapi-s1jobs-com-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/abotapi~s1jobs-com-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-abotapi-s1jobs-com-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": [
          "mode"
        ],
        "properties": {
          "mode": {
            "title": "Mode",
            "enum": [
              "search",
              "url"
            ],
            "type": "string",
            "description": "How to find jobs: build a search from filters, or paginate URLs you paste.",
            "default": "search"
          },
          "locations": {
            "title": "Locations",
            "type": "array",
            "description": "Towns, cities, or counties. Examples: 'Glasgow', 'Edinburgh', 'Aberdeen', 'Fife'. One search runs per location. s1jobs searches the area around the place you name, so nearby commutable towns come back too (a Glasgow search also returns jobs in Renfrew and Wishaw). If s1jobs does not list the name on its own, the closest name it does list is used instead, for example 'Oban' becomes 'Oban, Argyll and Bute'. Leave empty to list jobs from everywhere. Search mode only: this builds the search URL and is NOT applied to the URLs you paste in URL mode.",
            "items": {
              "type": "string"
            }
          },
          "keywords": {
            "title": "Keywords",
            "type": "string",
            "description": "Role, skill, or company to search for. Example: 'nurse', 'warehouse', 'project manager', 'driver'. Leave empty to list all jobs in the location. Search mode only: this builds the search URL and is NOT applied to the URLs you paste in URL mode."
          },
          "contractType": {
            "title": "Contract type",
            "enum": [
              "any",
              "permanent",
              "contract",
              "temporary"
            ],
            "type": "string",
            "description": "Filter by contract arrangement. Search mode only: this filter is applied to search results and is NOT applied to the URLs you paste in URL mode.",
            "default": "any"
          },
          "workingHours": {
            "title": "Hours",
            "enum": [
              "any",
              "full",
              "part"
            ],
            "type": "string",
            "description": "Filter by full time or part time. Search mode only: this filter is applied to search results and is NOT applied to the URLs you paste in URL mode.",
            "default": "any"
          },
          "advertiserType": {
            "title": "Advertiser type",
            "enum": [
              "any",
              "employer",
              "agency"
            ],
            "type": "string",
            "description": "Restrict to direct employers or recruitment agencies. Search mode only: this filter is applied to search results and is NOT applied to the URLs you paste in URL mode.",
            "default": "any"
          },
          "minSalary": {
            "title": "Minimum salary",
            "minimum": 0,
            "type": "integer",
            "description": "Lowest salary to include. Combined with the salary period below. Jobs that quote no numeric salary (for example 'Competitive') are always kept. Leave empty for no minimum. Search mode only: this filter is applied to search results and is NOT applied to the URLs you paste in URL mode."
          },
          "salaryType": {
            "title": "Salary period",
            "enum": [
              "annual",
              "daily",
              "hourly"
            ],
            "type": "string",
            "description": "Unit for the minimum salary filter. Search mode only, exactly like the minimum salary it belongs to.",
            "default": "annual"
          },
          "publicSectorOnly": {
            "title": "Public sector only",
            "type": "boolean",
            "description": "Keep only public-sector roles. Search mode only: this filter is applied to search results and is NOT applied to the URLs you paste in URL mode.",
            "default": false
          },
          "hasVideoOnly": {
            "title": "Jobs with video only",
            "type": "boolean",
            "description": "Keep only jobs that include a recruiter video. Search mode only: this filter is applied to search results and is NOT applied to the URLs you paste in URL mode.",
            "default": false
          },
          "sortBy": {
            "title": "Sort by",
            "enum": [
              "relevance",
              "date"
            ],
            "type": "string",
            "description": "Result ordering. Search mode only: it is written into the search URL. In URL mode the ordering already present in the URL you paste is used instead.",
            "default": "relevance"
          },
          "urls": {
            "title": "Search URLs",
            "type": "array",
            "description": "s1jobs.com search-result URLs to scrape (URL mode). Multi-URL supported. The Search mode fields above (locations, keywords, contract type, hours, advertiser type, minimum salary, public sector only, jobs with video only and sort) are NOT applied to these URLs, so build the filtering you want into the URL itself. A page number in the URL is honoured as the starting point for results.",
            "items": {
              "type": "string"
            }
          },
          "fetchDetails": {
            "title": "Fetch full job details",
            "type": "boolean",
            "description": "Fetch the per-job record to add the full description, postcode, structured location, salary band, matched and unmatched skills, accreditations and apply links. Adds ~20 fields. On = richest output (recommended). Off = fast, listing fields only.",
            "default": true
          },
          "maxListings": {
            "title": "Max jobs",
            "minimum": 0,
            "type": "integer",
            "description": "Total jobs to collect across all searches. This is THE limit on the run (default 20). Set 0 for unlimited.",
            "default": 20
          },
          "maxPages": {
            "title": "Max pages per search",
            "minimum": 0,
            "type": "integer",
            "description": "Optional per-search safety stop on pages walked (20 jobs per page). This does NOT cap the run - leave it empty (unlimited) and the run defers to Max jobs for its size, walking every result page. Only set a value if you want to hard-stop pagination for one location/URL early."
          },
          "resumeFromRunId": {
            "title": "Resume from a previous run (optional)",
            "type": "string",
            "description": "ID of a previous run of this actor (or a dataset ID). Jobs already in that dataset (matched by job id) are skipped, so this run returns only NEW jobs, a delta. Combine both runs' datasets for the full set. Leave empty for a normal fresh run. For recurring daily monitoring of the same search, use Incremental mode below instead."
          },
          "incrementalMode": {
            "title": "Incremental changes for scheduled runs",
            "type": "boolean",
            "description": "Turn this on for daily or recurring monitoring. The first run returns all matching jobs as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED jobs. Turn on \"Emit unchanged\" or \"Emit expired\" only when you also want those jobs returned (and billed). State is kept separately for each search/URL and detail-mode setup; use State key when you want to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above.",
            "default": false
          },
          "stateKey": {
            "title": "State key (optional, incremental mode only)",
            "type": "string",
            "description": "Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key automatically from the search/URL and detail settings: different searches then never mix state with each other."
          },
          "emitUnchanged": {
            "title": "Emit unchanged jobs (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return jobs that have not changed since the last run, marked UNCHANGED. This returns (and bills) extra rows you already have, so leave it off unless you specifically want the full snapshot every run.",
            "default": false
          },
          "emitExpired": {
            "title": "Emit expired jobs (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return jobs that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search, not when Max jobs capped it or when Resume was used. This returns (and bills) extra synthetic rows, so leave it off unless you need expiry tracking.",
            "default": false
          },
          "proxy": {
            "title": "Proxy",
            "type": "object",
            "description": "Connection settings. The default connection works well for this site. You can pick a different connection here for very large runs."
          },
          "maxResidentialRequests": {
            "title": "Residential request cap",
            "minimum": 0,
            "type": "integer",
            "description": "Safety cap on how many Residential proxy requests this run may use. 0 = unlimited. This cap stops a run from overspending on Residential bandwidth.",
            "default": 0
          },
          "maxResidentialMB": {
            "title": "Residential traffic budget (MB)",
            "minimum": 0,
            "type": "integer",
            "description": "Safety cap on how many megabytes of Residential proxy traffic this run may transfer. 0 = unlimited. Once spent, the run keeps going on the cheaper default connection so it can never silently overspend on Residential bandwidth.",
            "default": 0
          },
          "mcpConnectors": {
            "title": "Pipe results into your apps (optional)",
            "type": "array",
            "description": "Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON - the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com)."
          },
          "notionParentPageUrl": {
            "title": "Notion parent page (Notion connector only)",
            "type": "string",
            "description": "URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors."
          },
          "maxNotifyListings": {
            "title": "Max items to export per connector",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on items written to each connector per run. Does not affect the dataset.",
            "default": 50
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}