All platforms

Freshteam Jobs API.

HR software by Freshworks for growing companies with embedded job data attributes for easy scraping.

Freshteam
Live
40K+jobs indexed monthly
<3haverage discovery time
1hrefresh interval
Companies using Freshteam
A1FED IncFreshworksGrowing companies
Developer tools

Try the API.

Test Jobs, Feed, and Auto-Apply endpoints against https://connect.jobo.world with live request/response examples, then copy ready-to-use curl commands.

What's in every response.

Data fields, real-world applications, and the companies already running on Freshteam.

Data fields
  • SMB focus
  • HR integration
  • Easy setup
  • Candidate tracking
  • Employee management
  • Embedded data attributes
  • JSON-LD structured data
Use cases
  1. 01SMB job tracking
  2. 02HR software integration
  3. 03Growing company monitoring
Trusted by
A1FED IncFreshworksGrowing companies
DIY GUIDE

How to scrape Freshteam.

Step-by-step guide to extracting jobs from Freshteam-powered career pages—endpoints, authentication, and working code.

HTMLbeginnerNo official limit; use reasonable delays (1-2 seconds between requests)No auth

Fetch the job listings page

Request the company's Freshteam job board. All jobs are loaded on a single page with embedded data attributes for structured extraction.

Step 1: Fetch the job listings page
import requests
from bs4 import BeautifulSoup

company_slug = "a1fed"
url = f"https://{company_slug}.freshteam.com/jobs"

response = requests.get(url, timeout=10)
soup = BeautifulSoup(response.content, "html.parser")

# Find all job listings with data attributes
job_elements = soup.select("a[data-portal-title]")
print(f"Found {len(job_elements)} jobs")

Extract job data from data attributes

Freshteam embeds structured data in data-portal-* attributes on each job link. Extract these attributes for clean, structured job data.

Step 2: Extract job data from data attributes
jobs = []
for job_el in job_elements:
    job = {
        "title": job_el.get("data-portal-title", ""),
        "location": job_el.get("data-portal-location", ""),
        "job_type_id": job_el.get("data-portal-job-type", ""),
        "is_remote": job_el.get("data-portal-remote-location") == "true",
        "url": f"https://{company_slug}.freshteam.com{job_el.get('href', '')}",
    }
    # Extract display title from inner div
    title_div = job_el.select_one(".job-title")
    if title_div:
        job["display_title"] = title_div.get_text(strip=True)
    jobs.append(job)

print(f"Extracted {len(jobs)} jobs with structured data")

Build department and type mappings

Extract the select dropdown values to map department IDs and job type IDs to their human-readable names.

Step 3: Build department and type mappings
def build_mappings(soup):
    mappings = {"departments": {}, "job_types": {}, "locations": {}}

    # Extract department mappings
    dept_select = soup.select_one("select#department_id")
    if dept_select:
        for option in dept_select.select("option[value]"):
            mappings["departments"][option["value"]] = option.get_text(strip=True)

    # Extract job type mappings
    type_select = soup.select_one("select#work_type_id")
    if type_select:
        for option in type_select.select("option[value]"):
            mappings["job_types"][option["value"]] = option.get_text(strip=True)

    # Extract location mappings
    loc_select = soup.select_one("select#city_id")
    if loc_select:
        for option in loc_select.select("option[value]"):
            mappings["locations"][option["value"]] = option.get_text(strip=True)

    return mappings

mappings = build_mappings(soup)
print("Departments:", mappings["departments"])

Fetch detailed job information via JSON-LD

For full job descriptions, fetch individual job pages and extract the JSON-LD structured data embedded in script tags.

Step 4: Fetch detailed job information via JSON-LD
import json

def get_job_details(job_url: str) -> dict:
    response = requests.get(job_url, timeout=10)
    soup = BeautifulSoup(response.content, "html.parser")

    # Find JSON-LD structured data
    script_tag = soup.select_one('script[type="application/ld+json"]')
    if script_tag:
        data = json.loads(script_tag.string)
        return {
            "title": data.get("title"),
            "description": data.get("description"),
            "date_posted": data.get("datePosted"),
            "employment_type": data.get("employmentType"),
            "is_remote": data.get("remote") == "true",
            "location": data.get("jobLocation", {}).get("address", {}),
        }
    return {}

# Get details for first job
if jobs:
    details = get_job_details(jobs[0]["url"])
    print(f"Job: {details.get('title')}")

Handle errors and rate limiting

Add proper error handling and delays to avoid overwhelming the server. Freshteam has no official API limits, but be respectful.

Step 5: Handle errors and rate limiting
import time

def fetch_all_jobs(company_slug: str) -> list:
    url = f"https://{company_slug}.freshteam.com/jobs"
    jobs = []

    try:
        response = requests.get(url, timeout=10)
        response.raise_for_status()
        soup = BeautifulSoup(response.content, "html.parser")

        job_elements = soup.select("a[data-portal-title]")
        mappings = build_mappings(soup)

        for job_el in job_elements:
            job = {
                "title": job_el.get("data-portal-title", ""),
                "location": job_el.get("data-portal-location", ""),
                "is_remote": job_el.get("data-portal-remote-location") == "true",
                "url": f"https://{company_slug}.freshteam.com{job_el.get('href', '')}",
            }
            jobs.append(job)

    except requests.RequestException as e:
        print(f"Error fetching jobs: {e}")

    return jobs
Common issues
criticalAPI endpoint /api/jobs returns 401 Unauthorized

Freshteam does not expose a public REST API. Use HTML scraping with data attributes or JSON-LD extraction instead.

highCompany slug not found or invalid URL

Verify the company subdomain matches the actual Freshteam careers page URL. Some companies use custom domains.

mediumMissing department/job type names (only IDs available)

Parse the select dropdown elements on the page to build ID-to-name mappings before extracting job data.

mediumJob description not available on listings page

Fetch individual job detail pages and extract the JSON-LD structured data from script tags for full descriptions.

lowHTML structure changes break selectors

Use data-portal-* attributes which are more stable than CSS class names. These attributes are designed for client-side filtering.

Best practices
  1. 1Use data-portal-* attributes for reliable structured data extraction
  2. 2Extract JSON-LD from detail pages for complete job descriptions
  3. 3Build ID mappings from select dropdowns for human-readable values
  4. 4Cache results - job boards typically update daily
  5. 5Use reasonable delays between requests (1-2 seconds)
  6. 6Validate company slug exists before bulk scraping
Or skip the complexity

One endpoint. All Freshteam jobs. No scraping, no sessions, no maintenance.

Get API access
cURL
curl "https://enterprise.jobo.world/api/jobs?sources=freshteam" \
  -H "X-Api-Key: YOUR_KEY"
Ready to integrate

Access Freshteam
job data today.

One API call. Structured data. No scraping infrastructure to build or maintain — start with the free tier and scale as you grow.

99.9%API uptime
<200msAvg response
50M+Jobs processed