{
  "openapi": "3.0.1",
  "info": {
    "title": "RemoteOK Jobs Scraper - Remote Listings, Salaries & Details",
    "description": "Scrape RemoteOK jobs by keyword or job URL. Extract title, company, location, remote details, tags, salary when available, listing URL, description, and metadata into clean structured dataset rows.",
    "version": "1.0",
    "x-build-id": "OYlrs6fD22X4wziYl"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/abotapi~remoteok-com-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-abotapi-remoteok-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~remoteok-com-scraper/runs": {
      "post": {
        "operationId": "runs-sync-abotapi-remoteok-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~remoteok-com-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-abotapi-remoteok-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",
        "properties": {
          "mode": {
            "title": "Input mode",
            "enum": [
              "search",
              "url"
            ],
            "type": "string",
            "description": "Use keyword search to filter current listings by terms, or URL mode to read one or more RemoteOK listing URLs directly.",
            "default": "search"
          },
          "searchTerms": {
            "title": "Search terms",
            "type": "array",
            "description": "Enter job keywords or tag phrases such as python or senior+devops. Use all jobs for a broad default run. Each term is processed separately and capped by Max items.",
            "default": [
              "all jobs"
            ],
            "items": {
              "type": "string"
            }
          },
          "startUrls": {
            "title": "RemoteOK URLs",
            "type": "array",
            "description": "Paste RemoteOK URLs: tag listings, the homepage or /api feed, company pages, job pages and location pages (job, company and location pages return rows only when they match a job in the current feed), with optional ?tags= ?location= ?search= ?page= ?order_by= facets. Each URL is processed separately and capped by Max items. Unsupported URLs are skipped with a warning.",
            "default": [
              {
                "url": "https://remoteok.com/remote-react-jobs"
              },
              {
                "url": "https://remoteok.com/remote-dev-jobs.json?order_by=salary"
              },
              {
                "url": "https://remoteok.com/"
              },
              {
                "url": "https://remoteok.com/api?tag=python"
              },
              {
                "url": "https://remoteok.com/remote-python-jobs?page=2"
              },
              {
                "url": "https://remoteok.com/remote-jobs?search=python"
              },
              {
                "url": "https://www.remoteok.com/remote-dev-jobs"
              }
            ],
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "tags": {
            "title": "Require tags",
            "type": "array",
            "description": "Keep only jobs whose tag list contains at least one of these values.",
            "items": {
              "type": "string"
            }
          },
          "companies": {
            "title": "Company filters",
            "type": "array",
            "description": "Keep only jobs whose company name contains one of these values.",
            "items": {
              "type": "string"
            }
          },
          "locations": {
            "title": "Location filters",
            "type": "array",
            "description": "Keep only jobs whose location text contains one of these values.",
            "items": {
              "type": "string"
            }
          },
          "minSalary": {
            "title": "Minimum salary",
            "minimum": 0,
            "type": "integer",
            "description": "Keep only jobs whose salary range reaches at least this amount."
          },
          "maxSalary": {
            "title": "Maximum salary",
            "minimum": 0,
            "type": "integer",
            "description": "Keep only jobs whose salary range starts at or below this amount."
          },
          "postedWithinDays": {
            "title": "Posted within days",
            "minimum": 0,
            "maximum": 3650,
            "type": "integer",
            "description": "Keep only jobs posted within this many days. Leave empty for no age filter."
          },
          "sortBy": {
            "title": "Sort order",
            "enum": [
              "posted-desc",
              "posted-asc",
              "salary-desc",
              "salary-asc",
              "company-asc"
            ],
            "type": "string",
            "description": "Client-side sort order applied after filtering.",
            "default": "posted-desc"
          },
          "requireSalary": {
            "title": "Require salary",
            "type": "boolean",
            "description": "Keep only jobs where a salary range is present.",
            "default": false
          },
          "keywordFilter": {
            "title": "Keyword filter",
            "type": "string",
            "description": "Keep only jobs whose title, company, location, description or tags contain at least one of these comma-separated keywords (case-insensitive). Applied after the search terms."
          },
          "includeUnverified": {
            "title": "Include unverified listings",
            "type": "boolean",
            "description": "Turn off to keep only listings that RemoteOK marks as verified.",
            "default": true
          },
          "filterNonTech": {
            "title": "Technical roles only",
            "type": "boolean",
            "description": "Keep only technical roles: the job title must name an engineering, developer, devops, data, security, QA or similar role. Sales, recruiting, marketing, support and coordinator roles are dropped even when RemoteOK tags them with technology words.",
            "default": false
          },
          "includeDescriptionText": {
            "title": "Include cleaned description text",
            "type": "boolean",
            "description": "When enabled, the actor adds a cleaned plain-text version of the listing description.",
            "default": true
          },
          "includeRawFields": {
            "title": "Include raw source fields",
            "type": "boolean",
            "description": "When enabled, the actor keeps the full original job object alongside normalized fields.",
            "default": true
          },
          "maxItems": {
            "title": "Max items",
            "minimum": 1,
            "maximum": 5000,
            "type": "integer",
            "description": "Maximum matching rows to save for each search term or start URL. This is a cap, not a guarantee.",
            "default": 20
          },
          "maxResults": {
            "title": "Max results (alias of Max items)",
            "minimum": 0,
            "type": "integer",
            "description": "Alias of Max items. When set above 0 it replaces Max items; 0 means unlimited (every matching job). Leave empty to use Max items."
          },
          "maxPages": {
            "title": "Max pages",
            "minimum": 0,
            "type": "integer",
            "description": "Leave empty to walk every result page. When a source has more matching jobs than fit in one page, the actor keeps paginating until Max items is reached or the source is exhausted."
          },
          "proxy": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Requests go through Apify Proxy (automatic group by default). You can choose a proxy group or country, or paste your own proxy URLs. If the default connection is refused, a backup connection is used and logged."
          },
          "resumeFromRunId": {
            "title": "Resume from a previous run (optional)",
            "type": "string",
            "description": "Paste a previous run ID or dataset ID to continue a full-catalogue walk across separate runs. Jobs already collected there (matched by id) are skipped, so this run only saves the new ones. Leave empty for a normal fresh run."
          },
          "incrementalMode": {
            "title": "Incremental mode: only changed jobs",
            "type": "boolean",
            "description": "For scheduled runs. Remembers the jobs seen by the previous run with the same tracked scope (or the same State key) and delivers only NEW, UPDATED and REAPPEARED jobs, each tagged with changeType, changedFields, firstSeenAt and lastSeenAt. Unchanged jobs are not delivered or billed unless 'Also deliver unchanged jobs' is on. Leave off for a normal run. Different from 'Resume from a previous run', which continues one specific run.",
            "default": false
          },
          "stateKey": {
            "title": "State key (incremental mode only)",
            "type": "string",
            "description": "Optional name for the incremental baseline. Leave empty to derive it automatically from your search terms, URLs and filters, so differently configured runs never share a baseline. Set the same text on two runs to make them share one. Only used when Incremental mode is on."
          },
          "emitUnchanged": {
            "title": "Also deliver unchanged jobs (incremental mode only)",
            "type": "boolean",
            "description": "When Incremental mode is on, also push jobs that did not change since the last run (changeType UNCHANGED). Each delivered row is billed like any other row, and EXPIRED rows come in addition to the Max items cap. Off by default.",
            "default": false
          },
          "emitExpired": {
            "title": "Deliver jobs that disappeared (incremental mode only)",
            "type": "boolean",
            "description": "When Incremental mode is on, push a row with changeType EXPIRED for each job tracked last run that is no longer in the feed. Only when the run covered the whole tracked scope: a run capped by Max items, with a failed or skipped search, or starting past page 1 never reports expiry. Each delivered row is billed like any other row, and EXPIRED rows come in addition to the Max items cap. Off by default.",
            "default": false
          },
          "ignoreFieldsForChanges": {
            "title": "Ignore fields when detecting changes (incremental mode only)",
            "type": "array",
            "description": "Field names to leave out of change detection in incremental mode (dotted paths allowed for nested fields). scrapedAt, scraped_at and postedAgeDays are always ignored. Example: tags.",
            "items": {
              "type": "string"
            }
          },
          "mcpConnectors": {
            "title": "Pipe results into your apps (optional)",
            "type": "array",
            "description": "Optionally send scraped jobs into 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 summary per job; the full record stays in the dataset. Leave empty to skip. Supported: Notion, Linear, Airtable, and Apify."
          },
          "notionParentPageUrl": {
            "title": "Notion parent page (Notion connector only)",
            "type": "string",
            "description": "URL or id of the Notion page under which job pages are created. Required for Notion export; ignored by other connectors."
          },
          "maxNotifyJobs": {
            "title": "Max jobs to export per connector",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on jobs written to each connector. Does not affect the dataset.",
            "default": 50
          },
          "maxNotifyListings": {
            "title": "Max listings to export per connector",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Same cap as 'Max jobs to export per connector'. When set, this value wins. Does not affect the dataset."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}