All platforms

Workable Jobs API

Query jobs from Workable boards through one API — and why the endpoint you'd reach for first will get your IP locked out for most of a day.

?source=workablesource reference

Workable is hiring and onboarding software used mostly by small and mid-sized companies, with boards at apply.workable.com/<account>. It has a public API and a widget endpoint, and choosing the wrong one of the two is the difference between a whole board in one request and your IP being locked out for the rest of the day. This is the platform where we have the sharpest measurement of that difference, so this page is mostly about it.

Try it#

BASH
curl -G https://api.hyperjobs.io/v1/jobs \
  -H "Authorization: Bearer $HYPERJOBS_KEY" \
  --data-urlencode "source=workable" \
  --data-urlencode "time_frame=7d" \
  --data-urlencode "limit=2"
Illustrative — the shape, not a live response
{
  "data": [
    {
      "id": "workable:A1B2C3D4E5",
      "title": "Registered Nurse — Night Shift",
      "company": {
        "slug": "cedar-health",
        "name": "Cedar Health",
        "domain": "cedarhealth.org",
        "website": "https://cedarhealth.org",
        "logo": "https://media.licdn.com/dms/image/…",
        "industry": "Hospital & Health Care",
        "employee_count": 640
      },
      "location": {
        "remote": false,
        "countries": ["United States"],
        "cities": ["Portland"],
        "regions": ["Oregon"],
        "raw": ["Portland, Oregon, United States"]
      },
      "employment_type": ["FULL_TIME"],
      "work_arrangement": "On-site",
      "seniority": "Associate",
      "education_requirements": ["bachelor degree"],
      "salary": null,
      "skills": ["patient care", "triage"],
      "taxonomies": ["Healthcare"],
      "apply_url": "https://apply.workable.com/cedar-health/j/A1B2C3D4E5/",
      "url": "https://apply.workable.com/cedar-health/j/A1B2C3D4E5/",
      "source": "workable",
      "posted_at": "2026-07-09T00:00:00.000Z",
      "expires_at": null,
      "updated_at": "2026-07-13T22:08:41.000Z"
    }
  ],
  "total": 2,
  "limit": 2,
  "offset": 0
}

How Workable boards actually work#

There are two ways in. Take the second one.

BASH
# The obvious path: v3 list + v2 detail per posting. Don't.
# The one that works: the embed widget — whole board, descriptions included, ONE request.
curl "https://apply.workable.com/api/v1/widget/accounts/<account>?details=true"

<account> is the slug from apply.workable.com/<account> or <account>.workable.com. The response is { name, description, jobs: [...] }, and with details=true every job carries its full HTML description inline.

Why the widget instead of the list-plus-detail#

Because we measured both.

The N+1 path — one list call, then a detail fetch per posting at concurrency 5 — produces a flood of new TLS connections per account. Workable's WAF resets new TLS connections under burst: curl reported 000, not even a 429. There is no status code to catch, no Retry-After to respect, nothing that looks like rate limiting. It just fails.

PathResult
v3 list + v2 detail, concurrency 52,677 of 2,951 boards errored — 153 jobs total
Widget, one request per account18 of 18 boards returned 200

That's the entire argument. One request per account, and Node's in-process keep-alive reuses the connection across accounts, so the whole run shares a small pool instead of opening thousands of sockets. The practical rule that follows: keep concurrency on this provider low — one or two — because the fix isn't the endpoint alone, it's the connection count.

A burst gets your IP locked for hours, not seconds

Push it and Workable hard-locks the source IP. The observed Retry-After was roughly 19 hours. Not a backoff — a lockout.

Once that trips, failing through thousands of boards one at a time burns the entire run for nothing. Our adapter opens a circuit breaker on the first big Retry-After and skips every remaining Workable board instantly. Skipped boards are left unmarked, so they stay stale and retry next run rather than being recorded as empty.

This is why Workable sits in the proxy-only tier here. It works fine direct at low volume — which is exactly what makes it dangerous, because your test against three boards will succeed and tell you nothing about what 3,000 will do.

What the widget gives you#

Per job: shortcode, title, description (full HTML), employment_type, telecommuting, experience (LinkedIn's seniority vocabulary), department, function, industry, education, published_on, locations[], and application_url. industry is populated on close to every posting; function on roughly 30%, and education about the same.

What bites you#

The same job appears once per location. The widget repeats a shortcode for each of a job's locations, each copy carrying one location. Key by id and you keep one location and throw the rest away — a three-city role becomes a one-city role, quietly. Group by shortcode and union the locations into one document.

telecommuting is a clean binary with no hybrid. Unlike Ashby's hybrid-inclusive flag, this one is honest — but Workable has no hybrid concept at all, so false genuinely means on-site and hybrid roles are simply not expressible. A null work_arrangement on a Workable posting often means the platform had nowhere to put it.

A location can be hidden. locations[].hidden is a real flag. Include those and you publish a location the employer suppressed.

The account slug isn't always the first path segment. apply.workable.com/j/<code>, /api, /view, /embed and friends look structurally identical to an account URL. Derive a board token by taking segment one and you'll add j and api to your board list as if they were companies.

employment_type can be the literal string Other. It maps to nothing useful; storing it gives you an employment type of Other, which is worse than null.

Or use ours#

The honest summary of this platform: the endpoint is easy and the traffic discipline is not. One request per board, low concurrency, connection reuse, and a breaker for the day you get it wrong anyway. Our queue tracks 5,794 Workable boards — enough that the difference between the two paths is a run that works and a run that returns 153 jobs.

You also get the per-location duplicates collapsed into one posting with all its locations, hidden locations dropped, and the company join.

One caveat we'd rather you hear from us

Workable's shortcode is not the same identifier as the token in a jobs.workable.com/view/<token> URL. If you're reconciling our Workable rows against a dataset keyed on that other id, they won't match on the key. Every other source here deduplicates cleanly against external ids; this one doesn't.

Workable is in the proxy-only refresh tier, attempted every third cycle — a new posting can take several hours to appear, and expiry runs on the same clock. Coverage has the detail.

Quickstart · Pricing

Every source above normalises onto the same schema, with the hiring company already joined onto each posting.

Get an API key