Search SEEK job postings across Australia and New Zealand
The SEEK API returns Australian job listings as clean JSON.
4 active endpoints. Every call is 1 credit.
- POST/seek/v1/search
- POST/seek/v1/detail
- POST/seek/v1/company-jobs
- POST/seek/v1/classification
What SEEK endpoints does ReefAPI ship?
4 live read endpoints. Read-only data API: no writes, no account actions, no dashboard access on the target site.
SEEK API
3 of 4 endpoints, ready to run
Keyword search with SEEK's own facets. Twenty rows a page, and the total it reports is a total you can actually walk to.
// Press "Try it" and this pane shows exactly what the // live site returned this second — including an empty // result, if that is the truth. No key, no account.
How the SEEK API works
SEEK is a normal ReefAPI surface — the same four rules that hold for every other engine on the key.
No OAuth app, no request signing, no per-site account. One key covers all 185 engines.
Every route is a POST with a JSON body. Parameters are validated against the published schema before anything is charged.
Credits, not seats. Failed and blocked calls are never charged, and cache hits cost nothing.
One envelope everywhere. meta carries latency_ms, record_count and the endpoint that answered.
Walk a classification to the last page without guessing where it ends
SEEK is the one board in this batch whose reported total and reachable total are the same number, which makes an exhaustive crawl a loop with an exit condition rather than a hopeful one.
{"classification": "6281", "location": "Melbourne VIC", "page": 1}Reported 1,660 results and total_pages in the same meta. Twenty rows a page, each carrying advertiser_id so you can group by employer later.
{"keywords": "...", "page": <n>} — until the page comes back emptyThe end is unambiguous: the last page with rows returns 20 and says has_more true; one page past it returns zero rows with total 0 and total_pages 1. No silent repeats.
A complete category, with the arithmetic checked: 541 reported, 27 full pages, zero overlap between the first page and the last.
curl -X POST https://api.reefapi.com/seek/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"keywords":"developer","location":"Sydney NSW"}'{
"ok": true,
"data": { … },
"meta": {
"api": "seek",
"endpoint": "search",
"mode": "live",
"latency_ms": …,
"record_count": …
},
"error": null
}The same job in search and in detail is not the same shape
search and detail read different SEEK surfaces, and several fields change name, type or precision between them. If you merge the two into one record — which most people do — this is the table you need. Everything below is from measured responses.
| Field | In search | In detail |
|---|---|---|
| work arrangement | work_arrangement — singular, a string ("Hybrid") | work_arrangements — plural, an array, and empty on the measured job |
| classifications | {classification, classification_id, subclassification, subclassification_id} — the ids you filter with | {label: "Developers/Programmers (Information & Communication Technology)"} — no ids at all |
| posted_date | second precision: 2026-08-21T03:45:50Z | millisecond precision: 2026-06-22T01:42:44.196Z |
| location | location string plus locations[] with country_code | broken out: country, country_code, state, suburb, post_code, region |
| expiry | not present | expires_at, is_expired, status |
| employer | company, advertiser_id, company_url | the same, plus company_profile{name, slug, industry, size, website, rating, review_count, url} |
| description | teaser and bullet_points only | description_text, description_html and abstract |
Measured SEEK classification ids: 6281 Information & Communication Technology with subclassification 6287 Developers/Programmers, and 1211 Healthcare & Medical with 6341 Nursing - Educators & Facilitators. These only come back from search, so harvest one before you use the classification or subclassification filters.
How deep it really goes, and the location trap we walked into
Measured on 2026-08-28 by exhausting one query and comparing four location inputs. One of these lines goes against us and it is the one to read twice.
There is no SEEK login in the path and nothing you read is attributed to a candidate account of yours. Nothing here can put a job-seeker profile at risk.
This is the honest one in the batch. A Sydney query reported 541 results and 28 pages. Page 27 returned 20 rows with zero overlap against page 1; page 28 returned zero rows and reset its own meta to total 0, total_pages 1, has_more false. 27 pages times 20 rows is 540 — the reported number, within a row. Nothing is hidden behind a cap, and the end of the list announces itself.
Against us, and it will bite quietly. Passing "Auckland" returned zero rows. Passing "Auckland NZ" returned 382 results, every row carrying country_code NZ. Worse, passing "Wellington" on its own returned 248 rows — all of them in Brisbane, Australia, with no flag anywhere in the response saying the input had been resolved somewhere else. Always put the country or the state on the location string, and check locations[].country_code on the rows before you trust a market split.
With the country attached, both markets answer from the same call and come back in the same shape, with country_code on every row's locations array. The engine reads seek.com.au; there is no third country behind it.
posted_date came back as a full ISO timestamp on 20 of 20 rows, next to a human posted_relative like "1d ago". date_posted today narrowed a Melbourne query to 71 results — but the rows returned were stamped across two calendar days, not one. Treat today as "the last day or so", not as a midnight boundary.
Against us. salary_label was filled on 12 of 20 rows and it is prose — "$80,000 – $110,000 per year" — not a numeric pair. The currency field next to it was null on 20 of 20. The salary_from and salary_to search filters do work, in AUD; the payload just will not hand you the number back parsed. Plan on parsing salary_label yourself, and on eight rows in twenty having no pay at all.
A search row already carries classifications with their ids, work_types, work_arrangement, bullet_points, a teaser, advertiser_id, company_url and the logo. work_arrangement was filled on 13 of 20 and company_url on 7 of 20; everything else in that list was 20 of 20.
Every row carries the employer's numeric advertiser_id, and company-jobs takes it directly — so grouping a crawl by employer needs no name matching. A plain company name also resolves, which is the easier path when you do not have a row yet.
The posting and the advertiser: title, company, location breakdown, work type, classification, teaser, apply link, dates, and pay as SEEK prints it. Not candidate profiles, not recruiter contact details, not applications.
What people build with SEEK
The jobs this data is most often used for.
endpoints
credit per call
Australian job boards call search to aggregate SEEK listings by role and location.
Labor-market analysts use classification and search to measure demand across sectors.
Recruiting tools use company-jobs to track a specific employer's open roles.
What SEEK data costs
The cheapest call here is 1 credit, so $15/mo (Pro) buys 10,000 of them — $1.50 per 1,000 credits. Credits roll over and never expire, and failed or blocked calls are not charged.
Full pricing →- 1,000 free credits on signup, no card
- One key, all 185 APIs, one credit pool
- Failed and blocked calls are never charged
- Credits roll over and never expire
Call it in two lines
Sign up, get 1,000 credits and one key that works on every engine. Then this is the whole protocol.
curl -X POST https://api.reefapi.com/seek/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"keywords":"developer","location":"Sydney NSW"}'import requests
r = requests.post(
"https://api.reefapi.com/seek/v1/search",
headers={"x-api-key": REEF_KEY},
json={
"keywords": "developer",
"location": "Sydney NSW"
},
)
print(r.json()["data"])Have a question? We got answers.
The questions people actually ask before wiring up SEEK.
Get a free key →Why is currency null and salary just a string?▾
Because SEEK publishes what the employer typed, and there is no structured salary on the posting. Three measured salary_label values: "$90,000 – $120,000 per year", "Up to $180K (inc super)" and "Educator (Major) + Super + Salary Packaging" — the third contains no number at all. currency came back null on every one. Do not regex a number out of it and store it as pay; if you need a numeric band, use the salary_from and salary_to search filters, which run against SEEK's own indexed range rather than this text.
What does 'inc super' mean in an Australian salary?▾
Superannuation — the compulsory employer retirement contribution — and whether a quoted figure includes it changes the real base by a meaningful margin. Australian ads are inconsistent about it and salary_label is the only place it is ever stated, in free text. If you are comparing SEEK salaries against another market, treat an "inc super" figure and a bare figure as non-comparable rather than normalizing them.
Can I still fetch a job that has closed?▾
Yes, and this catches people out. A measured detail call on job_id 92851167 returned a complete posting — title, full description, salary, employer profile — together with expires_at 2026-07-22T01:42:00.000Z, is_expired true and status "Expired". Nothing about the response signals failure. Read is_expired or status before you show a job to a candidate; a full description is not evidence the role is open.
How many jobs come back per page, and how do I page correctly?▾
Do not hard-code a page size. Two measured searches each returned 20 jobs on page 1, with meta.pagination reporting total_pages 27 against a total of 524 for one query and 18 for the other. Page until meta.pagination.has_more is false and follow next_page rather than computing offsets yourself. total is SEEK's own match count for the query and is the cheap way to size a market before you page anything.
How do I pull every role at one employer?▾
Use company-jobs with the advertiser_id from any search or detail result — measured value 2852 for DWS Limited. It also accepts the SEEK company slug, a full SEEK company URL or the plain company name, and takes the same keyword, location, salary, work-type and date filters as search, so you can ask narrower questions like every part-time nursing role at one hospital group. advertiser_verified on a detail response tells you whether SEEK has verified that employer.
Which countries does this cover?▾
SEEK's Australian board, with New Zealand locations resolving through the same free-text location field. Salaries are AUD. Locations sharpen considerably when you include the state suffix — "Sydney NSW" and "Melbourne VIC" resolved cleanly in measured calls, and the response echoes country_code AU on each match so you can confirm what was matched.
Which fields commonly come back null?▾
More than you would expect on a live posting. Measured on real jobs: currency null, logo_url null, company_url null on search rows, share_link null on detail, posted_relative null on detail (it is populated on search rows as "5d ago"), and company_profile.size, rating and review_count all null. bullet_points is frequently an empty array. Treat all of these as absent data rather than errors, and never branch on truthiness alone when the meaningful value could be 0.
Can I filter by remote work?▾
Yes — work_arrangement accepts onsite, remote or hybrid, and a bad value is silently ignored rather than rejected, so a typo returns unfiltered results that look correct. Note the asymmetry with the response: search rows carry work_arrangement as a single string (measured "Hybrid"), while detail returns work_arrangements as an array that was empty on the measured job. Filter on the search side and trust the search row's value.
What is the SEEK API?▾
SEEK API is a ReefAPI endpoint group for seek It returns live JSON through POST requests under /seek/v1.
Is the SEEK API free to try?▾
Yes. ReefAPI starts with 1,000 free credits, no card required. SEEK calls use the same shared credit balance as every other ReefAPI engine.
Do I need a SEEK login or account?▾
No login to SEEK is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the SEEK data?▾
The page example is captured from a live search call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the SEEK API use?▾
SEEK actions currently cost 1 credit per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.
Can I call SEEK from an AI assistant or MCP client?▾
Yes. Connect ReefAPI once through MCP and your assistant can call seek actions with the same key, credit pool and JSON envelope used by normal REST requests.
15 Jobs & Hiring APIs on the same key
One key, one credit pool, one response envelope. If you are pulling SEEK, you are one call away from the rest of the category — no second contract, no second integration.
Need something this API does not do?
Name the endpoint, the field, or a source we do not carry yet. We ship new APIs every week and you would be first to get the key. Real people read every message and reply the same day.
Try it on your own data before you pay anything
The call above is the real endpoint, not a recording. A free key gives you 1,000 credits, the other 184 APIs, and the same envelope everywhere.
Endpoints, parameters and credit costs on this page are read from the live catalog and cannot drift from what the API accepts. Field notes were captured on 2026-08-28.