All platforms

Lumesse TalentLink Jobs API.

Pull structured vacancies from enterprise career sites running Lumesse TalentLink (formerly Infinite Talent) through its public guest Front Office API — full adverts, salary and locations returned as clean JSON.

Get API access
Lumesse TalentLink
Live
<3haverage discovery time
1hrefresh interval
Companies using Lumesse TalentLink
Age UKUnited UtilitiesFortem
Developer tools

Try the API.

Test Jobs and Feed 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 Lumesse TalentLink.

Data fields
  • Full Job Descriptions
  • Structured Salary Text
  • Contract Type & Schedule
  • Department & Team
  • Posting & Closing Dates
  • Location & Region Labels
Use cases
  1. 01Enterprise Vacancy Aggregation
  2. 02Careers Site Monitoring
  3. 03Salary & Benefits Benchmarking
  4. 04Job Board Syndication
Trusted by
Age UKUnited UtilitiesFortem
DIY GUIDE

How to scrape Lumesse TalentLink.

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

RESTintermediateNo published limit; keep ~150ms between requestsAuth required

Discover the site technical ID and regional host

Every TalentLink board is identified by a 25+ character site technical ID and served from a region-specific host. Both are published in the widget config on the corporate careers page, so read them from the HTML rather than hardcoding.

Step 1: Discover the site technical ID and regional host
import re
import requests

# The site technical ID and regional API host come from the TalentLink
# widget embedded on the corporate careers page.
CAREERS_URL = "https://www.unitedutilities.com/corporate/careers/jobs/"

html = requests.get(CAREERS_URL, timeout=30).text
match = re.search(r'data-talentlink-fo-site-tech-id="([A-Z0-9]{20,})"', html)
SITE_ID = match.group(1) if match else "PGLFK026203F3VBQB688MF6CR"

# Regional host varies per tenant, e.g. emea3.recruitmentplatform.com or
# emea5-foc.lumessetalentlink.com. Confirm it from the widget config.
API_HOST = "https://emea3.recruitmentplatform.com"
LANGUAGE = "UK"  # the board language passed in the lumesse-language header

Call the guest jobs API

POST to /fo/rest/jobs with an empty searchCriteria and the public guest credentials in the headers. The response carries the authoritative total in globals.jobsCount and the current page in jobs[].

Step 2: Call the guest jobs API
def fetch_page(offset=0, page_size=12):
    url = f"{API_HOST}/fo/rest/jobs"
    params = {
        "firstResult": offset,
        "maxResults": page_size,
        "sortBy": "DPOSTINGSTART",
        "sortOrder": "desc",
    }
    headers = {
        "Accept": "application/json",
        "username": f"{SITE_ID}:guest:FO",
        "password": "guest",
        "lumesse-language": LANGUAGE,
        "Referer": CAREERS_URL,
    }
    resp = requests.post(
        url, params=params, headers=headers,
        json={"searchCriteria": {}}, timeout=30,
    )
    resp.raise_for_status()
    return resp.json()

data = fetch_page()
total = data["globals"]["jobsCount"]
print(f"{total} vacancies on this board")

Parse each job row

Pull the numeric id, title, apply URL, location, salary, contract type and dates using ordered fallbacks across the key variants, and rebuild the description from the HTML sections in customFields[].

Step 3: Parse each job row
def strip_html(text):
    return re.sub(r"<[^>]+>", "", text or "").strip()

def first(fields, *names):
    for name in names:
        value = fields.get(name)
        if value:
            return value
    return None

def parse_job(row):
    fields = row.get("jobFields", {})
    sections = []
    for cf in row.get("customFields", []):
        content = strip_html(cf.get("content"))
        if content:
            heading = (cf.get("title") or "").strip()
            sections.append(f"{heading}\n{content}" if heading else content)
    return {
        "id": row.get("id"),
        "title": first(fields, "jobTitle", "sJobTitle", "SJOBTITLE"),
        "apply_url": fields.get("applicationUrl"),
        "location": first(fields, "SLOCATION", "SLOVLIST2", "REGLABEL"),
        "salary": fields.get("SALARY"),
        "contract_type": first(fields, "CONTRACTTYPLABEL", "SLOVLIST208"),
        "department": first(fields, "SDPTNAMELEVEL1", "SDPTNAME"),
        "posted_at": first(fields, "DPOSTINGSTART", "postingStartDate"),
        "closes_at": first(fields, "DPOSTINGEND", "postingEndDate"),
        "description": "\n\n".join(sections),
    }

Page through the full board

Advance firstResult by the number of rows returned and stop once the offset reaches globals.jobsCount. Dedupe on the numeric id and drop thin placeholder rows so the snapshot matches the authoritative total.

Step 4: Page through the full board
def scrape_all():
    jobs, seen, offset = [], set(), 0
    while True:
        data = fetch_page(offset)
        total = data["globals"]["jobsCount"]
        rows = data.get("jobs", [])
        if not rows:
            break
        for row in rows:
            job = parse_job(row)
            if job["id"] and job["id"] not in seen and len(job["description"]) >= 40:
                seen.add(job["id"])
                jobs.append(job)
        offset += len(rows)
        if offset >= total:
            break
    return jobs

all_jobs = scrape_all()
print(f"Collected {len(all_jobs)} vacancies")
Common issues
highThe regional API host differs per tenant. Some boards live on emea3.recruitmentplatform.com, others on emea5-foc.lumessetalentlink.com, and guessing the wrong host returns connection errors or 404s.

Read the correct host from the TalentLink widget config on the careers page instead of hardcoding one. The /fo/rest/jobs path is stable, but the origin must match the tenant's region.

highEvery request is keyed to a 25+ character site technical ID (for example Q26FK026203F3VBQB68798ND8). Without the exact ID the guest API returns no jobs.

Extract the site technical ID from the widget marker data-talentlink-fo-site-tech-id embedded on the corporate careers page, then reuse it in the username header and pagination calls.

mediumThe guest Front Office API rejects unauthenticated calls. Missing the username/password/lumesse-language headers returns HTTP 401 or 403.

Send the public guest identity on every request: username set to {siteId}:guest:FO, password set to guest, the board language in lumesse-language, and the corporate board URL as the Referer.

mediumField names are inconsistent across tenants. Titles appear as jobTitle, sJobTitle, or SJOBTITLE, and locations as SLOCATION, SLOVLIST2, or REGLABEL.

Read each value through an ordered fallback across the known key variants rather than a single property, so a missing key on one board does not blank the field.

lowFull descriptions are not one field. They live as HTML sections inside customFields[], and thin rows (under ~40 characters of text) are usually placeholders rather than real adverts.

Concatenate each customFields entry (title plus HTML-stripped content) into the description and skip rows whose combined text is below a small length threshold.

Best practices
  1. 1Read the site technical ID and regional host from the widget config on each careers page before calling the API.
  2. 2Send the full guest identity on every request: username {siteId}:guest:FO, password guest, lumesse-language and the board Referer.
  3. 3Treat globals.jobsCount as the authoritative total and page with firstResult until the offset reaches it.
  4. 4Resolve each field through ordered fallbacks (jobTitle/sJobTitle, SLOCATION/SLOVLIST2/REGLABEL) so tenant-specific keys never blank a value.
  5. 5Rebuild descriptions from customFields[], strip the embedded HTML, and skip thin placeholder rows.
  6. 6Dedupe on the numeric job id and pace requests (~150ms) to stay well within the guest API's tolerance.
Or skip the complexity

One endpoint. All Lumesse TalentLink jobs. No scraping, no sessions, no maintenance.

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

Access Lumesse TalentLink
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