{
  "openapi": "3.0.1",
  "info": {
    "title": "AI Job Search & Fit Scorer — 10 Sources + AI Matching",
    "description": "Search 10 public developer-job sources or score your own job list against a résumé or profile. Get a ranked shortlist with a 0–100 fit score, a 0–5 delivery score after hard-requirement checks, evidence, skill gaps, and links to the postings. No model key needed.",
    "version": "0.1",
    "x-build-id": "4BuKqr1fxICJxDC8v"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/job-atlas~ai-job-fit-scorer/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-job-atlas-ai-job-fit-scorer",
        "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/job-atlas~ai-job-fit-scorer/runs": {
      "post": {
        "operationId": "runs-sync-job-atlas-ai-job-fit-scorer",
        "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/job-atlas~ai-job-fit-scorer/run-sync": {
      "post": {
        "operationId": "run-sync-job-atlas-ai-job-fit-scorer",
        "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": "Run mode",
            "enum": [
              "search",
              "score-jobs"
            ],
            "type": "string",
            "description": "Choose Search + score to find current jobs, or Score supplied jobs to evaluate normalized jobs you already have.",
            "default": "search"
          },
          "search": {
            "title": "Search configuration",
            "type": "object",
            "description": "Used only in Search + score. The fresh form searches all ten public sources for software engineer roles posted in the last seven days around Madrid, skips intern and junior titles, and keeps at most three jobs per source. Edit sources, terms, and filters for your market. Free-text preferences never narrow the search: set the city or country in Location, ISO codes for Welcome to the Jungle in Country codes, and remote-only in Fully remote only. All collectors run inside this Actor—there are no paid child Actor runs or stacked child fees.",
            "properties": {
              "sources": {
                "title": "Sources",
                "type": "array",
                "description": "Pick 1–10 sources. All ten collectors are selected by default. Unknown keys are rejected before any search starts.",
                "editor": "select",
                "minItems": 1,
                "maxItems": 10,
                "uniqueItems": true,
                "items": {
                  "type": "string",
                  "enum": [
                    "linkedin",
                    "remote_boards",
                    "builtin",
                    "justjoinit",
                    "nofluffjobs",
                    "hackernews",
                    "ycombinator_was",
                    "wttj",
                    "infojobs",
                    "tecnoempleo"
                  ],
                  "enumTitles": [
                    "LinkedIn public job pages",
                    "Remote job boards",
                    "Built In",
                    "Just Join IT",
                    "No Fluff Jobs",
                    "Hacker News “Who is Hiring?”",
                    "Y Combinator Work at a Startup",
                    "Welcome to the Jungle",
                    "InfoJobs",
                    "Tecnoempleo"
                  ]
                }
              },
              "keywords": {
                "title": "Search terms",
                "type": "array",
                "description": "Required role or skill terms, up to 10. Most sources search each term natively; Built In and No Fluff Jobs use developer categories instead and report keyword support as unsupported.",
                "editor": "stringList",
                "minItems": 1,
                "maxItems": 10,
                "items": {
                  "type": "string",
                  "maxLength": 100
                }
              },
              "location": {
                "title": "City / province / location",
                "type": "string",
                "editor": "textfield",
                "maxLength": 200,
                "description": "Native location filter on LinkedIn and Just Join IT. InfoJobs maps recognized Spanish province names or its province IDs; an unrecognized location leaves its nationwide search unfiltered. Tecnoempleo resolves recognized province names. Other sources ignore this field. Locations in preferences or the candidate profile affect scoring only."
              },
              "countryCodes": {
                "title": "Country codes (Welcome to the Jungle)",
                "type": "array",
                "editor": "stringList",
                "maxItems": 30,
                "description": "ISO two-letter country codes forwarded to Welcome to the Jungle, such as ES or DE.",
                "items": {
                  "type": "string",
                  "minLength": 2,
                  "maxLength": 2
                }
              },
              "remoteOnly": {
                "title": "Fully remote only",
                "type": "boolean",
                "default": false,
                "description": "Keep only jobs explicitly normalized as fully remote, using native filters where a source has them. Hybrid and unknown arrangements are excluded, which removes most LinkedIn rows."
              },
              "titleExclude": {
                "title": "Exclude title terms",
                "type": "array",
                "editor": "stringList",
                "description": "Drop titles containing any of these terms, on sources that support native title exclusion.",
                "maxItems": 20,
                "items": {
                  "type": "string",
                  "maxLength": 100
                }
              },
              "experienceLevels": {
                "title": "Experience levels (Just Join IT)",
                "type": "array",
                "editor": "stringList",
                "description": "Optional Just Join IT experience-level filter, for example junior, mid, or senior. Ignored by other sources.",
                "maxItems": 12,
                "items": {
                  "type": "string",
                  "maxLength": 40
                }
              },
              "maxExperienceYears": {
                "title": "Maximum experience years (Welcome to the Jungle)",
                "type": "integer",
                "editor": "number",
                "description": "Optional maximum years of required experience, forwarded to Welcome to the Jungle only.",
                "minimum": 0,
                "maximum": 60
              },
              "postedWithinDays": {
                "title": "Posted within (days)",
                "type": "integer",
                "editor": "number",
                "default": 7,
                "minimum": 0,
                "maximum": 365,
                "description": "Freshness window, mapped to each source that supports one. Y Combinator and Welcome to the Jungle do not expose this filter; jobs with unknown dates are kept."
              },
              "maxItemsPerSource": {
                "title": "Maximum fetched per source",
                "type": "integer",
                "editor": "number",
                "description": "Cap on full postings kept from each selected source before cross-source merging and deduplication.",
                "default": 10,
                "minimum": 1,
                "maximum": 50
              },
              "cacheTtlSeconds": {
                "title": "Search cache time (seconds)",
                "type": "integer",
                "editor": "number",
                "description": "Reuse a source's HTTP responses for this long. Set 0 to force fresh requests.",
                "default": 1800,
                "minimum": 0,
                "maximum": 86400
              },
              "concurrency": {
                "title": "Source concurrency",
                "type": "integer",
                "editor": "number",
                "description": "Maximum concurrent source requests across the in-process collectors.",
                "default": 3,
                "minimum": 1,
                "maximum": 10
              },
              "sourceTimeoutSecs": {
                "title": "Per-source timeout (seconds)",
                "type": "integer",
                "editor": "number",
                "description": "Cooperative deadline for each native source request.",
                "default": 120,
                "minimum": 30,
                "maximum": 300
              }
            },
            "default": {
              "sources": [
                "linkedin",
                "remote_boards",
                "builtin",
                "justjoinit",
                "nofluffjobs",
                "hackernews",
                "ycombinator_was",
                "wttj",
                "infojobs",
                "tecnoempleo"
              ],
              "keywords": [
                "software engineer"
              ],
              "location": "Madrid",
              "remoteOnly": false,
              "titleExclude": [
                "intern",
                "junior"
              ],
              "postedWithinDays": 7,
              "maxItemsPerSource": 10,
              "cacheTtlSeconds": 1800,
              "concurrency": 3,
              "sourceTimeoutSecs": 120
            },
            "additionalProperties": false
          },
          "jobs": {
            "title": "Normalized jobs (inline)",
            "maxItems": 200,
            "type": "array",
            "description": "JSON array of complete nomad-agent-job-v1 records. Every item needs top-level schemaVersion, identity, data, custom, llm, and raw; identity needs source plus externalId or url, and raw.description contains the posting text. Copy the working shape from the public example https://github.com/Exdenta/nomad-agent-job-scrapers/blob/main/docs/examples/ai-job-fit-scorer/inline-input.json. Use this, sourceDatasetId, or sourceActorRunId—never more than one. Hard limits: 200 records and 20,000 plain-text description characters per job; oversized evidence is rejected, never truncated.",
            "items": {
              "type": "object"
            }
          },
          "sourceDatasetId": {
            "title": "Source dataset ID",
            "type": "string",
            "description": "Paste the immutable Apify dataset ID—not the dataset name or URL. Each dataset item must be one complete nomad-agent-job-v1 record. The dataset is read only and never modified. Use only one supplied-job source."
          },
          "sourceActorRunId": {
            "title": "Exact source Actor run ID",
            "type": "string",
            "description": "Paste the exact upstream run ID—not the Actor ID, build ID, or run URL. The run must be terminal SUCCEEDED with exit code 0; this Actor reads that run's default dataset as nomad-agent-job-v1 records. Use only one supplied-job source."
          },
          "expectedSourceBuild": {
            "title": "Expected upstream build (optional)",
            "type": "string",
            "description": "Optional guard for sourceActorRunId. Enter the upstream run's exact immutable build ID or build number; the run fails instead of reading jobs when it does not match."
          },
          "maxItems": {
            "title": "Maximum jobs",
            "minimum": 1,
            "maximum": 200,
            "type": "integer",
            "description": "Maximum unique jobs to evaluate (1–200). In search mode this caps the merged, deduplicated result set; in score-jobs mode it caps the supplied source.",
            "default": 25
          },
          "candidateProfile": {
            "title": "Structured candidate profile",
            "type": "object",
            "description": "Structured facts about the candidate. Needs at least one of primaryRole, targetTerms, skills, or freeText. Add seniority, years, language, location, and contract constraints only when the candidate actually stated them; leave unknowns empty. An example profile is prefilled so a first run works out of the box; replace every field with your own evidence before acting on the results. Use exactly one of this, Résumé, or Résumé text.",
            "properties": {
              "primaryRole": {
                "type": "string",
                "editor": "textfield",
                "title": "Primary role",
                "description": "Candidate's current or primary professional role, when explicitly evidenced."
              },
              "targetTerms": {
                "type": "array",
                "editor": "stringList",
                "items": {
                  "type": "string"
                },
                "title": "Target role terms",
                "description": "Role titles the candidate can credibly perform now. Do not add aspirational roles without evidence."
              },
              "skills": {
                "type": "array",
                "editor": "stringList",
                "items": {
                  "type": "string"
                },
                "title": "Evidenced skills",
                "description": "Skills explicitly supported by the candidate evidence."
              },
              "seniorityLevels": {
                "type": "array",
                "editor": "stringList",
                "items": {
                  "type": "string"
                },
                "title": "Target seniority",
                "description": "Target levels the evidence supports. Recognized values: intern, entry, junior, associate, mid, senior, lead, staff, principal."
              },
              "yearsExperience": {
                "type": "number",
                "editor": "number",
                "minimum": 0,
                "title": "Years of experience",
                "description": "Non-negative total relevant years supported by the candidate evidence."
              },
              "workableLanguages": {
                "type": "array",
                "editor": "json",
                "title": "Workable languages",
                "description": "JSON array of objects with language, level, and evidence, for example [{\"language\": \"English\", \"level\": \"C1\", \"evidence\": \"CV: English C1\"}].",
                "items": {
                  "type": "object",
                  "required": [
                    "language",
                    "evidence"
                  ],
                  "additionalProperties": false,
                  "properties": {
                    "language": {
                      "type": "string",
                      "title": "Language",
                      "description": "Language name."
                    },
                    "level": {
                      "type": "string",
                      "title": "Level",
                      "description": "Published or candidate-stated proficiency, such as C1, when known."
                    },
                    "evidence": {
                      "type": "string",
                      "title": "Evidence",
                      "description": "Short source statement supporting this language ability."
                    }
                  }
                }
              },
              "workableLanguagesComplete": {
                "type": "boolean",
                "title": "Language inventory is complete",
                "description": "True only when the supplied list is the candidate's complete workable-language inventory.",
                "default": false
              },
              "acceptedWorkArrangements": {
                "type": "array",
                "editor": "select",
                "title": "Accepted work arrangements",
                "description": "Optional explicit declaration. When set, it must match exactly the location lists you filled in: remote needs remote locations, hybrid needs hybrid locations, onsite needs on-site locations. Leave empty and the filled location lists decide.",
                "items": {
                  "type": "string",
                  "enum": [
                    "remote",
                    "hybrid",
                    "onsite"
                  ],
                  "enumTitles": [
                    "Remote",
                    "Hybrid",
                    "On-site"
                  ]
                }
              },
              "remoteLocations": {
                "type": "array",
                "editor": "stringList",
                "title": "Remote locations",
                "description": "Countries or regions from which the candidate explicitly accepts remote work, such as Spain or European Union.",
                "items": {
                  "type": "string"
                }
              },
              "hybridLocations": {
                "type": "array",
                "editor": "stringList",
                "title": "Hybrid locations",
                "description": "Cities where the candidate explicitly accepts hybrid work, such as Madrid, Spain.",
                "items": {
                  "type": "string"
                }
              },
              "onsiteLocations": {
                "type": "array",
                "editor": "stringList",
                "title": "On-site locations",
                "description": "Cities where the candidate explicitly accepts on-site work.",
                "items": {
                  "type": "string"
                }
              },
              "workArrangementPreferencesComplete": {
                "type": "boolean",
                "title": "Work arrangement inventory is complete",
                "description": "True only when the location lists describe every arrangement the candidate accepts. Leave false when you are unsure.",
                "default": false
              },
              "acceptedCountryCodes": {
                "type": "array",
                "editor": "stringList",
                "title": "Accepted country codes",
                "description": "Explicitly accepted two-letter country codes, used only when provided.",
                "items": {
                  "type": "string",
                  "minLength": 2,
                  "maxLength": 2
                }
              },
              "acceptedContractTypes": {
                "type": "array",
                "editor": "stringList",
                "title": "Accepted contract types",
                "description": "Explicitly accepted employment types, such as permanent, fixed_term, contract, contractor, freelance, or internship.",
                "items": {
                  "type": "string"
                }
              },
              "acceptedContractTypesComplete": {
                "type": "boolean",
                "title": "Contract inventory is complete",
                "description": "True only when the contract-type list is exhaustive.",
                "default": false
              },
              "asOf": {
                "type": "string",
                "editor": "textfield",
                "title": "Profile evidence as-of",
                "description": "Optional ISO timestamp describing when the structured evidence was current."
              },
              "freeText": {
                "type": "string",
                "editor": "textarea",
                "maxLength": 4000,
                "title": "Additional evidence",
                "description": "Short factual summary or explicit constraints, up to 4,000 characters. The scorer reads this as candidate evidence."
              }
            },
            "additionalProperties": false
          },
          "resume": {
            "title": "Résumé (PDF or TXT)",
            "type": "string",
            "description": "Text-based PDF or UTF-8 text, up to 5 MB, 50 PDF pages, and 8,000 readable characters. Read in memory and sent once for profile extraction; never written as a separate dataset or repeated in each fit prompt."
          },
          "resumeText": {
            "title": "Résumé text (API alternative to upload)",
            "type": "string",
            "description": "Plain-text alternative for API clients, up to 8,000 readable characters. Use exactly one of candidateProfile, resume, or resumeText."
          },
          "preferences": {
            "title": "Explicit preferences (optional)",
            "type": "string",
            "description": "Up to 4,000 characters of explicit role, location, work-mode, language, contract, or other constraints. Unknowns are never guessed. Used for scoring only: it never narrows the search, so a location written here does not change which jobs are fetched. Use search.location, search.countryCodes, and search.remoteOnly for that."
          },
          "resultMode": {
            "title": "Result mode",
            "enum": [
              "shortlist",
              "audit"
            ],
            "type": "string",
            "description": "Shortlist (default) returns and charges only successfully scored rows whose deliveryScore meets minDeliveryScore. Audit returns the complete evaluation dataset, including static_drop, static_hold, forward_cap_hold, and ai_failed rows; every Audit row except ai_failed is charged.",
            "default": "shortlist"
          },
          "minDeliveryScore": {
            "title": "Minimum delivery score",
            "minimum": 0,
            "maximum": 5,
            "type": "integer",
            "description": "Inclusive 0–5 threshold used only in Shortlist mode (default 2). deliveryScore already includes hard-gate reductions, so it is safer for delivery than the raw fitScore. Audit mode records this value but does not filter by it.",
            "default": 2
          },
          "minRankToForward": {
            "title": "Static screen rank floor",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "Jobs whose deterministic pre-screen rank is below this 0–100 value are held before any AI call (default 30). Hard contradictions are always dropped regardless of rank.",
            "default": 30
          },
          "maxAiItems": {
            "title": "Maximum AI verdicts (optional)",
            "minimum": 0,
            "maximum": 200,
            "type": "integer",
            "description": "Cap on AI verdict calls after the static screen (0–200). Remaining eligible jobs are returned as forward_cap_hold rather than given a fabricated score."
          },
          "recoverHolds": {
            "title": "Send recoverable holds to AI",
            "type": "boolean",
            "description": "Also send recoverable static holds to AI. Off by default so uncertain evidence stays visibly held instead of being scored on guesses.",
            "default": false
          },
          "aiConcurrency": {
            "title": "AI concurrency",
            "minimum": 1,
            "maximum": 8,
            "type": "integer",
            "description": "Concurrent fit verdict calls (1–8). Lower this for smaller or latency-sensitive batches.",
            "default": 4
          },
          "sourceApifyToken": {
            "title": "Source run access token (optional)",
            "type": "string",
            "description": "For sourceActorRunId when the run is outside this Actor’s limited access: supply your own Apify token with read access to that run and its dataset. Prefer sourceDatasetId for automatic access to just the selected dataset. This token is used only to read your selected Apify source."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}