spb/company-atlas
Public
Python 66.3%
TypeScript 22.7%
JavaScript 8.6%
HTML 1.4%
CSS 0.7%
1"""Ashby job board — public endpoint behind `jobs.ashbyhq.com/<token>`:2`GET https://api.ashbyhq.com/posting-api/job-board/{token}` → {"jobs":[{id, title, department, team, employmentType, location,3secondaryLocations, publishedAt, isListed, isRemote, workplaceType, address:{postalAddress:{addressLocality, addressRegion, addressCountry}},4jobUrl, applyUrl, compensation?}]}. Verified 2026-09-12 against the `ashby` board (fixture trimmed to 20 jobs, descriptions removed)."""5from __future__ import annotations67import re8from collections.abc import Mapping9from typing import Any1011from companyatlas.connectors._ats_base import AtsConnector12from companyatlas.connectors._util import country_code, dig, parse_date, text_of13from companyatlas.sdk.connector import ConnectorMeta, register14from companyatlas.sdk.models import ExtractedJob15from companyatlas.taxonomy import FetchMode, Surface161718@register19class AshbyConnector(AtsConnector):20 vendor = "ashby"21 token_re = re.compile(r"api\.ashbyhq\.com/posting-api/job-board/([a-z0-9_.-]+)", re.IGNORECASE)22 meta = ConnectorMeta(connector_id="ashby-v1", name="Ashby job board", version="1", category=Surface.JOBS_BOARD, fetch_mode=FetchMode.JSON,23 default_interval_s=6 * 3600, url_pattern=r"api\.ashbyhq\.com/posting-api/job-board/", priority=50, pattern_required=True, accept="application/json",24 description="Public Ashby posting API")2526 def parse_jobs(self, data: Any, sensor: Mapping[str, Any]) -> list[ExtractedJob]:27 out: list[ExtractedJob] = []28 for j in (data.get("jobs") if isinstance(data, dict) else []) or []:29 if not isinstance(j, dict) or not j.get("title") or j.get("isListed") is False:30 continue31 addr = dig(j, "address", "postalAddress", default={}) or {}32 comp = j.get("compensation") or {}33 summary = comp.get("compensationTierSummary") if isinstance(comp, dict) else None34 out.append(ExtractedJob(35 title=str(j["title"]), url=j.get("jobUrl") or j.get("applyUrl"), external_id=str(j.get("id") or ""),36 department=text_of(j.get("department")), team=text_of(j.get("team")), location_text=text_of(j.get("location")),37 city=text_of(addr.get("addressLocality")), region=text_of(addr.get("addressRegion")) or None,38 country=country_code(addr.get("addressCountry")), remote=bool(j.get("isRemote")) if j.get("isRemote") is not None else None,39 employment_type=text_of(j.get("employmentType")), posted_at=parse_date(j.get("publishedAt")),40 raw={"workplaceType": j.get("workplaceType"), "secondaryLocations": [text_of(s.get("location")) for s in (j.get("secondaryLocations") or [])41 if isinstance(s, dict)][:5], "compensation": summary},42 ))43 return out44