Job Opportunities API in JavaScript
Search jobs from Node.js with built-in fetch and cursor pagination.
- Official
Node.js 18 or later (built-in fetch) · free key, no card
Set it up in 3 steps
You need a free API key (no card) — get one here.
Set your key
Put your free key in an environment variable. Call the API from your server, never from browser code, so the key stays private.
Shellexport JOA_API_KEY=your_key_hereRun the snippet
Save as jobs.mjs and run node jobs.mjs. It fetches up to three pages and prints title, company, location and apply link (tested against the live API on 6 Oct 2026):
jobs.mjs// Node.js 18+ (built-in fetch). Save as jobs.mjs and run: node jobs.mjs const API = "https://api.jobopportunitiesapi.org/v1/jobs"; const headers = { Authorization: `Bearer ${process.env.JOA_API_KEY}` }; const params = new URLSearchParams({ country: "DE", q: "engineer", remote: "remote,hybrid", limit: "20" }); const jobs = []; for (let page = 0; page < 3; page++) { // every row returned is metered, so cap the pages const res = await fetch(`${API}?${params}`, { headers }); if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`); const body = await res.json(); jobs.push(...body.data); if (!body.has_more || !body.next_cursor) break; params.set("cursor", body.next_cursor); } for (const job of jobs.slice(0, 5)) { console.log(job.title, "|", job.company, "|", job.location, "|", job.apply_url); }Know the response
Each page is an object with data, next_cursor and has_more. Fields can be absent; field_sources tells you which ones the employer published and which were inferred.
Response shape{ "data": [ { "id": "…", "slug": "…", "title": "…", "company": "…", "location": "…", "country": "DE", "remote": "remote | hybrid | on_site | not_stated", "apply_url": "https://… (the employer's own apply page)", "posted_at": "2026-10-05T17:41:41Z", "field_sources": { "title": "published", "remote": "inferred", "…": "…" } } ], "next_cursor": "… (pass as ?cursor= for the next page)", "has_more": true }
Example: for job boards
In a Next.js or Astro site, run the fetch in a server route or at build time, cache the page, and link each job's apply button to apply_url.
Example: for AI agents
Expose the function as a tool in the Vercel AI SDK, LangChain.js or the OpenAI and Anthropic SDKs; the model fills country, q and remote, and your code adds the key server-side.
Questions
Straight answers about plans, metering and what to show.
How is usage counted?
Every job row the API returns counts against your plan's monthly record allowance, exactly as a direct API call would. The free key has a small monthly allowance and needs no card, so start with small page sizes and a daily schedule rather than polling every few minutes. Your key's largest page size is in GET /v1/me (limits.max_page_size).
Where do I get an API key?
At jobopportunitiesapi.org/register. The Explore key is free and needs no card. Keep it in your tool's credential store or an environment variable, never in a shared file.
Where do applicants apply?
On the employer's own site. Every job carries apply_url, the employer's application page or applicant-tracking-system link. Job Opportunities API never sits between the candidate and the employer, so always use apply_url as the apply button.
Do I need to show any attribution?
Yes, one line where listings are shown publicly: a visible credit "Data: Job Opportunities API" linking to https://jobopportunitiesapi.org (see /terms — storing, displaying, reselling and redistributing within your key's plan limits are all allowed). In addition, jobs listed through Erioun for Teams carry an attribution field (for example "via Erioun for Teams") and a canonical_url: when attribution is present, show it with the listing and link to canonical_url.
Related integrations
Get a free API key
No card. The same key works for every integration on this site.