{
  "openapi": "3.0.1",
  "info": {
    "title": "LinkedIn Jobs Scraper — Normalized Contract",
    "description": "Public LinkedIn jobs mapped to nomad-agent-job-v1 from guest cards, detail markup, and JobPosting JSON-LD. Includes ready-made MCP, n8n, Make, and Airtable integration presets. Optional owner-managed AI fills only missing description-backed facts; optional DeepL translates selected short fields.",
    "version": "0.6",
    "x-build-id": "IV0Igg3lBSvIQ02B9"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/nomad-agent~linkedin-enrich-translate-normalize-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-nomad-agent-linkedin-enrich-translate-normalize-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/nomad-agent~linkedin-enrich-translate-normalize-scraper/runs": {
      "post": {
        "operationId": "runs-sync-nomad-agent-linkedin-enrich-translate-normalize-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/nomad-agent~linkedin-enrich-translate-normalize-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-nomad-agent-linkedin-enrich-translate-normalize-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": [
          "schemaVersion"
        ],
        "properties": {
          "schemaVersion": {
            "title": "Input contract version",
            "enum": [
              "nomad-agent-job-search-input-v1"
            ],
            "type": "string",
            "description": "Version of the shared normalized job-search Actor input contract.",
            "default": "nomad-agent-job-search-input-v1"
          },
          "keyword": {
            "title": "Keyword",
            "type": "string",
            "description": "Job title, skill or role to search for (e.g. <code>software engineer</code>, <code>product manager react</code>). Leave empty to search all recent postings for the given location."
          },
          "location": {
            "title": "Location",
            "type": "string",
            "description": "City, region or country to filter by (e.g. <code>Spain</code>, <code>London</code>, <code>European Union</code>). Leave empty for worldwide results."
          },
          "linkedinSearch": {
            "title": "LinkedIn multi-search plan",
            "required": [
              "schemaVersion"
            ],
            "type": "object",
            "description": "Optional, separately versioned LinkedIn search extension. Supply up to 8 keyword/location partitions; the Actor visits them in deterministic round-robin order, makes at most 24 search-page requests across the entire run, deduplicates postings globally, and applies maxItems only once to the combined result. Omit searches (or use an empty array) to use the top-level keyword/location search. Non-empty top-level keyword/location cannot be combined with non-empty searches.",
            "properties": {
              "schemaVersion": {
                "title": "LinkedIn search schema version",
                "description": "Version of the source-specific LinkedIn search extension.",
                "type": "string",
                "default": "nomad-agent-linkedin-search-v1",
                "enum": [
                  "nomad-agent-linkedin-search-v1"
                ]
              },
              "searches": {
                "title": "Search partitions",
                "type": "array",
                "description": "Independent LinkedIn search partitions. Array order determines round-robin tie order before the deterministic local result sort.",
                "maxItems": 8,
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "keyword",
                    "location"
                  ],
                  "properties": {
                    "keyword": {
                      "title": "Keyword",
                      "description": "Job title, skill, or role for this partition.",
                      "type": "string"
                    },
                    "location": {
                      "title": "Location",
                      "description": "Location text for this partition.",
                      "type": "string"
                    }
                  }
                }
              },
              "orderBy": {
                "title": "Result order",
                "type": "string",
                "description": "Deterministic local ordering applied after normalization and filtering. Unknown posting dates sort last; LinkedIn job ID and canonical URL are stable tie-breakers.",
                "default": "newest",
                "enum": [
                  "newest",
                  "oldest"
                ]
              }
            },
            "additionalProperties": false
          },
          "strictGeography": {
            "title": "Strict physical geography",
            "required": [
              "schemaVersion"
            ],
            "type": "object",
            "description": "Optional fail-closed physical-location enforcement after static source normalization and before LLM enrichment. Every configured country, region, and city axis must match on the same normalized location object. Countries are uppercase ISO-2 codes. Unknown source geography is excluded by default or can abort the run; description prose and LLM-filled locations are never accepted as evidence.",
            "properties": {
              "schemaVersion": {
                "title": "Strict geography schema version",
                "description": "Version of the source-only strict geography contract.",
                "type": "string",
                "enum": [
                  "nomad-agent-linkedin-strict-geography-v1"
                ]
              },
              "countries": {
                "title": "Allowed countries",
                "description": "Uppercase ISO-3166 alpha-2 country codes; at least one country, region, or city target is required.",
                "type": "array",
                "maxItems": 25,
                "uniqueItems": true,
                "items": {
                  "type": "string",
                  "pattern": "^[A-Z]{2}$"
                }
              },
              "regions": {
                "title": "Allowed regions",
                "description": "Exact case-insensitive source region names; combined with other axes on the same location object.",
                "type": "array",
                "maxItems": 25,
                "uniqueItems": true,
                "items": {
                  "type": "string",
                  "minLength": 1
                }
              },
              "cities": {
                "title": "Allowed cities",
                "description": "Exact case-insensitive source city names; combined with other axes on the same location object.",
                "type": "array",
                "maxItems": 25,
                "uniqueItems": true,
                "items": {
                  "type": "string",
                  "minLength": 1
                }
              },
              "unknownPolicy": {
                "title": "Unknown-location policy",
                "description": "Exclude rows whose requested axes cannot be proven, or abort the whole run instead.",
                "type": "string",
                "enum": [
                  "exclude",
                  "abort"
                ]
              }
            },
            "additionalProperties": false
          },
          "workArrangements": {
            "title": "Work arrangements",
            "uniqueItems": true,
            "type": "array",
            "description": "Optional LinkedIn workplace filter. Select one or more values; unions such as <code>[\"remote\", \"hybrid\"]</code> are sent to LinkedIn together. Omit this field to include every arrangement.",
            "items": {
              "type": "string",
              "enum": [
                "remote",
                "hybrid",
                "onsite"
              ],
              "enumTitles": [
                "Remote",
                "Hybrid",
                "On-site"
              ]
            }
          },
          "translateToEnglish": {
            "title": "Translate selected fields to English",
            "type": "boolean",
            "description": "After normalization, optional LLM enrichment, and final filtering, fastText identifies each normalized job title, industry, and job-function value; confident English values are kept as-is and only the remaining values are translated with the Actor owner's DeepL account. Exact-text results are checked in a creator-owned Apify key-value store shared across runs and customers; a miss falls back directly to DeepL. English-only results incur no translation charge. The full description, raw text/HTML, company, location, LLM provenance, and LLM-enriched prose outside the three selected paths remain in their original language. Each English-translated result incurs an additional $0.006 whether cached or fresh.",
            "default": false
          },
          "aiEnrichment": {
            "title": "AI position-facts enrichment",
            "required": [
              "enabled",
              "accuracy"
            ],
            "type": "object",
            "description": "Reads only a complete public plain-text description and fills normalized fields that static LinkedIn markup left null. Static facts always win, and no customer API key is requested. Silver is the default: 99.44% measured parsing accuracy across three runs, $0.006 per successfully enriched result, and an average 117.5 seconds for a 50-description benchmark batch (110.2–127.6 seconds). Gold adds a corrections-only verification run over Silver: 99.15% initial measured parsing accuracy, $0.010 per successfully enriched result, and 335.0 seconds end to end for the same benchmark size (110.2-second first pass plus 224.8-second verification). Invalid verification output safely keeps the Silver result. Timings are benchmark measurements, not per-job guarantees, and vary with input size and provider load. Failed or unnecessary enrichment is not charged.",
            "properties": {
              "enabled": {
                "title": "Enable AI enrichment",
                "description": "Enable description-backed null-only position-facts extraction.",
                "type": "boolean",
                "default": false
              },
              "accuracy": {
                "title": "Accuracy tier",
                "description": "Silver is the default extraction tier. Gold adds a second, corrections-only verification run over the Silver result.",
                "type": "string",
                "default": "silver",
                "enum": [
                  "silver",
                  "gold"
                ],
                "enumTitles": [
                  "Silver — 99.44%, $0.006/result, ~118s/50 jobs",
                  "Gold — verified Silver, 99.15%, $0.010/result, ~335s/50 jobs"
                ]
              }
            },
            "default": {
              "enabled": false,
              "accuracy": "silver"
            },
            "additionalProperties": false
          },
          "companyProfileEnrichment": {
            "title": "Enrich public company profiles",
            "type": "boolean",
            "description": "When enabled, fetches a bounded set of public LinkedIn company pages already linked by selected job postings and places exact public profile facts in the versioned custom extension. Requests use no login, account cookie, caller token, redirect, or arbitrary external URL. Duplicate companies are fetched once per run and may reuse the Actor owner's validated one-day cache. A blocked, unavailable, oversized, unbound, or deadline-limited company page leaves the complete base job unchanged with custom null. This option adds no separate pay-per-event charge.",
            "default": false
          },
          "companyFilters": {
            "title": "Filter by public company facts",
            "required": [
              "schemaVersion",
              "expression"
            ],
            "type": "object",
            "description": "Optional nomad-agent-linkedin-company-filter-v1 expression over the separately versioned public company-profile extension. Requires companyProfileEnrichment=true. Eligible company profiles are retrieved after job and optional AI filters but before maxItems selects the final output prefix. Unavailable, blocked, unverified, deadline-limited, or over-cap profiles are unknown and are excluded by default or can abort the run.",
            "properties": {
              "schemaVersion": {
                "title": "Company filter schema version",
                "description": "Version of the source-specific public company filter contract.",
                "type": "string",
                "enum": [
                  "nomad-agent-linkedin-company-filter-v1"
                ]
              },
              "expression": {
                "title": "Company filter expression",
                "description": "Recursive all, any, or not groups and allowlisted typed company-profile predicates. See the README for fields and operators.",
                "type": "object"
              },
              "unknownPolicy": {
                "title": "Unavailable-profile policy",
                "description": "Exclude keeps unverifiable company profiles out; abort fails the run instead of returning a potentially non-compliant row.",
                "type": "string",
                "enum": [
                  "exclude",
                  "abort"
                ]
              }
            },
            "additionalProperties": false
          },
          "includeRaw": {
            "title": "Include raw description text and HTML",
            "type": "boolean",
            "description": "When enabled (default), each result includes the complete LinkedIn plain-text description and source HTML in <code>raw</code>. Disable it to return <code>raw: null</code>. Raw text remains available internally for requested position enrichment before it is removed from the output.",
            "default": true
          },
          "postedWithin": {
            "title": "Posted within",
            "enum": [
              "1h",
              "24h",
              "7d",
              "30d",
              "any"
            ],
            "type": "string",
            "description": "One freshness window for both live LinkedIn discovery and the retained unseen-job inventory. <code>any</code> omits LinkedIn's publication-time filter and disables inventory age expiry.",
            "default": "30d"
          },
          "maxItems": {
            "title": "Max items",
            "minimum": 0,
            "maximum": 200,
            "type": "integer",
            "description": "Maximum number of job postings to return. Set <code>0</code> to request up to the Actor's full bounded window of 200 items. Values above 200 are not accepted.",
            "default": 100
          },
          "dedupe": {
            "title": "Cross-run deduplication",
            "required": [
              "enabled",
              "key"
            ],
            "type": "object",
            "description": "Cross-run delivery suppression is enabled by default. Leave <code>key</code> empty to isolate history by this Apify user and the canonical query/filter scope, or provide a public opaque alert/profile key to intentionally share history across that profile's searches. Optional <code>replayEpoch</code> starts a new delivery generation; keep it stable after an intentional replay. Set <code>enabled</code> to false with both <code>key</code> and <code>replayEpoch</code> empty for an explicit storage-free opt-out. The first 0.6 run starts a new transactional history because the former KVS state is not migrated.",
            "properties": {
              "enabled": {
                "title": "Enabled",
                "type": "boolean",
                "description": "Suppress jobs already delivered in the same tenant-and-query/profile scope.",
                "default": true
              },
              "key": {
                "title": "Scope key",
                "type": "string",
                "description": "Public delivery scope key used only when enabled. Leave empty for an Apify-user-and-query-derived scope, or use a distinct opaque alert/profile key for intentional cross-search sharing.",
                "default": "",
                "maxLength": 256
              },
              "replayEpoch": {
                "title": "Replay epoch",
                "type": "string",
                "description": "Optional opaque reset generation used only when deduplication is enabled. Omit or leave empty to preserve the existing delivery scope exactly. Set a new value only for an intentional one-time replay, then keep it stable for later runs.",
                "default": "",
                "maxLength": 128
              }
            },
            "default": {
              "enabled": true,
              "key": ""
            },
            "additionalProperties": false
          },
          "filters": {
            "title": "Normalized job filters",
            "type": "object",
            "description": "Optional nomad-agent-job-filter-v1 AND/OR expression over allowlisted nomad-agent-job-v1 fields. Use the JSON shape documented in the README. The Actor strictly validates schemaVersion, expression depth, field paths, operators, and value types at runtime. Card-stable predicates run before detail requests; predicates proven false from final static normalized facts run before LLM enrichment; remaining predicates run exactly after optional LLM enrichment. Filters see source-language values before optional output translation. maxItems remains the final delivery limit.",
            "properties": {
              "schemaVersion": {
                "title": "Filter schema version",
                "description": "Version of the normalized job-filter expression contract.",
                "type": "string",
                "enum": [
                  "nomad-agent-job-filter-v1"
                ]
              },
              "expression": {
                "title": "Filter expression",
                "description": "Strict AND/OR expression over allowlisted normalized fields.",
                "type": "object"
              }
            },
            "additionalProperties": false
          },
          "analyticsEnabled": {
            "title": "Share anonymous run analytics",
            "type": "boolean",
            "description": "Opt in to one fail-open HTTPS event after the run. It contains only Actor/build version, a success category, a coarse duration bucket, emitted-item count, names of enabled features, closed-enum source-health codes, aggregate cache/retry counters, and the number of position-enrichment provider attempts. It never includes your Apify user/run/task IDs, search values, input or output records, URLs, raw errors, tokens, source text, translations, extracted values, or a persistent caller identifier.",
            "default": false
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}