{
  "openapi": "3.0.1",
  "info": {
    "title": "Job Radar — Deduped, Ghost-Filtered Job Alerts",
    "description": "Fresh job openings from Google Jobs, Indeed and employer career pages in one run — duplicates merged across boards, likely ghost/stale postings hidden, every job ranked by an explainable match score. Email digest + shareable dashboard. No auto-apply: you click.",
    "version": "0.1",
    "x-build-id": "eYateYK6XHObxd8FJ"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/inovaflow~job-radar/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-inovaflow-job-radar",
        "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/inovaflow~job-radar/runs": {
      "post": {
        "operationId": "runs-sync-inovaflow-job-radar",
        "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/inovaflow~job-radar/run-sync": {
      "post": {
        "operationId": "run-sync-inovaflow-job-radar",
        "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": [
          "queries"
        ],
        "properties": {
          "queries": {
            "title": "Job titles you're looking for",
            "maxItems": 10,
            "type": "array",
            "description": "Each line is ONE search, matched against the job TITLE. In the default Strict mode a one- or two-word search matches the WHOLE title only — `React Developer` returns jobs titled React Developer, not `Sr React Developer` or `React Developer Intern`; from three words up, a title that contains your phrase also counts — `Senior React Developer` also catches `Senior React Developer, Payments`. Switch Title match strictness to Broad to also catch titles that carry your words in any order (e.g. `Medior Frontend Developer`). Want more roles? Give each its own line (e.g. `React Engineer`, `Frontend Developer`).",
            "items": {
              "type": "string"
            }
          },
          "location": {
            "title": "Location",
            "type": "string",
            "description": "City, region or country to search in, e.g. `Berlin`, `Prague`, `New York`. Leave empty and turn on Remote only for a location-free search."
          },
          "remoteOnly": {
            "title": "Remote only",
            "type": "boolean",
            "description": "Only keep jobs that are remote (fully remote or remote-first).",
            "default": false
          },
          "seniority": {
            "title": "Seniority level",
            "enum": [
              "any",
              "intern",
              "junior",
              "mid",
              "senior",
              "lead"
            ],
            "type": "string",
            "description": "Preferred seniority. Jobs at exactly this level get a ranking boost; clear mismatches are ranked down (never silently dropped).",
            "default": "any"
          },
          "mustHaveKeywords": {
            "title": "Must-have keywords",
            "type": "array",
            "description": "Jobs are dropped unless the title or description contains ALL of these, e.g. `typescript`. Leave empty to skip this filter.",
            "items": {
              "type": "string"
            }
          },
          "excludeKeywords": {
            "title": "Exclude keywords",
            "type": "array",
            "description": "Jobs whose title or description contains ANY of these are dropped, e.g. `clearance`, `PHP`. Leave empty to skip this filter.",
            "items": {
              "type": "string"
            }
          },
          "minSalary": {
            "title": "Minimum salary (annual)",
            "minimum": 0,
            "type": "integer",
            "description": "Drop jobs whose stated salary tops out below this yearly amount (in the currency the posting uses). Jobs with no stated salary are kept — they lose ranking points instead."
          },
          "useGoogleJobs": {
            "title": "Google for Jobs",
            "type": "boolean",
            "description": "Search Google for Jobs — one scrape covers LinkedIn, Glassdoor, ZipRecruiter, Monster and 20+ other boards. Very cheap — a fraction of a cent per listing of your Apify credit. Off by default because it runs on — and bills — your own Apify account; tick it to add broad market coverage.",
            "default": false
          },
          "useIndeed": {
            "title": "Indeed",
            "type": "boolean",
            "description": "Search Indeed directly — the cheapest high-volume source (~$0.10 per 1,000 jobs of your Apify credit). Off by default (runs on your own Apify account) — tick it to enable.",
            "default": false
          },
          "followCompanies": {
            "title": "Companies you follow (career pages, free)",
            "type": "array",
            "description": "Employer career boards fetched directly — the freshest postings and true direct-apply links, at zero cost. Entries like `greenhouse:stripe`, `lever:palantir`, `ashby:ramp`, or just a company slug (e.g. `stripe`) to probe all three systems. Prefilled with a few examples — the free, zero-config default source.",
            "items": {
              "type": "string"
            }
          },
          "useGlassdoor": {
            "title": "Glassdoor",
            "type": "boolean",
            "description": "Also search Glassdoor (~$0.40 per 1,000 jobs of your Apify credit) — adds salary bands and a numeric posting age.",
            "default": false
          },
          "useLinkedIn": {
            "title": "LinkedIn (public listings)",
            "type": "boolean",
            "description": "Also search public LinkedIn job listings via a third-party scraper (~$0.70 per 1,000 jobs of your Apify credit; the scraper enforces a 150-result minimum per run). No LinkedIn login is ever used. If LinkedIn blocks the scrape, the run continues without it.",
            "default": false
          },
          "maxJobsPerSource": {
            "title": "Max matching jobs per source",
            "minimum": 5,
            "maximum": 300,
            "type": "integer",
            "description": "How many MATCHING jobs to keep from each source — counted AFTER filtering (title match → dedup → ghost removal), not raw scraped rows. We over-fetch a few times this many raw rows (bounded, so it still caps what the scrapers bill you) and keep the best matches up to this number.",
            "default": 100
          },
          "matchMode": {
            "title": "Title match strictness",
            "enum": [
              "strict",
              "broad"
            ],
            "type": "string",
            "description": "How strictly a job TITLE must match your search. Strict (default) keeps only titles that ARE your search — or, for searches of 3+ words, contain it verbatim — the highest-precision option. Broad also keeps titles that contain your search at any length, or contain every word of it in any order (e.g. \"Frontend Developer\" also matches \"Medior Frontend Developer\") — better recall in thin markets where only one board answers.",
            "default": "strict"
          },
          "maxAgeDays": {
            "title": "Only jobs posted in the last … days",
            "minimum": 1,
            "maximum": 365,
            "type": "integer",
            "description": "Hard cutoff on posting age. Our age is repost-proof on repeat runs: we remember when WE first saw a job, so reposting doesn't reset its clock. Default 60 days — above the ~44-day median time-to-fill, so still-open employer roles show; older-than-this is hidden and truly stale/evergreen postings are down-ranked by the ghost score on top.",
            "default": 60
          },
          "includeGhostJobs": {
            "title": "Show hidden (likely stale / ghost) postings",
            "type": "boolean",
            "description": "By default, postings that score as likely stale or ghost (old, endlessly reposted, evergreen \"always hiring\" ads…) are hidden and only counted. Turn this on to see them anyway, each with the reasons it was flagged.",
            "default": false
          },
          "hideStaffingAgencies": {
            "title": "Hide staffing-agency postings",
            "type": "boolean",
            "description": "Drop postings from recruiting/staffing agencies rather than the hiring company itself.",
            "default": false
          },
          "newOnly": {
            "title": "Only report new jobs on repeat runs",
            "type": "boolean",
            "description": "When on, repeat runs of the same search highlight only jobs that appeared since the previous run — ideal on a daily or weekly schedule. The very first run always reports everything.",
            "default": true
          },
          "outputEmail": {
            "title": "Your email address",
            "type": "string",
            "description": "Type an email address and every run emails you the digest — new matches ranked by fit, with direct apply links and the count of postings we hid as stale. Sent from job-radar@apify.inovaflow.app (no-reply). Leave blank to skip email."
          },
          "apifyMcpConnector": {
            "title": "Run the job scrapers under a different Apify account (connector)",
            "type": "string",
            "description": "An Apify MCP connector whose account runs and pays for the job-board scrapers — you authorize once, with no token to paste. Create it in the Apify Console under Settings → Integrations → MCP Connectors with the server URL https://mcp.apify.com, then pick it here. Takes precedence over the API token below if both are set. Optional — leave blank to run on the account executing this Actor."
          },
          "apifyToken": {
            "title": "Apify API token (advanced, optional)",
            "type": "string",
            "description": "By default the source scrapers run on — and bill — the Apify account running this Actor. Paste a token here to run them on a different account instead (Apify Console → Settings → API & Integrations). Treat it like a password. Leave blank in most cases."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}