{
  "openapi": "3.0.1",
  "info": {
    "title": "Wellfound Startup Job Scraper",
    "description": "Scrape wellfound.com startup jobs with salary and equity ranges, location, remote status, experience level, and company name and size. Company-only lead-gen mode, incremental runs, and Slack/Telegram/Discord alerts on new postings.",
    "version": "0.1",
    "x-build-id": "9U5gmJrQQUXChh7xa"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/blackfalcondata~wellfound-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-blackfalcondata-wellfound-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/blackfalcondata~wellfound-scraper/runs": {
      "post": {
        "operationId": "runs-sync-blackfalcondata-wellfound-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/blackfalcondata~wellfound-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-blackfalcondata-wellfound-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": {
          "query": {
            "title": "🔍 Search Query (free-text)",
            "type": "string",
            "description": "Free-text job search (e.g. \"rust engineer\", \"ML ops\", \"solidity developer\"). Maps to Wellfound's /jobs?q= endpoint. Combine with roles/searchUrls to union multiple searches."
          },
          "roles": {
            "title": "📁 Role Categories",
            "uniqueItems": true,
            "type": "array",
            "description": "Wellfound's built-in role categories. Each spawns a separate search thread. Common slugs: software-engineer, product-manager, product-designer, data-analyst, growth-marketer, sales-manager, account-manager, hr-manager, operations-manager, financial-analyst, graphic-designer, ui-ux-designer. Free-text — you can also try other slugs.",
            "items": {
              "type": "string"
            }
          },
          "searchUrls": {
            "title": "🔗 Search URLs (paste Wellfound URLs)",
            "uniqueItems": true,
            "type": "array",
            "description": "Paste full Wellfound search URLs (e.g. https://wellfound.com/role/l/product-manager/berlin). Each URL spawns a separate search thread. Mix with query/roles freely — all deduplicate by job ID.",
            "items": {
              "type": "string"
            }
          },
          "location": {
            "title": "📍 Locations",
            "uniqueItems": true,
            "type": "array",
            "description": "One or more location slugs (e.g. [\"new-york\", \"san-francisco\", \"berlin\"]). Each location × role combination spawns a separate search thread. For /jobs?q= searches, use a human-readable city name. Ignored for pasted searchUrls (they carry their own location).",
            "items": {
              "type": "string"
            }
          },
          "excludeLocations": {
            "title": "🚫 Exclude Locations",
            "uniqueItems": true,
            "type": "array",
            "description": "Drop jobs whose locationNames match any of these (substring match, e.g. \"India\" drops \"Bangalore, India\"). Applied after fetch.",
            "items": {
              "type": "string"
            }
          },
          "remote": {
            "title": "🏠 Remote Only",
            "type": "boolean",
            "description": "When true, scrapes remote-filtered URLs. Ignored for pasted searchUrls.",
            "default": false
          },
          "originLocation": {
            "title": "🎯 Origin Location (for radius filter)",
            "type": "string",
            "description": "City name for radius-based filtering (e.g. \"San Francisco\", \"New York\"). Used with radiusMiles or radiusKm. Supports ~35 major US + international startup hubs — unsupported cities skip the radius filter with a warning."
          },
          "radiusMiles": {
            "title": "📏 Radius (miles)",
            "minimum": 0,
            "maximum": 500,
            "type": "integer",
            "description": "Drop jobs further than N miles from originLocation, using job coordinates where available. US-standard unit.",
            "default": 0
          },
          "radiusKm": {
            "title": "📏 Radius (km, alt)",
            "minimum": 0,
            "maximum": 800,
            "type": "integer",
            "description": "Kilometer alternative to radiusMiles. If both set, radiusMiles wins. Use this for EU-based searches.",
            "default": 0
          },
          "jobType": {
            "title": "💼 Job Type",
            "enum": [
              "fulltime",
              "parttime",
              "contract",
              "internship"
            ],
            "type": "string",
            "description": "Filter by employment type. Matches Wellfound's jobType field (substring, case-insensitive)."
          },
          "experienceLevel": {
            "title": "🎓 Experience Level",
            "enum": [
              "entry",
              "mid",
              "senior",
              "staff"
            ],
            "type": "string",
            "description": "Filter by minimum required years of experience. Entry: 0-2, Mid: 2-5, Senior: 5-8, Staff+: 8+. Jobs without experience data are kept."
          },
          "salaryMin": {
            "title": "💰 Minimum Salary (USD)",
            "minimum": 0,
            "type": "integer",
            "description": "Drop jobs whose salary max is below this. 0 = no minimum. Jobs without salary data are dropped when minimum is set.",
            "default": 0
          },
          "salaryMax": {
            "title": "💰 Maximum Salary (USD)",
            "minimum": 0,
            "type": "integer",
            "description": "Drop jobs whose salary min exceeds this. 0 = no maximum.",
            "default": 0
          },
          "equityMin": {
            "title": "📈 Minimum Equity (%)",
            "minimum": 0,
            "maximum": 100,
            "type": "number",
            "description": "Drop jobs whose max equity grant is below this percent. 0 = no minimum. Jobs without equity data are dropped when minimum is set.",
            "default": 0
          },
          "visaSponsorship": {
            "title": "🛂 Visa Sponsorship",
            "type": "boolean",
            "description": "Filter by visa sponsorship stance detected from job description heuristics. true = only jobs that explicitly offer sponsorship; false = drop jobs that explicitly refuse sponsorship. Unset = no filter. Detection is conservative — jobs without clear phrasing pass when true is not required."
          },
          "includeKeywords": {
            "title": "📝 Include Keywords",
            "type": "object",
            "description": "Require at least one of these keywords. Example: {\"keywords\":[\"rust\",\"golang\"],\"matchTitle\":true,\"matchDescription\":true,\"matchSkills\":true}. Matches default to all three fields."
          },
          "excludeKeywords": {
            "title": "🚫 Exclude Keywords",
            "type": "object",
            "description": "Drop jobs containing any of these keywords. Same shape as includeKeywords."
          },
          "fromDate": {
            "title": "📅 From Date",
            "type": "string",
            "description": "Only include jobs posted on or after this date. Accepts YYYY-MM-DD or ISO-8601."
          },
          "toDate": {
            "title": "📅 To Date",
            "type": "string",
            "description": "Only include jobs posted on or before this date. Accepts YYYY-MM-DD or ISO-8601."
          },
          "maxAgeMinutes": {
            "title": "⏰ Max Age (minutes)",
            "minimum": 0,
            "type": "integer",
            "description": "Only include jobs posted within the last N minutes. 0 = no limit. Pairs well with scheduled runs for real-time monitoring.",
            "default": 0
          },
          "customFilters": {
            "title": "🔧 Custom Filters (advanced)",
            "type": "array",
            "description": "Array of rules applied to any output field. Each rule: {\"field\":\"<name>\",\"op\":\"includes|notIncludes|equals|notEquals|gt|gte|lt|lte\",\"value\":...}. Example: [{\"field\":\"companyFundingStage\",\"op\":\"equals\",\"value\":\"series-b\"}, {\"field\":\"description\",\"op\":\"notIncludes\",\"value\":\"wordpress\"}]."
          },
          "maxResults": {
            "title": "💯 Max Results",
            "minimum": 0,
            "maximum": 5000,
            "type": "integer",
            "description": "Maximum total job listings to return across all search threads (0 = unlimited).",
            "default": 100
          },
          "maxPages": {
            "title": "📄 Max Pages per Search",
            "minimum": 1,
            "maximum": 200,
            "type": "integer",
            "description": "Maximum SERP pages per search thread (each page has ~42 jobs). Defensive safety bound — `maxResults` is the primary record cap.",
            "default": 10
          },
          "enrichDetail": {
            "title": "📄 Enrich from Detail Pages",
            "type": "boolean",
            "description": "Core job fields — title, full description, compensation, location, remote status, experience level, job type, and company name/logo/size — are delivered inline for every listing, no toggle needed. This option additionally attempts deep per-listing fields (structured salary currency/period, company website, industry, benefits, skills). Those deep fields are not currently available and will return null, so leave this off unless you specifically need them and accept they may be empty.",
            "default": false
          },
          "enrichCompany": {
            "title": "🏢 Enrich Company Profiles",
            "type": "boolean",
            "description": "Company basics — name, logo, slug, size — are delivered inline for every listing. This option additionally attempts deep firmographics (funding stage, total raised, investors, founders, social links, founded year, markets). Those deep fields are not currently available and will return null.",
            "default": false
          },
          "companyOnlyMode": {
            "title": "🎯 Company-Only Output (lead-gen mode)",
            "type": "boolean",
            "description": "Emit ONE record per unique company instead of one per job, with aggregated jobCount and sample job titles. Ideal for lead-gen / recruiter / sourcer workflows. Incremental mode does not apply (aggregation is per-run). Pairs well with enrichCompany for rich contact data.",
            "default": false
          },
          "descriptionMaxLength": {
            "title": "✂️ Description Max Length",
            "minimum": 0,
            "type": "integer",
            "description": "Truncate job description to this many characters. 0 = no truncation.",
            "default": 0
          },
          "compact": {
            "title": "📦 Compact Output",
            "type": "boolean",
            "description": "Output only core fields (id, title, companyName, portalUrl, locationNames, remote, compensation, postedAt). For AI-agent/MCP workflows.",
            "default": false
          },
          "incrementalMode": {
            "title": "♻️ Incremental Mode",
            "type": "boolean",
            "description": "Compare against previous run state. Only emits NEW and UPDATED jobs. Requires stateKey.",
            "default": false
          },
          "stateKey": {
            "title": "🔑 State Key",
            "type": "string",
            "description": "Stable identifier for the tracked search universe (e.g. 'us-software-remote'). Required when incrementalMode is true. IMPORTANT: changing your filters (roles, searchUrls, location) will cause jobs outside the new universe to be marked EXPIRED. Use a NEW stateKey if you change search scope."
          },
          "emitUnchanged": {
            "title": "♻️ Emit Unchanged Records",
            "type": "boolean",
            "description": "When incremental, also emit records that have not changed since last run.",
            "default": false
          },
          "emitExpired": {
            "title": "⚰️ Emit Expired Records",
            "type": "boolean",
            "description": "When incremental, also emit records no longer found (job removed or expired).",
            "default": false
          },
          "skipReposts": {
            "title": "🚫 Skip Reposts",
            "type": "boolean",
            "description": "When enabled, suppress jobs that appear to be reposts of previously seen (and now expired) jobs based on content-hash matching.",
            "default": false
          },
          "telegramToken": {
            "title": "📱 Telegram Bot Token",
            "type": "string",
            "description": "Telegram bot token from @BotFather. Sends notifications when new jobs are emitted. Pairs well with incrementalMode for real-time alerts."
          },
          "telegramChatId": {
            "title": "💬 Telegram Chat / Channel ID",
            "type": "string",
            "description": "Chat ID (from @userinfobot) or channel ID (starts with -100 for channels). Required when telegramToken is set."
          },
          "slackWebhookUrl": {
            "title": "💼 Slack Incoming Webhook URL",
            "type": "string",
            "description": "Slack incoming webhook URL (Slack App → Incoming Webhooks → Add New Webhook). Formats jobs as Slack blocks with company, salary, funding stage, and location."
          },
          "discordWebhookUrl": {
            "title": "💬 Discord Webhook URL",
            "type": "string",
            "description": "Discord channel webhook URL (Server Settings → Integrations → Webhooks → New Webhook). Sends rich embeds colour-coded by change type (green=NEW, amber=UPDATED)."
          },
          "whatsappPhoneNumberId": {
            "title": "📱 WhatsApp Phone Number ID",
            "type": "string",
            "description": "WhatsApp Business phone number ID from Meta Business Manager (the numeric ID next to your number — NOT the phone number itself). Free service-conversation messages within 24 hours of last user-initiated contact."
          },
          "whatsappAccessToken": {
            "title": "🔐 WhatsApp Access Token",
            "type": "string",
            "description": "Meta Cloud API access token with whatsapp_business_messaging scope. Get a permanent token from a system user in Meta Business Manager."
          },
          "whatsappTo": {
            "title": "📨 WhatsApp Recipient",
            "type": "string",
            "description": "Recipient phone number in E.164 format (e.g. +4512345678). The recipient must have messaged your business number within the last 24 hours."
          },
          "webhookUrl": {
            "title": "🪝 Generic Webhook URL",
            "type": "string",
            "description": "Universal escape hatch for n8n / Make / Zapier / custom HTTP backends. Receives a JSON POST { metadata, items } per run. Single attempt, 15 s timeout."
          },
          "webhookHeaders": {
            "title": "🪝 Webhook Headers (optional)",
            "type": "object",
            "description": "Additional HTTP headers sent with the generic webhook POST (e.g. {\"Authorization\":\"Bearer ...\"})."
          },
          "notificationLimit": {
            "title": "🔢 Notification Limit",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "Maximum number of jobs to send per notification batch. Prevents spam on large result sets.",
            "default": 5
          },
          "includeRunMetadata": {
            "title": "📣 Include Run Summary in Notifications",
            "type": "boolean",
            "description": "Prepend a one-line summary (search label + total count) to each notification batch.",
            "default": true
          },
          "notifyOnlyChanges": {
            "title": "🆕 Notify Only on Changes",
            "type": "boolean",
            "description": "When ON (default) AND incrementalMode is ON, send notifications only for NEW and UPDATED jobs. Without incrementalMode, this has no effect (all emitted jobs are notified).",
            "default": true
          },
          "proxyConfiguration": {
            "title": "🛡️ Proxy Configuration",
            "type": "object",
            "description": "Wellfound can reject automated traffic. The default network settings are tuned for reliable runs, and advanced users can provide their own connection settings.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ],
              "apifyProxyCountry": "US"
            }
          },
          "descriptionFormat": {
            "title": "Description format",
            "enum": [
              "all",
              "text",
              "html",
              "markdown"
            ],
            "type": "string",
            "description": "Pick a single description representation. `all` keeps every variant; `text` / `html` / `markdown` drop the others.",
            "default": "all"
          },
          "excludeEmptyFields": {
            "title": "Exclude empty fields from output",
            "type": "boolean",
            "description": "Drop null, empty-string, and empty-array fields from each record before push. Smaller payloads for AI agents and dashboards.",
            "default": false
          },
          "appConnector": {
            "title": "Send results to Notion (or another connected app)",
            "type": "string",
            "description": "Optional. Pick a connected app under Settings → API & Integrations to receive your results. Notion is supported today (a run-summary page); other MCP connectors are best-effort as Apify expands its catalog."
          },
          "mcpIssueTeam": {
            "title": "Issue tracker team",
            "type": "string",
            "description": "Only when the connected app is an issue tracker: the team (name or ID) the summary issue is created under, if that app requires one."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}