The Problem: Job Data is Scattered Everywhere
If you've ever tried to build anything that touches job market data, you know the pain. Every job board has its own API, its own auth, its own rate limits, its own response format.
Want global coverage? You need Adzuna for 16 countries, Reed for UK, Arbeitnow for EU, Remotive for remote roles, TheirStack for tech stack analysis, Jooble for aggregated results, and probably five more I'm forgetting.
That's 7 API keys, 7 auth schemes (Basic Auth, Bearer tokens, keys-in-URL-path, no auth at all), 7 different response formats, and 7 sets of rate limit rules. For a single query like "find me Python developer jobs in Europe, preferably remote."
I spent the last week wiring all of these into a single MCP endpoint. Here's exactly how it works and how you can use it.
What MCP Changes About Multi-API Orchestration
Model Context Protocol (MCP) is the standard that lets AI agents discover and call tools dynamically. Instead of hardcoding API calls, your agent connects to an MCP server and gets a catalog of available tools — with typed schemas, descriptions, and pricing.
The key insight: the agent decides which tools to call based on the user's question. You don't write if/else logic for "if the user asks about UK jobs, call Reed; if they ask about remote, call Remotive." The LLM reads the tool descriptions and routes naturally.
Here's what 20 job-related tools look like through one MCP connection:
# Connect and discover job tools
curl -X POST https://apibase.pro/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "prompts/get",
"params": {
"name": "discover_tools",
"arguments": { "category": "jobs" }
}
}'
The response lists every job tool with its parameters:
| Tool | What It Does | Coverage |
|---|---|---|
adzuna.search |
Job search with salary data | 16 countries |
adzuna.salary |
Salary histograms by role | 16 countries |
adzuna.categories |
Job category taxonomy | Per-country |
theirstack.jobs |
Tech stack-filtered job search | Global, 181M+ postings |
theirstack.companies |
Find companies by technology | Global |
jooble.search |
Aggregated search, 70+ countries | Global |
reed.search |
UK jobs with salary (GBP) | UK |
reed.details |
Full job details by ID | UK |
arbeitnow.jobs |
EU job listings | DE, AT, CH, NL |
remotive.search |
Remote-only curated listings | Global remote |
jobs.salary_data |
BLS salary statistics | US |
jobs.occupation_search |
O*NET occupation database | US |
jobs.esco_search |
EU skills/occupation taxonomy | EU |
jobs.job_search |
CareerJet search | Global |
That's one connection, one auth token, one response format. The agent picks which tool fits the question.
Building the Agent: From Question to Multi-Source Results
Let me walk through what happens when a user asks: "Find me senior Python developer jobs in Berlin, preferably remote, and compare salaries with London."
A well-prompted agent would break this into 3-4 tool calls:
Call 1: TheirStack for tech-stack-specific results
curl -X POST https://apibase.pro/api/v1/tools/theirstack.jobs/call \
-H "Authorization: Bearer ak_live_..." \
-H "X-PAYMENT: ..." \
-H "Content-Type: application/json" \
-d '{
"keywords": "senior python developer",
"country": "DE",
"remote": true,
"technologies": "python, django, fastapi",
"limit": 10
}'
Response:
{
"jobs": [
{
"title": "Senior Python Developer",
"company": "Delivery Hero",
"location": "Berlin",
"country": "DE",
"remote": true,
"salary_min_usd": 75000,
"salary_max_usd": 95000,
"posted": "2026-03-28",
"url": "https://..."
}
],
"count": 10
}
Call 2: Reed for UK salary comparison
curl -X POST https://apibase.pro/api/v1/tools/reed.search/call \
-H "Authorization: Bearer ak_live_..." \
-H "X-PAYMENT: ..." \
-d '{
"keywords": "senior python developer",
"location": "London",
"salary_min": 60000,
"permanent": true,
"limit": 10
}'
{
"jobs": [
{
"id": 56671234,
"title": "Senior Python Developer",
"company": "Revolut",
"location": "London",
"salary_min": 80000,
"salary_max": 110000,
"currency": "GBP",
"applications": 47,
"url": "https://www.reed.co.uk/jobs/..."
}
],
"total": 443,
"count": 10
}
Call 3: Remotive for remote-only options
curl -X POST https://apibase.pro/api/v1/tools/remotive.search/call \
-H "Authorization: Bearer ak_live_..." \
-H "X-PAYMENT: ..." \
-d '{
"search": "python senior",
"category": "software-dev",
"limit": 10
}'
{
"jobs": [
{
"id": 982341,
"title": "Senior Python Backend Engineer",
"company": "GitLab",
"category": "Software Development",
"salary": "$130,000 - $170,000",
"location_requirement": "Americas, EMEA",
"tags": ["python", "django", "postgresql"],
"url": "https://remotive.com/remote-jobs/..."
}
],
"count": 10,
"total": 2847
}
Call 4: Adzuna salary histogram
curl -X POST https://apibase.pro/api/v1/tools/adzuna.salary/call \
-H "Authorization: Bearer ak_live_..." \
-H "X-PAYMENT: ..." \
-d '{
"what": "python developer",
"where": "london",
"country": "gb"
}'
The agent now has: Berlin jobs with tech stack filters, London jobs with GBP salaries, global remote positions with USD salary ranges, and a salary distribution histogram. Total cost: 4 API calls × $0.001-0.002 each = less than $0.01 for a comprehensive multi-market job analysis.
The Part Nobody Talks About: Why 7 Providers, Not 1
Here's what I learned integrating all these job APIs in one day.
No single provider covers everything:
| Need | Best Provider | Why |
|---|---|---|
| "Show me Python jobs" | TheirStack | Only one with tech stack filter (technologies_or) |
| "UK jobs with salary" | Reed | Structured min/max GBP salary, not free text |
| "Remote jobs only" | Remotive | Curated remote-only board, salary strings included |
| "Jobs in Germany" | Arbeitnow | EU-native, German market coverage |
| "Salary comparison" | Adzuna | Statistical salary histograms, not just listings |
| "Global search" | Jooble | 70+ countries, widest aggregation |
| "How competitive is this role?" | Reed |
applications count per listing |
The auth diversity is wild. In one afternoon I dealt with:
- Bearer JWT tokens (TheirStack)
- API key in URL path — literally
/api/{key}(Jooble) - HTTP Basic Auth with key as username, empty password (Reed)
- No auth at all (Arbeitnow, Remotive)
- App ID + App Key as query params (Adzuna)
That's 5 different auth schemes for one category. An MCP gateway normalizes this — your agent sends one Authorization: Bearer header and the gateway handles the rest.
Response Format Normalization
This is the unsexy-but-critical part. Each API returns salary differently:
TheirStack: "salary_min_usd": 75000, "salary_max_usd": 95000
Reed: "minimumSalary": 80000.0, "maximumSalary": 110000.0, "currency": "GBP"
Remotive: "salary": "$130,000 - $170,000"
Adzuna: "salary_min": 45000, "salary_max": 65000 (no currency field, inferred from country)
Arbeitnow: no salary field at all
Jooble: "salary": "" (often empty)
The adapter layer normalizes each response into a consistent shape. Reed's minimumSalary becomes salary_min. Remotive's free-text salary string gets passed through as-is (parsing "$130,000 - $170,000" into min/max is the agent's job — the API shouldn't guess).
Every adapter also strips HTML from descriptions (job boards love injecting and <b> tags into plain text fields) using a shared stripHtml() utility. This sounds trivial until you're debugging why an agent is hallucinating HTML entities.
Payment: Per-Call, Not Per-Month
Each job search costs $0.001 to $0.002 per call. The payment happens via x402 — the HTTP standard where:
- Agent calls a tool → gets
402 Payment Requiredwith price - Agent signs a USDC micropayment on Base
- Agent retries with payment proof in
X-PAYMENTheader - Server verifies, escrows funds, calls the upstream API, returns data
- Escrow settles to the platform wallet
For a recruiting agent that runs 100 job searches per day across 7 providers, that's roughly $0.15/day. Compare that to subscribing to 7 different job APIs at $30-100/month each.
Traditional: 7 APIs × ~$50/month = $350/month
Per-call: 100 calls/day × $0.002 × 30 days = $6/month
This is why per-call pricing matters for agents. Most agents are bursty — they run a batch of searches, synthesize results, then go idle. Paying subscriptions for idle capacity is exactly the wrong model.
Try It Yourself
The entire jobs toolkit is live right now. Connect any MCP client:
{
"mcpServers": {
"apibase": {
"url": "https://apibase.pro/mcp",
"transport": "streamable-http"
}
}
}
Or use REST directly:
# Get all available job tools
curl -s https://apibase.pro/api/v1/tools | \
python3 -c "
import sys,json
tools = json.load(sys.stdin)['data']
jobs = [t for t in tools if t['category'] == 'jobs' or 'job' in t['name'].lower()]
for t in jobs:
print(f\"{t['id']:30s} \${t['pricing']['price_usd']}\")
"
The MCP endpoint is at https://apibase.pro/mcp. The full tool catalog (409 tools across 30+ categories — not just jobs) is at https://apibase.pro/api/v1/tools. Source code is on GitHub.
The jobs category alone now has 20 tools across 7 specialized providers. Each one was chosen for a specific coverage gap — there's no overlap where one provider does everything another does. That's the point of a gateway: you pick the best tool for each question, not the best "one API to rule them all."
Built with APIbase.pro — 409 tools, 121 providers, one MCP endpoint.
Top comments (0)