#!/usr/bin/env python3 """Read one supported public Greenhouse board. Copyright 2026 VendorCensus. MIT license: see public-job-collector-LICENSE.txt. Python 3.9+, no dependencies. Usage: python3 public-job-collector.py https://job-boards.greenhouse.io/figma """ import datetime import json import re import sys import urllib.request from urllib.parse import urlsplit BOARDS = {'figma', 'stripe', 'airbnb', 'cloudflare', 'datadog'} class NoRedirect(urllib.request.HTTPRedirectHandler): def redirect_request(self, req, fp, code, msg, headers, newurl): raise ValueError('Unexpected redirect; request stopped') def collect(value): u = urlsplit(value) match = re.fullmatch(r'/([a-z0-9-]+)/?', u.path) if (u.scheme != 'https' or u.hostname not in {'boards.greenhouse.io', 'job-boards.greenhouse.io'} or u.username or u.password or u.port not in (None, 443) or u.query or u.fragment or not match or match[1] not in BOARDS): raise ValueError('Use a supported Greenhouse board URL: ' + ', '.join(sorted(BOARDS))) board = match[1] source = f'https://boards-api.greenhouse.io/v1/boards/{board}/jobs' request = urllib.request.Request(source, headers={'Accept': 'application/json', 'User-Agent': 'VendorCensus-public-job-collector/1.0'}) with urllib.request.build_opener(NoRedirect).open(request, timeout=15) as response: body = json.load(response) if not isinstance(body, dict) or not isinstance(body.get('jobs'), list): raise ValueError('Invalid response; not a zero-job result') jobs = [] for j in body['jobs']: if not isinstance(j, dict) or not isinstance(j.get('id'), int) or not isinstance(j.get('title'), str): continue link = j.get('absolute_url') if not isinstance(link, str) or not link.startswith('https://'): continue location = j.get('location') name = location.get('name') if isinstance(location, dict) else None jobs.append({'id': j['id'], 'title': j['title'], 'url': link, 'location': name if isinstance(name, str) else 'Not stated'}) return {'provider': 'Greenhouse', 'board': board, 'sourceUrl': source, 'checkedAt': datetime.datetime.now(datetime.timezone.utc).isoformat(), 'jobCount': len(jobs), 'jobs': jobs} if __name__ == '__main__': try: if len(sys.argv) != 2: raise ValueError(__doc__) print(json.dumps(collect(sys.argv[1]), indent=2)) except Exception as exc: print(f'Collection failed: {exc}', file=sys.stderr) sys.exit(1)